none
运行 Inside COM 最后一个例子失败 RRS feed

  • 问题

  • 大家好,

    出于学习的目的我翻了翻 Inside COM 这本书. 现在正在尝试编译运行作者在第13章给出的示例程序 - TANGRAM

    由于作者提供的是 VC 6.0 的项目文件. 我做了必要的改变使其能在 VS2013 上编译. 没有改变源码.

    这个程序以 Tangram.exe 作为 Client.

    生成的 Canvas.dll, GdiWrld.dll, GlWrld.dll 都是 In-process server, Model 有2个版本, 一个是 Model.dll 作为 In-process server, 或者 Model.exe + Proxy.dll 作为 Local Server.

    Tangram.exe 通过使用 Canvas, GdiWrld/GlWrld, Model 组件实现用 Windows GDI 或者 OpenGL 进行2D / 3D图形绘制和操作.

    经过调试, 我现在能够成功生成 Tangram.exe, Canvas.dll, GdiWrld.dll/GlWrld.dll, Model.dll 并让它们组合在一起正常运行.

    但是, 如果我把 Model.dll 替换为 Model.exe + Proxy.dll 便会报错 E_NOINTERFACE (最终导致 CONNECT_E_CANNOTCONNECT ,  HRESULT = 80040202).

    经调试, Tangram.exe 进程 会通过 RPC 请求 Model.exe 进程创建组件 (返回 S_OK), 并调用 QueryInterface IID_ITangramModelEvent 获取接口.

    Model.exe 进程在 CTangramModelEventSink::QueryInterface 查询到接口并返回 S_OK, 但回到 Tangram.exe 进程的调用处 (CConnectionPoint::Advise) 返回值却变成了 E_NOINTERFACE. 最终导致 CTangramGdiVisual::Initialize 中 Advise 返回  CONNECT_E_CANNOTCONNECT, HRESULT = 80040202.

    经测试, 我把作者的 Proxy.dll 拿过来替换掉我自己编译的 Proxy.dll, 一切就运行正常. (其他 DLL 和 EXE 全部是我自己生成的.)

    我把作者提供的 VC 6.0 解决方案迁移到了我使用的 VS2013 解决方案. 解决方案目录如下:

    Tangram>
    CANVAS> // Canvas 项目文件
    COMMON> // 共享的 CPP 和 H 文件
    GDIWRLD> // GdiWrld 项目文件
    GLWRLD> // GlWrld 项目文件
    IDL> // 各个组件的 IDL 文件
    MODEL> // Model 项目文件
    Proxy.mak // 利用 MODEL_I.IDL, MODEL_C.IDL, EVENT_I.IDL, EVENT_C.IDL 生成的 .C 文件构建 Proxy.dll
    Proxy.def // Proxy.dll 的 .DEF 文件
    ... // 其他文件
    SHARE> // IDL 文件生成 .C 和 .H 文件的临时目录
    TANGRAM> // Tangram 项目文件

    构建过程如下. 
    首先运行 MIDL 编译所有的 IDL 文件, 
    然后运行 NMAKE 生成 Proxy.dll,
    最后把解决方案配置选择为 "Local Server", 生成其他的 DLL 和 EXE.
    然后把所有的生成 DLL 和 EXE 放到一个目录下, 运行作者提供的 REGISTER.BAT 注册组件.
    最后运行 Tangram.exe, 选择 "Local Server".

    我到底在哪里做错了? 能否帮我看看问题在哪里?

    谢谢大家的帮助!


    下载地址(OneDrive):

    作者提供的 DLL 和 EXE

    https://onedrive.live.com/redir?resid=35B1796075417EEE!107&authkey=!AA93r97h8XxR8_Q&ithint=file%2czip

    作者提供的 VC 6.0 项目文件

    https://onedrive.live.com/redir?resid=35B1796075417EEE!156&authkey=!AH_WiJQsC11AUaQ&ithint=file%2czip

    我生成的 DLL 和 EXE

    https://onedrive.live.com/redir?resid=35B1796075417EEE!108&authkey=!AFClTreEaH9BcNQ&ithint=file%2czip

    我的 VS2013 项目文件

    https://onedrive.live.com/redir?resid=35B1796075417EEE!155&authkey=!AHDP_Ohnq4w_DQ8&ithint=file%2czip

    2015年11月30日 13:46

