【发布时间】:2016-01-27 15:42:25
【问题描述】:
我有一个 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。
【问题讨论】:
-
当您使用
PowerShell.Invoke()时,您是否在调用后检查了PowerShell.Streams.Error的值? -
如果我使用
PowerShell.Invoke()没有错误,它会很好地跳过该行,但 PowerShell 没有返回任何内容...我的result是一个空集合 -
它没有回答我的问题。事实上,您没有从
PowerShell.Invoke()引发任何异常并不意味着您在错误流中没有任何错误。 -
啊...我明白了...我错误地认为缺少异常意味着没有错误,但实际上,相同的错误显示在流中。
The term '.\Get-AzureAssistantSubscription.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.和另一个与外部脚本调用的 ps1 未运行有关。 -
您确定将脚本文件放在当前工作目录中吗?尝试使用完整的绝对路径而不是相对路径。
标签: asp.net .net powershell azure