How to Embed a COM Interop DLL in a .NET Application

When you add a COM library reference in a .NET project, Visual Studio generates an interop DLL that marshals calls between managed and unmanaged code. With BoxedApp SDK, you can embed such interop assemblies directly into your executable, keeping the app self-contained and avoiding external DLLs.

Virtual files created by BoxedApp SDK do not exist on disk. They are visible only to the current process and inheriting child processes through the virtualization layer, which intercepts file I/O and serves data from memory.

What Is an Interop DLL?

When a COM library reference is added to a .NET project, a special assembly - an interop DLL - is generated. The Common Language Runtime (CLR) uses this assembly to marshal calls to the native COM methods. Sometimes it's convenient to embed these DLLs directly into your application, especially if you want to deliver a single executable.

Project Setup (Embedded Resources)

In this example, we'll use the Windows Media Player ActiveX control. When you add it to your project, Visual Studio automatically creates two interop DLLs: AxInterop.WMPLib.dll and Interop.WMPLib.dll. Add both DLLs to your project and mark them as Embedded Resources.

If you forget to mark them as embedded, GetManifestResourceStream() will fail. Here's how it should look in Visual Studio:

Initialize BoxedApp SDK

Initialize BoxedApp SDK early - before any COM objects are instantiated or assemblies loaded.

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
    // Initialize BoxedApp SDK
    BoxedAppSDK.NativeMethods.BoxedAppSDK_Init();

Create Virtual Interop DLLs

Now create virtual files for both interop assemblies so they appear in the application directory. The code below exposes them from the embedded resources using BoxedAppSDK_CreateVirtualFile:

// Create virtual files from embedded resources
CreateFileInMemory(
    Application.StartupPath + @"\AxInterop.WMPLib.dll",
    Assembly.GetExecutingAssembly().GetManifestResourceStream("EmbedInteropDll.AxInterop.WMPLib.dll"));
 
CreateFileInMemory(
    Application.StartupPath + @"\Interop.WMPLib.dll",
    Assembly.GetExecutingAssembly().GetManifestResourceStream("EmbedInteropDll.Interop.WMPLib.dll"));

Implementation of CreateFileInMemory

The method below creates a virtual file and writes data from an embedded resource stream to it. Handles are managed safely with SafeFileHandle to prevent leaks.

// Helper function to create a virtual file from an embedded resource
static void CreateFileInMemory(string virtualPath, Stream stream)
{
    const int bufferSize = 1024;
    byte[] buffer = new byte[bufferSize];
 
    using (new SafeFileHandle(
            BoxedAppSDK.NativeMethods.BoxedAppSDK_CreateVirtualFile(
                virtualPath,
                BoxedAppSDK.NativeMethods.EFileAccess.GenericWrite,
                BoxedAppSDK.NativeMethods.EFileShare.Read,
                IntPtr.Zero,
                BoxedAppSDK.NativeMethods.ECreationDisposition.New,
                BoxedAppSDK.NativeMethods.EFileAttributes.Normal,
                IntPtr.Zero
            ),
            true
        )
    )
    {
    }
 
    int readBytes;
 
    using (FileStream virtualFileStream = new FileStream(virtualPath, FileMode.Open))
    {
        while ((readBytes = stream.Read(buffer, 0, bufferSize)) > 0)
            virtualFileStream.Write(buffer, 0, readBytes);
    }
}

Result

That's it! When the process requests AxInterop.WMPLib.dll or Interop.WMPLib.dll, BoxedApp SDK provides them through its virtual file system. The application works exactly as if the DLLs were on disk.