C++ / CLI - преодоление зависимости от Microsoft Visual C++ Redistributable
Если ваше .NET приложение использует компоненты, написанные на Managed C++, то вы сталкиваетесь с необходимостью распространять Microsoft Visual C++ Redistributable вместе с ним. Если попытаться запустить такое приложение в системе, где не установлен соответствующий Microsoft Visual C++ Redistributable, то будет получено сообщение “приложение не может быть запущено, так как оно неправильно настроено”. Почему так происходит, и можно ли обойтись без установки Microsoft Visual C++ Redistributable?
При обычном подходе DLL, написанная на Managed C++, имеет зависимость от Microsoft Visual C++ Runtime, DLL-ки которого невозможно прилинковать статически. Традицонное решение - это включение Microsoft Visual C++ Redistributable в инсталлятор.
С помощью BoxedApp SDK можно эмулировать наличие Microsoft Visual C++ Runtime’а. Сразу после старта приложения, до использования собранных на Managed C++ компонентов, создайте те самые файлы, от которых зависит Managed C++ DLL (как узнать пути к зависимостям):
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;
namespace WindowsApplication1
{
static class Program
{
[STAThread]
static void Main()
{
BoxedAppSDK.NativeMethods.BoxedAppSDK_Init();
string PathOfWinSxS =
Directory.GetParent(Environment.SystemDirectory).FullName +
@"\WinSxS";
if (!Directory.Exists(PathOfWinSxS))
// Win2k
PathOfWinSxS = Application.StartupPath;
Stream fromStream =
Assembly.
GetExecutingAssembly().
GetManifestResourceStream("WindowsApplication1.res.msvcm80d.dll");
CreateDLLInMemory(
PathOfWinSxS +
@"\x86_Microsoft.VC80.DebugCRT_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_f75eb16c\msvcm80d.dll",
fromStream);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
BoxedAppSDK.NativeMethods.BoxedAppSDK_Exit();
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hObject);
static void CreateDLLInMemory(string strVirtualPath, Stream stream)
{
const int BufferSize = 1024;
byte[] buffer = new byte[BufferSize];
IntPtr hHandle =
BoxedAppSDK.NativeMethods.BoxedAppSDK_CreateVirtualFile(
strVirtualPath,
BoxedAppSDK.NativeMethods.EFileAccess.GenericWrite,
BoxedAppSDK.NativeMethods.EFileShare.Read,
IntPtr.Zero,
BoxedAppSDK.NativeMethods.ECreationDisposition.New,
BoxedAppSDK.NativeMethods.EFileAttributes.Normal,
IntPtr.Zero);
CloseHandle(hHandle);
int nReadBytes;
using (FileStream VirtualFileStream = new FileStream(strVirtualPath, FileMode.Open))
{
while ((nReadBytes = stream.Read(buffer, 0, BufferSize)) > 0)
VirtualFileStream.Write(buffer, 0, nReadBytes);
}
}
}
}
Чтобы узнать, от каких именно DLL-ек имеет зависимость ваша Managed C++ DLL, воспользуйтесь приложением depends.exe из поставки Visual Studio. Открыв вашу Managed C++ DLL в depends.exe, вы легко установите от каких составляющих VC++ Runtime она зависит:



Написать комментарий
Вы должны залогиниться чтобы комментировать. Залогиниться