答案

  • 你好,

    我按照你提供的 [https://connect.microsoft.com/VisualStudio/feedback/details/1031687/jsonpackage-did-not-load-correctly], 以及[http://stackoverflow.com/questions/17727872/microsoft-visualstudio-web-pastejson-jsonpackage-did-not-load-properly], 修复了我的VS,但是还是打不开项目,很奇怪。不知道是不是我装了VS2015 和VS2013两个版本在一台机器上。

    我看了你的分析,我觉得你分析的都有道理。尤其是你的dll 里没有idata。从这个问题链接我们可以看到idata 的主要作用http://stackoverflow.com/questions/19012300/whats-the-difference-between-rdata-and-idata-segments

    .rdata is for const data. It is the read only version of the .data segment.

    .idata holds the import directory (.edata for exports). It is used by EXE's and DLL's to designate the imported and exported functions.

    我觉得你重点看一下你在改装6.0项目为2013项目的时候,在组件定义那块查一下,看是否丢失什么内容导致proxy dll 不完整。

    May


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • 已标记为答案 threedts167 2015年12月8日 11:06
    2015年12月2日 8:16

全部回复

  • 你好,

    我下载了你的代码并尝试重现。但是项目在我的VS2013无法打开,你是VS2013 哪个版本的?运行这个程序还需要安装什么吗?

    你可以网上找一个工具可以帮你对比dll 文件差异的,你看下两个dll有什么不同。

    May


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    2015年12月1日 8:55
  • 谢谢你的建议.

    1.

    我的VS2013安装了Qt5的插件. 但是我没有把这个解决方案创建为Qt项目. 除了MFC和OpenGL, 不依赖其他库. 

    我搜索了类似你遇到的问题, 参考[https://connect.microsoft.com/VisualStudio/feedback/details/1031687/jsonpackage-did-not-load-correctly], 以及[http://stackoverflow.com/questions/17727872/microsoft-visualstudio-web-pastejson-jsonpackage-did-not-load-properly], 应该你就可以打开我创建的解决方案了, 可能是因为我最近安装了 Microsoft WebMatrix 以及 IIS 8 Express 而你的计算机上没有安装?

    我的VS2013版本及安装信息如下:

    Microsoft Visual Studio Ultimate 2013
    版本 12.0.21005.1 REL
    Microsoft .NET Framework
    版本 4.5.50938

    已安装的版本: Ultimate

    LightSwitch for Visual Studio 2013   06181-004-0451047-02532
    Microsoft LightSwitch for Visual Studio 2013

    Microsoft Visual Studio 2013 的 Office 开发工具(简体中文)   06181-004-0451047-02532
    Microsoft Visual Studio 2013 的 Office 开发工具(简体中文)

    Visual Basic 2013   06181-004-0451047-02532
    Microsoft Visual Basic 2013

    Visual C# 2013   06181-004-0451047-02532
    Microsoft Visual C# 2013

    Visual C++ 2013   06181-004-0451047-02532
    Microsoft Visual C++ 2013

    Visual F# 2013   06181-004-0451047-02532
    Microsoft Visual F# 2013

    Visual Studio 2013 代码分析拼写检查器   06181-004-0451047-02532
    Microsoft® Visual Studio® 2013 代码分析拼写检查器

    International CorrectSpell™ spelling correction system © 1993 部分版权归 Lernout & Hauspie Speech Products N.V. 所有。保留所有权利。

    The American Heritage® Dictionary of the English Language 第三版,版权所有© 1992 Houghton Mifflin Company。获得 Lernout & Hauspie Speech Products N.V. 的电子版许可。保留所有权利。

    Visual Studio 2013 的团队资源管理器   06181-004-0451047-02532
    Microsoft Visual Studio 2013 的团队资源管理器

    体系结构和建模工具   06181-004-0451047-02532
    Microsoft 体系结构和建模工具
        
    UML(R) 和 Unified Modeling Language(TM) 是 Object Management Group, Inc. 在美国和其他国家/地区的商标或注册商标。

    ASP.NET Web Frameworks and Tools 2012.2   4.1.21001.0
    For additional information, visit http://go.microsoft.com/fwlink/?LinkID=309563

    ASP.NET Web Frameworks and Tools 2013   5.0.11001.0
    For additional information, visit http://www.asp.net/

    Microsoft Web Developer Tools 2013   2.0.40926.0
    Microsoft Web Developer Tools 包含以下组件:
    支持创建和打开 ASP.NET Web 项目
    Browser Link: Visual Studio 与浏览器之间的通信通道
    用于 HTML、CSS 和 JavaScript 的编辑器扩展
    Page Inspector: 用于 ASP.NET Web 项目的检查工具
    基架: 用于构建和运行代码生成器的框架
    用于 Windows Azure 网站的服务器资源管理器扩展
    Web 发布: 用于将 ASP.NET Web 项目发布到托管提供程序、本地服务器或 Windows Azure 的扩展

    NuGet 程序包管理器   2.7.40911.287
    Visual Studio 中的 NuGet 程序包管理器。有关 NuGet 的详细信息,请访问 http://docs.nuget.org/。

    PreEmptive Analytics 可视化工具   1.2
    Microsoft Visual Studio 扩展可以可视化 PreEmptive Analytics 产品的聚合摘要。

    SQL Server Data Tools   12.0.30919.1
    Microsoft SQL Server Data Tools

    Windows Azure 移动服务工具   1.0
    Windows Azure 移动服务工具

    Workflow Manager Tools 1.0   1.0
    此程序包包含 Workflow Manager 的必要 Visual Studio 集成组件。

    通用 Azure 工具   1.0
    通过 Azure 移动服务和 Windows Azure 工具提供通用服务。

    Qt Add-in 1.2.4
    This is Visual Studio Add-in component for Qt. For more information about Qt, see 
    http://qt.digia.com
    Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies)

    2.

    我尝试使用 dumpbin 查看我的 proxy.dll 和 D.Rogerson 提供的 proxy.dll 的不同.

    dumpbin /exports 的结果:

    proxy.dll by Me

    Dump of file proxy.dll
    
    File Type: DLL
    
      Section contains the following exports for Proxy.dll
    
        00000000 characteristics
        565C2CC7 time date stamp Mon Nov 30 19:02:31 2015
            0.00 version
               1 ordinal base
               5 number of functions
               5 number of names
    
        ordinal hint RVA      name
    
              1    0 00001080 DllCanUnloadNow
              2    1 00001000 DllGetClassObject
              3    2 00001160 DllRegisterServer
              4    3 000011D0 DllUnregisterServer
              5    4 000010B0 GetProxyDllInfo
    
      Summary
    
            3000 .data
            1000 .orpc
            5000 .rdata
            1000 .reloc
            C000 .text

    proxy.dll by D.Rogerson

    Dump of file proxy_d_roger.dll
    
    File Type: DLL
    
      Section contains the following exports for Proxy.dll
    
        00000000 characteristics
        3293A804 time date stamp Thu Nov 21 08:53:24 1996
            0.00 version
               1 ordinal base
               5 number of functions
               5 number of names
    
        ordinal hint RVA      name
    
              2    0 00001090 DllCanUnloadNow
              1    1 00001041 DllGetClassObject
              4    2 000010D3 DllRegisterServer
              5    3 00001116 DllUnregisterServer
              3    4 00001000 GetProxyDllInfo
    
      Summary
    
            3000 .data
            1000 .idata
            2000 .orpc
            1000 .rdata
            1000 .reloc
            5000 .text

    这里面最明显的就是我生成的 proxy.dll 没有 idata section. 这会不会是原因之一?

    另外, dumpbin /imports 显示如下

    proxy.dll by Me

    Dump of file proxy.dll
    
    File Type: DLL
    
      Section contains the following imports:
    
        KERNEL32.dll
                  1000E000 Import Address Table
                  10012478 Import Name Table
                         0 time date stamp
                         0 Index of first forwarder reference
    
                      113 DisableThreadLibraryCalls
                       7F CloseHandle
                      5DE WriteConsoleW
                      4FC SetFilePointerEx
                      520 SetStdHandle
                      1EE GetConsoleMode
                      1DC GetConsoleCP
                      192 FlushFileBuffers
                      396 LCMapStringW
                      338 HeapSize
                      3FA OutputDebugStringW
                      2C5 GetStringTypeW
                      336 HeapReAlloc
                      32F HeapAlloc
                      1C8 GetCommandLineA
                      20E GetCurrentThreadId
                      250 GetLastError
                      50A SetLastError
                      121 EncodePointer
                       FE DecodePointer
                      151 ExitProcess
                      266 GetModuleHandleExW
                      29D GetProcAddress
                      3D1 MultiByteToWideChar
                      5CB WideCharToMultiByte
                      2A2 GetProcessHeap
                      2C0 GetStdHandle
                      23E GetFileType
                      105 DeleteCriticalSection
                      2BE GetStartupInfoW
                      262 GetModuleFileNameA
                      333 HeapFree
                      42D QueryPerformanceCounter
                      20A GetCurrentProcessId
                      2D6 GetSystemTimeAsFileTime
                      227 GetEnvironmentStringsW
                      19D FreeEnvironmentStringsW
                      580 UnhandledExceptionFilter
                      541 SetUnhandledExceptionFilter
                      348 InitializeCriticalSectionAndSpinCount
                      550 Sleep
                      209 GetCurrentProcess
                      55F TerminateProcess
                      571 TlsAlloc
                      573 TlsGetValue
                      574 TlsSetValue
                      572 TlsFree
                      267 GetModuleHandleW
                      125 EnterCriticalSection
                      3A2 LeaveCriticalSection
                      372 IsValidCodePage
                      1A4 GetACP
                      286 GetOEMCP
                      1B3 GetCPInfo
                      367 IsDebuggerPresent
                      36D IsProcessorFeaturePresent
                      5DF WriteFile
                      263 GetModuleFileNameW
                      3A7 LoadLibraryExW
                      4AC RtlUnwind
                       C2 CreateFileW
    
        RPCRT4.dll
                  1000E0F8 Import Address Table
                  10012570 Import Name Table
                         0 time date stamp
                         0 Index of first forwarder reference
    
                        4 CStdStubBuffer_DebugServerRelease
                        3 CStdStubBuffer_DebugServerQueryInterface
                        2 CStdStubBuffer_CountRefs
                        7 CStdStubBuffer_IsIIDSupported
                        6 CStdStubBuffer_Invoke
                        5 CStdStubBuffer_Disconnect
                        1 CStdStubBuffer_Connect
                        0 CStdStubBuffer_AddRef
                        8 CStdStubBuffer_QueryInterface
                       11 IUnknown_Release_Proxy
                        F IUnknown_AddRef_Proxy
                       10 IUnknown_QueryInterface_Proxy
                      108 NdrOleFree
                      107 NdrOleAllocate
                       D0 NdrDllUnregisterProxy
                       CF NdrDllRegisterProxy
                       CD NdrDllCanUnloadNow
                       CE NdrDllGetClassObject
                       99 NdrCStdStubBuffer_Release
    
      Summary
    
            3000 .data
            1000 .orpc
            5000 .rdata
            1000 .reloc
            C000 .text
    

    proxy.dll by D.Rogerson

    Dump of file proxy_d_roger.dll
    
    File Type: DLL
    
      Section contains the following imports:
    
        RPCRT4.dll
                  1000C1E0 Import Address Table
                  1000C0C8 Import Name Table
                         0 time date stamp
                         0 Index of first forwarder reference
    
                       EF NdrSimpleStructMarshall
                       77 NdrConformantArrayBufferSize
                       ED NdrSimpleStructBufferSize
                       F1 NdrSimpleStructUnmarshall
                       F8 NdrStubInitialize
                       79 NdrConformantArrayMarshall
                       7B NdrConformantArrayUnmarshall
                       D7 NdrProxyGetBuffer
                       F7 NdrStubGetBuffer
                       D8 NdrProxyInitialize
                       D6 NdrProxyFreeBuffer
                       D9 NdrProxySendReceive
                       90 NdrConvert
                       10 IUnknown_QueryInterface_Proxy
                       66 NdrClearOutParameters
                       D5 NdrProxyErrorHandler
                        8 CStdStubBuffer_QueryInterface
                        F IUnknown_AddRef_Proxy
                       11 IUnknown_Release_Proxy
                        5 CStdStubBuffer_Disconnect
                        0 CStdStubBuffer_AddRef
                        1 CStdStubBuffer_Connect
                        2 CStdStubBuffer_CountRefs
                        6 CStdStubBuffer_Invoke
                        7 CStdStubBuffer_IsIIDSupported
                       C9 NdrOleAllocate
                        3 CStdStubBuffer_DebugServerQueryInterface
                        4 CStdStubBuffer_DebugServerRelease
                       94 NdrDllRegisterProxy
                       CA NdrOleFree
                       95 NdrDllUnregisterProxy
                       93 NdrDllGetClassObject
                       65 NdrCStdStubBuffer_Release
                       92 NdrDllCanUnloadNow
    
        KERNEL32.dll
                  1000C154 Import Address Table
                  1000C03C Import Name Table
                         0 time date stamp
                         0 Index of first forwarder reference
    
                      1E5 RtlUnwind
                       AA GetCommandLineA
                      18E LCMapStringW
                      18D LCMapStringA
                      12B GetStringTypeA
                      12E GetStringTypeW
                      25B VirtualAlloc
                      16E HeapFree
                      190 LoadLibraryA
                      27B WriteFile
                      26E WideCharToMultiByte
                      168 HeapAlloc
                       E1 GetEnvironmentStrings
                       97 FreeEnvironmentStringsW
                       E3 GetEnvironmentStringsW
                       96 FreeEnvironmentStringsA
                      109 GetOEMCP
                      1AB MultiByteToWideChar
                       A3 GetCPInfo
                       FC GetModuleFileNameA
                       9D GetACP
                      16A HeapCreate
                      16C HeapDestroy
                      25E VirtualFree
                       EF GetFileType
                      12A GetStdHandle
                      128 GetStartupInfoA
                       D3 GetCurrentProcess
                      246 TerminateProcess
                      21B SetHandleCount
                      14C GetVersion
                       FE GetModuleHandleA
                      116 GetProcAddress
                       6B ExitProcess
    
      Summary
    
            3000 .data
            1000 .idata
            2000 .orpc
            1000 .rdata
            1000 .reloc
            5000 .text
    

    而这里显示出来的问题是: 我生成的 proxy.dll 没有 import RPCRT4.dll 中的大多数 NdrXXXXXXXXXXX 函数.

    上面是我目前发现的问题, 谢谢!

    2015年12月1日 14:09
  • 你好,

    我按照你提供的 [https://connect.microsoft.com/VisualStudio/feedback/details/1031687/jsonpackage-did-not-load-correctly], 以及[http://stackoverflow.com/questions/17727872/microsoft-visualstudio-web-pastejson-jsonpackage-did-not-load-properly], 修复了我的VS,但是还是打不开项目,很奇怪。不知道是不是我装了VS2015 和VS2013两个版本在一台机器上。

    我看了你的分析,我觉得你分析的都有道理。尤其是你的dll 里没有idata。从这个问题链接我们可以看到idata 的主要作用http://stackoverflow.com/questions/19012300/whats-the-difference-between-rdata-and-idata-segments

    .rdata is for const data. It is the read only version of the .data segment.

    .idata holds the import directory (.edata for exports). It is used by EXE's and DLL's to designate the imported and exported functions.

    我觉得你重点看一下你在改装6.0项目为2013项目的时候,在组件定义那块查一下,看是否丢失什么内容导致proxy dll 不完整。

    May


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • 已标记为答案 threedts167 2015年12月8日 11:06
    2015年12月2日 8:16
  • 谢谢你的建议!



    前几天一直忙于别的事情. 今天重新折腾了一下这个问题. 我终于解决了.



    是因为我从IDL文件生成DLLDATA.C 的时候出现了问题. 



    MODEL.EXE 支持 MODEL_I.IDL 以及 EVENT_I.IDL 中定义的接口.



    我的 MIDL "输出" 设置是

    Proxy/Stub File: %(FILENAME)_P.c

    Dlldata File: %(FILENAME)_DLLDATA.C

    IID File: %(FILENAME)_I.C

    Header File: %(FILENAME).H



    这样会导致每一个 FILENAME.IDL 文件都生成单独的 FILENAME_DLLDATA.C 文件.

    然而我在生成 Proxy.dll 的时候. 只链接了 MODEL_I_DLLDATA.OBJ 没有链接 EVENT_I_DLLDATA.OBJ , 因此 DLLDATA 缺少了 EVENT_I.IDL 中接口的信息.



    参考 MIDL 生成 DLLDATA.C 的规则: https://msdn.microsoft.com/en-us/library/windows/desktop/aa367282(v=vs.85).aspx

    可以看出 DLLDATA 是采取 "Append" 的形式写入接口信息的. (这是关键)

    因此解决的办法就是让 MODEL_I.IDL 与 EVENT_I.IDL 都生成一个 DLLDATA.C 文件.

    通过修改 MIDL 的设置, 我让 MODEL_I.IDL 与 EVENT_I.IDL 都生成名为 ME_DLLDATA.C(因此这个文件同时包含2个IDL文件的接口信息), 编译并链接进 Proxy.dll 即可.



    Proxy.dll : MODEL_I.OBJ, EVENT_I.OBJ, MODEL_I_P.OBJ, EVENT_I_P.OBJ, ME_DLLDATA.OBJ, RPCRT4.LIB, KERNEL32.LIB, UUID.LIB

    2015年12月8日 11:06