none
free com registration manifest for .Net

    Question

  • I have a .Net exe application which has a reference to a .net assembly called for example Anet.dll which has a reference to a free com registration c++ dll called Bcppcom.dll. My question is if is possible to add this free com registration manifest to the Anet.dll assembly or in .net only the exe application can have manifest because Visual studio .Net 9 doesn’t have the option to add manifest to a class library assembly?

    Thanks

    Wednesday, January 20, 2010 1:03 PM

Answers

  •  

    Hi,

    In B.dll, you may use following code snippet to activate different activation context:

     

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Runtime.InteropServices;

     

    namespace CSClient

    {

        public class csclient

        {

            [DllImport("Kernel32.dll", SetLastError = true)]

            private static extern IntPtr CreateActCtxW(ref ACTCTX pActCtx);

     

            [DllImport("Kernel32.dll", SetLastError = true)]

            [return: MarshalAs(UnmanagedType.Bool)]

            private static extern bool ActivateActCtx(IntPtr hActCtx, out IntPtr lpCookie);

     

            [DllImport("Kernel32.dll", SetLastError = true)]

            [return: MarshalAs(UnmanagedType.Bool)]

            private static extern bool DeactivateActCtx(int dwFlags, IntPtr lpCookie);

     

            private const int ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004;

           

            public static void Run()

            {

                // The folder where regfree COM dll locates in.

                string comAssemblyPath = @"D:\myapp\plugin";

     

                // The manifest file for B.dll, to construct a context for invoking COM server.

                string manifestPath = @"D:\myapp\plugin\plugin.manifest";

     

                ACTCTX ac = new ACTCTX();

                ac.cbSize = Marshal.SizeOf(typeof(ACTCTX));

                ac.lpAssemblyDirectory = comAssemblyPath;

                ac.lpSource = manifestPath;

                ac.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;

     

                IntPtr cookie;

                IntPtr hActCtx = CreateActCtxW(ref ac);

                if (ActivateActCtx(hActCtx, out cookie))

                {

                    try

                    {

                        // Invoke COM server here.

                    }

                    finally

                    {

                        DeactivateActCtx(0, cookie);

                    }

                }

     

                Console.ReadLine();

            }

        }

     

        [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]

        public struct ACTCTX

        {

            public int cbSize;

            public uint dwFlags;

            public string lpSource;

            public ushort wProcessorArchitecture;

            public Int16 wLangId;

            public string lpAssemblyDirectory;

            public string lpResourceName;

            public string lpApplicationName;

            public IntPtr hModule;

        }

    }


    Sincerely,
    Eric

    Please remember to mark helpful replies as answers.
    • Marked as answer by Ioan Toader Friday, January 29, 2010 10:17 AM
    Friday, January 29, 2010 3:10 AM

