2010-10-05 15 views
14

Tengo un código contenedor C# que llama a funciones desde un dll nativo (C++). Actualmente, puedo agregar una referencia al dll de C# y establecer la opción 'Copiar local' en verdadero. Sin embargo, el dll nativo, que es una dependencia, no se puede agregar como referencia, por lo que no existe la opción 'Copiar local'.¿Hay alguna forma mejor de copiar un dll nativo a la carpeta bin?

He tratado los siguientes enfoques

  1. El uso de un poste de construir-eventos para copiar el archivo DLL nativa de la carpeta Liberaciones a la $(TargetFolder)

    copy "$(ProjectDir)Libs\NQuantLibc.dll" "$(TargetDir)NQuantLibc.dll"

  2. Incluido el DLL nativa como un elemento existente en el proyecto (Agregar -> Artículo existente -> Incluir dll). Esta opción me permite usar la opción 'Copiar local'. La desventaja de este enfoque es que el dll siempre se muestra como un elemento del proyecto.

También probé "Mostrar todos los archivos", lo que me permitió ver la carpeta Libs. Luego incluyo el archivo NQuantLibc.dll en el proyecto que me permitió establecer la opción 'Copiar local'. Sin embargo, esto me dio un resultado inesperado. Creó una subcarpeta Libs que contiene el dll dentro de la carpeta bin (por ejemplo, bin/debug/Libs/NQuantLibc.dll). No es ideal ya que el dll de C# no podía llamar correctamente al dll nativo ya que no estaba allí.

Las dos opciones anteriores funcionan. ¿Hay alguna forma mejor de copiar un dll nativo a la carpeta bin para que la dependencia siempre se resuelva? Alternativamente, ¿hay un enfoque diferente para este tipo de escenario?

+0

Pregunta relacionada: http://stackoverflow.com/questions/126331/specifying-a-non-net-dependency-in-visual-studio – Ahmad

Respuesta

20

Use Project + Add Existing Item y seleccione la DLL. Seleccione el archivo agregado en la ventana del Explorador de soluciones. En la ventana Propiedades, cambie la configuración de Copiar a directorio de salida a "Copiar si es más nuevo".

+0

+1 Solución fácil y sin dolor – Christian

+2

He hecho eso como uno posible opción - vea el punto 2 – Ahmad

+0

No entiendo el problema, * es * un elemento del proyecto. No se ejecutará sin él, del mismo modo que no se ejecutará cuando falta un archivo de código fuente. –

1

Agregue el dll como un archivo en el proyecto ("Como enlace", tal vez si todavía desea que resida en otro directorio). Luego configure la Acción de compilación en el contenido y el directorio Copiar en salida en verdadero.

+0

¿Esto se aplica a VS 2010 Express? Parece que no puedo encontrar la opción 'Agregar enlace'. El resto de las respuestas parece muy similar a lo que se describió en el punto 2. ¿Estoy equivocado? – Ahmad

+0

@Ahmad puede agregar el archivo como enlace presionando la pequeña flecha hacia abajo en el botón "Agregar" (desde Agregar → Elemento existente ...) y seleccionando "Agregar como enlace" –

+0

@hmemcpy - no parece funcionar . Dll no se está copiando en la carpeta bin y se está lanzando una excepción correspondiente. – Ahmad

1

Si estás bien con la carpeta creada "Liberaciones", se puede tratar de añadir a la probing path para su aplicación, añadiendo lo siguiente en el archivo app.config:

<configuration> 
    <runtime> 
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <probing privatePath="Libs;Bin2"/> 
     </assemblyBinding> 
    </runtime> 
</configuration> 

Esto hará que el tiempo de ejecución buscar en todos los directorios especificados para la DLL.

EDIT Desafortunadamente, este does not impact the unmanaged DLL loading by DllImport.

+0

Estaba ocupado tratando de averiguar por qué se estaba lanzando la excepción :(. Gracias. – Ahmad

3

Encontré una mejor manera. Nuget puede agregar archivos .targets, que se almacenan en la carpeta de compilación del paquete, en su proyecto. De esta forma, puede copiar en cada compilación algunos archivos de su paquete donde desee. En el siguiente ejemplo, he almacenado algunas DLL de Non DotNet en una carpeta "binarios". En cada compilación, comprueba si las DLL ya están copiadas en la carpeta de salida (variable $ OutputPath) y las copia si es necesario.

contenido Nuspec:

<?xml version="1.0" encoding="utf-8"?> 
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> 
    <metadata> 
     <id>Example</id> 
     <version>1.0.0</version> 
     <authors>Example</authors> 
     <requireLicenseAcceptance>false</requireLicenseAcceptance> 
     <description>Example</description> 
    </metadata> 
    <files> 
     <file src="Non-DotNet.dll" target="binaries\Non-DotNet.dll" /> 
     <file src="DotNet.dll" target="lib\net40\DotNet.dll" /> 
     <file src="Example.targets" target="build\Example.targets" /> 
    </files> 
</package> 

Ejemplo.metas contenido:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <Target Name="CopyBinaries" BeforeTargets="BeforeBuild"> 
     <CreateItem Include="$(MSBuildThisFileDirectory)..\binaries\**\*.*"> 
      <Output TaskParameter="Include" ItemName="PackageBinaries" /> 
     </CreateItem> 

     <Copy SourceFiles="@(PackageBinaries)" 
       DestinationFolder="$(OutputPath)" 
       SkipUnchangedFiles="true" 
       OverwriteReadOnlyFiles="true" 
     /> 
    </Target> 
</Project> 
13

Puedes añadir el DLL nativa como un elemento vinculado, y el uso de "Copiar si es más nuevo".
El problema con los dlls nativos es que a veces querrás usar diferentes dlls de acuerdo con la configuración del proyecto (Debug/Release o platform).

Puede editar .csproj del proyecto y vincular el DLL nativa condicionalmente:

<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Win32' "> 
    <Content Include="..\..\bin\Win32\Release\NQuantLibc.dll"> 
     <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> 
    </Content> 
</ItemGroup> 
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Win32' "> 
    <Content Include="..\..\bin\Win32\Debug\NQuantLibc_d.dll"> 
     <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> 
    </Content> 
    </ItemGroup> 
    <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' "> 
    <Content Include="..\..\bin\x64\Debug\NQuantLibc_d.dll"> 
     <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> 
    </Content> 
    </ItemGroup> 
    <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' "> 
    <Content Include="..\..\bin\x64\Release\NQuantLibc.dll"> 
     <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> 
    </Content> 
    </ItemGroup> 

Nota la opción de copia se establece en PreserveNewest que significa "copia si es más nuevo".

+2

Es sorprendente que lo que solía ser un patrón de desarrollo de línea principal ahora es tan extraño que tienes que editar manualmente un archivo .csproj. – zumalifeguard

Cuestiones relacionadas