BoxedApp

BoxedApp: примеры использования, советы, приемы

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 она зависит:

Как посмотреть зависимости







Написать комментарий

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