2011-01-05 4 views
7

Mam program, który musi działać zarówno w środowisku x86, jak i x64. Używa sterowników ODBC Oracle. Mam odniesienia do Oracle.DataAccess.DLL. Ta biblioteka DLL różni się w zależności od tego, czy jest to system x64 czy x86.Próbuję nie potrzebować dwóch oddzielnych rozwiązań dla programu x86 i x64

Obecnie mam dwa oddzielne rozwiązania i utrzymuję kod na obu. To jest okropne. Zastanawiałem się, jakie jest właściwe rozwiązanie?

Mam platformę ustawioną na "Dowolny procesor". i rozumiem, że VS powinien skompilować bibliotekę DLL do języka pośredniczącego, tak aby nie miało to znaczenia, jeśli użyję wersji x86 lub x64. Jednak jeśli spróbuję użyć biblioteki DLL x64, pojawia się błąd "Nie można załadować pliku lub zestawu" Oracle.DataAccess, wersja = 2.102.3.2, Culture = neutral, PublicKeyToken = 89b483f429c47342 'lub jedna z jego zależności. załadować program o nieprawidłowym formacie. "

Używam komputera 32-bitowego, więc komunikat o błędzie ma sens, ale zastanawia mnie, jak powinienem wydajnie rozwijać ten program, kiedy musi działać na x64.

Dzięki.

+2

Jeśli masz zamiar rozwijać aplikację 32/64-bitową, powinieneś być na 64-bitowym systemie operacyjnym. Przynajmniej w systemie Windows 32-bitowy system operacyjny nie może uruchamiać programów 64-bitowych, ale 64-bitowy system operacyjny może uruchamiać programy 32-bitowe. – rossipedia

+1

Kolejne pytanie do rozważenia to: "Czy moja aplikacja * naprawdę * musi działać w wersji 64-bitowej?" WOW wykonuje cudowną pracę, uruchamiając 32-bitową aplikację na x64. – vcsjones

Odpowiedz

0

Używanie AnyCPU z natywnym wczesnym wiązaniem po prostu nie zadziała, ponieważ potrzebujesz dwóch oddzielnych rozwiązań i buildów, tak jak widziałeś. Musisz zdobyć 64-bitowy system do opracowania lub przynajmniej przetestowania bibliotek skompilowanych x64.

Jednak z późnym wiązaniem można użyć AnyCPU i właściwości systemu, aby dowiedzieć się, jaka architektura jest uruchomiona i link do właściwej biblioteki dll, jeśli zachowasz nazwany jak Oracle.DataAccess.x86.dll. Jeśli są one zainstalowane w GAC, jest jeszcze łatwiej, możesz nawet bez problemu zawczasu testować architekturę, ale uważam, że musisz się spóźnić.

Należy pamiętać, że VMware może uruchamiać gościa 64-bitowego na hoście 32-bitowym, jeśli naprawdę nie można się martwić o ponowną instalację systemu Windows.

2

Jeśli używasz komputera 32-bitowego, musisz załadować 32-bitową wersję biblioteki DLL Oracle. Program 32-bitowy nie może odwoływać się do 64-bitowej biblioteki DLL. 64-bitowy program nie może odwoływać się do 32-bitowej biblioteki DLL.

"Każdy procesor" jest właściwym celem, jeśli masz wiele wersji zewnętrznej biblioteki DLL. Sztuką jest upewnienie się, że właściwa biblioteka DLL Oracle jest zlokalizowana i załadowana. Najlepiej jest zlokalizować 64-bitową wersję biblioteki DLL w systemie 32-bitowym i zmienić jej nazwę, aby środowisko wykonawcze nie mogło jej znaleźć.

+0

Myślę, że jesteśmy w tym samym klubie, ale że moje myśli nie są przenoszone zupełnie poprawnie. Ręcznie zawierałem właściwą 32-bitową bibliotekę dll w moim "rozwiązaniu 32-bitowym" i 64-bitowym dll w "rozwiązaniu 64-bitowym". Kiedy potrzebuję generować executeables, buduję oba oddzielne rozwiązania. Kiedy pracuję, pracuję tylko na 32-bitach, a kiedy skończę zmiany kodu, muszę replikować te zmiany w 64-bitowym rozwiązaniu. Chciałbym używać tylko jednego rozwiązania zamiast dwóch, ale mam takie same wyniki. –

0

