2010-07-30 80 views
53

我目前正在C#中編寫一個庫,並且正在使用PowerShell在某些場合快速測試它。但是,這阻止了我重新構建項目,因爲PowerShell顯然仍然會打開DLL。您可以再次刪除PowerShell中的添加類型嗎?

在使用Add-Type添加DLL之後,有沒有辦法再次卸載DLL?文件似乎沒有線索,明顯的候選人將是Remove-Type(這不存在 - 只有一個命令與Type作爲它的名詞)。關閉PowerShell並執行導航到構建目錄並在每次重新構建時重新添加類型的所有內容變得非常麻煩。

回答

49

像其他人說,這是一個.NET的行爲。加載到AppDomain中的程序集不能被卸載。只有AppDomain可以被卸載,而powershell使用一個appdomain。幾年前我就這樣寫了一些內容:http://www.nivot.org/2007/12/07/WhyAppDomainsAreNotAMagicBullet.aspx

當我這樣測試時,我通常會打開一個shell並使用嵌套shell來做測試。啓動powershell,cd到bin位置,然後運行「powershell」啓動嵌套shell(新進程)。「exit」重新開始,然後再次運行「powershell」。

0

我一直面臨類似的問題。無法卸載類型/程序集(這是因爲它適用於.NET框架)。

在.NET中,如果創建新的應用程序域(System.AppDomain)並將程序集加載到該域中,則可以解決該問題。卸載應用程序域並卸載所有dll也是可能的。

我還沒有嘗試過,因爲對於我來說,關閉Console中的一個標籤並打開一個新標籤要簡單得多。

+0

Powershell只使用一個appdomain,創建一個新的appdomain,將類型加載到該appdomain中,然後卸載appdomain不會卸載該類型。 – 2015-09-04 13:25:08

20

如果您的程序集不需要binding context你可以這樣做:

$bytes = [System.IO.File]::ReadAllBytes("Path_To_Your_Dll.dll") 
[System.Reflection.Assembly]::Load($bytes) 
+0

以及如何使卸載程序集成爲可能? – 2013-10-11 06:19:31

+5

您將無法卸載,但OTOH DLL不會被保持打開並被鎖定,因爲讀取與加載無關(「ReadAllBytes」不會保持文件打開或鎖定)。所以這取決於OP想要什麼;這將解決似乎是想要卸載的驅動程序的「我無法建立」的問題。 – 2014-02-07 13:20:00

+2

我欠你一分。 – samaspin 2014-09-02 15:00:10

31

我發現解決此問題的最簡單方法是將Add-Type和測試代碼包裝在Start-Job的內部。 Start-Job將創建一個後臺進程,並且類型將被加載到那裏。一旦你完成了,這個過程就會消失,你可以自由地重試。

下面是它的外觀的例子:

$job = Start-Job -ScriptBlock { 

    Add-Type -path 'my.dll' 
    $myObj = new-object My.MyTestClassName 

    $result = $myObj.TestMethod 
    $result 
} 
Wait-Job $job 
Receive-Job $job 

從測試方法的輸出將被回顯到控制檯。

+1

我喜歡這種方法,但在我的情況下,我需要在後臺作業中設置變量的結果。沒有將它寫入文件,我不知道我將如何獲取該信息。不過,我認爲它值得+1 – 2015-09-22 18:40:48

+1

@SlogmeisterExtraordinaire在工作中,迴應結果。在主腳本中,調用'Receive-Job'來獲取它。 – 2015-12-17 08:32:35

+1

我添加了一個如何做到這一點的例子。這個例子中的任何拼寫或錯誤都是我自己的,而不是@ Start-Automated的。 – 2017-02-01 22:15:56

2

下面是一個完整的例子,它允許一旦完成,使得組件空載運行Add-Type命令作爲後臺作業:

# Start-Job will not preserve the working directory, so do it manually 
# Other arguments can also be passed to the job this way 
$cd = Split-Path $MyInvocation.MyCommand.Path 
$jobParams = @{ 
    'cd' = $cd 
} 

Start-Job -InputObject $jobParams -ScriptBlock { 
    cd $Input.cd 
    Add-Type -Path assembly.dll 
} | Receive-Job -Wait -AutoRemoveJob 

Receive-Job -Wait將確保工作以來的輸出接收否則會丟失。

相關問題