我正在将非托管代码中的CoCreateInstance调用到已注册的托管类中(HKEY_CLASSES_ROOT \ CLSID {xxxxx-xxxxxx-xxxxxx-xxxxx-xxxxxx-xxxxx}注册表项存在,并且已从另一个程序正确加载了文件。
代码如下:
HRESULT hRC;
CoInitialize(NULL);
char* sUTProgID = "My.Utilities";
CLSID UTClassID;
hRC = CLSIDFromProgID(
_CW(sUTProgID), // Pointer to the ProgID
&UTClassID ); // Pointer to the CLSID
if ( S_OK != hRC )
{
DOTRACE((_T(" CLSIDFromProgID error 0x%X\n", hRC)));
}
IUnknown* pUnknown;
hRC = CoCreateInstance(
UTClassID, // Class identifier (CLSID) of the object
0, // Pointer to whether object is or isn't part of an aggregate
CLSCTX_ALL, // Context for running executable code
IID_IUnknown, // Reference to the identifier of the interface
(void**) &pUnknown); // Address of output variable that receives the interface pointer requested in riid
if ( S_OK != hRC )
{
//code makes it here with an 80040145 class not registered error
}
Run Code Online (Sandbox Code Playgroud)
相同的代码适用于其他应用程序。该代码针对x86进行编译,并在x86机器上运行。
编辑:这是一台Windows XP机器,所以我认为UAC已退出。我已经记录了ClassID,它的确是正确的。我还检查了ProcMon日志,它显示成功访问了注册表项,并且在注册表项内访问了以下路径:InProcServer32-成功InProcServerx86-找不到名称LocalServer32-找不到名称InProcHandler32-找不到名称AppId-找不到名称找到InProcServer32 \ ThreadingModel-成功InProcServer32 \ 1.0.0.0-成功InProcServer32 \ 1.0.0.0 \ assembly-缓冲区溢出InProcServer32 \ 1.0.0.0 \ assembly-成功InProcServer32 \ 1.0.0.0 \ class-成功InProcServer32 \ 1.0.0.0 \ RuntimeVersion-成功InProcServer32 \ CodeBase-成功(返回文件路径)
然后在访问DLL之前先检查GAC缓存,然后检查几个目录。
CLIENT.EXE 1092 RegQueryKey HKCR \ CLSID {...}成功查询:名称CLIENT.EXE 1092 RegOpenKey HKCR \ CLSID {...} \ InprocHandler名称找不到所需的访问量:允许的最大值CLIENT.EXE 1092 RegCloseKey HKCR \ CLSID {9935FEE6 -39FD-4EF0-87DB-8372B0992610} SUCCESS CLIENT.EXE 1092 RegOpenKey HKLM \ Software \ Policies \ Microsoft \ Windows \ App Management找不到所需的名称:查询值CLIENT.EXE 1092 CreateFile LogFile.txt
我认为这是记录错误的最后一条日志消息。
EDIT2:使用以下代码注册Dll:
Assembly asm = Assembly.LoadFile(dll_name);
RegistrationServices regAsm = new RegistrationServices();
bool bResult = regAsm.RegisterAssembly(asm, AssemblyRegistrationFlags.SetCodeBase);
Run Code Online (Sandbox Code Playgroud)
EDIT3:在(我)失败的DLL输出上运行CorFlags.exe:
Version : v2.0.50727
CLR Header: 2.5
PE : PE32
CorFlags : 11
ILONLY : 1
32BIT : 1
Signed : 1
Run Code Online (Sandbox Code Playgroud)
在调用DLL的EXE上运行相同的命令:
Version : v1.1.4322
CLR Header: 2.0
PE : PE32
CorFlags : 9
ILONLY : 1
32BIT : 0
Signed : 1
Run Code Online (Sandbox Code Playgroud)
在 EXE 上运行相同的...
您遇到 CLR 版本不匹配问题。该 EXE 以 .NET 1.1 为目标,并将加载 v1.1 版本的 CLR。该版本无法加载 DLL,它的目标是 CLR v2 版本,即 .NET 2.0 到 3.5 中使用的版本
解决方法是编写一个 .config 文件,强制使用正确版本的 CLR。将其放在与 .exe 相同的目录中,名称为 somefile.exe.config,将“somefile”替换为 .exe 的名称:
<configuration>
<startup>
<supportedRuntime version="v2.0.50757"/>
</startup>
</configuration>
Run Code Online (Sandbox Code Playgroud)