Użytkownik może skonfigurować to samo rozwiązanie, aby oddzielnie budować wersje x86/x64. Konieczne może być również dodanie kroków kompilacji po skopiowaniu poprawnej wersji biblioteki DLL do odpowiednich folderów wyjściowych ...

Przynajmniej jeśli musisz zbudować 2 rozwiązania - użyj tego samego źródła (dodaj pliki jako odniesienie do drugiego rozwiązania, nie skopiuj do drugiego rozwiązania).

3

To jest wyłącznie problem z wdrożeniem, nie powinieneś nigdy utrzymywać różnych projektów. Jest to jednak niezręczne, a Boo na Oracle za to, że nie dba o to sam. Innym problemem jest to, że ten zestaw naprawdę powinien być ngen-ed na maszynie docelowej. Niektóre opcje:

  • Utwórz dwa instalatory, jeden dla x64 i jeden dla x86. Klient wybiera właściwą, w zależności od systemu operacyjnego, z którego korzysta. Wystarczy, że po prostu skopiujesz właściwy plik.
  • Wdróż oba zespoły do ​​GAC. Teraz jest to automatyczne, .NET wybiera właściwą na każdym typie maszyny.Duże firmy powinny prawie zawsze używać GAC, aby mogły wdrażać aktualizacje zabezpieczeń, nie wiedząc, dlaczego Oracle tego nie robi.
  • Wdrożenie złożeń w podkatalogu x86 i x64 katalogu instalacyjnego. Będziesz musiał napisać procedurę obsługi zdarzeń AppDomain.AssemblyResolve, która, w zależności od wartości IntPtr.Size, wybierze właściwy katalog.
  • Zmień platformę docelową w projekcie EXE na x86. Biorąc pod uwagę, że twój kod musi działać na maszynie 32-bitowej, a także na maszynie 64-bitowej, nie ma/nie powinno być powodu do budowania dla AnyCPU.
3

Jest to roztwór roboczy dla swojego problemu:

dodać 2 DLL (x86 i x64) do roztworu w podfolderze. Zrób je "Kopiuj jeśli jest nowsza"

Odsyłam do poprawnej biblioteki DLL, której używasz do programowania w celu debugowania z 2 dodanych bibliotek DLL. Make it Copy Local = false.

Co to jest, że po uruchomieniu aplikacji biblioteka DLL nie jest ładowana automatycznie. Nie zostanie załadowany, dopóki nie zostanie użyty typ z tego zespołu. Gdy to się stanie, zdarzenie zostanie wywołane w .Net, które zapyta, gdzie może znaleźć swój zespół.

Tak więc przed pierwszym użyciem tego zestawu upewnij się, że przyłączyłeś się do tego wydarzenia.

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; 

W treści przewodnika upewnij się załadować biblioteki DLL (x86 lub x64), gdy o to poprosi.

static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { 
     if (args.Name.Equals("MyFullAssemblyName")) { 
      var path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); 
      if (IntPtr.Size > 4) { 
       var dll = System.IO.Path.Combine(path, @"MySubDir\MyDLL_x64.dll"); 
       return System.Reflection.Assembly.LoadFile(dll); 
      } 
      else { 
       var dll = System.IO.Path.Combine(path, @"MySubDir\MyDLL.dll"); 
       return System.Reflection.Assembly.LoadFile(dll); 
      } 
     } 
     return null; 
    } 

Voila. Możesz teraz uruchomić aplikację zarówno w wersji 32-bitowej, jak i 64-bitowej.

Alternatywnie do dodawania DLL w podkatalogu, można dokonać ich jako zasobów wbudowanych, a następnie załadować je tak:

static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { 
     if (args.Name.Equals("MyFullAssemblyName")) { 
      var ass = Assembly.GetExecutingAssembly(); 

      if (IntPtr.Size > 4) { 
       var strm = ass.GetManifestResourceStream("the.resource.name.for.MyDLL_x64.dll"); 
       var data = new byte[strm.Length]; 
       strm.Read(data, 0, data.Length); 
       return Assembly.Load(data); 
      } 
      else { 
       var strm = ass.GetManifestResourceStream("the.resource.name.for.MyDLL.dll"); 
       var data = new byte[strm.Length]; 
       strm.Read(data, 0, data.Length); 
       return Assembly.Load(data); 
      } 
     } 
     return null; 
    } 

ta nie działa dla wszystkich zespołów. Niektóre zespoły "hybrydowe" zwykle ulegają awarii, chyba że są ładowane z dysku (można je rozwiązać, zapisując je na dysku tuż przed załadowaniem).

Powiązane problemy