[C#] Detekcja środowiska


Recommended Posts

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 by Parikon
Link to comment
Share on other sites

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. 

 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

Ł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 by perlon
Link to comment
Share on other sites

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


 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...