I have a Windows application built in C++ (c++App.exe), and a .NET Windows application built in C# (c#App.exe).
I'm embedding the c#App.exe as a resource into c++App.exe.
When I run c++App.exe, I perform some checks, and if they all pass, I'd like to execute the c#App.exe embedded as resource.
What I've tried so far:
Extract the csharpApp.exe to a temporary file, and execute it via CreateProcess
Host the .NET CLR in my C++ app, and load the C# assembly into an AppDomain, and call the Program.Main function via Reflection
Is there any other alternative to what I've tried? What I would like is to be able to call the c#App.exe directly from c++App.exe, without having to write to disk, and without having all the complications of loading the .NET Common Language Runtime into my C++ app.
Is there something like CreateProcessFromBytes where I can pass a reference to my c#App.exe embedded resource, and its entry point gets called like a normal executable (and the entry point is then in charge of loading the CLR, etc...)?
I know I cannot use ILMerge, because the it's C++
I don't want to use any setup-kind of app such as MSI / NSIS, WiX, etc. I would like to do everything programatically myself
I don't want to use any self-extracting packer like 7-zip, or WinZip, etc. I would like to do everything programatically myself
Related
I am working within a 32-bit ETL tool (Pervasive Data Integrator v9). I need to give this tool the ability to call an external function that will remove a file from within a ZIP archive without extracting the archive.
The ETL tool provides the ability to load an external DLL and call its functions. The DLL and its function gets referenced by ETL tool's custom script language like this:
Declare function OemToCharA lib "user32" (byval lpszSrc as string, byval lpszDst as string) as long
The function (OemToCharA in this example) is then called somewhere in the lines of the script that follow that declaration. I have tested this with a registered DLL and it works.
So I want to build a DLL with a function that will do the zip manipulation.
Since I don't know how to manipulate zip files programatically, I found DotNetZip - a free .NET class library that provides the heavy lifting for the zip archive operations. Problem for me is that it is .NET (managed). I would still like to try to use it. So I built a C# DLL (.NET 4.0) with a function that utilizes DotNetZip to do the required zip file manipulation. I pass in two parameters, "zip file location" and the "file to remove" and the zip archive gets updated.
I read about the idea of building a mixed-mode C++/CLI DLL to take advantage of managed .NET code in the native world. I found this VS solution which consists of 3 basic projects:
Managed (C#) DLL project
Mixed-mode C++ DLL wrapper project which references the C# DLL
A native (unmanaged) C++ console test app project which references the C++ wrapper
I built a test solution based on that pattern which removes a file from a zip archive and it works great. Please note however that the mixed mode DLL is called from a native C++ console app which is part of the VS solution. I didn't have to register any DLLs and it just works.
However ultimately I need the ETL tool to call the mixed mode DLL. I am not able to get this to work.
Things I have tried on the ETL server thus far:
I tried to register the mixed-mode wrapper DLL but SysWow64\regsvr32 fails to find an entry point in the DLL.
I installed VS 2015 VC++ x86 and x64 redistributable libraries on the ETL server.
I placed the DLLs from my solution (i.e., the mixed mode, c# and dotnetzip dlls) in the ETL engine folder because the console app worked when the DLLs were in its deploy folder.
The ETL tool has the ability to call an external application so I believe I could let it call a console app similar to my VS test solution but I'd really like to get this to work with only the DLLs. Is this possible? If so, what am I missing?
Kudos to Matt, thanks for the hint to use Process Monitor.
ETL tool was not finding the DLL but Process Monitor told me the folders it was checking...I moved the DLLs to one of the checked folders
My wrapper function was originally void with an output parameter for the return value - that was causing issues as I didn't have a good example in the ETL documentation of how to call a void function. I changed the function to return a "long" and removed the output parameter.
After making those two changes it started working. Thanks again Matt!
I am maintaining an ActiveX control developed in MFC to be used as a plug-in for a multiple of commercial applications. This was all working perfectly until I wanted AES encryption included because the control needs to logon to a remote location automatically. No big deal, created a C# class library (SimpleAES.dll) that only provides a class with 2 members, encrypt and decrypt. Mixing managed and unmanaged code, I wrote a wrapper library in C++/CLR wrapping my encryption class (SimpleAESWrapper.dll).
This all works like a charm when tested using my ocx test container application, storing all 3 libraries in the same directory as the test container application (that is the test.exe together with ocx, together with the two dll's).
Unfortunately when I run a third party application, that loads the ocx, the ocx will not get loaded because it does crash as soon as I create an instance of the encryption class due to the fact that it cannot find the WrapperSimpleAES.dll. The third party application is ran from another location. Adding the libraries location to the path or even system32 folder does not resolve the issue.
Am I missing something crucial, like do the libraries have to be registered in some way like the ocx has to with regsvr32.exe? i.e. Applications know where to find the ocx because it is registered into the registry right?
I have been pulling my hair out as I can nowhere find a useful lead.
Try storing the WrapperSimpleAES.dll in the 3rd party program directory.
The Problem is that you ActiveX Control is found by a LoadLibrary call. COM resolves the needed DLL via the registry entries. Your Problem now, is that when your code executes the next DLL needed isn't found.
As a Workaround:
Set your secondary DLL as delay load. So it is not needed when your ActiveX Control loads.
When your ActiveX needs the secondary DLL use GetDllDirectory to get the current Setting and save it.
Now use SetDllDirectory to the Path of your main ActiveX.
Execute your code. The Delay-Load will succeed.
After the call use SetDllDirectory to restore the old settings.
HTH
I have a given code written in unmanaged C++ that I added as a resource in a C# program.
When trying to load the unmanaged EXE using Assembly.Load, I get a BadImageFormatException whose InnerException says that "the IL Format is incorrect" (obviously).
How can I make this work?
I know that using the code as a DLL would be better, but for some reason, the dll call does not behave the same way as when I run the unmanaged exe with System.Diagnostics.Process.Start.
And I don't want to have two separates EXE files. Any idea?
EDIT: OK, I no longer need to do that. My dll behaved a different way because I was using it in a different context (winform instead of console); therefore the function causing the problem, SetThreadDesktop, couldn't work as expected. Gonna close post now, thanks for all those who answered.
You can't load an unmanaged exe/dll with Assembly.Load(), it works only with managed ones. if you need to PInvoke on that unmanaged file, and the reason you want a single exe is just deploy, you can pack it as an embedded resource (as you currently did ) and unpack on the target machine in a file, and use it as usual.
If you have unmanaged DLL as resource - basic steps:
Save resource to disk at run-time
use LoadLibrary (Win32 call to LoadLibrary using PInvoke)
either use methods from this library by calling methods annotated for PInvoke, or manually via GetProcAddress.
Slightly different approach, that could be automated, is using the so-called "assembly weaving"
Costura.Fody - https://github.com/Fody/Costura - is the one of the 'weavers'. The embedding process (with tests automation) for incorporating unmanaged resources and transparently loading them at runtime without much of effort -
Install-Package Fody.Costura
Then all of embedding, unpacking, assembly locating and loading is automated by default, and controlled by including 'FodyWeavers.xml' config, added to your project.
<Costura>
<Unmanaged32Assemblies>
Foo32
Bar32
</Unmanaged32Assemblies>
<Unmanaged64Assemblies>
Foo64
Bar64
</Unmanaged64Assemblies>
</Costura>
The concept behind approach, is static <Module> class loader, that is binary changed by Fody project tasks, after your project assembly was successfully built. Internally Mono.Cecil is used for the static '<Module>' loader injection that unpacks resources automatically, saves them to temporary directory, telling to load dll's from that location, etc. at assembly load event.
I'm using some code to start the CLR Runtime inside a native process, then call my .NET DLL to load another .NET executable inside that process.
To load the other .NET executable I'm using reflection, like so:
Assembly.Load(file).EntryPoint.Invoke(null, null);
Now, I inject a C++ dll that starts the runtime, it then calls the .NET dll which uses Assembly.Load to load another .NET executable into memory and execute it.
Once the dll loads my .NET executable, calling:
System.Reflection.Assembly.GetExecutingAssembly().Location;
or even
Process.GetCurrentProcess().MainModule.FileName;
This, of course, returns the location of the executable itself, even though its running inside another host process. Is there any way I can grab the name of that host process? Process explorer shows it as running inside the host process so I know I have that part working correctly.
Of course if I were to run these commands inside the .NET DLL that was loaded first then it would show the proper process name.
Thanks.
EDIT:
I have tried GetEntryAssembly() and GetCallingAssembly() as well.
DON'T DO THAT.
You may not inject the .NET framework into any process that is not yours. It might have a different framework already loaded or desire to load a different framework version later.
You can get the name of the host process by calling GetModuleFileName(GetModuleHandle(NULL)); (Both API calls are P/Invoke. [1] and [2]).
IF I understand your question correctly then you want to find the "parent process"... There are different ways to do that, either managed or via P/Invoke... for nice code samples on how to do this see How to get parent process in .NET in managed way
I have an existing EXE and DLL file (both unmanaged) that I'd ideally like to embed in my C# app and execute at runtime of the C# app. The EXE, when executed normally via command-line or Explorer, requires the DLL to be in the same directory as the EXE. How would I be able to:
1) Embed the EXE and DLL in my app and execute them via C# code?
2) Make sure that the EXE will be able to access its dependent DLL file?
Thanks!
Put them in Project embedded Resources.
When your program runs extract them from Resources, copy into known location and execute via Process.Start
Add the files as embedded resources. You can then export them to wherever you like in your code. Use the System.Diagnostics.Process class to run it.
Edit:
You may also want to cache the location name so that you can delete the files when your C# application exits (if you want to be nice and cleanup after yourself that is)
There is .NETZ which I have used once successfully. It seems that the tool also supports native unmanaged DLLs to some degree.
Maybe it helps as a pointer to give you some ideas for your actual desired solution.