Skompiluj wersję DLL in.NET

Scenariusz

Mam dwa opakowania wokół Microsoft Office, jeden dla 2003 i jeden dla 2007. Ponieważ posiadanie dwóch wersji pakietu Microsoft Office działających obok siebie jest "oficjalnie niemożliwe" ani zalecane przez Microsoft, mamy dwa pudełka, jedno z Office 2003, a drugie z Office 2007. Kompilujemy opakowania osobno. Biblioteki DLL są zawarte w naszym rozwiązaniu, każde pudełko ma ten sam checkout, ale z Office 2003 lub 2007 "rozładowany", więc nie próbuje się skompilować tego konkretnego DLL. Niewykonanie tego spowoduje błędy przy kompilacji z powodu niedostępnych bibliotek DLL Office COM.

Używamy. NET 2.0 i Visual Studio 2008.

Fakty

Ponieważ Microsoft w tajemniczy sposób zmienił API Office 2003 w 2007 roku, zmieniając nazwy i zmieniając niektóre metody ( sigh), co czyni je nie kompatybilnymi wstecz, potrzebujemyobu wrapperów. Mamy każdą maszynę do budowania z rozwiązaniem i jedną bibliotekę DLL Office aktywowaną. Np.: maszyna z Biurem 2003 ma bibliotekę DLL" Office 2007 " rozładowaną, dlatego nie kompiluje jej. Drugie pudełko to ten sam pomysł, ale na odwrót. Wszystko to dlatego, że nie możemy mieć 2 różnych biur w tym samym pudełku do celów programistycznych. (technicznie można mieć dwa Office razem według Microsoftu), ale NIE do programowania i nie bez pewnych problemów.

Problem

Kiedy zmienimy wersję aplikacji (np. z 1.5.0.1 na 1.5.0.2) musimy przekompilować bibliotekę DLL tak, aby pasowała nowa wersja aplikacji, odbywa się to automatycznie, ponieważ pakiet Office wrapper jest zawarty w rozwiązaniu. Ponieważ wrappery są zawarte w rozwiązaniu, te dziedziczą wersję aplikacji, ale musimy to zrobić dwa razy, a następnie "skopiować" drugą bibliotekę DLL na maszynę, która utworzy instalator. (Ból...)

Pytanie

Czy możliwe jest skompilowanie biblioteki DLL, która będzie działać z dowolną wersją aplikacji, mimo że jest "starsza"? Czytałem coś o manifestach ale Nigdy nie musiałem z nimi wchodzić w interakcję. Wszelkie wskazówki będą mile widziane.

Tajnym powodem tego jest to, że nie zmienialiśmy naszych wrapperów w "wiekach", podobnie jak Microsoft z ich starożytnymi interfejsami API, jednak rekompilujemy DLL, aby pasował do wersji aplikacji na każdym wydaniu. Chciałbym zautomatyzować ten proces, zamiast polegać na dwóch maszynach.

Nie mogę usunąć DLL z projektu (żaden z nich), ponieważ istnieją zależności.

Mógłbym stworzyć trzeci "master wrapper", ale jeszcze o tym nie myślałem.

Jakieś pomysły? Ktoś jeszcze ma takie same wymagania?

UPDATE

Wyjaśnienie:

Mam 1 rozwiązanie z N projektów.

"Aplikacja" + Office11Wrapper.dll + Office12Wrapper.dll.

Oba "wrappery" używają zależności dla aplikacji + innych bibliotek w rozwiązaniu (datalayer, businesslayer, framework, itp.)

Każda owijka ma odniesienia do odpowiedni pakiet biurowy (2003 i 2007).

Jeśli kompiluję i nie mam zainstalowanego pakietu office 12, dostaję błędy z Office12Wrapper.dll nie znajduje bibliotek Office 2007. Mam więc dwie maszyny budowlane, jedną z Office 2003, drugą z Office 2007. Po pełnej aktualizacji SVN + kompilacji na każdym komputerze, po prostu używamy office12.dll w "instalatorze", aby wrapper został skompilowany według "tego samego kodu, tej samej wersji".

Uwaga: Maszyna do budowy Office 2007, posiada owijarkę dla Office 2003 "unloaded" i viceversa.

Z góry dzięki.
Author: bluish, 2008-11-10

5 answers

Gdy resolver. NET assembly nie jest w stanie znaleźć odwołanego assembly w czasie wykonywania (w tym przypadku nie może znaleźć konkretnej wersji biblioteki DLL wrapper, z którą aplikacja była powiązana), jego domyślnym zachowaniem jest awaria i zasadniczo awaria aplikacji. Jednak to zachowanie można przesłonić, zaczepiając AppDomain.AssemblyResolve event. To zdarzenie jest wywoływane, gdy nie można znaleźć przywołanego zestawu i daje możliwość zastąpienia innego zestawu w miejsce brakujące (pod warunkiem, że są kompatybilne). Na przykład możesz zastąpić starszą wersję biblioteki DLL wrapper, którą sam załadujesz.

Najlepszym sposobem, jaki znalazłem, jest dodanie statycznego konstruktora na głównej klasie aplikacji, która hookuje Zdarzenie, np.:

