注册C#的COM对象,而不必为RegAsm一个真正的文件 [英] Register C# COM Object without having a real file for RegAsm

查看:244
本文介绍了注册C#的COM对象,而不必为RegAsm一个真正的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个奇怪的应用程序加载机制。我与所有其他DLL和应用程序本身里面的资源boostrapping exe文件。这些文件(组件)是从资源提取和加载OND emand因为我连接到当前的AppDomain的AssemblyResolve事件。

I have a wierd application loading mechanism. I have a boostrapping exe file with all the other DLLs and the application itself inside it's resources. These files (assemblies) are extracted from resources and loaded ond emand because i'm attaching to the Assemblyresolve event of the current AppDomain.

 [STAThread]
        static void Main()
        {
            // if the command line contains extract then extract the dlls, next run will resolve assemblies from disk
            bool saveDllsToDisk = new List<string>(Environment.GetCommandLineArgs()).Contains("extract");
            // if the command line contains bin then use the bin folder instead of temp to extract dlls
            bool useBinFolder = new List<string>(Environment.GetCommandLineArgs()).Contains("bin");

            if (!Directory.Exists(tempFolder)) {
                Directory.CreateDirectory(tempFolder);
            }

            // the assembly resolver will get here because it will not find the dlls in the bin folder
            // we load assemblies in our specific way:
            // - if exists in our temp/bin folder load from there
            // - else load from resources
            // - if specified extract DLLs to the temp/bin folder
            AppDomain.CurrentDomain.AssemblyResolve += (sender, args2) =>
            {
                string name = new AssemblyName(args2.Name).Name;
                Debug.WriteLine("START LOADING " + name);

                Assembly assembly = null;
                string folder = useBinFolder ? binFolder : Path.Combine(tempFolder, APP_NAME);
                string fileName = name.Replace(".","_").Replace("#EXE#", ""); // in resources we use _ instead of .
                string extension = name.Contains("#EXE#") ? "exe" : "dll"; // hack for our embedded exe files
                name = name.Replace("#EXE#", ""); // hack for our embedded exe files

                if (File.Exists(Path.Combine(folder,String.Format("{0}.{1}", name, extension))))
                {
                    // load from file in app temp folder
                    assembly = Assembly.LoadFile(Path.Combine(folder, String.Format("{0}.{1}", name, extension)));
                }
                else
                {
                    // extract assembly from resources
                    byte[] assemblyBytes = (byte[])resMan.GetObject(fileName, CultureInfo.InvariantCulture);
                    assembly = Assembly.Load(assemblyBytes);

                    // if selected save to file so the next run JIT will resolve from disk
                    if (saveDllsToDisk)
                    {
                        string outDll = Path.Combine(folder, String.Format("{0}.{1}", name, extension));
                        using (var fs = File.Create(outDll))
                        {
                            fs.Write(assemblyBytes, 0, assemblyBytes.Length);
                        }
                    }
                }

                Debug.WriteLine("LOADED " + name);
                return assembly;
            };

            splashScreen = new frmSplash();
            // as soon as splashscreen starts animating assembly preloading will be launched on this eventhandler
            splashScreen.Started += new EventHandler(splash_Started);
            // splashscreen has finished fadein we must now wait for all libraries to be preloaded and set CanContinue
            splashScreen.Finishing += new EventHandler(splash_Finishing);
            splashScreen.CanContinue = false;

            // run splashscreen while preloading of DLLs is going on
            Application.Run(splashScreen);
        }

该引导程序只有一个参考,那就是主要的应用程序,但它并没有引用它的主要方法,以避免集搜索的开始。我要做的就是在启动画面的动画在大会有效载荷:

This bootstrapper has only one reference and that is to the main application, but it does not reference it in the main method to avoid assembly search at start. What I do is force assembly loading during the splashscreen animation:

ObjectHandle instance;

                string[,] assemblies = {
                     {"WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","dummy"}, // will go from GAC, not our resolver
                     {"PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","dummy"}, // will go from GAC, not our resolver
                     {"PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","dummy"}, // will go from GAC, not our resolver
                     {"WindowsFormsIntegration, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","dummy"}, // will go from GAC, not our resolver
                     {"PresentationFramework.Aero, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","dummy"}, // will go from GAC, not our resolver
                     {"System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","dummy"}, // will go from GAC, not our resolver                     
                     {"AvalonDock, Version=1.3.3585.0, Culture=neutral, PublicKeyToken=85a1e0ada7ec13e4", "dummy"}, // out reference inside resources
                     {"AvalonDock.Themes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "dummy"}, // out reference inside resources
                     {"ICSharpCode.AvalonEdit, Version=4.0.0.5950, Culture=neutral, PublicKeyToken=9cc39be672370310", "dummy"}, // out reference inside resources
                     {"WPG, Version=2.0.4120.37542, Culture=neutral, PublicKeyToken=null","dummy"}, // out reference inside resources
                     {"WPGBrushEditor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","dummy"}, // out reference inside resources
                     {"HLSLEditor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","dummy"} // preload even our main file that will launch after the splashscreen
                };

                for (int i = 0; i <= assemblies.GetUpperBound(0); i++)
                {
                    try
                    {
                        instance = AppDomain.CurrentDomain.CreateInstance(assemblies[i,0], assemblies[i,1]);
                    }
                    catch (Exception ex) {
                        /* must not raise errors, it will fail because we are not actually asking for a
                         *  valid type and we only need this assembly loaded right now*/
                    }
                }

现在你看到有任何文件夹中没有实际的dll文件,但是从资源直接加载的程序集。

Now you see that there are no actual dll files in any folder but are assemblies directly loaded from resources.

我现在的问题是:如何注册delared在我的dll文件一个COM对象

RegAsm使用文件路径来注册COM对象...:(

RegAsm uses filepaths to register a COM object... :(

任何帮助AP preciated!

Any help appreciated!

推荐答案

我挖一点点,也许实施中的DllRegisterServer()intot他主要的可执行文件,然后登记在所有的嵌入式DLL的所有COM类型将工作...

I digged a little and maybe implementing DllRegisterServer() intot he main executable and then registering all the COM types in all the embedded DLLs would work...

谁能证实?

编辑:是的,这是可以做到的,但主要的可执行文件必须是一个COM代理里面的DLL文件

Yes it can be done, but the main executable must be a COM proxy to the DLLs inside.

这篇关于注册C#的COM对象,而不必为RegAsm一个真正的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