簡體   English   中英

如何在不同的 PowerShell 運行空間中重用本地函數?

[英]How do you reuse local functions in different PowerShell runspaces?

我一直在玩耍並學習運行空間和 Winforms,我想知道我如何 go 為我制作的每個不同的運行空間重用 function。 我可以通過在每個腳本塊中包含 function 的完整腳本來使其工作,但我希望只編寫一次 function 並在創建新運行空間時引用它。

這是我目前擁有的:

$hash = [hashtable]::Synchronized(@{})
$Script:Jobs = [system.collections.arraylist]::Synchronized((New-Object System.Collections.ArrayList))
# Our main GUI Form object
$hash.Form = New-Object System.Windows.Forms.Form

# Results that come back from the query get saved here
$script:hash.ServerResults = $null

# Buttons
$hash.QueryServerButton = New-Object System.Windows.Forms.Button

# Button properties
$hash.QueryServerButton.Location = New-Object System.Drawing.Point(40,300)
$hash.QueryServerButton.Size = New-Object System.Drawing.Size (105,40)
$hash.QueryServerButton.Text = "Get Servers"
$hash.QueryServerButton.Add_Click({
    PerformRunspaceAction($QueryServer)
})
$hash.ServerTab.Controls.Add($hash.QueryServerButton)

$QueryServer = {
    $connectionString = "Server=xxx\xxx;Database=xxxx;Trusted_Connection=True;"
    $sql = @"
    SELECT * FROM DB_DB;
    "@

    do {
        Start-Sleep -Seconds 30  
        $script:hash.ServerResults = sqlExecuteRead $connectionString $sql $pars
    } while ($true)
}


Function PerformRunspaceAction {
            param($scriptRun)
    
            $newRunspace = [runspacefactory]::CreateRunspace()
            $newRunspace.ApartmentState = "STA"
            $newRunspace.ThreadOptions = "ReuseThread"
            $newRunspace.Open()
            $newRunspace.SessionStateProxy.SetVariable("hash", $hash)
    
            $Powershell = [powershell]::Create().AddScript($scriptRun)
            $Powershell.Runspace = $newRunspace
            [void]$Script:Jobs.Add((
                [PSCustomObject]@{
                    PowerShell = $PowerShell
                    Runspace = $PowerShell.BeginInvoke()
                }
            ))
    }

function sqlExecuteRead($connectionString, $sqlCommand, $pars) {

    $connection = new-object system.data.SqlClient.SQLConnection($connectionString)
    $connection.Open()
    $command = new-object system.data.sqlclient.sqlcommand($sqlCommand, $connection)

    if ($pars -and $pars.Keys) {
       foreach($key in $pars.keys) {
        # avoid injection in varchar parameters
            $par = $command.Parameters.Add("@$key", [system.data.SqlDbType]::VarChar, 512);
            $par.Value = $pars[$key];
        }
    }

    $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
    $dataset = New-Object System.Data.DataSet
    $adapter.Fill($dataset) | Out-Null
    $connection.Close()
    return $dataset.tables[0].rows
}

它的布局方式不起作用,但是如果我將 sqlExecuteRead function 移動到 $QueryServer 中,它可以正常工作。 問題是我想在許多其他運行空間中使用這個 function 並且希望不要到處復制粘貼它。 抱歉,如果代碼似乎缺少部分/用例沒有意義,因為我不得不刪掉很多。 :)

任何幫助表示贊賞!

這是一種初始化運行空間的方法,包括本地 session 中的預定義函數 下面的代碼將函數添加到InitialSessionState實例,在這種情況下,我們將使用Default2 session state因為這是一個更輕的版本。 然后使用RunspacePool CreateRunspacePool(Int32, Int32, InitialSessionState, PSHost)構造函數實例化 RunspacePool,它允許我們將預定義的InitialSessionState實例與其中的函數一起包含在內。

using namespace System.Management.Automation.Runspaces

function Say-Hello1 {param($i) "Hello from function 1 - Runspace $i" }
function Say-Hello2 {param($i) "Hello from function 2 - Runspace $i" }

[SessionStateFunctionEntry[]] $funcs = Get-Command Say-Hello* | ForEach-Object {
    [SessionStateFunctionEntry]::new($_.Name, $_.Definition)
}

$iss    = [initialsessionstate]::CreateDefault2()
$iss.Commands.Add($funcs)
$rspool = [runspacefactory]::CreateRunspacePool(1, 10, $iss, $Host)
$rspool.Open()

$runspaces = 1..10 | ForEach-Object {
    $ps = [powershell]::Create().AddScript({
        param($i)

        Start-Sleep 2

        Say-Hello1 $i
        Say-Hello2 $i

    }).AddParameters(@{ i = $_ })

    $ps.RunspacePool = $rspool

    @{
        Instance    = $ps
        AsyncResult = $ps.BeginInvoke()
    }
}

foreach($runspace in $runspaces) {
    $runspace.Instance.EndInvoke($runspace.AsyncResult)
    $runspace.Instance.Dispose()
}

$rspool.Dispose()

在上面的示例中,您會注意到我們可以使用Get-Command來定位將使用運行空間初始化的所需函數,此 cmdlet 允許使用通配符以及多個 function 名稱。 假設您有函數Get-ThisSet-ThatAdd-SomethingElse ,您還可以創建具有確切函數名稱的SessionStateFunctionEntry枚舉:

[SessionStateFunctionEntry[]] $funcs = Get-Command Get-This, Set-That, Add-SomethingElse | ForEach-Object {
    [SessionStateFunctionEntry]::new($_.Name, $_.Definition)
}

暫無
暫無

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

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