using System.Reflection;

static Program()
{
    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e)
    {
        AssemblyName requestedName = new AssemblyName(e.Name);

        if (requestedName.Name == "Office11Wrapper")
        {
            // Put code here to load whatever version of the assembly you actually have

            return Assembly.LoadFile("Office11Wrapper.DLL");
        }
        else
        {
            return null;
        }
    }
}

Umieszczając to w statycznym konstruktorze głównej klasy aplikacji, jest gwarantowane, że zostanie uruchomione, zanim jakikolwiek kod spróbuje uzyskać dostęp do czegokolwiek z biblioteki DLL wrapper, zapewniając, że hook jest na miejscu przed czasem.

Możesz również użyć plików zasad do przekierowania wersji, ale jest to bardziej złożone.

 17
Author: Eric Rosenberger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-12 16:19:00

Tylko myśl - Czy mógłbyś użyć TlbExp do stworzenia dwóch zestawów interop (o różnych nazwach i zestawach) i użyć interfejsu/fabryki do kodowania przeciwko dwóm za pomocą własnego interfejsu? Gdy masz interop dll, nie potrzebujesz zależności COM (z wyjątkiem oczywiście do testowania itp.).

TlbImp ma /asmversion dla wersji, więc może to być wykonane jako część skryptu budowania; ale jestem pewien, że nawet tego potrzebujesz: upewnij się, że "konkretna wersja" jest fałszywa W referencji (solution explorer)?

Również-Wiem, że to nie pomaga, ale C# 4.0 z dynamic i / lub "No PIA" może tu pomóc (w przyszłości; może).

 2
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-10 13:19:15

Nie jestem pewien, czy całkowicie podążam za wszystkim, co powiedziałeś, ale pozwól mi spróbować:

Wygląda na to, że masz jedno rozwiązanie z 2 (?) projekty. Jeden to rzeczywista aplikacja, a drugi to opakowanie dla Office API. Twoja aplikacja ma następnie odniesienie do projektu do pakietu Office API. Nigdy wcześniej nie programowałem dla pakietu office, ale wygląda na to, że interfejsy API programowania są powszechnym komponentem, którego można mieć tylko jedną wersję na komputerze(np. 2003 lub 2007, nie oba). Oraz być może w tym miejscu jest problem, ale ponieważ masz odniesienie do projektu, wrapper zostanie skompilowany jako pierwszy, skopiowany do katalogu bin Twojej aplikacji, gdzie Twoja aplikacja zostanie połączona z tą kompilacją wrappera. Spowoduje to, że manifest aplikacji poprosi o konkretną wersję owijarki w czasie wykonywania.

Gdybyś miał wrapper w osobnym rozwiązaniu i dodał odniesienie do skompilowanej biblioteki, a nie do projektu, zawsze łączyłbyś aplikacji do tej wersji owijarki i można uniknąć problemu.

Innym możliwym wyborem jest przekierowanie wiązań montażowych. To jest bardziej zaawansowane i zawiera własny zestaw problemów, ale możesz o tym przeczytać tutaj .

Lub podobnie jak pomysł marca, można wyodrębnić interfejs i pobrać kilka wspólnych obiektów do biblioteki frameworku, a następnie zakodować aplikację na interfejsie i wspólnych obiektach. Następnie w czasie wykonywania użyj reflection, aby załadować montaż i tworzenie instancji owijarki, którą chcesz.

Myślę, że kluczem jest usunięcie zależności od projektu, jeśli możesz. Wygląda na to, że wrapper jest dość stabilny i się nie zmienia, w przeciwnym razie nie prosiłbyś o link do poprzedniej wersji.

 2
Author: NerdFury,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-10 13:50:58

Instalacja Office 2003 i 2007 obok siebie na tej samej maszynie jest zdecydowanie możliwa - robimy to w naszej organizacji nawet na stacjach produkcyjnych użytkowników końcowych.

W tym powiązanym artykule Microsoft zaleca, aby nie robić tego do rzeczywistego użytku. Ale w Twoim przypadku wydaje się to być tylko dla pojedynczej maszyny kompilacyjnej, tzn. nie będziesz używał żadnej wersji pakietu Office na tej maszynie. W tym kontekście, chciałbym spróbować zobaczyć, czy można zrobić side-by-side prace instalacyjne.

Moje założenie może być błędne, a ty próbujesz to zrobić dla każdej maszyny deweloperskiej. W takim przypadku należy zignorować tę odpowiedź: -)

 1
Author: RoadWarrior,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-10 21:37:42

Niezła robota! Po prostu rzuciłem razem implementację opartą na koncepcji przedstawionej powyżej, i działa cudownie:

static Assembly domain_AssemblyResolve(object sender, ResolveEventArgs args)
{
     string partialName = args.Name.Substring(0, args.Name.IndexOf(','));
     return Assembly.Load(new AssemblyName(partialName));
}

Oczywiście jest miejsce na ulepszenia, ale to mi wystarczy!

 0
Author: Sean Aitken,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-16 17:12:51