[英]Error "Cannot bind argument to parameter 'Name' because it is null" when running PowerShell script from C#
AFAIK,将 Office 365 邮箱类型更改为共享的唯一方法是通过 Exchange Online Powershell,看到我必须从 ASP.NET Core 3.1 web 应用程序这样做,我已经实现了以下内容:
从 C# 运行 PowerShell 脚本的方法:
public async Task<List<string>> RunScript(string script, Dictionary<string, object> parameters)
{
var result = new List<string>();
PowerShell ps = null;
try
{
ps = PowerShell.Create();
ps.AddScript(script);
ps.AddParameters(parameters);
var pipeline_objs = await ps.InvokeAsync().ConfigureAwait(false);
foreach (var item in pipeline_objs)
{
result.Add(item.BaseObject.ToString());
}
}
catch (Exception ex)
{
throw;
}
finally
{
if (ps != null)
{
ps.Dispose();
}
}
return result;
}
方法调用如下:
async Task GetMailboxDataAsync()
{
var script = //Script content
var parameters = new Dictionary<string, object>
{
{ "$username", "user@domain.org" },
{ "$password", "password" },
{ "$principal", "user2@domain.org" },
{ "$organization", "domain.onmicrosoft.com" }
};
var result = await RunScript(script, parameters);
result.Dump();
}
PowerShell 我正在尝试运行的脚本(请注意,出于测试目的,我实际上并没有使用Set-EXOMailbox
,只是暂时运行Get-EXOMailbox
):
Param($username,$password,$organization,$principal)
Import-Module ExchangeOnlineManagement
$secured_password = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($username, $secured_password)
Connect-ExchangeOnline -UserPrincipalName $username -DelegatedOrganization $organization -Credential $cred -ShowBanner:$false
Get-EXOMailbox -Identity $principal
Disconnect-ExchangeOnline -Confirm:$false
硬编码 PowerShell 脚本中的值并按预期在命令行中运行它,但从 C# 调用它(即使使用硬编码参数)会返回以下RuntimeException
: Cannot bind argument to parameter 'Name' because it is null.
。。 ScriptStackTrace 属性说:
at Disconnect-ExchangeOnline<Process>, C:\Users\[OMITTED]\Documents\PowerShell\Modules\ExchangeOnlineManagement\2.0.5\netCore\ExchangeOnlineManagement.psm1: line 666
at <ScriptBlock>, <No file>: line 7
我错过了什么?
它在命令行上运行的事实表明它可能是主机应用程序 (3.1) 的 .NET 版本的问题。 您可以尝试使用 Invoke-Command 包装脚本,它可能会利用 Powershell 和 .NET 的最新版本。这是我最近用来从 .NET 主机应用调用 EXO V2 cmdlet 的模式。 我添加了一些额外的错误处理和多线程,以便 PS 远程处理异常不会逃逸到主机应用程序。
$result = $null
# Outer try-catch.
try {
# Run the script asynchronously. Please note that script blocks must be self-contained,
# meaning you must pass parameters to them and define all functions inside them.
Start-Job -Name "$i" -ArgumentList @($username,$password,$organization,$principal) -ScriptBlock {
param($username,$password,$organization,$principal)
$result = $null
# Try-catch inside async script.
try {
# Another self-contained script block inside Invoke-Command.
$result = Invoke-Command -ComputerName localhost -ErrorAction Stop `
-ArgumentList @($username,$password,$organization,$principal) `
-ScriptBlock {
<# BEGIN Original script, with edits. #>
Param($username,$password,$organization,$principal)
Import-Module ExchangeOnlineManagement
$secured_password = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($username, $secured_password)
Connect-ExchangeOnline -UserPrincipalName $username -DelegatedOrganization $organization -Credential $cred -ShowBanner:$false
$result = Get-EXOMailbox -Identity $principal
# This should allow the script to continue without interruption,
# but any remoting exceptions could still escape to the .NET host app.
try { Disconnect-ExchangeOnline -Confirm:$false -ErrorAction Stop } catch { $Error.Clear() }
<# END Original script, with edits. #>
return $result
}
} catch {
Write-Warning ($_ | Out-String) # Do NOT use Write-Error!
$Error.Clear()
}
return $result
} | Out-Null
# Wait for the job to finish and get the result.
$jobs = Get-Job
while($jobs) {
$job = $jobs | Wait-Job -Any
$result = $job | Receive-Job
$job | Remove-Job
$jobs = Get-Job
}
} catch {
Write-Warning ($_ | Out-String) # Do NOT use Write-Error (unless you want certain exceptions to bubble up, of course).
$Error.Clear()
}
return $result
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.