如何在PowerShell中查询.pdb文件?

时间:2016-09-09 15:41:36

标签: powershell com

Querying the .Pdb File我可以看到有一个COM接口可以访问.pdb文件的内容。现在,我将如何从PowerShell访问该界面?我知道我需要使用New-Object -ComObject ...,但我不知道我需要在...部分指定的内容。

2 个答案:

答案 0 :(得分:2)

DIA2界面的问题在于它没有提供后期绑定支持,这使得它可以很容易地从像Powershell这样的脚本语言中使用。
在COM术语中,它不提供从IDispatch派生的双接口,只提供从IUnknown派生的接口。没有IDispatch,这是不可能的 让调用者在运行时计算出任何给定对象可用的方法。

第1步:生成类型库

在COM世界中,您将使用类型库(.tlb文件)来传达此元数据,尽管DIA SDK不提供此类型库 开箱即用,您可以从作为DIA SDK一部分的dia2.idl文件生成它。

此步骤要求您提供MIDL编译器,如果已安装,则将其作为Visual Studio 2015的一部分安装 Visual C ++常用工具(在"编程语言/ Visual C ++ / Visual C ++ 2015常用工具"在安装程序菜单中)。

打开提升(即以管理员身份运行)Visual Studio命令提示符并导航到DIA SDK:

cd C:\Program Files (x86)\Microsoft Visual Studio 14.0\DIA SDK

从此处,在idl \ dia2.idl文件上运行Microsoft IDL编译器:

midl idl\dia2.idl /tlb dia2.tlb /I .\include

这将生成文件dia2.tlb,其中包含coclass和接口元数据。

第2步:生成COM类包装器

为了能够使用.NET中的这些元数据,microsoft提供了一个类型库导入器工具,可以根据.tlb文件生成托管包装器。 有关更多信息,请参阅https://msdn.microsoft.com/en-us/library/aa645736(VS.71).aspx。从以下相同的目录中调用它:

tlbimp dia2.tlb

应该回复:

TlbImp : Type library imported to Dia2Lib.dll

换句话说,您现在拥有DIA SDK的.NET类型定义。如果您愿意,请与ILSpy一起检查。

步骤3:使用Powershell中的这些类型。

使用这些类型现在变得轻而易举。首先在包装器dll中加载(假设它位于当前工作目录中):

[void][System.Reflection.Assembly]::LoadFile("$pwd\Dia2Lib.dll")

现在,只需实例化其中一个CoClasses并开始使用它们:

$ds = new-object Dia2Lib.DiaSourceClass
$ds.lastError

修改:从Powershell致电openSession时,我无法获得有用的结果。也就是说,Powershell知道它是IDiaSession对象

$sessionObj = $null
$ds.openSession([ref]$sessionObj)
$sessionObj -is [Dia2Lib.IDiaSession]
True

但不知何故不提供对此界面公开的成员的访问权限:

$sessionObj | Get-Member

TypeName: System.__ComObject

Name                      MemberType Definition
----                      ---------- ----------
CreateObjRef              Method     System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
Equals                    Method     bool Equals(System.Object obj)
GetHashCode               Method     int GetHashCode()
GetLifetimeService        Method     System.Object GetLifetimeService()
GetType                   Method     type GetType()
InitializeLifetimeService Method     System.Object InitializeLifetimeService()
ToString                  Method     string ToString()

编辑2:显然,正如x0n所说here" 你无法做到这一点。 PowerShell使用透明的" com适配器"阻止此工作的图层,但在脚本中启用后期绑定。对于大多数情况来说这是一件好事,但不是你的。"

由于问题出在Powershell中,而不是一般的.NET,您仍然可以使用Powershell中的C#代码来访问SDK:

# Declare a C# helper class inline, and make it available in the current Powershell session:
$diaSessionHelperClassDef = @"
    using Dia2Lib;

    public class DiaSessionHelper
    {
        public IDiaSession Session { get; private set; }

        public DiaSessionHelper(IDiaDataSource dataSource)
        {
            IDiaSession result = null;
            dataSource.openSession(out result);
            Session = result;
        }

        public string GlobalScopeName
        {
            get{ return Session.globalScope.name; }
        }
    }

"@

Add-Type -TypeDefinition $diaSessionHelperClassDef -ReferencedAssemblies "$pwd\Dia2Lib.dll"

# Use this class to access the SDK's functionality:
$diaHelper = new-object DiaSessionHelper($ds)
$diaHelper.GlobalScopeName
Acme

答案 1 :(得分:1)

从文档的外观来看,Debug Interface Access SDK旨在用于C ++,而不是.NET语言。出于这个原因,我认为你将很难从PowerShell中使用它。

严格地说,使用New-Object -COM时您需要了解的是PROGID,相当于CLSID_DiaSource。不幸的是,有些COM类没有注册PROGID并以C / C ++特定形式(“.h”和“.lib”文件提供它们的绑定元数据,而不是像ITypeLib,ITypeComp甚至IDispatch那样以语言无关的形式提供。)结果,超越新对象的障碍只是一个开始。

请参阅this post,了解一些很难从任何.NET语言中解决的COM操作(基本上是QueryInterface)。另一个显示了PowerShell中具有内置支持的相关sort of limitations that occur even on ADSI COM objects

如果您在C ++ / COM开发方面经验丰富,那么几乎可以节省您在项目的这一部分用C ++编写的时间。