【发布时间】:2016-09-11 17:34:03
【问题描述】:
从Querying the .Pdb File 我可以看到有一个COM 接口可以访问.pdb 文件的内容。现在,我将如何从 PowerShell 访问该接口?我知道我需要使用New-Object -ComObject ...,但我不知道我需要在... 部分指定什么。
【问题讨论】:
标签: powershell com
从Querying the .Pdb File 我可以看到有一个COM 接口可以访问.pdb 文件的内容。现在,我将如何从 PowerShell 访问该接口?我知道我需要使用New-Object -ComObject ...,但我不知道我需要在... 部分指定什么。
【问题讨论】:
标签: powershell com
DIA2 接口的问题在于,它不提供后期绑定支持,因此无法在 Powershell 等脚本语言中轻松使用它。
在 COM 术语中,它不提供从 IDispatch 派生的双重接口,只提供从 IUnknown 派生的接口。没有 IDispatch,这是不可能的
让调用者在运行时找出任何给定对象都可以使用哪些方法。
在 COM 世界中,您将使用类型库(.tlb 文件)来传达此元数据,尽管 DIA SDK 不提供这样的类型库 开箱即用,您可以从 DIA SDK 中的 dia2.idl 文件生成它。
此步骤要求您有可用的 MIDL 编译器,如果您已安装,则该编译器将作为 Visual Studio 2015 的一部分安装 Visual C++ 常用工具(在安装程序菜单中的“Programming Languages/Visual C++/Common Tools for 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 和接口元数据。
为了能够使用 .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 进行检查。
现在使用这些类型变得轻而易举。首先加载包装器dll(假设它位于当前工作目录中):
[void][System.Reflection.Assembly]::LoadFile("$pwd\Dia2Lib.dll")
现在,只需实例化其中一个 CoClass 并开始使用它们:
$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
【讨论】:
从文档的外观来看,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 一样基本)的示例。另一个显示了相关的sort of limitations that occur even on ADSI COM objects,它在 PowerShell 中具有 内置 支持。
如果您在 C++/COM 开发方面经验丰富,那么几乎可以肯定地为您在项目的这一部分中使用 C++ 编写代码节省您的时间。
【讨论】: