从.NET调用父ps1时如何执行子ps1

时间:2016-01-27 15:42:26

标签: asp.net .net powershell azure

我有一个ASP.NET应用程序,我希望调用Powershell脚本来获得结果。我已经做了一些挖掘,并提出了许多与PS1 / 2相关的非常过时的信息,但PS4向上没有任何信息。

我有一个PowerShell脚本,目前完成一些操作并将一个ArrayList输出到PowerShell控制台。 Powershell脚本调用另一个PowerShell脚本:

.\Get-AzureSubscription.ps1

$environments = New-Object System.Collections.ArrayList
$resourceGroups = Get-AzureRMResourceGroup

foreach($thisResourceGroup in $resourceGroups)
{
    $resourceGroupVMs = Get-AzureRmVM -ResourceGroupName $thisResourceGroup.ResourceGroupName

    $environment = New-Object -TypeName PSObject
    $environment | Add-Member -MemberType NoteProperty -Name ResourceGroupName -Value $thisResourceGroup.ResourceGroupName
    $environment | Add-Member -MemberType NoteProperty -Name Id -Value $thisResourceGroup.ResourceId

    $machines = New-Object System.Collections.ArrayList

    foreach($thisMachine in $resourceGroupVMs)
    {
        $machine = New-Object -TypeName PSObject
        $machine | Add-Member -MemberType NoteProperty -name Name -value $thisMachine.Name
        $machine | Add-Member -MemberType NoteProperty -name ResourceGroupName -value $thisResourceGroup.ResourceGroupName 

        $status = Get-AzureRmVM -ResourceGroupName $thisResourceGroup.ResourceGroupName -Name $thisMachine.Name -Status | `
                         Select-Object -ExpandProperty Statuses | `
                         Where-Object { $_.Code.StartsWith("PowerState") } | `
                         Select-Object -ExpandProperty Code

        $regex = [Regex] '\/(.*?)$'
        $machine | Add-Member -MemberType NoteProperty -name Status -value $regex.Match($status).Groups[1].Value


        $machines.Add($machine) > $null;
    }

    $environmentStatuses = $machines | Select-Object ResourceGroupName -ExpandProperty Status | Group-Object ResourceGroupName, Status

    $environment | Add-Member -MemberType NoteProperty -name Statuses -value $environmentStatuses
    $environments.Add($environment) > $null;
}

$environments

我还有以下.NET代码,它试图通过将PS1脚本的内容作为字符串传入来执行外部脚本:

public Collection<PSObject> RunScript(string script, Dictionary<string, string> parameters = null)
{
    // Validate parameters
    if (string.IsNullOrEmpty(script)) { throw new ArgumentNullException(nameof(script)); }
    RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();

    using (Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration))
    {
        runspace.Open();

        using (RunspaceInvoke invoker = new RunspaceInvoke(runspace))
        {
            invoker.Invoke("Set-ExecutionPolicy Unrestricted");

            Pipeline pipeline = runspace.CreatePipeline();

            Command scriptCommand = new Command(script, true);
            parameters?.Select(kvp => new CommandParameter(kvp.Key, kvp.Value))
                .ForEach(scriptCommand.Parameters.Add);

            pipeline.Commands.Add(scriptCommand);

            var result = pipeline.Invoke();

            return result;
        }
    }
}

问题是,如果我从.NET调用ps1,它就会失败抱怨The term '.\Get-AzureSubscription.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.如果我从PowerShell执行ps1,它会毫无问题地执行。

如果我将Get-AzureSubscription.ps1的内容复制并粘贴到由.NET直接调用的ps1中而不是链接这两个脚本,则所有内容都会成功传递回.NET。

1 个答案:

答案 0 :(得分:1)

无法保证.NET应用程序的工作目录与您从其中调用的脚本相同。

您可以使用此技巧找出调用脚本的完整路径(用此替换第一行):

$AzureSubscriptionScript = Join-Path $PSScriptRoot "Get-AzureAssistantSubscription.ps1"
& $AzureSubscriptionScript

$PSScriptRoot是一个自动变量,它将当前/调用脚本在磁盘上的位置路径保存为其值