SORU
23 Aralık 2009, ÇARŞAMBA


Tek-montaj çoklu dil Windows Dağıtım (İLMerge ve uydu derlemeleri / yerelleştirme) Form - mümkün mü?

Basit bir Windows Form var (#, C .NET 2.0) uygulaması, Visual Studio 2008 ile inşa edilmiş.

Birden çok UI dil desteği istiyorum, "" şeklinde, ve kültüre özgü .Localizable özelliğini kullanarak resx yerelleştirme yönü sorunsuz ve kolay çalışır dosyaları. Visual Studio otomatik olarak kültüre özgü resx dosyaları uydu derlemeler derler, derlenmiş uygulama klasöründe kültür özel klasörleri bu uydu derlemelerini içeren vardır.

Uygulama dağıtıldıktan (kopyalar) olarak istiyorumtek bir derlemeve yine birden fazla setleri içerir yeteneği korumak kültüre özgü kaynakları.

ILMerge (ya da ILRepack) kullanarak, ana yürütülebilir derleme, ama standart uydu derleme birleştirme edebilirim .NET ResourceManager geri dönüş mekanizmaları ana derleme derlenmiş olan kültüre özgü kaynakları bulmak.

(Yürütülebilir) birleştirilmiş benim montaj alıyorum ve kültüre özgü alt klasörler içine kopyaları yer ilginçtir, eğer, o zaman her şey çalışıyor! Aynı şekilde kullandığımda birleştirilmiş kurultayın ana ve kültüre özgü kaynakları görebiliyorum Reflector (ya da ILSpy). Ama kültüre özgü alt klasörler içine ana birleştirme kopyalama zaten birleştirme amacı yendi - gerçekten orada tek Kurul sadece tek bir kopya olması gerekiyor

Merak ediyorumya ResourceManager geri dönüş mekanizmaları kültüre özgü GAC aynı montaj yerine ve kültür adlı kaynakları alt klasörleri aramak için kaçırmak etkilemek için herhangi bir yolu yoktur. Geri dönüş mekanizması aşağıdaki makalelerde açıklanan görüyorum, ama değişiklik olacağını nasıl hiçbir ipucu: BCL Team Blog Article on ResourceManager.

Herkes herhangi bir fikir var mı? Bu nispeten sık soru bir online görünüyor (örneğin, burada başka bir Yığın Taşması soru: "ILMerge and localized resource assemblies"), ama herhangi bir yerde herhangi bir yetkili cevap bulamadım.


GÜNCELLEME 1: Temel Çözüm

casperOne's recommendation below aşağıdaki en sonunda bu işi başardı.

Soru casperOne tek cevap, benim kendi eklemek istemiyorum sağladı çünkü burada çözüm kodu koyuyorum.

Çerçeve kaynak bulma geri dönüş mekanizmaları uygulanan "" yöntem ve aynı montaj bizim arama yapma . İnternalGetResourceSet bağırsaklarını çekerek işe almak başardı ^strong>ilkmekanizma kullanılır. Eğer kaynak şu anda mecliste bulunursa, o zaman varsayılan arama başlatmak için temel yöntem dediğimiz mekanizmalar (@Wouter aşağıda yorumun için teşekkürler).

Bunu yapmak için, "" sınıf, ve sadece tek bir yöntem (ve yeniden uygulanan özel bir çerçeve yöntemi) bozdu: . ComponentResourceManager ben türetilmiş

class SingleAssemblyComponentResourceManager : 
    System.ComponentModel.ComponentResourceManager
{
    private Type _contextTypeInfo;
    private CultureInfo _neutralResourcesCulture;

    public SingleAssemblyComponentResourceManager(Type t)
        : base(t)
    {
        _contextTypeInfo = t;
    }

    protected override ResourceSet InternalGetResourceSet(CultureInfo culture, 
        bool createIfNotExists, bool tryParents)
    {
        ResourceSet rs = (ResourceSet)this.ResourceSets[culture];
        if (rs == null)
        {
            Stream store = null;
            string resourceFileName = null;

            //lazy-load default language (without caring about duplicate assignment in race conditions, no harm done);
            if (this._neutralResourcesCulture == null)
            {
                this._neutralResourcesCulture = 
                    GetNeutralResourcesLanguage(this.MainAssembly);
            }

            // if we're asking for the default language, then ask for the
            // invariant (non-specific) resources.
            if (_neutralResourcesCulture.Equals(culture))
                culture = CultureInfo.InvariantCulture;
            resourceFileName = GetResourceFileName(culture);

            store = this.MainAssembly.GetManifestResourceStream(
                this._contextTypeInfo, resourceFileName);

            //If we found the appropriate resources in the local assembly
            if (store != null)
            {
                rs = new ResourceSet(store);
                //save for later.
                AddResourceSet(this.ResourceSets, culture, ref rs);
            }
            else
            {
                rs = base.InternalGetResourceSet(culture, createIfNotExists, tryParents);
            }
        }
        return rs;
    }

    //private method in framework, had to be re-specified here.
    private static void AddResourceSet(Hashtable localResourceSets, 
        CultureInfo culture, ref ResourceSet rs)
    {
        lock (localResourceSets)
        {
            ResourceSet objA = (ResourceSet)localResourceSets[culture];
            if (objA != null)
            {
                if (!object.Equals(objA, rs))
                {
                    rs.Dispose();
                    rs = objA;
                }
            }
            else
            {
                localResourceSets.Add(culture, rs);
            }
        }
    }
}

Aslında bu sınıf kullanmak için, Sistemi değiştirmek gerekir.ComponentModel.Bu ComponentResourceManager "XXX.Tasarımcı.cs" dosyalarını Visual Studio - ve bu tasarlanmış bir form değişikliği her zaman yapmak gerekir - tarafından oluşturulan Visual Studio otomatik olarak bu kodu değiştirir. (Sorun "Customize Windows Forms Designer to use MyResourceManager", daha zarif bir çözüm bulamadım - Oto-Yedek pre-build bir adımda fart.exe kullanıyorum.) tartışılır oldu


GÜNCELLEME 2: Başka bir Pratik Göz - 2'den fazla dilde

Zamanda çözüm yukarıda bildirdim, aslında sadece iki dili çok beğeniyordum ve İLMerge son birleştirilmiş Meclisine uydu montaj birleştirme işini gayet iyi yapıyordu.

Son zamanlarda bulunduğu benzer bir proje üzerinde çalışmaya başladımbirden fazlabirden fazla uydu derlemeleri birleştirmek Yerine talep vardı, birden çok kez ilk uydu derleme birleştirme! dilleri, ve bu nedenle birden fazla uydu derlemeler ikincil ve İLMerge çok tuhaf bir şey yapıyordu:

komut satırı örneğin:

"c:\Program Files\Microsoft\ILMerge\ILMerge.exe" /t:exe /out:%1SomeFinalProg.exe %1InputProg.exe s\InputProg.resources.dll r\InputProg.resources.dll

Bu komut satırı ile birleştirilmiş montaj kaynakların aşağıdaki ayarlar (İLSpy biçimleri ile gözlenen) alıyordum

InputProg.resources
InputProg.es.resources
InputProg.es.resources <-- Duplicated!

Biraz oynadıktan sonra, bu karşılaştığında İLMerge sadece bir hata olduğunu fark ediyor ve sona erdiaynı ada sahip birden fazla dosyakomut satırı tek bir çağrı. Çözüm basit komut satırı Ara bir farklı her bir uydu derleme birleştirme için:

"c:\Program Files\Microsoft\ILMerge\ILMerge.exe" /t:exe /out:%1TempProg.exe %1InputProg.exe s\InputProg.resources.dll
"c:\Program Files\Microsoft\ILMerge\ILMerge.exe" /t:exe /out:%1SomeFinalProg.exe %1TempProg.exe r\InputProg.resources.dll

Bu olduğunda, son montaj elde edilen kaynakların doğru

InputProg.resources
InputProg.es.resources
InputProg.fr.resources

Bu açıklığa kavuşturmak yardımcı olur diye nihayet, burada post-build parti tam bir dosya

"%ProgramFiles%\Microsoft\ILMerge\ILMerge.exe" /t:exe /out:%1TempProg.exe %1InputProg.exe s\InputProg.resources.dll 
IF %ERRORLEVEL% NEQ 0 GOTO END

"%ProgramFiles%\Microsoft\ILMerge\ILMerge.exe" /t:exe /out:%1SomeFinalProg.exe %1TempProg.exe r\InputProg.resources.dll 
IF %ERRORLEVEL% NEQ 0 GOTO END

del %1InputProg.exe 
del %1InputProg.pdb 
del %1TempProg.exe 
del %1TempProg.pdb 
del s\*.* /Q 
del r\*.* /Q 
:END

GÜNCELLEME 3: İLRepack

Başka bir hızlı not - Bir şeyler rahatsız etti beni İLMerge olduğunu ek bir özel Microsoft aracı, yüklü varsayılan olarak, Visual Studio, ve bu nedenle ekstra bir bağımlılık yapar ki bu biraz daha zor bir üçüncü parti başlamak için ile benim açık kaynak kodlu projeler.

Geçenlerde keşfetti ILRepack bir açık kaynak (Apache 2.0) eşdeğer şimdiye kadar işleri de bana (drop-in yerine), ve serbestçe dağıtılan ile projenin kaynakları.


Bu birileri yardımcı olur umarım!

CEVAP
23 Aralık 2009, ÇARŞAMBA


Bu çalışma görebildiğim tek yolu 26 ** InternalGetResourceSet GetResourceFileName yöntemleri geçersiz kılma türeyen bir sınıf oluşturarak. Oradan, kaynakları elde nerede geçersiz kılmak mümkün, CultureInfo bir örneği verilmelidir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • AceHoodVEVO

    AceHoodVEVO

    12 Mayıs 2009
  • bobono1baby

    bobono1baby

    14 AĞUSTOS 2011
  • Marques Brownlee

    Marques Brow

    21 Mart 2008