Back to Home

Choosing a platform-specific library in runtime

Summary In most cases · .NET applications are platform independent. We expect that our application will run equally on both 32-bit and 64-bit operating systems. So...

Choosing a platform-specific library in runtime

Essence of the question

In most cases, .NET applications are platform independent. We expect that our application will run equally on both 32-bit and 64-bit operating systems.

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

We may need to support twice as many project configurations. In this case, when debugging, you will have to switch configurations, because the Cassini development web server exists only inx86option, and ReSharper can run tests in a 64-bit process. In addition, you will have to release two distributions and provide the user with a download from the site, oh, what a difficult choice. Therefore, choosing a library suitable for operation already in runtime looks like a reasonable decision, depending on which process (32-bit or 64-bit) the code is executed. 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 as an runtime/assemblyBindingapplication configuration file tag . In app.configadding the following:

<configuration><!-- Выбор версии библиотеки ODP.NET в зависимости от Runtime архитектуры --><runtime><assemblyBindingxmlns="urn:schemas-microsoft-com:asm.v1"><dependentAssembly><assemblyIdentityname="Oracle.DataAccess"publicKeyToken="89b483f429c47342"culture="neutral"processorArchitecture="x86" /><codeBaseversion="4.112.2.0"href=".\x86\Oracle.DataAccess.dll"/></dependentAssembly><dependentAssembly><assemblyIdentityname="Oracle.DataAccess"publicKeyToken="89b483f429c47342"culture="neutral"processorArchitecture="amd64" /><codeBaseversion="4.112.2.0"href=".\x64\Oracle.DataAccess.dll"/></dependentAssembly></assemblyBinding></runtime></configuration>

We attribute processorArchitecturefour possible values: x86, amd64, msil, ia64. The paths in codeBasemay vary depending on the type of project (for example, for ASP.NET should be href=".\bin\x64\Oracle.DataAccess.dll").

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

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

A project file usually has a commented out target AfterBuild. It must be uncommented / added / edited:
<TargetName="AfterBuild"DependsOnTargets="CopyDataAccessFiles" >

The file CommonItems.targetscontains a description of these common elements for executable projects. The goal for copying dependencies is defined here:

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

Limitations

The proposed method has limitations:
  • It is assumed that we do not use types of a managed platform-specific library and, therefore, do not need an assembly reference (Oracle.DataAccess.dll) in our project. Those. dependence on the assembly is, but implicit, dynamic.
  • Now we are dragging libraries with us for all supported platforms. For OracleIC, this is over 100 MB per platform.

References

<assemblyBinding> Element for <runtime>

Read Next