All replies

  • Hi,

    CodeFx has an existing solution for your case, you may get a sampel form All-In-One Code Framework Samples.

    Download the sample, open CSRegFreeCOMServer solution, then we can follow below steps to embed a manifest file into the assembly, and make it ready for registration-free activation.
     

    Step1. Add a CSRegFreeCOMServer.manifest file to the project with this content:

     

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    <assembly xmlns="urn:schemas-microsoft-com:asm.v1"

      manifestVersion="1.0">

    <assemblyIdentity

      type="win32"

    name="CSRegFreeCOMServer"

    version="1.0.0.0" />

    <clrClass

    clsid="{2384B3E7-4FFD-460d-A5B9-284182707922}"

    progid="CSRegFreeCOMServer.CSSimpleObject"

    threadingModel="Both"

    name="CSRegFreeCOMServer.CSSimpleObject" >

    </clrClass>

    </assembly>

     

    clsid="{2384B3E7-4FFD-460d-A5B9-284182707922}" is the CLSID of the COM class defined in CSSimpleObject.cs, and progid="CSRegFreeCOMServer.CSSimpleObject" is its ProgID.

     

    Step2. In the project's folder create a resource-definition script file (a text file) and call it CSRegFreeCOMServer.rc. Paste the following into the

    file:

     

    #define RT_MANIFEST 24

    1 RT_MANIFEST CSRegFreeCOMServer.manifest

     

    Step3. Open Project Properties, and turn to the Build Events page. In Pre-build event command line, enter this command:

     

    @echo.

    IF EXIST "$(DevEnvDir)..\..\..\Microsoft SDKs\Windows\v6.0A\bin\rc.exe"

    ("$(DevEnvDir)..\..\..\Microsoft SDKs\Windows\v6.0A\bin\rc.exe" /r

    "$(ProjectDir)CSRegFreeCOMServer.rc")

    ELSE (IF EXIST "$(DevEnvDir)..\..\SDK\v2.0\Bin\rc.exe"

    ("$(DevEnvDir)..\..\SDK\v2.0\Bin\rc.exe"/r "$(ProjectDir)CSRegFreeCOMServer.rc")

    ELSE (IF EXIST "$(DevEnvDir)..\Tools\Bin\rc.exe"

    ("$(DevEnvDir)..\Tools\Bin\rc.exe"/r "$(ProjectDir)CSRegFreeCOMServer.rc")

    ELSE (IF EXIST "$(DevEnvDir)..\..\VC\Bin\rc.exe"

    ("$(DevEnvDir)..\..\VC\Bin\rc.exe"/r "$(ProjectDir)CSRegFreeCOMServer.rc")

    ELSE (@Echo Unable to find rc.exe, using default manifest instead))))

    @echo.

     

    The command searches for the Resource Compiler (rc.exe), and use the tool to compile the resource definition file and any resource files (binary files

    such as icon, bitmap, and cursor files) into a binary resource (.RES) file: CSRegFreeCOMServer.RES.

     

    Step4. Turn to the Application page of Project Properties. In the section "Specify how application resources will be managed", select "Resource File",

    and enter the full path of CSActiveX.RES that is generated in step 3.

     

    Step5. (Optional) If you perfer a relative path to the full path of CSRegFreeCOMServer.RES, you need to modify the project file (CSRegFreeCOMServer.csproj). The "Resource File" value corresponds to the XML element:

     

    <Win32Resource>CSRegFreeCOMServer.res</Win32Resource>

     

     

    See also:

    Registration-Free Activation of .NET-Based Components: A Walkthrough

    http://msdn.microsoft.com/en-us/library/ms973915.aspx


    Sincerely,
    Eric

    Please remember to mark helpful replies as answers.
    Thursday, January 21, 2010 9:16 AM
  • Maybe you understand me wrong,, my problem is I have an application .Net 3.5 which can load on start up some plugg-ins/add-ins wrote in .Net and this plug-in use unmanaged c++ com dlls, I want to deploy this com dlls in isolated mode, my problem is how can add a manifest to my plug-in to describe the used com dlls whit hot changing the application host manifest.

    Thanks

    Thursday, January 21, 2010 9:53 AM
  •  

    Hi,

    On the target platforms, one of the stages of initializing a process and its dependent modules is to load any associated manifest files into a memory structure called an activation context. In the absence of corresponding registry entries, it is an activation context that provides the binding and activation information the COM run time needs. No special code is required in the COM server or in the client unless you choose to obviate the use of files by building activation contexts yourself using the activation context API.

     

    So, without modifying host's manifest, we can specify a manifest at runtime using the activation context API, something like this:

    Supposing that we have two versions of regfree COM server,

    1. SideBySide.dll, version 1.0.0.0, its assembly name is SideBySide.X, has manifest SideBySide.X.manifest embed in. 
    1. SideBySide2.dll, version 2.0.0.0,  its assembly name is SideBySide.X2, has manifest SideBySide.X2.manifest embed in.

    If application folder is "D:\myapp\", we can

    1. Put SideBySide.dll into folder "D:\myapp\v1\", put SideBySide2.dll into folder "D:\myapp\v2\".
    2. Create a manifest file app.manifest with content:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    <assembly xmlns="urn:schemas-microsoft-com:asm.v1"

      manifestVersion="1.0">

    <assemblyIdentity

                type = "win32"

                name = "client"

                version = "1.0.0.0" />

    <dependency>

                <dependentAssembly>

                            <assemblyIdentity

                                        type="win32"

                                        name="SideBySide.X"

                                        version="1.0.0.0" />

                </dependentAssembly>

    </dependency>

    </assembly>

    Put this manifest file to folder "D:\myapp\v1\".

    1. Create a manifest file app.manifest with content:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    <assembly xmlns="urn:schemas-microsoft-com:asm.v1"

      manifestVersion="1.0">

    <assemblyIdentity

                type = "win32"

                name = "client"

                version = "1.0.0.0" />

    <dependency>

                <dependentAssembly>

                            <assemblyIdentity

                                        type="win32"

                                        name="SideBySide.X2"

                                        version="2.0.0.0" />

                </dependentAssembly>

    </dependency>

    </assembly>

    Put this manifest file to folder "D:\myapp\v2\".

    1. In the host application, use following code snippet to invoke COM server of version 1.0.0.0:

     

    ULONG_PTR ulpCookie;

    HANDLE hActCtx;

     

    ACTCTX* ac = new ACTCTX();

    ac->cbSize = sizeof(ACTCTX);

     

    ac->lpSource = _T("D:\\myapp\\v1\\app.manifest");

    ac->lpAssemblyDirectory = _T("D:\\myapp\\v1");

     

    // You can invoke COM server of version 2.0.0.0 by below commented code.

    // ac->lpSource = _T("D:\\myapp\\v2\\app.manifest");

    // ac->lpAssemblyDirectory = _T("D:\\myapp\\v2");

     

    ac->dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;

    hActCtx =  CreateActCtx(ac);

     

    if(ActivateActCtx(hActCtx, &ulpCookie))

    {

                   // Your code here.
     

       DeactivateActCtx(0, ulpCookie);

    }

     


    Sincerely,
    Eric

    Please remember to mark helpful replies as answers.
    Monday, January 25, 2010 2:43 AM
  • you understod wrong my question.

    My problem is I have an application .Net 3.5 which can load on start up some plugg-ins/add-ins wrote in .Net and this plug-in use unmanaged c++ com dlls (third party components), I want to deploy this com dlls in isolated mode, my problem is how can add a manifest to my plug-in to describe the used com dlls whit hot changing the application host manifest.


    Monday, January 25, 2010 4:54 PM
  • Hi,
    I'm sorry, may I take the question as: You have a third party COM dll, the dll acts a plug-in component, and you are looking for methods that can make it regfree by embeding a manifest to the COM dll; And you don't want to modify host application's manifest file, am I right?


    Sincerely,
    Eric

    Please remember to mark helpful replies as answers.
    Tuesday, January 26, 2010 1:38 AM
  • Is not right, I have a application in . net, and I have a .net dll which acts as a plug-in and have a reference to a com dll which is deployed as free com, and my question is if is posibile to add the manifest to my .net dll assambly to specify the free com registration not to the exe aplication manifest.

    Thanks
    Wednesday, January 27, 2010 9:15 AM
  • Hi,


    I see, the reference hierarchy may looks like:

        A.exe (the hot application)  --> B.dll (the plugin managed dll) --> C.dll (a regfree COM written by C++)

    And you want to make it work by only modifying manifest file of B.dll.

     

    Since it is manifest file which provides activation context for activating COM objects, and the manifest file is loaded when process initiating, we cannot achieve our goal by adding manifest to B.dll.

     

    If we have opportunity to modify B.dll's source code, with interop call to activation context API, we may activate different activation context at runtime, is it acceptable for your case?


    Sincerely,
    Eric

    Please remember to mark helpful replies as answers.
    Thursday, January 28, 2010 1:49 PM
  • Thnks eryang

    Its ok for me to modify B.dll, but I don't know how to do interop call to activation context API activation context at runtime. Could you write me how?

    Thursday, January 28, 2010 3:15 PM
  •  

    Hi,

    In B.dll, you may use following code snippet to activate different activation context:

     

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Runtime.InteropServices;

     

    namespace CSClient

    {

        public class csclient

        {

            [DllImport("Kernel32.dll", SetLastError = true)]

            private static extern IntPtr CreateActCtxW(ref ACTCTX pActCtx);

     

            [DllImport("Kernel32.dll", SetLastError = true)]

            [return: MarshalAs(UnmanagedType.Bool)]

            private static extern bool ActivateActCtx(IntPtr hActCtx, out IntPtr lpCookie);

     

            [DllImport("Kernel32.dll", SetLastError = true)]

            [return: MarshalAs(UnmanagedType.Bool)]

            private static extern bool DeactivateActCtx(int dwFlags, IntPtr lpCookie);

     

            private const int ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004;

           

            public static void Run()

            {

                // The folder where regfree COM dll locates in.

                string comAssemblyPath = @"D:\myapp\plugin";

     

                // The manifest file for B.dll, to construct a context for invoking COM server.

                string manifestPath = @"D:\myapp\plugin\plugin.manifest";

     

                ACTCTX ac = new ACTCTX();

                ac.cbSize = Marshal.SizeOf(typeof(ACTCTX));

                ac.lpAssemblyDirectory = comAssemblyPath;

                ac.lpSource = manifestPath;

                ac.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;

     

                IntPtr cookie;

                IntPtr hActCtx = CreateActCtxW(ref ac);

                if (ActivateActCtx(hActCtx, out cookie))

                {

                    try

                    {

                        // Invoke COM server here.

                    }

                    finally

                    {

                        DeactivateActCtx(0, cookie);

                    }

                }

     

                Console.ReadLine();

            }

        }

     

        [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]

        public struct ACTCTX

        {

            public int cbSize;

            public uint dwFlags;

            public string lpSource;

            public ushort wProcessorArchitecture;

            public Int16 wLangId;

            public string lpAssemblyDirectory;

            public string lpResourceName;

            public string lpApplicationName;

            public IntPtr hModule;

        }

    }


    Sincerely,
    Eric

    Please remember to mark helpful replies as answers.
    • Marked as answer by Ioan Toader Friday, January 29, 2010 10:17 AM
    Friday, January 29, 2010 3:10 AM
  • Thanks a lot Eric, is working
    Friday, January 29, 2010 10:18 AM
  • Hi, Eric,

    We tried this method on the DSOFile.dll and it didn't work.

      IntPtr hActCtx = CreateActCtxW(ref ac); // this line return -1 but no exception

    We used DSOFile.dll as reference in a class library which is part of a web site project. It's working fine as long as it is registered on the running machine. Now we are looking for a way that can use it reg-free or side by side.

    Please advice.

    Thanks,
    Wednesday, March 10, 2010 5:13 PM
  • Tim, please add more info about DSOFile.dll to new thread which I created based on Eric's request.
    -Karel
    Wednesday, March 10, 2010 9:35 PM
  • Hi Eric,

    I'm currently in the same situation below where I can't modify A.exe, manifest file of A.exe, nor C.dll (provided by third party).

        A.exe (the hot application)  --> B.dll (the plugin managed dll) --> C.dll (a regfree COM written by C++)

    I'm trying to make sense of the solution you provided above but I'm just a beginner in C# and .NET. Could you guide me on the solution you provided? Where should I put the code snippet in my plugin source code and how do I make use of the class?

     

    Thank you so much!

     

    Best Regards,

    Bruce 

    Tuesday, October 19, 2010 10:57 AM