简体   繁体   中英

How to call a C# script from PowerShell and pass arguments

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

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM