📜 ⬆️ ⬇️

Choosing a platform-specific library at runtime

Essence of the question

In most cases, .NET applications are platform independent. We expect that our application will be executed in the same way as in a 32-bit OS, and in a 64-bit OS.

This usually happens until we need to use external platform-specific libraries, such as unmanaged ones. If such a library exists in the versions for both x86 and x64 , then it can bring us a certain headache. We will proceed from the fact that limiting our application, for example, only to the 32-bit process is not in our rules.

We may have to support twice as many project configurations. In this case, when debugging, you have to switch configurations, because the Cassini development web server exists only in the x86 version, and ReSharper can run tests in the 64-bit process. In addition, you will have to release two distributions and provide the user with oh when downloading from the site what a difficult choice. Therefore, a reasonable solution seems to be the choice of a library that is suitable for operation already at runtime, depending on which process (32 or 64 bits) the code executes. At the same time, the projects themselves remain AnyCPU .
')
In our application, you need to connect to the Oracle Database, which uses the Oracle Instant Client and Oracle Data Provider for .NET libraries.

Decision

The solution was found in the form of a runtime/assemblyBinding tag of the application configuration file. Add the following to app.config :

 <configuration> <!--    ODP.NET    Runtime  --> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Oracle.DataAccess" publicKeyToken="89b483f429c47342" culture="neutral" processorArchitecture="x86" /> <codeBase version="4.112.2.0" href=".\x86\Oracle.DataAccess.dll"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Oracle.DataAccess" publicKeyToken="89b483f429c47342" culture="neutral" processorArchitecture="amd64" /> <codeBase version="4.112.2.0" href=".\x64\Oracle.DataAccess.dll"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration> 

The processorArchitecture attribute has four possible values: x86 , amd64 , msil , ia64 . Paths in codeBase may differ depending on the type of project (for example, for ASP.NET it should be href=".\bin\x64\Oracle.DataAccess.dll" ).

Well, in order for the libraries to be in the right folders, in the files of the "executable" projects (test builds, web services and websites, and truly executable .exe applications) after the line
 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> 

The inclusion of MSBuild own goals is added:
 <Import Project="$(MSBuildProjectDirectory)\..\CommonItems.targets" /> 

There is usually a commented goal of AfterBuild project file. It must be uncommented / added / edited:
  <Target Name="AfterBuild" DependsOnTargets="CopyDataAccessFiles" > 

The CommonItems.targets file contains the description of these common elements for executable projects. The goal for copying dependencies is defined here:

 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <OracleICFilesx86 Include="$(MSBuildProjectDirectory)\..\externals\OracleIC\x86\*.dll"> <Visible>False</Visible> </OracleICFilesx86> <OracleICFilesx64 Include="$(MSBuildProjectDirectory)\..\externals\OracleIC\x64\*.dll"> <Visible>False</Visible> </OracleICFilesx64> <OdpNetFilesx86 Include="$(MSBuildProjectDirectory)\..\externals\Odp.Net\x86\*.dll"> <Visible>False</Visible> </OdpNetFilesx86> <OdpNetFilesx64 Include="$(MSBuildProjectDirectory)\..\externals\Odp.Net\x64\*.dll"> <Visible>False</Visible> </OdpNetFilesx64> </ItemGroup> <Target Name="CopyDataAccessFiles" > <Copy SourceFiles="@(OracleICFilesX86);@(OdpNetFilesx86)" DestinationFolder="$(MSBuildProjectDirectory)\$(OutputPath)\x86\" SkipUnchangedFiles="true" UseHardLinkIfPossible="true" /> <Copy SourceFiles="@(OracleICFilesX64);@(OdpNetFilesx64)" DestinationFolder="$(MSBuildProjectDirectory)\$(OutputPath)\x64\" SkipUnchangedFiles="true" UseHardLinkIfPossible="true" /> </Target> </Project> 

Restrictions

The proposed method has limitations:

Links

<assemblyBinding> Element for <runtime>

Source: https://habr.com/ru/post/165767/


All Articles