簡體   English   中英

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

[英]How can I query a .pdb file in PowerShell?

通過查詢.Pdb文件,我可以看到有一個COM接口可以訪問.pdb文件的內容。 現在,我將如何從PowerShell訪問該接口? 我知道我需要使用New-Object -ComObject ...但是我不知道我需要在...部分中指定什么。

DIA2接口的問題在於它不提供后期綁定支持,因此無法從腳本語言(如Powershell)輕松使用。
用COM術語來說,它不提供從IDispatch派生的雙重接口,僅提供從IUnknown派生的接口。 如果沒有IDispatch,調用者將無法在運行時確定從任何給定對象中可以使用哪些方法。

步驟1:生成類型庫

在COM世界中,您將使用類型庫(.tlb文件)來傳達此元數據,盡管DIA SDK並沒有提供這種類型庫,但是您可以從dia2.idl文件中生成它是DIA SDK的一部分。

此步驟要求您具有可用的MIDL編譯器,如果您已安裝Visual C ++通用工具(在安裝程序的“ Programming Languages / Visual C ++ / Visual Tools for the Visual C ++ 2015”下),則應將其作為Visual Studio 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,其中包含協類和接口元數據。

步驟2:生成一個COM類包裝器

為了能夠從.NET使用此元數據,Microsoft提供了一種類型庫導入器工具,該工具可基於.tlb文件生成托管包裝。 有關更多信息,請參見https://msdn.microsoft.com/zh-cn/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")

現在,只需實例化一個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 在這里所說的:“ 您無法完成這項工作 。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

從文檔的外觀來看, 調試接口訪問SDK旨在從C ++(而不是.NET語言)中使用。 因此,我認為您將很難從PowerShell中使用它。

嚴格來說,使用New-Object -COM需要知道的是與CLSID_DiaSource等效的PROGID 不幸的是,某些COM類沒有注冊PROGID,而是以C / C ++特定形式(“ .h”和“ .lib”文件,而不是以獨立於語言的形式,例如ITypeLib,ITypeComp甚至IDispatch)提供它們的綁定元數據。結果,克服新對象障礙僅僅是開始。

請參閱此帖子 ,以獲取各種COM操作的示例(與QueryInterface一樣基本),這些操作很難從任何.NET語言中解決。 另一個示例顯示了即使在PowerShell中內置支持的ADSI COM對象上也會出現的相關限制

如果您具有C ++ / COM開發的經驗,那么幾乎可以肯定會節省您為項目的這一部分編寫C ++的時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM