gpt4 book ai didi

c++ - OCX AfxOleRegisterTypeLib失败,错误0x80040200

转载 作者:太空宇宙 更新时间:2023-11-04 12:32:42 28 4
gpt4 key购买 nike

我将OCX库从VS2010 / Win7升级到VS2019 / Win10。该项目生成,但是当我尝试从提升的命令提示符下使用RegSvr32.exe时,收到错误0x0040200。我做了一些调试,令人讨厌的调用是对AfxOleRegisterTypeLib的调用。

RegSvr32.exe OCX error 0x80040200

是的,我看到了this SO文章,内容为“dll附近没有tlb文件”。其他搜索状态从管理命令提示符运行。

我在OCX控件附近没有TLB。如果我尝试使用tlbexp.exe创建一个,则会出现以下错误:

TlbExp : error TX0000 : Could not load file or assembly 'file:///C:\pathto.ocx' or one of its dependencies. The module was expected to contain an assembly manifest.



TlbExp命令行(用于所有cmd.exe以管理员身份运行):
"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7.2 Tools\x64\tlbexp.exe" /VERBOSE "<path to OCX file>" /out:"<path to .tlb output file>"

我下载了 Resource Tuner,它很好地显示了 list 。 list 没有任何TLB信息。

Manifest for OCX file

我认为OCX list 可能需要更多帮助 TlbExp获得其所需信息的信息,只是一个想法。
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="DriveOps.ocx"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
</assembly>

我确实使用了 Depends64(又名 Dependency Walker 64-bit),并且没有缺少的组件DLL。它很好地找到了所有这些文件,就像RegSvr32.exe一样。

Dependency Walker 64 output of 64-bit OCX (debug version)

将OCX文件放在C:\ Windows \ System32中无济于事。

