I've been playing around and learning about runspaces and Winforms and am wondering how I'd go about reusing a function for each different runspace I make. I can get it to work by including the full script of the function in each scriptblock, but I was looking to just have the function written once and reference it whenever I make a new runspace.
Here's what I currently have:
$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
}
It doesn't work how it's laid out there, but if I move the sqlExecuteRead function into $QueryServer it works fine. The problem is I want to use this function in many other runspaces as well and was hoping not to copypaste it everywhere. Apologies if the code appears to be missing pieces/use case doesn't make sense as I had to cut quite a bit out. :)
Any help is appreciated!