Еще одна опция, которую я использовал в прошлом, - это чтобы ваша программа / dll действовала как самораспаковывающийся архив. Загрузите управляемый dll как сжатый ресурс и распакуйте его во временную папку любой машины, на которой вы работаете.
У меня есть приложение, которое использует AlphaVSS , в которое встроено несколько встроенных DLL. Я хотел, чтобы приложение было полностью переносимым как единый исполняемый файл и не требовало установки. Вот как я с этим справился.
public static void ExtractResources()
{
Directory.CreateDirectory(Path.Combine(Program.DataPath, FolderName));
//Extract the runtime in case it is not installed on the destination computer
if (NativeMethods.Is64BitOperatingSystem)
{
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\Microsoft.VC90.CRT.manifest"),
Resources.x64.X64Resources.Microsoft_VC90_CRT_manifest);
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\msvcm90.dll"), Resources.x64.X64Resources.msvcm90_dll);
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\msvcp90.dll"), Resources.x64.X64Resources.msvcp90_dll);
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\msvcr90.dll"), Resources.x64.X64Resources.msvcr90_dll);
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\AlphaVSS.52.x64.dll"), Resources.x64.X64Resources.AlphaVSS_52_x64_dll);
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\AlphaVSS.60.x64.dll"), Resources.x64.X64Resources.AlphaVSS_60_x64_dll);
}
else
{
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\Microsoft.VC90.CRT.manifest"),
Resources.x86.X86Resources.Microsoft_VC90_CRT_manifest);
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\msvcm90.dll"), Resources.x86.X86Resources.msvcm90_dll);
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\msvcp90.dll"), Resources.x86.X86Resources.msvcp90_dll);
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\msvcr90.dll"), Resources.x86.X86Resources.msvcr90_dll);
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\AlphaVSS.51.x86.dll"), Resources.x86.X86Resources.AlphaVSS_51_x86_dll);
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\AlphaVSS.52.x86.dll"), Resources.x86.X86Resources.AlphaVSS_52_x86_dll);
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\AlphaVSS.60.x86.dll"), Resources.x86.X86Resources.AlphaVSS_60_x86_dll);
}
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\AlphaVSS.Common.dll"), Resources.VssResourcesCommon.AlphaVSS_Common_dll);
FileUtils.DecompressFile(Path.Combine(Program.DataPath, FolderName + @"\ClientDataSnapshotVssAgent.exe"), Resources.VssResourcesCommon.ClientDataSnapshotVssAgent_exe);
}
Теперь в моем коде у меня был исполняемый файл агента, работающий во временной папке, которая ссылалась на эти извлеченные dll, однако вы могли легко использовать ваш P / Invoke и указать полный путь, к которому вы извлекли его, в сигнатуре P / Invoke.
В качестве дополнительного совета я написал небольшую программу, которая просто скопирует любой файл, который вы передадите ему, а затем вставил следующее в событие Post-build для программы агента.
"$(SolutionDir)\DataCompressor\DataCompressor.exe" "$(TargetPath)" "$(SolutionDir)\ClientDataSnapshot\VSS\Resources\$(TargetFileName).gz"
Вы могли бы сделать что-то похожее для вашего события посткомпиляции для вашей родной dll, просто обновите файл gz в вашем управляемом проекте каждый раз, когда он завершает сборку, и убедитесь, что родная dll предшествует управляемой dll в порядке сборки, и у вас всегда будет самая последняя копия в качестве ресурса в вашем управляемом проекте.
using System;
using System.IO;
using System.IO.Compression;
namespace DataCompressor
{
class Program
{
//This program is used to compress the compiled VssAgent for storage in the snapshot program
static void Main(string[] args)
{
//Will quit directly if any args are invalid.
ValidateArgs(args);
using (var sourceFile = File.OpenRead(args[0]))
using (var destFile = new FileStream(args[1], FileMode.Create))
using (var gz = new GZipStream(destFile, CompressionMode.Compress))
{
sourceFile.CopyTo(gz);
}
}
private static void ValidateArgs(string[] args)
{
if (args.Length == 2)
{
if (File.Exists(args[0]) == false)
{
Console.Error.WriteLine("The source file did not exist.");
Environment.Exit(-2);
}
if (Directory.Exists(Path.GetDirectoryName(args[1])) == false)
{
Console.Error.WriteLine("The destination directory did not exist.");
Environment.Exit(-3);
}
}
else
{
Console.Error.WriteLine("You must pass two arguments.");
Environment.Exit(-1);
}
}
}
}