Reputation: 12586
I want to call a PowerShell script with 3 arguments.
The first argument is the path of a C# script file.
Inside the PowerShell script, I want to execute a method in the C# script and also pass all the arguments to it.
# RunBackup.ps1
$csharp = Get-Content -Path $args[0]
$job = Start-Job -ScriptBlock {
Add-Type -TypeDefinition "$csharp"
$obj = New-Object Main
$result = $obj.Execute($args)
$result
}
Wait-Job $job
Receive-Job $job
// Main.cs
using System;
public class Main
{
public int Execute(string[] args)
{
Console.WriteLine(args[0]);
return 0;
}
}
But when I run the PS script with ./RunBackup Main.cs 1 2 3
, I got the following error.
Cannot bind argument to parameter 'TypeDefinition' because it is an empty string.
+ CategoryInfo : InvalidData: (:) [Add-Type], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.AddTypeCommand
+ PSComputerName : localhost
Cannot find type [Main]: verify that the assembly containing this type is loaded.
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
+ PSComputerName : localhost
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
+ PSComputerName : localhost
Upvotes: 0
Views: 349
Reputation: 29919
You're trying to access the $csharp
variable, but it's not in scope within the child ScriptBlock
, so it automagically gets set to $null
as per PowerShell's default lax rules for variable initialization and reference. You can verify this by using Set-StrictMode
to prevent and warn about this default behaviour:
$csharp = Get-Content -Path $args[0]
$job = Start-Job -ScriptBlock {
Set-StrictMode -Version Latest
Add-Type -TypeDefinition $csharp
$obj = New-Object Main
$result = $obj.Execute($args)
$result
}
Wait-Job $job
Receive-Job $job
Output:
The variable '$csharp' cannot be retrieved because it has not been set.
+ CategoryInfo : InvalidOperation: (csharp:String) [], RuntimeException
+ FullyQualifiedErrorId : VariableIsUndefined
+ PSComputerName : localhost
Cannot find type [Main]: verify that the assembly containing this type is loaded.
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
+ PSComputerName : localhost
The variable '$obj' cannot be retrieved because it has not been set.
+ CategoryInfo : InvalidOperation: (obj:String) [], RuntimeException
+ FullyQualifiedErrorId : VariableIsUndefined
+ PSComputerName : localhost
The variable '$result' cannot be retrieved because it has not been set.
+ CategoryInfo : InvalidOperation: (result:String) [], RuntimeException
+ FullyQualifiedErrorId : VariableIsUndefined
+ PSComputerName : localhost
To fix, you need to explicitly pass the value of $csharp
to the ScriptBlock
:
$csharp = Get-Content -Path $args[0]
$job = Start-Job -ScriptBlock {
Add-Type -TypeDefinition $input # powershell implicit param provided by InputObject
$obj = New-Object Main
$result = $obj.Execute($args)
$result
} -InputObject $csharp
Wait-Job $job
Receive-Job $job
Of course, now you get different errors, but those are outside the scope of this question!
Upvotes: 2