2012-01-05 52 views
11

我有以下代碼。Powershell start-job -scriptblock無法識別在同一個文件中定義的函數?

function createZip 
{ 
Param ([String]$source, [String]$zipfile) 
Process { echo "zip: $source`n  --> $zipfile" } 
} 

try { 
    Start-Job -ScriptBlock { createZip "abd" "acd" } 
} 
catch { 
    $_ | fl * -force 
} 
Get-Job | Wait-Job 
Get-Job | receive-job 
Get-Job | Remove-Job 

但是,該腳本返回以下錯誤。

Id    Name   State  HasMoreData  Location    Command     
--    ----   -----  -----------  --------    -------     
309    Job309   Running True   localhost   createZip "a... 
309    Job309   Failed  False   localhost   createZip "a... 
Receive-Job : The term 'createZip' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. 
At line:17 char:22 
+ Get-Job | receive-job <<<< 
    + CategoryInfo   : ObjectNotFound: (function:createZip:String) [Receive-Job], CommandNotFoundException 
    + FullyQualifiedErrorId : CommandNotFoundException 

似乎在腳本塊start-job內部無法識別函數名稱。我也試過function:createZip

回答

13

Start-Job實際上會創建另一個沒有createZip函數的PowerShell.exe實例。您需要包括它所有的腳本塊:

$createZip = { 
    param ([String]$source, [String]$zipfile) 
    Process { echo "zip: $source`n  --> $zipfile" } 
} 

Start-Job -ScriptBlock $createZip -ArgumentList "abd", "acd" 

一個例子從後臺作業返回一條錯誤消息:

$createZip = { 
    param ([String] $source, [String] $zipfile) 

    $output = & zip.exe $source $zipfile 2>&1 
    if ($LASTEXITCODE -ne 0) { 
     throw $output 
    } 
} 

$job = Start-Job -ScriptBlock $createZip -ArgumentList "abd", "acd" 
$job | Wait-Job | Receive-Job 

還要注意,通過使用throw作業對象State會「失敗「,所以你只能得到失敗的作業:Get-Job -State Failed

+0

謝謝。看來在PowerShell的另一個實例中引發的異常無法捕獲。捕獲異常的最佳方法是什麼? – ca9163d9 2012-01-05 22:48:46

+0

@NickW你當然可以。看看我更新的答案。 – 2012-01-05 23:02:34

+1

謝謝你 - 我有一個類似的問題,現在我是金! – marceljg 2012-04-18 15:20:52

5

如果你還在新使用的啓動工作程序和接收工作,並希望更容易調試功能,嘗試這種形式:

$createZip = { 
    function createzipFunc { 
    param ([String]$source, [String]$zipfile) 
    Process { echo "zip: $source`n  --> $zipfile" } 
    } 
    #other funcs and constants here if wanted... 
    } 
    # some secret sauce, this defines the function(s) for us as locals 
    invoke-expression $createzip 

    #now test it out without any job plumbing to confuse you 
    createzipFunc "abd" "acd" 

    # once debugged, unfortunately this makes calling the function from the job 
    # slightly harder, but here goes... 
    Start-Job -initializationScript $createZip -scriptblock {param($a,$b) ` 
createzipFunc $a $b } -ArgumentList "abc","def" 

所有未被其實我沒有定義變得更簡單我的功能就像你擁有的一個簡單的過濾器,但是我所做的是因爲我想在最後傳遞一些功能到我的工作中。

對不起,挖掘這個線程,但它也解決了我的問題,太優雅了。所以我只需要添加我在調試PowerShell工作時編寫的一點點醬。

+2

我喜歡這種方法。有一點需要補充,有時候'Invoke-Expression'會抱怨'Invoke-Expression:無法評估參數'Command',因爲它的參數 被指定爲腳本塊並且沒有輸入。腳本塊不能 評估沒有輸入.'。我發現如果你把變量作爲一個字符串'invoke-expression「傳遞給$ createzip」'解決了這個問題。 – Adarsha 2017-04-05 14:29:13