2013-05-01 23 views
5

C# .NET 4.0 Windows Service uygulamasında ILMerge ve Quartz.NET kullanıyorum. Uygulama, ILMerge kullanmadan gayet iyi çalışıyor, ancak şimdi gönderi sürümüne yaklaştığımıza göre, tüm DLL'leri tek bir yürütülebilir dosyada birleştirmek istedim.Yürütülebilir tuhaf istisna ile başarısız

Sorun ILMerge iyi iş gibi görünüyor ki, ama kombine yürütülebilir çalıştırdığınızda, bu istisna atar:

işlenmeyen İstisna: Quartz.SchedulerException: threadpool tipi 'Quartz.Simpl.SimpleThreadPool' could örneklendirilemez. ---> System.InvalidCastException: 'Quartz.SlimplThreadPool' türünde 'Quartz.Spi.IThreadPool' yazmak için nesne dönüştürülemiyor. içinde Quartz.Util.ObjectUtils.InstantiateType [T] (Tip tipi) en
: hattı 0
Quartz.Impl.StdSchedulerFactory.Instantiate (at) 'de: hattı 0
--- iç durum yığın izleme sonu - - içinde Quartz.Impl.StdSchedulerFactory.Instantiate() at
: in Quartz.Impl.StdSchedulerFactory.GetScheduler (satır 0
): satır 0

herkes bu yüzden bir fikri var mı? Zaten 4 saatten fazla harcadım ve anlayamıyorum. ILMerge ile birleşmezse, her şey iyi çalışır (Quartz.dll ve Common.Logging.dll ile aynı dizinde).

Eminim ki birileri daha önce böyle bir şekilde Quartz.net'i paketlemeyi denemeli, herhangi bir fikir var mı?

+0

Bu, ilk kez ILMerge ile birleştirmeyi denediniz mi? Ya da son değişikliklerden önce mi çalıştı? –

+1

