If you use PowerShell remoting in some scripts, you will ses you cannot use a string to send it with the Invoke-Command cmdlet.
So you can simple convert a String to a Scriptblock
$scriptBlock = [Scriptblock]::Create($string)
Now here an example
$remoteCommand = @" Import-Module ActiveDirectory New-ADOrganizationalUnit -name "@ $scriptBlock = [Scriptblock]::Create($remoteCommand) Invoke-Command -ComputerName AD01 -ScriptBlock $scriptBlock
Basically you could create a function for that.
function ConvertTo-Scriptblock { <# Function to Convert a String into a Script Block #> Param( [Parameter( Mandatory = $true, ParameterSetName = '', ValueFromPipeline = $true)] [string]$string ) $scriptBlock = [scriptblock]::Create($string) return $scriptBlock }
Thanks, this was exactly what I needed.
Thanks much!
Nice. Just what I was looking for.
great it helped you
Why couldn’t you make me google this 18hours ago??? :-)
Thanks Thomas
no problem ;)
this one really saved my, i was trying all kinds of Invoke-Expression they needed to implement something like [scriptblock]$string
before i put a full powershell string into a variable and used invoke-expression
Used this for a project where I build a string of properties and values stored in a hashtable to be passed to Where-Object:
# Filter Hash
$filterItems = @{
#”Property Value” = “Property Name”
‘ODB’ = ‘Folder’
‘NetApp’ = ‘Folder’
‘cl_Prod’ = ‘Cluster’
}
# Bulid Filter String for Where-Object
$filterItems.Keys | ForEach-Object{
$pValue = $_
$pName = $($filterItems[$_])
if (! $fString) { $fString = “`$_.$pName -ne `”$pValue`”” } else { $fString += ” -And `$_.$pName -ne `”$pValue`”” }
}
# Convert Filter String to a Scriptblock
$scriptBlock = [ScriptBlock]::Create($fString)
# Extract the filtered VMs
$filteredVMs = $allVMs | where-object $scriptBlock
cool thanks!
This has been a lifesaver to a project of mine, where I store a set of commands in two variables (base command + path parameter tacked onto it), which I wanted to then wanted to combine and finally pass on to Invoke-Command. This didn’t work before you’ve shown how to convert a string to scriptblock.
Also the error message from PowerShell is quite straightforward:
“Invoke-Command : Cannot bind parameter ‘ScriptBlock’. Cannot convert the “asfewfasd” value of type “System.String” to
type “System.Management.Automation.ScriptBlock”.”
Nonetheless, I have expected PowerShell to be more “intelligent” and do the conversion automatically.
In any case, to contribute back to the community, I’m providing the function back that I’ve put togethe on top of your solution, to address my issue. I know I could have used a string array instead of two strings as the function’s parameters, but for my purposes I wanted to have EXACTLY 2 strings and not more:
function CombineTo-Scriptblock ()
{
[CmdletBinding()]
param(
[Parameter(Mandatory=$True,Position=1)]
[string]$command1,
[Parameter(Mandatory=$True,Position=2)]
[string]$command2
)
$newscriptblock = [scriptblock]::Criceate($($command1+$command2))
return $newscriptblock
}
thanks for sharing :)
Thank you, great help!
Love you. 2 Hours of searching.
Works like a charm!
Only problem I’m having is when I have a $variable in the command which is defined locally but not remotely. When converted to a scriptblock and executed through Invoke-Command in a remote session, it would need a $using:variable.
For instance a command string like = “Test-Path -LiteralPath $Folder -PathType Container” will work when executed locally, but throws an error when in Invoke-Command:
Invoke-Command -Session $session -ScriptBlock $CommandAsScriptBlock
Invoke-Command : Missing an argument for parameter ‘Session’. Specify a parameter of type ‘System.Management.Automation.Runspaces.PSSession[]’ and try again.
Cannot bind argument to parameter ‘LiteralPath’ because it is null.
+ CategoryInfo : InvalidData: (:) [Test-Path], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.TestPathCommand
+ PSComputerName : Windows Server 2016 – test
Is there a way to force the substitution of variables in a string or scriptblock before respectively the conversion to scriptblock or the execution of the scriptblock?
Apologies for error in previous post: posted too much error message which is unrelated. The correct error message is below:
Cannot bind argument to parameter ‘LiteralPath’ because it is null.
+ CategoryInfo : InvalidData: (:) [Test-Path], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.TestPathCommand
+ PSComputerName : Windows Server 2016 – test
I had something like Couli had. A local variable that was not passed to the remote scriptBlock. Also my $string had single quotes and ampersands which is not permitted in my older powershell [scriptblock]::Create($string) method; So I had to use invoke-expression in combo with invoke-command for remote server execution.
get-acl C:\MyShare | select -expand access | select IdentityReference | where IdentityReference -match ‘My Media group’ | foreach
{
$samid=[regex]::matches($_.IdentityReference,'(?i)(?<=^MyDomain\\).*').value;
$SB="get-adgroup '$samid' -Properties * -ErrorAction SilentlyContinue";
$exp = ("Invoke-Command -ComputerName myDC -Credential "+'$cred'+" -EnableNetworkAccess -ScriptBlock {"+$SB+"}") ;
Invoke-Expression $exp
}
Hello Thomas,
Thanks for writing this. I have a situation where I have to pass Credential to a method using string script block.
the method call and other params are build as string then that string is used to create scriptBlock using ScriptBlock::Ceate(string) method.
when i pass in the credetials I get this error:
Exception : System.Management.Automation.MethodInvocationException: Exception calling “Invoke” with “1” argument(s): “Cannot process argument transformation on parame
ter ‘Credential’. A command that prompts the user failed because the host program or the command type does not support user interaction.
I have tried to invoke this scripBlock like this
& $scriptBlock
and
Invoke-Command $ScriptBlock -Credentail $Credential
both dont work.
Thanks in advace.
I was trying to pass a string containing a script block to the Filter parameter of Where-Object.
Why oh why couldn’t it convert it and why couldn’t I just do
[scriptblock]$filter
or
$filter -as [scriptblock]
Thanks for this article!
Year 2022 :) Thanks for the saver. Nowherelse.