C# 正在注册的类上获取未注册的类80041054

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

我正在从非托管代码调用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
    }
同样的代码适用于其他应用程序。该代码是为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,所以这不是简单的事情。谢谢你的回答-我将其标记为正确,并奖励奖金,因为它确实让我解决了这个问题提高。