C# 正在注册的类上获取未注册的类80041054
我正在从非托管代码调用CoCreateInstance到已注册的托管类(HKEY_CLASSES_ROOT\CLSID{xxxxx-xxxxxx-xxxxxx-xxxxx-xxxxxx-xxxxx}注册表项存在,并且该文件已从另一个程序正确加载 代码如下:C# 正在注册的类上获取未注册的类80041054,c#,c++,com,C#,C++,Com,我正在从非托管代码调用CoCreateInstance到已注册的托管类(HKEY_CLASSES_ROOT\CLSID{xxxxx-xxxxxx-xxxxxx-xxxxx-xxxxxx-xxxxx}注册表项存在,并且该文件已从另一个程序正确加载 代码如下: HRESULT hRC; CoInitialize(NULL); char* sUTProgID = "My.Utilities"; CLSID UTClassID; hRC = CLSIDFrom
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
}
同样的代码适用于其他应用程序。该代码是为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-success(返回文件路径)
然后它检查GAC缓存,然后在访问DLL之前检查几个目录
CLIENT.EXE 1092 RegQueryKey HKCR\CLSID{…}成功查询:Name
CLIENT.EXE 1092 RegOpenKey HKCR\CLSID{…}\InprocHandler NAME未找到所需的访问权限:允许的最大值
CLIENT.EXE 1092 RegCloseKey HKCR\CLSID{9935FEE6-39FD-4EF0-87DB-8372b092610}成功
找不到CLIENT.EXE 1092 RegOpenKey HKLM\Software\Policies\Microsoft\Windows\App Management NAME所需访问权限:查询值
CLIENT.EXE 1092 CreateFile LogFile.txt
我认为这是记录错误的最后一条日志消息
编辑2:
Dll是使用以下代码注册的:
Assembly asm = Assembly.LoadFile(dll_name);
RegistrationServices regAsm = new RegistrationServices();
bool bResult = regAsm.RegisterAssembly(asm, AssemblyRegistrationFlags.SetCodeBase);
编辑3:
在(my)失败的DLL输出上运行CorFlags.exe:
Version : v2.0.50727
CLR Header: 2.5
PE : PE32
CorFlags : 11
ILONLY : 1
32BIT : 1
Signed : 1
Version : v1.1.4322
CLR Header: 2.0
PE : PE32
CorFlags : 9
ILONLY : 1
32BIT : 0
Signed : 1
在调用DLL输出的EXE上运行相同的命令:
Version : v2.0.50727
CLR Header: 2.5
PE : PE32
CorFlags : 11
ILONLY : 1
32BIT : 1
Signed : 1
Version : v1.1.4322
CLR Header: 2.0
PE : PE32
CorFlags : 9
ILONLY : 1
32BIT : 0
Signed : 1
在EXE上运行相同的
存在CLR版本不匹配问题。EXE以.NET 1.1为目标,将加载CLR的v1.1版本。该版本无法加载DLL,它以.NET 2.0到3.5中使用的CLR的v2版本为目标
一种解决方法是编写一个.config文件,强制使用正确版本的CLR。将其与名为somefile.exe.config的.exe文件放在同一目录中,将“somefile”替换为.exe文件名:
<configuration>
<startup>
<supportedRuntime version="v2.0.50757"/>
</startup>
</configuration>
如果失败,那是因为它缺少所需的注册。这有多种原因:x86对x64(请参见此处的SMS),以及安全性(注册表权限、UAC激活等)。我建议您使用sysinternals procmon来监视访问了哪些注册表项。您应该能够发现问题。您应该跟踪CLSIDFromProgID返回的classid。可能不是您认为的那样。@manuell感谢您的建议-尝试过,但没有产生任何意外。更新后的问题到Reflect都是应用程序以相同的位(32或64位)运行?程序集是否标记为“两者”或32/64特定?需要检查的事项还有:正在使用的.net运行时版本(请尝试在配置中显式设置),检查CoInitializeX并查找公寓模型。是的,这很有意义,感谢您的帮助。不幸的是,调用exe第三方legacy并将该标记放入配置中会导致它崩溃。还有其他解决方法吗?嗯,我至少可以想到3种方法,其中没有一种涉及到按下按钮来解决您的问题。这个按钮已经按下11年了,它肯定已经完全磨损了。如果你想再按下一次,你必须做一个比“它崩溃了”更好的选择是的,我的观点是正确的,很抱歉缺少有用的信息-我将尝试调试它。不幸的是,这是一台prod机器,运行kiosk软件,其中缺少了一些有用的东西,如explorer,所以这不是简单的事情。谢谢你的回答-我将其标记为正确,并奖励奖金,因为它确实让我解决了这个问题提高。