Merge managed program into unmanaged C++ Executable - c#

My goal is to only have a single executable file.
Is it possible to merge a managed .exe into an unmanaged .exe?
There is a lot of information about doing things the other way around (merging unmanaged code into a managed project) but I haven't been able to find anything about going the other direction.
Background:
It's for a system requirements / compatibility checker.
I've written the bulk of it using C# in .NET 2.
However, this part will only run if it's determined that the system at least has .NET 2 installed.
That's where "DotNetVersionIdentifier.exe" comes into play.
It's unmanaged code will run regardless of if the .NET Framework is installed. Instead of showing a dialog box of installed .NET versions, I've modified the code to run my C# program if .NET 2.0 or greater is installed, or else report a custom message.
I'd like to pack the C# program inside the C++ executable so that I only need to distribute a single .exe
I've tried using ILMerge, but since my unmanaged code doesn't compile to Intermediate Language, it crashes...
I can add my C# project to the C++ solution, but it still compiles to two separate executables.
This approach: How to Append Data to the End of an .EXE File sounds like a fascinating, yet outdated hack.
This idea seems like it might work: How to embed an exe inside another exe as a resource and then launch it and I'm looking into it now.

I managed to accomplish my goal by using Resources, as outlined here.
Here's how I made it work. (I'm new to C++, so let me know if you see any stupidity)
Compile the managed code as a single file
Rename the managed code executable as .txt
Create a new Visual C++ Win32 Console Application
Add new item - Resource File (.rc)
Open the resource file, Add Resource, choose Import, enter "TEXT" as the type
Modify "DWORD size" to match the size of the managed .txt file
The rest can be explained with a code dump.
Hopefully this will help someone (C++ newbies like myself...)
#include "stdafx.h"
#include "resource.h"
#include "windows.h"
#include "iostream"
#include <string>
#include <sstream>
using namespace std;
namespace std
{
HRSRC hrsrc = NULL;
HGLOBAL hGlbl = NULL;
BYTE *pExeResource = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD size = 8192; //hardcoding the size of the exe resource (in bytes)
HINSTANCE g_Handle = NULL;
HINSTANCE hInstance = NULL; // Passing NULL uses the instance that started the process( CSMerged.exe ).
template <typename T>
string NumberToString(T pNumber)
{
ostringstream oOStrStream;
oOStrStream << pNumber;
return oOStrStream.str();
}
}
int _tmain(int argc, _TCHAR* argv[])
{
hrsrc = FindResource(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_TEXT1), _T("TEXT"));
if (hrsrc == NULL)
{
cout << "hrsc is null! \n";
cin.get(); // leave the console open.
return FALSE;
}
hGlbl = LoadResource(hInstance, hrsrc);
if (hGlbl == NULL)
{
cout << "hGlbl is null! \n";
cin.get(); // leave the console open.
return FALSE;
}
pExeResource = (BYTE*)LockResource(hGlbl);
if (pExeResource == NULL)
{
cout << "pExeResource is null! \n";
cin.get(); // leave the console open.
return FALSE;
}
hFile = CreateFile(L"ManagedCode.exe", GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD bytesWritten = 0;
WriteFile(hFile, pExeResource, size, &bytesWritten, NULL);
CloseHandle(hFile);
}
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
int ret = CreateProcess(L"ManagedCode.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (ret == 1) { return 0; } // the process started successfully, so I'm done here.
else
{
cout << "CreatePrecess returns " + NumberToString(ret) + ". \n";
cin.get(); // leave the console open
}
return 0;
}
Resource.h
- This was auto generated, along with the modifications to Recource.rc when I imported the resource using VS2013's GUI.
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Resource.rc
//
#define IDR_TEXT1 101
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
I should a add a couple of other things I had to change to make this run on Windows XP:
Ensure that the Platform target is Win32
Set Configuration Properties>General>Platform Toolset to "Visual Studio 2013 - Windows XP (x120_xp)"
Set Configuration Properties>C/C++>Code Generation>Runtime Library to "Multi-threaded (/MT)

Related

Call .NET dll from C++ code failes when calling GetProcAddress(...)

