You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不同PowerShell Runspace中复用本地函数?

在PowerShell Runspace中复用函数(WinForms场景)

问题背景

在WinForms与Runspace结合的开发中,当前只能将sqlExecuteRead函数完整复制到每个脚本块(如$QueryServer)才能在Runspace中执行,希望仅定义一次函数,就能在多个新建Runspace中直接引用,避免重复代码。

解决方案

以下两种方法可实现Runspace间的函数复用:

方法1:通过PowerShell实例预加载函数定义

创建[powershell]实例时,先将函数定义添加到执行管道,再添加目标脚本块。Runspace执行时会先加载函数,后续脚本块可直接调用。

修改PerformRunspaceAction中的代码:

$Powershell = [powershell]::Create().AddScript($function:sqlExecuteRead).AddScript($scriptRun)

方法2:通过SessionStateProxy注入函数

利用Runspace的SessionStateProxy将函数作为变量注入到Runspace会话状态,脚本块可直接调用该函数。

修改PerformRunspaceAction函数,在设置hash变量后添加注入代码:

$newRunspace.SessionStateProxy.SetVariable("sqlExecuteRead", $function:sqlExecuteRead)

修改后的完整代码

$hash = [hashtable]::Synchronized(@{})
$Script:Jobs = [system.collections.arraylist]::Synchronized((New-Object System.Collections.ArrayList))
# 主GUI窗体对象
$hash.Form = New-Object System.Windows.Forms.Form

# 存储查询返回结果
$script:hash.ServerResults = $null

# 创建按钮
$hash.QueryServerButton = New-Object System.Windows.Forms.Button

# 按钮属性设置
$hash.QueryServerButton.Location = New-Object System.Drawing.Point(40,300)
$hash.QueryServerButton.Size = New-Object System.Drawing.Size (105,40)
$hash.QueryServerButton.Text = "获取服务器"
$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)
    # 注入sqlExecuteRead函数到Runspace会话状态
    $newRunspace.SessionStateProxy.SetVariable("sqlExecuteRead", $function:sqlExecuteRead)

    $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) {
        # 避免varchar参数注入
            $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
}

补充说明

  • $function:sqlExecuteRead用于获取函数的定义字符串,通过SessionStateProxy.SetVariable将其注入目标Runspace,使脚本块可直接调用。
  • 若需复用多个函数,可批量注入,或封装为PowerShell模块,在Runspace中通过Import-Module加载,这种方式更适合复杂场景。

内容的提问来源于stack exchange,提问作者Jurm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 05:15:32