1

Given the following...

  1. Powershell script that implements a runspace pool
  2. A HashTable of named scriptblocks
  3. Scriptblocks that call New-Object to create SQL related objects (SMO, SqlClient, etc)

My script iterates through a list of servers and adds every scriptblock and their parameters from the hashtable to the runspace pool. Some of the scriptblocks call New-Object to instantiate instances of various .net objects.

Code is something like this (updated to more accurately reflect the problem)...

# add, configure and execute runspace script block
$_ps                = [Powershell]::Create()
$_ps.RunspacePool   = $this._pool

$_script_block = {
   $_obj = New-Object Microsoft.SqlServer.Management.Smo.Server($InstanceName) 
}

$_wrapper_script_block = { &$_script_block }  # returns cmdlet not found error
$_wrapper_script_block = { Invoke-Command -ScriptBlock $_script_block } # works

$null = $_ps.AddScript($_wrapper_script_block)
$null = $_ps.AddParameters($Parms)

# syntax may be off - just for demonstration
[ArrayList] $jobs += @{process = $_ps; handle = $_ps.BeginInvoke()}

Problem...

Scriptblocks return "New-Object is not recognized..." error when multiple runspaces are in the pool. If I use the exact same code but submit only one scriptblock containing a New-Object call (same scriptblock fails with multiple runspaces) to the runspace pool, it works fine.

Microsoft's documentation (https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7) says "The call operator does not parse strings. This means that you cannot use command parameters within a string when you use the call operator." I changed from & to Invoke-Command and it seems to be working fine now. I'm not entirely sure what is happening.

  • Is the "v" below the if statement supposed to be there? – Uuuuuumm Aug 06 '20 at 19:11
  • no. it is a typo – AlwaysLearning Aug 06 '20 at 23:30
  • So why not fix the typo? Why not provide more of the actual script? – Doug Maurer Aug 08 '20 at 03:15
  • If you are suggesting the typo may be the issue, the typo was part of my attempt to format my post and not part of the script. As far as including more of the script, it is difficult to guess what code is useful. I was hoping the code provided would be a sufficient example of what I'm doing. – AlwaysLearning Aug 10 '20 at 16:08
  • Does anybody have any suggestions on how I might resolve my problem? – AlwaysLearning Aug 13 '20 at 17:26
  • Swapping between the call operator (&) and Invoke-Command seems to have an impact. When I do something like &$script_block it generates the cmdlet not found error. When I do Invoke-Command -ScriptBlock $script_block it seems to work fine. Any ideas on what the difference is? – AlwaysLearning Aug 13 '20 at 19:14
  • Or you can use start-threadjob or foreach-object -parallel. – js2010 Aug 18 '20 at 14:46

1 Answers1

1

I think I found my problem.

According to https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7, "The call operator does not parse strings. This means that you cannot use command parameters within a string when you use the call operator". The example they give describes the behavior in my script.

In short, one cannot use cmdlet parameters in script blocks invoked with the & operator. For example, something like &"get-command -Verb 'get'" will throw an error indicating get-command cannot be found.

I apologize for not including it in my code example.