perlon Posted October 26, 2018 Report Share Posted October 26, 2018 Witam. Czy jest możliwość skonstruowania .dll'ki wczytywanej przez NETLOAD tak aby po jej załadowaniu automatycznie wykonał się jakiś kod z jej wnętrza? Coś w rodzaju autostartu wewnątrz dll bez wydawania komendy z commandline. I pytanie główne raczej dotyczy ogólnie C# czy w takim kodzie jest możliwe sprawdzenie jaka aplikacja załadowała do swoich assemblies taką właśnie dll'kę. Chodzi mi o możliwość używania jednej skompilowanej dll w różnych środowiskach CAD (AutoCAD, ZwCAD, BricsCad etc.) gdzie wewnętrzna metoda sprawdzałaby środowisko i za pomocą fabryki tworzyła instancję klasy Document zgodną z tym środowiskiem. Tak na marginesie, czy w ogóle jest możliwe stworzenie takiej dll która raz skompilowana będzie pracowała na różnych platformach CAD obsługujących .NET'a Quote Link to comment Share on other sites More sharing options...
kruszynski Posted October 26, 2018 Report Share Posted October 26, 2018 Godzinę temu, perlon napisał: Czy jest możliwość skonstruowania .dll'ki wczytywanej przez NETLOAD tak aby po jej załadowaniu automatycznie wykonał się jakiś kod z jej wnętrza Podejrzewam że tak. W ZRX jest to możliwe. Poszukam czegoś, albo dopytam w ZWSOFT. Godzinę temu, perlon napisał: czy jest możliwe sprawdzenie jaka aplikacja załadowała do swoich assemblies taką właśnie dll'kę. Również postaram się czegoś dowiedzieć Godzinę temu, perlon napisał: czy w ogóle jest możliwe stworzenie takiej dll która raz skompilowana będzie pracowała na różnych platformach CAD obsługujących .NET'a Tu mam najgorsze przeczucia. Raczej stworzyłbym 2 projekty , czy nawet więcej i ładowałbym te same pliki źródłowe. Problem może wynikać z dodawania różnych "References" do tego samego projektu. A może to tylko bezpodstawne moje obawy. Quote Link to comment Share on other sites More sharing options...
kruszynski Posted October 26, 2018 Report Share Posted October 26, 2018 52 minuty temu, kruszynski napisał: czy jest możliwe sprawdzenie jaka aplikacja załadowała do swoich assemblies taką właśnie dll'kę. Mogę się mylić, ale tak na szybko szukałbym czegoś takiego: Assembly.GetExecutingAssembly() Quote Link to comment Share on other sites More sharing options...
perlon Posted October 26, 2018 Author Report Share Posted October 26, 2018 Tak sobie trochę sam odpowiem 😉 Co do generowania różnych dll to myślę że rozwiązaniem połowicznym może być globalny #define i w poszczególnych deklaracjach using zamykać je w #ifdef #endif. Jeszcze tylko muszę poszukać czy da się zautomatyzować generowanie nazwy dll w zależności od takiego #define 10 minut temu, kruszynski napisał: Mogę się mylić, ale tak na szybko szukałbym czegoś takiego: Assembly.GetExecutingAssembly() Będę to sprawdzał. Na razie AppDomain.CurrentDomain.SetupInformation.ApplicationName; zwraca mi ZwCAD.exe więc już jest jakieś zaczepienie. Quote Link to comment Share on other sites More sharing options...
kruszynski Posted October 26, 2018 Report Share Posted October 26, 2018 2 godziny temu, perlon napisał: Czy jest możliwość skonstruowania .dll'ki wczytywanej przez NETLOAD tak aby po jej załadowaniu automatycznie wykonał się jakiś kod z jej wnętrza? Znalazłem: namespace test { public class Class1 : ZwSoft.ZwCAD.Runtime.IExtensionApplication { public void Initialize() { MessageBox.Show("Initialize!"); } public void Terminate() { Console.WriteLine("Cleaning up..."); } [CommandMethod("test2492")] public static void test2492() { MessageBox.Show("Hello World!"); } } } Ale jestem z siebie dumny Parikon 1 Quote Link to comment Share on other sites More sharing options...
Parikon Posted October 26, 2018 Report Share Posted October 26, 2018 (edited) using System; using System.Windows.Forms; using zza = ZwSoft.ZwCAD.Runtime; namespace StartDLL { public class Class1 : zza.IExtensionApplication { public void Initialize() { MessageBox.Show("Initialize!"); } public void Terminate() { Console.WriteLine("Cleaning up..."); } [zza.CommandMethod("test2492")] public static void test2492() { MessageBox.Show("Hello World!"); } } } Przy załadowywaniu wykonuje się metoda Initialize(), po wywołaniu komendy test2492 metoda test2492(). Jak wywołać metodę Terminate() - zakończenie? Edited October 26, 2018 by Parikon Quote Link to comment Share on other sites More sharing options...
perlon Posted October 28, 2018 Author Report Share Posted October 28, 2018 Dnia 26.10.2018 o 14:18, kruszynski napisał: Znalazłem: namespace test { public class Class1 : ZwSoft.ZwCAD.Runtime.IExtensionApplication { public void Initialize() { MessageBox.Show("Initialize!"); } public void Terminate() { Console.WriteLine("Cleaning up..."); } [CommandMethod("test2492")] public static void test2492() { MessageBox.Show("Hello World!"); } } } Ale jestem z siebie dumny No jest z czego Próbowałem coś przez konstruktora ale jest wołany przy pierwszym użyciu dowolnej metody. O Initialize nie doczytałem. Wygląda na to, że metoda Initialize jest wywoływana tylko z jednej klasy pomimo zdefiniowania interfejsu IExtensionApplication w kilku. Wniosek : trzeba stworzyć klasę np. Autostart z interfejsem IExtensionApplication niekoniecznie zawierającą CommandMethod. Dzięki za rozwiązanie Z testów mi wyszło że Terminate() jest wołana przy niszczeniu obiektu a to następuje przy zamykaniu ZwCAD'a. Chyba może być wykorzystana do ręcznego wywołania Garbage Collector ewentualnie zapisu stanu aplikacji przed zamknięciem zwcad'a. Ale żeby tak w trakcie działania wywołać terminate() to chyba się nie da bo trzeba by mieć do tego obiektu referencję. A zdaje się że obiekt jest powoływany na zapleczu bez globalnie wystawionej referencji. Quote Link to comment Share on other sites More sharing options...
kruszynski Posted October 29, 2018 Report Share Posted October 29, 2018 hm. jeszcze nie wiem do czego, ale mam takie podskórne wrażenie, że będę tego używał. Quote Link to comment Share on other sites More sharing options...
Parikon Posted October 29, 2018 Report Share Posted October 29, 2018 W PI mam stworzonego lispa, który ładuje dll-kę, w której jest metoda ładująca inne dll-ki. Przy czym ta metoda wywołuje się jako komenda, którą trzeba uruchomić z poziomu aplikacji lisp. Teraz mogę stworzyć dll, które na stale mogę wpisać do dll-startowych w oryginalnym pliku ZwCAD. Ta dll-ka sama wywoła metodę, która załaduje resztę moich plików *.dll Metoda Terminate() zapewne powinna być wywoływana przy zamykaniu ZwCAD, ale nie zauważyłem aby wyskakiwała konsola z napisem. Zapewne jej wywołanie jest blokowane przez ZwCAD. Mówię o kodzie , jak powyżej. Quote Link to comment Share on other sites More sharing options...
perlon Posted October 29, 2018 Author Report Share Posted October 29, 2018 (edited) Ładowanie innych dll z głównego dll może rozwiązać problem platformy xxxCAD i zwiększyć uniwersalność aplikacji Tak jeszcze w uzupełnieniu do terminate(). U mnie komunikat z terminate() wyskakuje po zamknięciu okna ZwCAD'a. (w trybie debug) wtedy już nie ma okna konsoli. Żeby to sprawdzić wystarczy zamienić Console.WriteLine("Cleaning up..."); na MessageBox.Show("Cleaning up..."); Można w metodzie Initialize() zapisać referencję do obiektu IExtensionApplication np w jakimś singleton globalnym dla całej aplikacji i wołać jego metody w tym również terminate w dowolnym momencie ale i tak metoda terminate() będzie wywołana przy zamknięciu całego CAD'a. Tu pojawia się chyba kwestia niemożności odładowania dll'ki (brak NETUNLOAD) w trakcie trwania sesji CAD'a. Może są jakieś inne sposoby na usunięcie z pamięci wskazanej dll przez mechanizmy ogólne systemu a nie to co oferuje ZwCAD. Edited October 29, 2018 by perlon Quote Link to comment Share on other sites More sharing options...
perlon Posted October 31, 2018 Author Report Share Posted October 31, 2018 Niestety poniższe podejście nie daje efektu. Initialize() w ogóle nie startuje. Uruchomi się tylko gdy usunę interfejs z klasy AcAutoStart (ciekawe dlaczego tak jest). Wymuszenie za pomocą [assembly: ...] również nic nie daje. Żeby mieć wspólną dll'kę dla ZwCAD i AutoCAD musiałbym chyba przejść na typy dynamic i stosować jakieś fabryki obiektów. Na 4programers ktoś zaproponował opakować klasy CAD'a klasą proxy. Ale to trzeba by zrobić 1:1 całe API .NET'a. W czort roboty i trzeba jeszcze to umieć 😞 using System; // [assembly: ZwSoft.ZwCAD.Runtime.ExtensionApplication(typeof(CADKit.ZwAutoStart))] // [assembly: Autodesk.AutoCAD.Runtime.ExtensionApplication(typeof(CADKit.AcAutoStart))] namespace CADKit { public class ZwAutoStart : ZwSoft.ZwCAD.Runtime.IExtensionApplication { public void Initialize() { string env = AppDomain.CurrentDomain.SetupInformation.ApplicationName; System.Windows.Forms.MessageBox.Show("ZwCAD -> " + env.ToUpper()); } public void Terminate() { } } public class AcAutoStart : Autodesk.AutoCAD.Runtime.IExtensionApplication { public void Initialize() { string env = AppDomain.CurrentDomain.SetupInformation.ApplicationName; System.Windows.Forms.MessageBox.Show("AutoCAD ->" + env.ToUpper()); } public void Terminate() { } } } Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.