I want to call a method of .NET dll (v4.5) from C++ code. This dll uses a third party dll (SKCLNET .NET v1.0)
I build a simple C++ code for that (see below).
The problem is that GetProcAddress(...) returns NULL for some reason.
I'm not sure what is wrong with the code...
I tried to invoke the dll-function via .NET-Console-App directly this worked fine.
#include "pch.h"
#include <iostream>
#include <Windows.h>
using namespace System;
typedef std::string(*GetLicenseStatusFunction)();
int main(array<System::String ^> ^args)
{
HMODULE hDLL = LoadLibrary(L"LicenseCheck.dll");
if (hDLL == NULL) {
std::cout << "Error loading the DLL" << std::endl;
return 1;
}
GetLicenseStatusFunction pGetLicenseStatus = (GetLicenseStatusFunction)GetProcAddress(hDLL, "ValidateLicense.GetLicenseStatus");
if (pGetLicenseStatus == NULL) {
std::cout << "Error getting the function pointer" << std::endl;
return 1;
}
std::string result = pGetLicenseStatus();
std::cout << result << std::endl;
return 0;
}
Here the structure of the used dll:
Here the ValidateLicense class in the .NET dll with the function GetLicenseStatus() I would like to access.
From using namespace System; and the prototype of main,
I assume this is a C++/CLI project (and not a native C++ one).
Since using C++/CLI means it is a .NET project, you can consume other .NET assemblies similarly to the way you would do that in C#.
Just use "add reference" from the project tree and add the assembly you want to consume.
LoadLibrary() and GetProcAddress() are used only to load and call native functions, from native code. As explained above this is not the case here.
Note that in C++/CLI reference types use the handle to object operator (^). So from C++/CLI side the method ValidateLicense.GetLicenseStatus returns a String^.
Also in C++/CLI use :: instead of . for scopes of namespaces and classes:
using namespace ....
//...
String^ sts = ValidateLicense::GetLicenseStatus();
In order to print it you can use:
Console::WriteLine(sts);
You can also convert it to a native std::string:
#include <string>
#include <msclr/marshal_cppstd.h>
//...
std::string sts_cpp = msclr::interop::marshal_as<std::string>(sts);

Getting full name and usage of gpu using nvapi

