2014-02-07 34 views
0

我正在嘗試創建一個運行線程特定命令的腳本,以將每個線程的信息輸出到一個單獨的文件中。有沒有辦法獲得線程ID,我可以在類似如下的命令中運行:~${threadId} e!clrstack。 最終這裏是我拍攝的:如何從WinDbg中的內存轉儲中獲取線程ID?

.foreach(tid {!threads}) 
{ 
    .logopen c:\temp\${tid}.txt; 
    ~${tid}e !dumpstack; 
    ~${tid}e !clrstack; 
    ~${tid}e !dso; 
    ~${tid}e kb 200; 
    .logclose 
} 

這是我走到這一步:

.foreach /pS 1 /pS2 /pS3 /pS4 /pS5 /ps 3 (l {!runaway}) 
{ 
    .printf "${l}\n"; 
} 

問題與此,它有我在尋找與OSID值。看起來像這樣<wantedID>:<OSID>。 如何分離我需要的零件或者是否有從存儲器轉儲中獲取線程ID的更簡單方法?

回答

2

我有點困惑的使用.foreach~e在一起,因爲這在某種程度上複製(只是你限制~e一個線程不會導致嵌套循環的事實)。

是命令

~*e .logopen /t d:\debug\log.txt; !dumpstack; !clrstack; !dso; kb 200; .logclose 

夠你用的?日誌文件名將不具有線程ID。

關於您的跳過標記.foreach,我認爲您只能使用/pS/ps一次。你的語句相當於

.foreach /pS 5 /ps 3 (l {!runaway}) { ... } 

如果線程ID真的很重要

看來,操作系統的線程ID是非常重要的。

直接使用.foreach!threads~!runaway任何命令似乎不靈活和可靠的不夠,我建議使用.shell find得到至少在輸出一定的一致性。

我將使用!teb來獲取線程ID,因爲它由空格分隔,因此.shell find的輸出可用作.foreach的輸入。

完整的命令我想出了:

~*e .foreach /pS 3 /ps 20 (tid {.shell -ci "!teb" find "ClientId"}) { .logopen d:\debug\logs\log${tid}.txt; !dumpstack; !clrstack; !dso; kb 200; .logclose} 

使用pykd作爲擴展

使用PyKd - Python extension for WinDbg,結果可以達到這樣的:

創建一個文件TID .py,將它放在pykd.pyd擴展名的旁邊,並給它以下內容:

from pykd import * 
threads = getProcessThreads() 
for t in threads: 
    print(hex(ptrPtr(t+0x24))[2:-1]) 

getProcessThreads()爲您提供TEB的地址。在偏移量0x24處,您可以找到線程ID。ptrPtr()讀取內存地址,hex()是自我解釋,[2:刪除0x頭和:-1]刪除尾隨L(不要問我爲什麼它有一個尾隨L)。

WinDbg裏

.load pykd.pyd 
!py tid.py; *** Gives one thread ID per line, nice for .foreach 
.foreach (tid {!py tid.py}) { .logopen d:\debug\logs\log_${tid}.txt; ~~[${tid}]s; !dumpstack; !clrstack; !dso; kb 200; .logclose} 
+0

我可以使用〜* E遍歷所有線程,但我的首要目標是讓我可以用一個文件名線程ID。我可以使用@ $ tid變量來獲取線程ID,但它給了我OSID而不是特定於進程的十進制ID#。 感謝您糾正我的/ pS使用情況! – ishara

+1

@iSharemore:更新了我的答案,不使用像pykd這樣的擴展。我正在研究pykd以獲得相同的結果。 –

+0

@iSharemore:我使用pykd –