C++ 非托管 程序调用托管程序
2010-01-26 13:43
211 查看
This is a sample native console application which will query the registry to verify if a specific version of the .NET Framework is installed. It will then use the CorBindToRuntimeEx API to load a specific version of the Common Language Runtime (CLR). Finally, it uses the Interfaces and methods exposed in mscorlib.tlb to load an assembly and type and execute methods.
Create a new C++ Console application named CheckCLR and replace the code in CheckCLR.cpp with the following code:
/*
CheckCLR.cpp - A Native Code CLR Host Sample
CheckCLR is a native console application which queries the registry to
determine if a specific version of the .NET runtime is installed on the
machine. It then loads the specific CLR required.
It will then load a managed console app and execute the Main method.
It then loads a managed assembly and executes a method.
*/
#include "stdafx.h"
#include <windows.h>
#include <mscoree.h>
#include <assert.h>
#include <stdio.h>
#include <tchar.h>
// Import mscorlib typelib. Using 1.0 for maximum backwards compatibility
#import "C:\windows\Microsoft.NET\Framework\v1.0.3705\mscorlib.tlb" auto_rename
// Link with mscoree.dll import lib.
#pragma comment(lib,"mscoree.lib")
using namespace mscorlib;
int _tmain(int argc, _TCHAR* argv[])
{
//
// Query 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5\Install' DWORD value
// See http://support.microsoft.com/kb/318785/ (http://support.microsoft.com/kb/318785/) for more information on .NET runtime versioning information
//
HKEY key = NULL;
DWORD lastError = 0;
lastError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5"),0,KEY_QUERY_VALUE,&key);
if(lastError!=ERROR_SUCCESS) {
_putts(TEXT("Error opening HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5"));
return 1;
}
DWORD type;
BYTE data[4];
DWORD len = sizeof(data);
lastError = RegQueryValueEx(key,TEXT("Install"),NULL,&type,data,&len);
if(lastError!=ERROR_SUCCESS) {
RegCloseKey(key);
_putts(TEXT("Error querying HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5\\Install"));
return 2;
}
RegCloseKey(key);
// Was Install DWORD key value == 1 ??
if(data[0]==1)
_putts(TEXT(".NET Framework 3.5 is installed"));
else {
_putts(TEXT(".NET Framework 3.5 is NOT installed"));
return 3;
}
//
// Load the runtime the 3.5 Runtime (CLR version 2.0)
//
LPWSTR pszVer = L"v2.0.50727"; // .NET Fx 3.5 needs CLR 2.0
LPWSTR pszFlavor = L"wks";
ICorRuntimeHost *pHost = NULL;
HRESULT hr = CorBindToRuntimeEx( pszVer,
pszFlavor,
STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN | STARTUP_CONCURRENT_GC,
CLSID_CorRuntimeHost,
IID_ICorRuntimeHost,
(void **)&pHost);
if (!SUCCEEDED(hr)) {
_tprintf(TEXT("CorBindToRuntimeEx failed 0x%x\n"),hr);
return 1;
}
_putts(TEXT("Loaded version 2.0.50727 of the CLR\n"));
pHost->Start(); // Start the CLR
//
// Get a pointer to the default domain in the CLR
//
_AppDomainPtr pDefaultDomain = NULL;
IUnknownPtr pAppDomainPunk = NULL;
hr = pHost->GetDefaultDomain(&pAppDomainPunk);
assert(pAppDomainPunk);
hr = pAppDomainPunk->QueryInterface(__uuidof(_AppDomain),(void**) &pDefaultDomain);
assert(pDefaultDomain);
//
// Load an Exe Assembly and call Main()
//
_bstr_t bstrExeName = L"ConsoleApplication1.exe";
try {
hr = pDefaultDomain->ExecuteAssembly_2(bstrExeName);
}
catch(_com_error& error) {
_tprintf(TEXT("ERROR: %s\n"),(_TCHAR*)error.Description());
goto exit;
}
/*
Load a type from a DLL Assembly and call it
Doing the same thing from native code as this C# code:
System.Runtime.Remoting.ObjectHandle objptr;
objptr = AppDomain.CurrentDomain.CreateInstanceFrom("ClassLibrary1.dll",
"ClassLibrary1.Class1");
object obj = objptr.Unwrap();
Type t = obj.GetType();
t.InvokeMember("Test",
BindingFlags.InvokeMethod,
null,
obj,
new object[0]);
*/
try {
_ObjectHandlePtr pObjectHandle;
_ObjectPtr pObject;
_TypePtr pType;
SAFEARRAY* psa;
// Create an instance of a type from an assembly
pObjectHandle = pDefaultDomain->CreateInstanceFrom(L"ClassLibrary1.dll", // no path -- local directory
L"ClassLibrary1.Class1");
variant_t vtobj = pObjectHandle->Unwrap(); // Get an _Object (as variant) from the _ObjectHandle
vtobj.pdispVal->QueryInterface(__uuidof(_Object),(void**)&pObject); // QI the variant for the Object iface
pType = pObject->GetType(); // Get the _Type iface
psa = SafeArrayCreateVector(VT_VARIANT,0,0); // Create a safearray (0 length)
pType->InvokeMember_3("Test", // Invoke "Test" method on pType
BindingFlags_InvokeMethod,
NULL,
vtobj,
psa );
SafeArrayDestroy(psa); // Destroy safearray
}
catch(_com_error& error) {
_tprintf(TEXT("ERROR: %s\n"),(_TCHAR*)error.Description());
goto exit;
}
exit:
pHost->Stop();
pHost->Release();
return 0;
}
/*** End of file CheckCLR.cpp ***/
Create a C# Console Application named ConsoleApplication1. Add a Console.WriteLine call in the Main method and output a simple string message. Build ConsoleApplication1. Copy the ConsoleApplication1.exe build target to the ouput directory where CheckCLR.exe is built. Alternatively, you can change the code above to have the full path name to where ConsoleApplication1.exe is built.
Create a C# Class Library named ClassLibrary1. In the Class1 class, add a public method named Test. In Test, add a Console.WriteLine call and output a simple string message. Build ClassLibrary1.dll. Copy the ClassLibrary1.dll build target to the outut directory where CheckCLR.exe is built. Alternatively, you can change the code above to have the full path name to where ClassLibrary1.dll is built.
After building CheckCLR, you should should be able to run CheckCLR.exe from a command prompt and see the output of the Console.WriteLine calls:
.NET Framework 3.5 is installed
Loaded version 2.0.50727 of the CLR
Hello World from ConsoleApplication1.Main
Hello World from ClassLibrary1.Class1
If running CheckCLR.exe under the debugger from your Visual C++ project, you may get could not load file or assembly error messages. In that case, copy ConsoleApplication1.exe and ClassLibrary1.dll to the folder containing the CheckCLR.sln solution file. The debugger uses that folder as the application default directory.
Create a new C++ Console application named CheckCLR and replace the code in CheckCLR.cpp with the following code:
/*
CheckCLR.cpp - A Native Code CLR Host Sample
CheckCLR is a native console application which queries the registry to
determine if a specific version of the .NET runtime is installed on the
machine. It then loads the specific CLR required.
It will then load a managed console app and execute the Main method.
It then loads a managed assembly and executes a method.
*/
#include "stdafx.h"
#include <windows.h>
#include <mscoree.h>
#include <assert.h>
#include <stdio.h>
#include <tchar.h>
// Import mscorlib typelib. Using 1.0 for maximum backwards compatibility
#import "C:\windows\Microsoft.NET\Framework\v1.0.3705\mscorlib.tlb" auto_rename
// Link with mscoree.dll import lib.
#pragma comment(lib,"mscoree.lib")
using namespace mscorlib;
int _tmain(int argc, _TCHAR* argv[])
{
//
// Query 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5\Install' DWORD value
// See http://support.microsoft.com/kb/318785/ (http://support.microsoft.com/kb/318785/) for more information on .NET runtime versioning information
//
HKEY key = NULL;
DWORD lastError = 0;
lastError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5"),0,KEY_QUERY_VALUE,&key);
if(lastError!=ERROR_SUCCESS) {
_putts(TEXT("Error opening HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5"));
return 1;
}
DWORD type;
BYTE data[4];
DWORD len = sizeof(data);
lastError = RegQueryValueEx(key,TEXT("Install"),NULL,&type,data,&len);
if(lastError!=ERROR_SUCCESS) {
RegCloseKey(key);
_putts(TEXT("Error querying HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5\\Install"));
return 2;
}
RegCloseKey(key);
// Was Install DWORD key value == 1 ??
if(data[0]==1)
_putts(TEXT(".NET Framework 3.5 is installed"));
else {
_putts(TEXT(".NET Framework 3.5 is NOT installed"));
return 3;
}
//
// Load the runtime the 3.5 Runtime (CLR version 2.0)
//
LPWSTR pszVer = L"v2.0.50727"; // .NET Fx 3.5 needs CLR 2.0
LPWSTR pszFlavor = L"wks";
ICorRuntimeHost *pHost = NULL;
HRESULT hr = CorBindToRuntimeEx( pszVer,
pszFlavor,
STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN | STARTUP_CONCURRENT_GC,
CLSID_CorRuntimeHost,
IID_ICorRuntimeHost,
(void **)&pHost);
if (!SUCCEEDED(hr)) {
_tprintf(TEXT("CorBindToRuntimeEx failed 0x%x\n"),hr);
return 1;
}
_putts(TEXT("Loaded version 2.0.50727 of the CLR\n"));
pHost->Start(); // Start the CLR
//
// Get a pointer to the default domain in the CLR
//
_AppDomainPtr pDefaultDomain = NULL;
IUnknownPtr pAppDomainPunk = NULL;
hr = pHost->GetDefaultDomain(&pAppDomainPunk);
assert(pAppDomainPunk);
hr = pAppDomainPunk->QueryInterface(__uuidof(_AppDomain),(void**) &pDefaultDomain);
assert(pDefaultDomain);
//
// Load an Exe Assembly and call Main()
//
_bstr_t bstrExeName = L"ConsoleApplication1.exe";
try {
hr = pDefaultDomain->ExecuteAssembly_2(bstrExeName);
}
catch(_com_error& error) {
_tprintf(TEXT("ERROR: %s\n"),(_TCHAR*)error.Description());
goto exit;
}
/*
Load a type from a DLL Assembly and call it
Doing the same thing from native code as this C# code:
System.Runtime.Remoting.ObjectHandle objptr;
objptr = AppDomain.CurrentDomain.CreateInstanceFrom("ClassLibrary1.dll",
"ClassLibrary1.Class1");
object obj = objptr.Unwrap();
Type t = obj.GetType();
t.InvokeMember("Test",
BindingFlags.InvokeMethod,
null,
obj,
new object[0]);
*/
try {
_ObjectHandlePtr pObjectHandle;
_ObjectPtr pObject;
_TypePtr pType;
SAFEARRAY* psa;
// Create an instance of a type from an assembly
pObjectHandle = pDefaultDomain->CreateInstanceFrom(L"ClassLibrary1.dll", // no path -- local directory
L"ClassLibrary1.Class1");
variant_t vtobj = pObjectHandle->Unwrap(); // Get an _Object (as variant) from the _ObjectHandle
vtobj.pdispVal->QueryInterface(__uuidof(_Object),(void**)&pObject); // QI the variant for the Object iface
pType = pObject->GetType(); // Get the _Type iface
psa = SafeArrayCreateVector(VT_VARIANT,0,0); // Create a safearray (0 length)
pType->InvokeMember_3("Test", // Invoke "Test" method on pType
BindingFlags_InvokeMethod,
NULL,
vtobj,
psa );
SafeArrayDestroy(psa); // Destroy safearray
}
catch(_com_error& error) {
_tprintf(TEXT("ERROR: %s\n"),(_TCHAR*)error.Description());
goto exit;
}
exit:
pHost->Stop();
pHost->Release();
return 0;
}
/*** End of file CheckCLR.cpp ***/
Create a C# Console Application named ConsoleApplication1. Add a Console.WriteLine call in the Main method and output a simple string message. Build ConsoleApplication1. Copy the ConsoleApplication1.exe build target to the ouput directory where CheckCLR.exe is built. Alternatively, you can change the code above to have the full path name to where ConsoleApplication1.exe is built.
Create a C# Class Library named ClassLibrary1. In the Class1 class, add a public method named Test. In Test, add a Console.WriteLine call and output a simple string message. Build ClassLibrary1.dll. Copy the ClassLibrary1.dll build target to the outut directory where CheckCLR.exe is built. Alternatively, you can change the code above to have the full path name to where ClassLibrary1.dll is built.
After building CheckCLR, you should should be able to run CheckCLR.exe from a command prompt and see the output of the Console.WriteLine calls:
.NET Framework 3.5 is installed
Loaded version 2.0.50727 of the CLR
Hello World from ConsoleApplication1.Main
Hello World from ClassLibrary1.Class1
If running CheckCLR.exe under the debugger from your Visual C++ project, you may get could not load file or assembly error messages. In that case, copy ConsoleApplication1.exe and ClassLibrary1.dll to the folder containing the CheckCLR.sln solution file. The debugger uses that folder as the application default directory.
相关文章推荐
- C#调用C++的dll两种方法(托管与非托管)
- c++ 非托管程序调用c#托管程序l的实现操作方式
- C# CLRInsideOut 托管代码与非托管代码互操作,产生相关调用代码的好工具 C++ 头文件转C# 的好工具(转
- C#调用C++的dll两种方法(托管与非托管)
- C# CLRInsideOut 托管代码与非托管代码互操作,产生相关调用代码的好工具 C++ 头文件转C# 的好工具
- c# 调用 研华库函数中 C++ 非托管 Dll 一例(包含指针成员的结构体的调用)
- 《对“XXX::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们》的问题的解决方法
- C# DllImport“调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配 ”
- C#托管代码与C++非托管代码互相调用
- c# 调用 研华库函数中 C++ 非托管 Dll 一例(包含指针成员的结构体的调用)
- 同一程序中混合调用C和C++代码
- 如果C++程序要调用已经被编译后的C函数,该怎么办?
- 非托管环境语言(c,c++)和托管环境语言(c#,java)的编译过程差别
- Windows命令行调用微软cl编译C/C++程序
- C++调用IDL程序的做法(一)
- C++调用IDL程序的做法(二)
- C++ win32 dll 引用外部CLR,加载托管程序集异常-Error 10 error LNK2019: unresolved external symbol _CLRCreateInstancet
- C#对于C++程序方法的调用
- 使用c++/CLI实现c++托管与非托管混合编程
- Java通过JNI调用C++程序