对于任何查看DLL的人来说,这些相同的DLL在Win7机器上都可以正常工作。这是有关非Windows DLL的更多信息
  • PlxApi720_x64.dll:PLX v7.2 API(Broadcom PLX芯片是一个PCIe交换机(认为USB /网络交换机,仅带有PCIe通道)
  • LSIDirectAccess.dll:LSI API是一个自包含的DLL,它使软件可以与LSI HBA RAID适配器
  • 进行通信
  • Ipp * .dll:Ipp前缀是Intel Code Composer Studio重新分发(x64)文件(此处为2011年版本)所使用的DLL,这是一个较旧的文件,需要更新为最新和最大的文件,更不用说现在的免费API。这些都在System32文件夹中。

  • 这是代码:
    // DllRegisterServer - Adds entries to the system registry
    STDAPI DllRegisterServer(void)
    {
    AFX_MANAGE_STATE(_afxModuleAddrThis);

    if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
    return ResultFromScode(SELFREG_E_TYPELIB); // <- failure line, through debugging

    if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
    return ResultFromScode(SELFREG_E_CLASS);

    return NOERROR;
    }

    就像在Win7框中一样, Intel Code Composer Studio 2011文件位于 C:\Windows\System32目录中。

    值得一提的是, TlbExp在Win7框上也失败了,只是注册了,这可能就是UI可以添加控件的原因。我记得,我曾经在Win7项目上替换过OCX,而VS201 0 auto 创建了TLB,并在前面加上了Ax,但这是几年前的事,所以我的记忆可能不是最准确的。尝试将OCX添加到UI(.Net WinForms)失败了,只是说无法添加。

    OCX确实使用了最新的平台工具集( Visual Studio 2019 (v142))。

    OCX property page

    对于开发人员新手, regasm.exe是.Net汇编的注释。 RegSvr32.exe用于 ActiveX Controls (OCX/DLL),这就是我所拥有的。 RegSvr32用于动态加载的模块,因此适用于DllRegister入口点。

    有什么想法吗?

    进一步测试的注意事项
  • (2019年9月21日星期六)升级时,我创建了一个空的C++ DLL项目,然后添加了所有文件,将目标扩展名更改为OCX,以进行旧项目设置,并在需要时合理地将它们与新项目文件对齐保持不变。我想做一个测试,看看一个全新的OCX项目会发生什么。我看到VS2019中的项目类型有诸如“MFC ActiveX控件”之类的东西。我创建了该文件,并看到了不同的基本文件,但更重要的是RegSvr32.exe可以运行。这意味着错误是最初的项目文件,因此,如果可能的话,我需要导入到一个干净的项目中或逐个导入,然后看看有什么地方出错。
  • (2019年9月21日星期六)新的测试项目没有 list 文件,并且TlbExp.exe失败,并显示了与我的真实项目相同的错误消息。我去添加新物品,看到了“包装 list ”。该 list 文件尽管仍会产生相同的TlbExp.exe错误,但与上面的应用程序 list 文件看起来有很大不同。我创建了另一个新的MFC ActiveX Control项目,并从上面添加了 list ,只是更改了名称,然后看到该项目拒绝构建并抛出1)错误c1010001属性“level”的值在不同的 list 片段中不相等。和2)在运行mt.exe期间LNK1327失败。这告诉我原始的Win7项目和我的Win10项目文件中可能有一些错误,否则VS应该向我抛出了这些错误。这不能回答为什么即使在测试项目上TlbExp.exe也会失败的原因。 list 中的某些属性可能是必需的。我只是保留了默认值。

  • 包装 list
    (这是我第一次看到其中之一。我总是看到app.manifest类型。)
    <?xml version="1.0" encoding="utf-8"?>
    <!-- TODO: Make sure to set the Package attributes -->
    <Package xmlns="urn:Microsoft.WindowsPhone/PackageSchema.v8.00"
    Owner=""
    OwnerType="OEM"
    Platform=""
    Component=""
    SubComponent="Package"
    ReleaseType="Test" >

    <Components>
    <Driver InfSource="$(_RELEASEDIR)$(TARGETNAME).inf">
    <Reference Source="$(_RELEASEDIR)$(TARGETNAME)$(TARGETEXT)" />
    <Files>
    <!-- For kernel mode drivers, $(DRIVER_DEST) evaluates to "drivers" by default -->
    <!-- For user mode drivers, $(DRIVER_DEST) evaluates to "drivers\umdf" by default -->
    <File Source="$(_RELEASEDIR)$(TARGETNAME)$(TARGETEXT)" DestinationDir="$(runtime.system32)\$(DRIVER_DEST)" />
    </Files>
    </Driver>

    </Components>
    </Package>
  • article有一种有趣的方法,即创建一个C++ DLL,然后调用LoadLibrary(dll),然后调用GetProcAddress(module, "DllRegisterServer")以查看哪个失败。好吧,就我而言,这两个功能都成功了。这意味着作者错过了另一个失败分支,这两个API调用并不是RegSvr32.exe唯一要做的。
  • 最佳答案

    尽管我还没有走到尽头,但由于OCX上存在aximp.exe / tlbimp.exe问题,所以我发现了导致我无法注册ActiveX控件的问题。

    答案是主CPP文件中的GUID:

    (我正在做研究,因为我找不到任何人解释RegSvr32.exe的工作原理和作用。我想与大家分享,希望它对其他人有帮助。)

    const GUID CDECL _tlid = { 0xFE5C7D88,0xD53C,0x4977,{0xBA,0x56,0x4B,0xF3,0x02,0x0A,0x5D,0x8A} };

    在主要注册函数 STDAPI DllRegisterServer(void)中使用的代码必须与IDL中存在的 GUID匹配:
    [uuid(FE5C7D88-D53C-4977-BA56-4BF3020A5D8A), version(1.0),
    helpfile("DriveOps.hlp"),
    helpstring("DriveOps ActiveX Control module"),
    control]
    library DriveOpsLib
    {
    ...
    }

    我有2个不同的值,因此失败了。

    这是我用来发现问题的方法和研究,但首先我要说明注册功能,因为这又是关键。
    STDAPI DllRegisterServer(void)
    {
    AFX_MANAGE_STATE(_afxModuleAddrThis);

    HINSTANCE hiTypeLib = AfxGetInstanceHandle();

    if (!AfxOleRegisterTypeLib(hiTypeLib, _tlid))
    return ResultFromScode(SELFREG_E_TYPELIB);

    if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
    return ResultFromScode(SELFREG_E_CLASS);

    return NOERROR;
    }

    正如我在问题中提到的那样,失败是在这条线上。
    if (!AfxOleRegisterTypeLib(hiTypeLib, _tlid))

    我已经在互联网上找到 RegSvr32.exe的源代码。它是位于 GitHub中的Microsoft VCSamples-master源的一部分。

    直接链接到 RegSvr32.exe: here

    直接下载zip的链接: here

    该代码是一种死胡同,因为它告诉我什么应该是显而易见的,即该实用程序调用了DLL的 DllRegisterServer入口点来完成所有工作。我应该知道这一点,但是,好吧,我必须看到它才有意义。

    使用 procmon.exe并没有发现任何问题,并且对注册表的各种调用就像阅读外语一样,没有帮助。

    在这里我画了一个空白,直到我想到获取 AfxOleRegisterTypeLib的源代码,因为那是失败的。我想看看这件事做了什么,以及源文件 ctlreg.cpp的第113行是什么。

    我仍在考虑 procmon的注释和注册表问题,但我认为该代码可以告诉我哪个。我花了一些时间进行研究,但发现了 code。我喜欢Microsoft共享代码。他们的错误消息没有帮助,但是能够真正看到他们试图这样做的情况完全有帮助。

    这是代码:
    BOOL AFXAPI AfxOleRegisterTypeLib(HINSTANCE hInstance, REFGUID tlid,
    LPCTSTR pszFileName, LPCTSTR pszHelpDir)
    {
    USES_CONVERSION;

    BOOL bSuccess = FALSE;
    CString strPathName;
    TCHAR *szPathName = strPathName.GetBuffer(_MAX_PATH);
    ::GetModuleFileName(hInstance, szPathName, _MAX_PATH);
    strPathName.ReleaseBuffer();
    LPTYPELIB ptlib = NULL;

    // If a filename was specified, replace final component of path with it.
    if (pszFileName != NULL)
    {
    int iBackslash = strPathName.ReverseFind('\\');
    if (iBackslash != -1)
    strPathName = strPathName.Left(iBackslash+1);
    strPathName += pszFileName;
    }

    if (SUCCEEDED(LoadTypeLib(T2COLE(strPathName), &ptlib)))
    {
    ASSERT_POINTER(ptlib, ITypeLib);

    LPTLIBATTR pAttr;
    GUID tlidActual = GUID_NULL;

    if (SUCCEEDED(ptlib->GetLibAttr(&pAttr)))
    {
    ASSERT_POINTER(pAttr, TLIBATTR);
    tlidActual = pAttr->guid;
    ptlib->ReleaseTLibAttr(pAttr);
    }

    // Check that the guid of the loaded type library matches
    // the tlid parameter.
    ASSERT(IsEqualGUID(tlid, tlidActual));

    if (IsEqualGUID(tlid, tlidActual))
    {
    // Register the type library.
    if (SUCCEEDED(RegisterTypeLib(ptlib, T2OLE((LPTSTR)(LPCTSTR)strPathName), T2OLE((LPTSTR)pszHelpDir))))
    bSuccess = TRUE;
    }

    RELEASE(ptlib);
    }
    else
    {
    TRACE1("Warning: Could not load type library from %s\n", (LPCTSTR)strPathName);
    }

    return bSuccess;
    }

    我一直收到 ASSERT,因此尽管第113行确实在非代码行上,但实际失败是显而易见的。我知道我没有在 ASSERT_POINTER上失败,因为该错误消息是不同的,这意味着我失败了:
            ASSERT(IsEqualGUID(tlid, tlidActual));

    我详细查看了代码以及入口参数。我决定将此函数内容复制并粘贴到OCX中的真实注册代码中,以便在调试时获得进一步的可见性。我想看看这些值。

    果然,我看到了2个不同的 GUID值,其中一个是顶部的 _tlid,另一个是从实例句柄返回的值。我拿出了方便的 TextPad文本编辑器,尽管 Visual Studio具有 Find in Files,但是TextPad更加易于使用。这导致了整个解决方案中的另一个实例,即 DriveOps.idl。直到那一刻,该文件对我都没有任何意义,但是突然我发现这里的 GUIDRegSvr32.exe从实例句柄中提取的。

    我统一了ID,对其进行了重建,现在 RegSvr32.exe不再抱怨了。是的,自从我有了代码后,除了注册外别无选择。据我所知,它不修改注册表是一个不同的故事和问题,但这是另一个问题。 RegSvr32.exe现在注册,无需投诉。

    (是的,我仍然有 tlbimp.exeaximp.exe,并将OCX项目添加到我的 WinForms项目问题中,但是在过程中我发现了这件事并学到了一些东西。我猜行号的不同可能是Microsoft对 header 所做的一些更改,无论哪种方式,功能看起来都是一样的。)

    关于c++ - OCX AfxOleRegisterTypeLib失败,错误0x80040200,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58036192/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com