i am trying to get the full name of my gpu and my gpu usage using nvapi.dll.
i have encounter this post on this website: C# Performance Counter Help, Nvidia GPU.
he uses 2 sources, one in the dll itself (for getting the usage) and for full name he uses the header file of nvapi downloaded from the nevidia website.
There is any way i can avoid this duplication in my project?
using only the dll or using only the header files brought by nevidia.
Thanks for all the helpers
you can load DLL file dynamically when you need it,
in c# you can use .Net Reflection (if dll is developed in .Net framework), for example :
var DLL = Assembly.LoadFile(#"path\to\your.dll");
Type t = DLL.GetType("myAssembly.ClassName");
CustomType result = t.InvokeMember("methodName", BindingFlags.InvokeMethod, null, t, new object[] { #"method argument" });
if mentioned dll is not developed under .Net framework but you are forced to use .Net framework (for more information see this) :
int hModule = LoadLibrary(#"path\to\your.dll");
if (hModule == 0) return false;
IntPtr intPtr = GetProcAddress(hModule, "yourmethod_PTR");
if you want to use in c/c++ you can use following code :
HINSTANCE hGetProcIDDLL = LoadLibrary("path\\to\\your.dll");
if (hGetProcIDDLL == NULL) {
std::cout << "dll not found" << std::endl;
}
int a = function_to_call("arguments");
NOTE: if you want to load dll from unknown source I recommend to use c/c++, because in c/c++ you can manage your memory easier and free all your resources after dll loading,
I have found the list of functions id in https://github.com/processhacker/plugins-extra/blob/master/NvGpuPlugin/nvidia.c
In addition to
http://eliang.blogspot.com/2011/05/getting-nvidia-gpu-usage-in-c.html
i declared
typedef int(*nvAPI_GPU_getFullName_t)(int *handle , char* name); nvAPI_GPU_getFullName_t nvAPI_GPU_getFullName=NULL; nvAPI_GPU_getFullName=(nvAPI_GPU_getFullName_t)(*NvAPI_QueryInterface)(0xCEEE8e9FUL);

Call Cobol or C functions in Cobol program called by C# program

I work on a simple console application in C# 4.6.1.
I can make cobol program using Micro Focus environnent.
My goal is to call, from console application, cobol program which have calls to another cobol program.
Today I can call with success cobol methods in cobol dll file, using DllImport or LoadLibrary.
In my example, my cobol method named Hello, in dll file hello.dll, print "Hello :D" and in the same way, my another cobol program named Itsme, in dll file itsme.dll, print "It's me".
Inside Cobol program, we can call another program with his name. In my example, I add the the following line in my Hello program :
CALL "ITSME"
In my console application, I load both dll file (hello.dll and itsme.dll).
When I call my method Hello, it's supposed to print "Hello It's me".
But it won't, because of :
Load error : file 'Itsme'
error code: 173, pc=0, call=1, seg=0 173
Called program file not found in drive/directory
I know it work on Unix system, using dlopen instead of LoadLibrary.
LoadLibrary isn't the equivalent of dlopen ?
EDIT : There is a little sample of code after looking to Simon Sobisch answer :
#include "stdafx.h"
#include "stdio.h"
#include "windows.h"
#include "cobtypes.h"
typedef int(__stdcall *f_cobinit)();
typedef cobrtncode_t(__stdcall *f_cobcall)(const cobchar_t *callname, int argcnt, cobchar_t **argvec);
int main()
{
HINSTANCE dll1 = LoadLibrary("CobolDlls.dll");
HINSTANCE dll2 = LoadLibrary("CobolDlls2.dll");
HINSTANCE dllCbl = LoadLibrary("cblrtsm.dll");
printf("cobinit : ");
f_cobinit init = (f_cobinit)GetProcAddress(dllCbl, "cobinit");
printf("%d", init());
f_cobcall hi = (f_cobcall)GetProcAddress(dllCbl, "cobcall");
cobrtncode_t c = hi((cobchar_t*)"P2", 0, NULL);
getchar();
}
I successfully load librairies, and my call to cobinit is working (result : 0).
But when I call cobcall method, I have the error code 173 seen previously.
I precise that "P2" is refering to a cobol program named "P2" included in "CobolDlls.dll", which is build as a shared single dynmic library with MicroFocus, and all Dlls are in the same directory than the console application.
P2 program :
identification division.
program-id. P2.
data division.
working-storage section.
local-storage section.
procedure division.
display "Hello I'm P2"
goback.
Thanks for your help,
Yoann
Note: This is a guess as I did not tested it, but for most COBOL implementations there is a a runtime library (which should be the target for dlopen / LoadLibrary) which provides functions to use it.
A quick search in the Micro Focus documentation showed C Functions for Calling COBOL, you likely want to use cobinit(), cobcall() and cobtidy().
As everything concerning the COBOL parts is done by the runtime library (which needs to be either linked or loaded itself) you'll need to set options like where to find the modules and other possibly relevant settings before the call to cobinit().
One setting possibly needed:
COBPATH - If the COBOL modules do not reside in the process' current directory - set the same way you'd set PATH variable (entries separated by ";" on Windows)
I'd try something like the following in this case (in C#, the sample was C++)
System.Environment.SetEnvironmentVariable("COBPATH", "X:\path;Y:\other-path");
According to the documentation about Calling Programs combined programs are loaded by loading the library containing them first with a plain CALL. Your adjusted program would then look like:
#include "stdafx.h"
#include "stdio.h"
#include "windows.h"
#include "cobtypes.h"
typedef int(__stdcall *f_cobinit)();
typedef cobrtncode_t(__stdcall *f_cobcall)(const cobchar_t *callname, int argcnt, cobchar_t **argvec);
int main()
{
HINSTANCE dllCbl = NULL;
f_cobinit cobInit = NULL;
f_cobcall cobCall = NULL;
int retCode;
printf("load COBOL runtime : ");
HINSTANCE dllCbl = LoadLibrary("cblrtsm.dll");
if (!dllCbl) {
retCode = (int)GetLastError();
printf("failure: %d\n", retCode);
return retCode;
}
puts("success");
printf("lookup COBOL functions : ");
cobInit = (f_cobinit)GetProcAddress(dllCbl, "cobinit");
cobCall = (f_cobcall)GetProcAddress(dllCbl, "cobcall");
printf("init: %p, call: %p - ", (void *)cobInit, (void *)cobCall);
if (!cobInit || !cobCall) {
retCode = (int)GetLastError();
printf("failure: %d\n", retCode);
return retCode;
}
puts("success");
printf("cobinit : ");
retCode = cobInit();
if (retCode) {
printf("failure: %d\n", retCode);
return retCode;
}
puts("success");
printf("preload CobolDlls : ");
retCode = cobCall((cobchar_t*)"CobolDlls", 0, NULL);
puts("success");
//printf("preload CobolDlls2 : ");
//retCode = cobCall((cobchar_t*)"CobolDlls2", 0, NULL);
//puts("success");
printf("do actual CALL "P2" : ");
retCode = cobCall((cobchar_t*)"P2", 0, NULL);
printf("returned with: %d\n", retCode);
getchar();
}
Note: Be aware that the COBOL runtime may issue an exit (especially when there are errors in the COBOL parts or a module does STOP RUN). You want to make sure to be able to catch it.

Unity3D call external dll

I am trying to build a native plugin for Unity3D Pro (5.0). So far, I have built a DLL file in VS express 2013 for Windows, I have created a sample Unity project just for that and linked the library, but I am still getting an error and I cannot seem to move. Google wasn't very helpful in that matter ...
I am trying to add a DLL with my own low-level stuff for Windows Store target.
The stuff I am trying to access this way doesn't matter, I am stuck at hello world example app.
Visual Studio project
Dll3.cpp
#include "pch.h"
#include "Dll3.h"
extern "C" __declspec(dllexport) int testFunc(int a, int b) {
return a + b;
}
Dll3.h
#pragma once
using namespace std;
extern "C" __declspec(dllexport) int testFunc(int a, int b);
dllmain.cpp
#include "pch.h"
BOOL APIENTRY DllMain(HMODULE /* hModule */, DWORD ul_reason_for_call, LPVOID /* lpReserved */)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
pch.h
#pragma once
#include "targetver.h"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#endif
// Windows Header Files:
#include <windows.h>
pch.cpp
#include "pch.h"
and I set the build target to x64, the DLL file exported successfully without any errors or warnings.
Unity Project
I plopped the Dll3.dll file to the Assets/ folder. At first, I had it in Assets/Plugins/ but I figured out it didn't matter at all.
test.cs
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class test : MonoBehaviour {
// Dll import according to Unity Manual
#if UNITY_IPHONE || UNITY_XBOX360
[DllImport ("__Internal")]
#else
[DllImport ("Dll3")]
#endif
private static extern int testFunc (int a, int b);
// Use this for initialization
void Start () {
int a = 1;
int b = 2;
int c = testFunc (a, b);
Debug.Log (c.ToString ());
}
// Update is called once per frame
void Update () {
}
}
Then I created an empty game object, assigned this script to it, compiled and run. It compiled without any errors or warnings, but when running (in Editor), I got this:
Failed to load 'Assets/Dll3.dll' with error 'This operation is only valid in the context of an app container.', GetDllDirectory returned ''. If GetDllDirectory returned non empty path, check that you're using SetDirectoryDll correctly.
Failed to load 'Assets/Dll3.dll' with error 'This operation is only valid in the context of an app container.', GetDllDirectory returned ''. If GetDllDirectory returned non empty path, check that you're using SetDirectoryDll correctly.
DllNotFoundException: Assets/Dll3.dll
test.Start () (at Assets/test.cs:18)
Can anyone, please point me to where I am doing the mistake? I am used to Unix (OSX/Linux) environment and Windows very non-standard for me. I do not understand completely the concept of the VS DLL project. I would be grateful for any help. Thank you
Yeah, it was correct from the start. I just needed to run it in Visual Studio Simulator, as a Store App on my desktop or deploy it to my development tablet PC. It does NOT run in the Unity Editor - I am such a fool :-)

How to make CUDA dll that can be used in C# application?

It would be good if you could give me a brief tutorial instead of a few words.
My CUDA application is working as I wanted. Now, the problem is how to export CUDA code to C# as I would like to make front end and everything else in C#.
From this link:
http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w
I know how to make a library in C language that can be imported into C# application as Win32 dll.
But my question is, how to make CUDA application dll (or some other extension) that can be shipped to C# and used from C# application?
It would be good if there is somewhere tutorial for CUDA like the one for C library to C# app(above link).
I am using Win7 64 bit, Visual Studio 2010 Ultimate, Cuda Toolikt 5.0 and NSight 2.2.012313
ManagedCUDA is perfect for this type of thing. First you need to follow the instructions in the documentation to set up your Visual Studio Project.
Here is an example of a solution:
test.cu (compiles to test.ptx)
#if !defined(__CUDACC__)
#define __CUDACC__
#include <host_config.h>
#include <device_launch_parameters.h>
#include <device_functions.h>
#include <math_functions.h>
#endif
extern "C"
{
__global__ void test(float * data)
{
float a = data[0];
float b = data[1];
float c = data[2];
data[0] = max(a, max(b, c));
}
}
and here is the C# code:
private static void Test()
{
using (CudaContext ctx = new CudaContext())
{
CudaDeviceVariable<float> d = new CudaDeviceVariable<float>(3);
CUmodule module = ctx.LoadModulePTX("test.ptx");
CudaKernel kernel = new CudaKernel("test", module, ctx)
{
GridDimensions = new dim3(1, 1),
BlockDimensions = new dim3(1, 1)
};
kernel.Run(d.DevicePointer);
}
}
This is just a proof of concept, the device memory is not even initialized and the result is not read but is enough to illustrate how to do it.
You have several options how to distribute your application. In this case i opted for compiling the .cu file into PTX and load it inside the C# project from filesystem.
You could also embed the PTX as a resource directly into your C# application.
You could also compile into a cubin and load or embed that instead of PTX.

Categories