[C#] Detekcja środowiska


Rekomendowane odpowiedzi

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

Odnośnik do komentarza
Udostępnij na innych stronach

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.

Odnośnik do komentarza
Udostępnij na innych stronach

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.

Odnośnik do komentarza
Udostępnij na innych stronach

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 :)

Odnośnik do komentarza
Udostępnij na innych stronach

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?

Edytowane przez Parikon
Odnośnik do komentarza
Udostępnij na innych stronach

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 :hi: 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. 

 

Odnośnik do komentarza
Udostępnij na innych stronach

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.

Odnośnik do komentarza
Udostępnij na innych stronach

Ł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.

Edytowane przez perlon
Odnośnik do komentarza
Udostępnij na innych stronach

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()
        {
        }
    }
}


 

Odnośnik do komentarza
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Gość
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Usuń formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

Ładowanie