What is interop dll?

If a COM library reference is added to a .Net project, a special assembly - interop dll - is created.

With that assembly, CLR marshalls calls to COM methods.

Sometimes it's handy to embed interop DLL in an executable file. Let's look how to do this with BoxedApp SDK.

You can download the sample from GitHub.

BoxedApp SDK to the rescue

As BoxedApp SDK can create pseudofiles, the developer just creates a virtual file of interop DLL, and the application works as expected even though the real file of interop DLL doesn't exist.

Example

In this sample, we will use Windows Media Player ActiveX. Let's add the control to the project. As you see, two interop DLLs, AxInterop.WMPLib.dll and Interop.WMPLib.dll, are added to References:

Now the task is to virtualize these two DLLs. In order to do that, we need to get data for the files somewhere. The easiest way is just to add the file to the project and mark them as Embedded Resources.

Important: Mark Files as Embedded Resources.

After adding the file to embed, go to their properties and set Build Action as "Embedded Resources".

If you don't do it, GetManifestResourceStream() will fail.

Look how to do this in Visual Studio:


Let's go to the code! The first thing you need to take care of when BoxedApp SDK in the game is BoxedApp SDK initialization:

/// 
/// The main entry point for the application.
/// 
[STAThread]
static void Main()
{
    // First of all initialize BoxedApp SDK
    BoxedAppSDK.NativeMethods.BoxedAppSDK_Init();
			

Then create the virtual files of interop DLLs. They should be located at the application directory, that's why we use Application.StartupPath:

// Create virtual files using the data of 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"));
			

The method CreateFileInMemory creates a virtual file using data from embedded resources.

First, it creates a virtual file called BoxedAppSDK_CreateVirtualFile. This method returns virtual file handle. Close it immediately, you don't need it now. SafeFileHandle from Microsoft.Win32.SafeHandles helps.

Then just copy the data from the embedded resource to the virtual file:

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);
    }
}
			

That's all! Once the process asks for AxInterop.WMPLib.dll or Interop.WMPLib.dll, they are provided by BoxedApp virtualization.

Download

Sources are available on GitHub.