积极答复者
运行 Inside COM 最后一个例子失败

问题
-
大家好,
出于学习的目的我翻了翻 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 和 EXEhttps://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
答案
-
你好,
我按照你提供的 [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
全部回复
-
你好,
我下载了你的代码并尝试重现。但是项目在我的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.- 已编辑 May Wang - MSFT 2015年12月1日 9:00
-
谢谢你的建议.
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 函数.
上面是我目前发现的问题, 谢谢!
-
你好,
我按照你提供的 [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
-
谢谢你的建议!
前几天一直忙于别的事情. 今天重新折腾了一下这个问题. 我终于解决了.
是因为我从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