当前位置:编程学习 > C/C++ >>

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

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

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

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

    首先是main函数。main函数做的工作跟之前的这篇博客http://www.zzzyk.com/kf/201203/122573.html 说的一样,当然还是要创建一个IDiaSymbol的COM对象。一般来说,COM对象是需要被注册到windows里面(基本上都在注册表里)才能使用CoCreateInstance来创建。但是后来我发现msdia100.dll十分良心,还提供了一个NoRegCoCreate函数,可以在你只有msdia100.dll但却没有注册它的COM对象的情况下创建该对象: #include <Windows.h>
#include <iostream>
#include <string>
#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<<L"importing "<<argv[1]<<std::endl;
        IDiaSymbol* exeSymbol=CreateDiaSymbol(argv[1]);
        if(exeSymbol)
        {
            std::wcout<<L"exporting "<<argv[2]<<std::endl;
            dumppdb::DumpPdbToXml(exeSymbol, argv[2]);
            std::wcout<<L"exported "<<argv[2]<<std::endl;
        }
        else
        {
            std::wcout<<L"Failed to read pdb("<<argv[1]<<L")"<<std::endl;
        }
    }
    else
    {
        std::wcout<<L"Pdb2Xml.exe <pdb-path> <xml-path>"<<std::endl;
    }
    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<level;i++) PrintString(file, L"  ");
    }

    void PrintEscapedName(TextWriter& file, const wchar_t* name)
    {
        const wchar_t* head=name;
        const wchar_t* reading=head;
        while(*reading)
        {
            switch(*reading)
            {
            case L'<':
                PrintString(file, head, reading-head);
                PrintString(file, L"<");
                head=reading+1;
                reading=head;
                break;
            case L'>':
               

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,