Register C # COM object without real file for RegAsm

I have a wierd application download mechanism. I have an exex file with the extension, with all the other DLLs and the applications themselves inside it. These files (assemblies) are extracted from resources and loaded into emd, because I am joining 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 bootloader has only one link and refers to the main application, but does not refer to the main method in order to avoid an assembly search at startup. What I do is force build during splash screen 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*/ } } 

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

Now my problem is: how to register a COM object processed in one of my DLL files?

RegAsm uses file paths to register a COM object ... :(

Any help appreciated!

0
source share
2 answers

I figured out a bit and maybe executed the DllRegisterServer () intot, which it executed, and then registering all COM types in all the built-in DLLs will work ...

Can anyone confirm?

EDIT: Yes, it can be done, but the main executable must be a COM proxy for internal DLLs.

0
source

I am doing something very similar in Excel-DNA . You do not need to deserialize COM types to disk or register them in advance. What I did was define a class that implements IClassFactory, and then register it as the current factory class for a particular CLSID (type) by calling CoRegisterClassObject. When COM tries to create an object, the factory class is called and can return an instance of your .NET type.

Depending on the context, you may need to register ProgID / CLSID on the fly.

(If you contact me, I would be happy to help you grab the correct bits from Excel-DNA code to get you started.)

+1
source

All Articles