Soru .Net: Montaj yüklendiğinde koşu kodu


Yükleme kodunda belirli bir şey yapmadan bir montaj yüklendiğinde bazı kodların çalıştırılması mümkün mü? Aradığım şey, bir türdeki statik bir kurucu gibi.

Örneğin:

Meclis A, B Kurulumu hakkında bilgi sahibi değildir, fakat B, B hakkında bilgi sahibidir. Montaj A, B yüklüyse, B ile ilgili bazı şeyleri bilmelidir. Assembly B çalışma zamanı tarafından (başvurulan veya açık) yüklendiğinde, Assembly A'da bir yöntemi çağıran bir kod parçası (statik yöntem veya öznitelik) istiyorum.

Bu problemin temel nedeni, ara yüzler kullanıldığında derleme zamanında bilinmeyen B türlerini içeren A türünü serileştirirken, bilinmeyen türlerle karşılaşılır.


32
2018-02-02 22:30


Menşei




Cevaplar:


CLR destekliyor modül başlatıcılar. Kullanmak için C ++ / CLI kodunu veya ilasm.exe'yi kesmeniz gerekir.


38
2018-02-02 22:56



Hiçbir saldırı gerekli github.com/Fody/ModuleInit - Richard Collette
@RichardCollette hala hack yapıyor, ama Fody sadece yapmak için kolaylaştırmak için inşa sürecine hack otomatize ediyor. - Scott Chamberlain


(düzenleme - C ++ için geçerlidir; C ++ yaklaşımı için bkz. bu cevap)

Temel olarak, hayır: yapamazsın. Bu büyük bir saldırı yüzeyi ve izin verilmez. Init kodunun yürütülmesini sağlayan bazı B türlerine statik bir ctor koymak isteyebilirsiniz, ancak bu konuyla ilgili ...


6
2018-02-02 22:34



Neden saldırı yüzeyi? - Robert Wagner
Görünüşe göre, kodları bilerek çağrıştıran kodları gizlemek oldukça kolay olurdu. İz sürmesi zor, vb. Hangi iş parçacığının çalışacağı sorusuyla baş başa kalsın ... Belki de düzgün bir şekilde seslendiremiyorum ama sesler bana karşı değil. Ama yine de yapamazsın çünkü - Marc Gravell♦
Üzerinde herhangi bir bilgi olup olmadığını biliyor musunuz (modül başlatıcıları yükte değil, statik yapıcılardan önce çalışmaktadır), bu yüzden kod kendini yükleme sırasında çalışabilirse ilginçtir. Bu çok yakın soruyu da cevaplayıp veremeyeceğinizi kontrol ederseniz - stackoverflow.com/questions/24718917/... - Alexei Levenkov


.Net'de statik yapıcılar kullanabilirsiniz, ancak maalesef istediğinizi yapmıyorlar. Statik kurucular sadece bir tür kullanılmadan önce yürütülür. Görmek http://msdn.microsoft.com/en-us/library/k9x6w0hc(VS.80).aspx detaylar için.

AppDomain'in AssemblyLoad olayına abone olmanızdan biraz mesafe alabilirsiniz. Görmek http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyload.aspx.

Olay işleyicinizde yeni yüklenen montajı yansıtabilir ve istediğiniz kodu çalıştırabilirsiniz.


5
2018-02-02 23:05



Maalesef, 30 adet garnizonun sadece bir tanesi bu kayıt işleminin yapılmasına ihtiyaç duyduğundan, AssemblyLoad aşırı bir şekilde biraz aşırı olabilir. - Robert Wagner


.NET derlemesini başlatmak için 3 seçenek vardır:

  1. Başlamanız için Meclisinizde Statik bir işlev Init () veya Main () yazarsınız ve bu işlevi, bu Kurulumu yükleyen C # kodundan yansıtarak çağırırsınız.
  2. Kodunuzu DllMain () içine yerleştirdiğiniz Yönetilen C ++ Derlemesi yazın. Dikkatli olun çünkü kodunuz Loader Lock'da (bazı DLL'lerin yüklenmesi gibi) yasaklanmış olan bazı şeylerin yasaklanmasıyla gerçekleştirilecektir. Ancak, HERHANGİ başlatma işlemini yapan yeni bir konu başlatabilirsiniz. (LoaderLock Hakkında: https://msdn.microsoft.com/en-us/library/ms173266.aspx) (Hakkında DllMain'de: C # C ++ / CLI C DLL System.IO.FileNotFoundException için)
  3. Saf bir C # derleme derleyin ve burada açıklandığı gibi bir modül başlatıcı kodu eklemek için derlenmiş bir DLL dosyasını değiştirin: http://einaregilsson.com/module-initializers-in-csharp/ Bu yöntemin dezavantajı, derleme işlemin içine yüklendiğinde başlatma işlevinin hemen çağrılmamasıdır. Ancak mecliste başka bir şeyden önce ilk önce erişilir.

4
2018-02-11 21:57



1) tartışmasız tatmin etmiyor msgstr "yükleme koduna özel bir şey yapmadan?" - MickyD
Yükleme kodunu değiştirmemenin tek yolu seçenek 2'dir.) - Elmue
Evet, seçenek 2'yi çok seviyorum - MickyD


Bu sorunu hafifletmek için muhtemelen serileştirme yaklaşımınızı tekrar gözden geçirmelisiniz. Kullanarak serileştirirseniz ISerializable ve SerializableAttribute öznitelik, seri hale getirme grafiğinin, gerektiğinde montaj A olmadan, montaj B'yi açıkça bilmesi gerektiğinde, montaj B'yi yükleyeceği şekilde yapabilirsiniz.


3
2018-02-02 22:55



Bu yöntemi kullanarak B Grubunu nasıl tanımlayabilir ve yükleyebilirim? - Robert Wagner
Serileştirirseniz, bir BinaryFormatter, serileştirme grafiğinizde ISerializable uygulayan herhangi bir tür, kurdunuz deserialize sırasında çağrılır, hangi ihtiyacınız olursa olsun kodu arayabilirsin. Serileştirdiğinizde, arabirim için seri hale getirme sorguları ... - Jeff Yates
... A'nın sadece bir arabirim tarafından B türlerine başvurması önemli değil, düzgün bir şekilde serileştirecekler. - Jeff Yates
WCF ile XML Serileştirme kullanıyoruz. - Robert Wagner
O zaman bu yaklaşımla şanstan da uzaklaşabilirsiniz. ISerializable türlerini SOAP XML'e kalıcı olarak koruyan bir SoapFormatter var ve XmlFormatter'ın çevrimiçi olarak var olmasına rağmen (ne kadar başarılı olduklarını bilmiyorum). - Jeff Yates


Karma bir montaj kullanarak, DllMain'in bir montaj yükünde çalışmasını sağlayabilirsiniz.


0
2018-02-04 04:42