İlk kez ILMerge'i kullanmaya çalıştım, koştum, artık işe yaramadı. Figürlü, ILMerge olmalı, içselleştirmeyi denedi, hiçbir şeyi değiştirmedi. Normalde derlenmiş ILMerge'i (bunu denemeden önce kullandığım gibi), tüm işleri (DLL'ler aynı dizinde bulunuyorsa) kaldırın. –

+0

ILMerge'nin işleyemediği şeylerden biri, harici bir derlemeden yükleme yapmaktır (stacktrace üzerinde bir bakışa dayalı durum böyle olabilir). Belki de (burada) http://chrisghardwick.blogspot.nl/2012/01/ilmerge-getting-started-merging-and.html) – rene

cevap

1

Sorumluluk Reddi: Ben Quartz.NET'i hiç bilmiyorum, ancak ILMerge ile zaman geçirdim. Sonunda sınırlamalarını anladığımda ... kullanmayı bıraktım. ILMerge'd uygulama, "yansıma" sözcüğünü içeren her şeyle ilgili sorunlara sahip olma eğilimindedir. Tahmin edebiliyorum (Quartz.NET'i hiç kullanmadım), bazı sınıfların yansıma kullanarak çözüldüğünü ve yapılandırma dosyaları tarafından çalıştırıldığını.

Sınıf sadece ismiyle (ad alanıyla) değil, aynı zamanda montajla da (istisna mesajında ​​görüntülenmeyen maalesef gösterilmektedir) ile tanımlanır. Öyleyse, (ILMerging'den önce) iki derlemenin A (sizin için Uygulama) ve Q (Quartz.NET için) olduğunu varsayalım. Montaj 'A', 'Q' aksamını referans alıyordu ve 'Q: QCnt' uygulayan bir sınıf 'Q: QClass' kullanıyordu. Birleştirildikten sonra, bu sınıflar 'A: QClass' ve 'A: QIntf' oldular (Q'dan A'ya aktarıldılar) ve koddaki tüm referanslar, (tamamen) yeni sınıfları/arayüzleri kullanmak için değiştirildi. A: QClass "şimdi" A: QIntf "uyguluyor. Ancak, "Q: QClass" öğesine hala başvurabilecek herhangi bir yapılandırma dosyası/katıştırılmış dizge değiştirmedi.Uygulama, bu güncelleştirilmemiş yapılandırma dosyalarını okuyorsa, hala "Q: QClass" yüklüyor (neden bu farklı bir sorudur, belki de şu anki klasörde 'Q' grubu bırakılmış olabilir veya belki GAC'de - bakınız 1). Neyse, "Q: QClass" "A: QIntf" uygulamıyor, hala ikili olsalar bile "Q: QIntf" uygular - böylece 'Q: QClass' öğesini 'A: QIntf' yapamazsınız.

İdeal olmayan, ancak çalışmayan çözüm, bunları "birleştirmek" yerine "gömmek" demektir. Açık kaynak kodlu bir araç yazdım (birleştirmek yerine yerleştirmek) ama bu soruyla ilgili değil. Yani eğer gömülmeye karar verirsen, bana sor.

  1. Bilgisayarınızdaki Q.dll dosyasının her bir örneği kaldırılarak (gizleme, sizin için ne olursa olsun) kaldırarak bunu test edebilirsiniz. Haklıysam, istisna şimdi 'FileNotFound' demeliydi.
+0

ILMERGE kullanmamaya son verdim, sadece işe yaramazdı ve sadece bir dosya dosyalarının dağıtımda daha az çalışmasının yararından çok daha fazla iş gerektiriyordu. Gömülü parçaları yüklemeyi ve dinamik olarak yüklemeyi de denedim, bu da sahnelerin arkasındaki şeylerin çok daha fazlasını anlamamda bana yardımcı oldu, ama sadece cehennem için işe yaramayacaktı. Meclisleri en erken noktaya yükledim, ancak onlara ulaşan çok sayıda statik sınıf vardı ve yeniden yüklenmeleri gerekiyordu, ama statik kurucu bile çok garipti. her zaman başarısız oldu. Cevabınız en arka plana sahipti, bu yüzden teşekkürler! –

+0

'Montajları en erken noktaya yükleme' ile ne demek istiyorsunuz? Jeffrey Richter'in blogunda açıkladığı yöntemi başarılı bir şekilde kullandım (önceki yorumuma bakın). Çok ileriye doğru ilerliyordu ve izlemesi gereken tek şey, AssemblyResolve etkinliğinizin başka bir şeyden önce başlatıldığından emin olmanız gerekiyor. Bu durumda, AssemblyResolve olayını ayarlayan ve daha sonra eski giriş noktasını belirleyen yeni bir giriş noktası oluşturmak gerekiyordu. – sgmoore

+0

@RomanMittermayr: Ayrıca "en erken" noktası şaşkın. Statik kurucu oldukça erken olmasına rağmen, kulaklar noktası modül başlatıcısıdır. Ne yazık ki, modül başlatıcısı C# ile değiştirilemez ancak bazı küçük IL manipülasyonu ile değiştirilebilir (bakınız: https://github.com/Fody/ModuleInit). "Yeniden yükleme" dediğinizde, Quartz.NET'in ayrı Uygulama Alanları oluşturduğuna dair bir fikrim var. Aslında, onlara erişemiyor ve bunları AssemblyResolver'a enjekte ederseniz sorun olabilir. Https://libz.codeplex.com/ adresini de deneyebilirsiniz. –

1

Kendi ISchedulerFactory'nizi oluşturmayı deneyebilir ve tüm türlerinizi yüklemek için yansımayı kullanmaktan kaçabilirsiniz. StdSchedulerFactory, bir threadpool oluşturmak için bu kodu kullanır.

 Type tpType = loadHelper.LoadType(cfg.GetStringProperty(PropertyThreadPoolType)) ?? typeof(SimpleThreadPool); 

     try 
     { 
      tp = ObjectUtils.InstantiateType<IThreadPool>(tpType); 
     } 
     catch (Exception e) 
     { 
      initException = new SchedulerException("ThreadPool type '{0}' could not be instantiated.".FormatInvariant(tpType), e); 
      throw initException; 
     } 

denir ObjectUtils.InstantiateType yöntem bu biridir ve son satırı, istisna atma biridir:

Bu sizin hata oluyor ve yapım değişikliklere bakarak başlamak için bir yer olurdu nerede
public static T InstantiateType<T>(Type type) 
    { 
     if (type == null) 
     { 
      throw new ArgumentNullException("type", "Cannot instantiate null"); 
     } 
     ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes); 
     if (ci == null) 
     { 
      throw new ArgumentException("Cannot instantiate type which has no empty constructor", type.Name); 
     } 
     return (T) ci.Invoke(new object[0]); 
    } 

Fabrikada bu bölümden hemen sonra, veri kaynakları aynı kalıp kullanılarak yüklenir ve sonra işlerin kendileri de dinamik olarak yüklenir; bu da kendi JobFactory'nizi de yazmanız gerektiği anlamına gelir. Quartz.Net bu yoldan aşağıya inerek bir dizi bit ve parçaları dinamik olarak yüklediğinden, bu sayede adil bir şeylerin yeniden yazılmasını sağlayabilirsiniz.