使用VS API开发一个PDB Dumper并且可以在没装VS2010的计算机上运行 (一)

2014-11-24 12:15:06 · 作者: · 浏览: 0

GacUI到了撰写文档的时候了。虽然GacUI本身的功能还没有全部完成,但是发布一个alpha版还是可以的。因此GacUI需要一份文档。自从.net语言支持XML注释生成文档之后,Visual Studio的本地C++也支持使用XML注释了。只要打开了[工程属性 -> C/C++ -> Output Files -> Generate XML Documentation Files]之后,Visual Studio会在编译本地C++工程之后,将所有的XML注释收集起来,放在和可执行文件同一个目录下的里面。然后我就尝试bing了一下有没有从C++的XML文档生成可读文档的工具,结果发现只有.net才支持。

后来我稍微研究了一下(详细内容将会在下一篇博客透露),发现之所以没人写这个工具,是因为只有.net的可执行文件才包含足够多的元数据,而且这些元数据是必须的,否则无法生成一个完整的文档。举个例子,虽然包含了xml注释和该注释所在的符号,但是却没有包含该符号的结构信息。结果你试图生成一个函数的文档的时候,发现你获取不到它的返回类型!不过这也是情有可原的,因为本地C++程序根本就没有元数据。

由此我联想到了之前写程序读pdb的时候的一些内容,我想到pdb生成的那份xml显然是可以当成元数据的。而且我找到了一个方法,让你在使用Visual Studio2010的PDB API msdia100.dll的时候,可以不需要安装Visual Studio 2010了。下面就来介绍PDB Dumper的代码。

首先是main函数。main函数做的工作跟之前的这篇博客http://www.2cto.com/kf/201203/122573.html 说的一样,当然还是要创建一个IDiaSymbol的COM对象。一般来说,COM对象是需要被注册到windows里面(基本上都在注册表里)才能使用CoCreateInstance来创建。但是后来我发现msdia100.dll十分良心,还提供了一个NoRegCoCreate函数,可以在你只有msdia100.dll但却没有注册它的COM对象的情况下创建该对象: #include
#include
#include
#include "dia2.h"
#include "diacreate.h"

#pragma comment(lib, "diaguids.lib")

namespace dumppdb
{
extern void DumpPdbToXml(IDiaSymbol* exeSymbol, const wchar_t* xml);
}

IDiaSymbol* CreateDiaSymbol(const wchar_t* pdbPath)
{
IDiaDataSource* pSource=0;
IDiaSession* pSession=0;
IDiaSymbol* pSymbol=0;
CoInitialize(NULL);
//HRESULT hr = CoCreateInstance(
// CLSID_DiaSource,
// NULL,
// CLSCTX_INPROC_SERVER,
// IID_IDiaDataSource,
// (void**) &pSource
// );
HRESULT hr = NoRegCoCreate(
L"msdia100.dll",
CLSID_DiaSource,
IID_IDiaDataSource,
(void**) &pSource
);
if(SUCCEEDED(hr))
if(SUCCEEDED(pSource->loadDataFromPdb(pdbPath)))
if(SUCCEEDED(pSource->openSession(&pSession)))
if(SUCCEEDED(pSession->get_globalScope(&pSymbol)))
{
return pSymbol;
}
return 0;
}

int wmain(int argc, wchar_t* argv[])
{
if(argc==3)
{
std::wcout< IDiaSymbol* exeSymbol=CreateDiaSymbol(argv[1]);
if(exeSymbol)
{
std::wcout< dumppdb::DumpPdbToXml(exeSymbol, argv[2]);
std::wcout< }
else
{
std::wcout< }
}
else
{
std::wcout< "< }
return 0;
}
这里的dia2.h、diacreate.h、diaguids.lib和msdia100.dll都可以在C:\Program Files (x86)\Microsoft Visual Studio 10.0\DIA SDK下找到。我们需要做的就是将这些文件都复制到我们的工程目录下面。至于如何读取IDiaSymbol的内容,各位就自己查MSDN了。下面贴出我使用IDiaSymbol将PDB的关键内容输出成xml的函数,也就是上面的代码提到的DumpPdbToXml函数了:

#include "Dia2.h"
#include "..\..\..\..\..\Library\Stream\Accessor.h"
#include "..\..\..\..\..\Library\Stream\CharFormat.h"
#include "..\..\..\..\..\Library\Stream\FileStream.h"
#include "..\..\..\..\..\Library\Stream\CacheStream.h"
#include "..\..\..\..\..\Library\Collections\Dictionary.h"

using namespace vl;
using namespace vl::collections;
using namespace vl::stream;

namespace dumppdb
{

//--------------------------------------------------------------------

void PrintString(TextWriter& file, const wchar_t* text, int len=-1)
{
if(len==-1) len=(int)wcslen(text);
file.WriteString(text, len);
}

void PrintSpaces(TextWriter& file, int level)
{
for(int i=0;i }

void PrintEscapedN