为什么相同的脚本在 Exchange Management Shell 2010 中有效,但不能通过 C# 使用 Powershell 和 Exchange Connection
Why does the same script work in Exchange Management Shell 2010 but not through C# with Powershell and Exchange Connection
我有以下用于 Exchange 2010 的 powershell 脚本来获取转发电子邮件地址
$fwds = get-mailbox | Where-Object { $_.ForwardingAddress -ne $null } | select Name, ForwardingAddress
foreach ($fwd in $fwds)
{
$fwd | add-member -membertype noteproperty -name "ContactAddress" -value (Get-ADObject -Identity $(($fwd.ForwardingAddress).DistinguishedName) -Properties mail).mail
if($fwd.ContactAddress)
{
#Maakt objecten aan die in C# uit te lezen zijn
$properties = @{
Name = $fwd.Name
ContactAddress = $fwd.ContactAddress
}
$o = New-Object psobject -Property $properties;
# Dit zet het object bruikbaar als object in c#
Write-Output $o
}
}
当我在 Exchange Management Shell (2010) 中 运行 它工作正常.. 昨天我也能够通过 C# 中的 Powershell 运行 这个。
我打开一个运行空格
后使用下面的代码连接
PSCommand commandExchangePSSession = new PSCommand();
commandExchangePSSession.AddCommand("New-PSSession");
commandExchangePSSession.AddParameter("ConfigurationName", "Microsoft.Exchange");
commandExchangePSSession.AddParameter("ConnectionUri", argUri);
commandExchangePSSession.AddParameter("Credential", creds);
commandExchangePSSession.AddParameter("Authentication", "Kerberos");
PSSessionOption sessionOption = new PSSessionOption();
sessionOption.SkipCACheck = true;
sessionOption.SkipCNCheck = true;
sessionOption.SkipRevocationCheck = true;
commandExchangePSSession.AddParameter("SessionOption", sessionOption);
然后我使用 Get-Session
命令,然后是 Import-Session
。之后,我使用 PowerShell.Create()
创建一个新的 PowerShell 对象,将脚本添加到 with:
var powershellExecScript = PowerShell.Create();
powershellExecScript.Commands.AddScript(tempTotalScript);
powershellExecScript.Runspace = runspace;
Collection<PSObject> results = powershellExecScript.Invoke();
其中 tempTotalScript
是上述脚本...但是当我 运行 它时,我得到错误,Identity can't be NULL.
Exception: System.Management.Automation.ParameterBindingValidationException: Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try running the command again.
所以我将问题缩小到 $(($fwd.ForwardingAddress).DistinguishedName
$fwd.ForwardingAddress
有效,它 returns 通过 C# 的有效值。所以这也意味着我的 powershell 连接代码不是无效的。但是 DistinguishedName
没有,它 returns 为空。这就是我通过 C# 编译代码时出现错误 运行 的原因。
当我在 Exchange Management Shell 中尝试相同的代码时...DistinguishedName
属性 不为空并显示正确的可分辨名称..
所以我的问题是,为什么我通过C# Powershell运行代码时,$fwd.ForwardingAddress里面的DistinguishedName属性没有填充值?
编辑:这不是正确答案。
似乎 Get-ADObject
在 Exchange 2010 中不起作用。我不得不使用 get-contact
#Exchange 2010 Script
$fwds = get-mailbox | Where-Object { $_.ForwardingAddress -ne $null } | select Name, ForwardingAddress, DeliverToMailboxAndForward
foreach ($fwd in $fwds)
{
$ErrorActionPreference = "SilentlyContinue"
$fwd | add-member -membertype noteproperty -name "ContactAddress" -value (get-contact $fwd.ForwardingAddress).WindowsEmailAddress
$ErrorActionPreference = "Continue"
#Maakt objecten aan die in C# uit te lezen zijn
if($fwd.ContactAddress)
{
$properties = @{
Name = $fwd.Name
ContactAddress = $fwd.ContactAddress
DeliverToMailboxAndForward = $fwd.DeliverToMailboxAndForward
}
$o = New-Object psobject -Property $properties;
# Dit zet het object bruikbaar als object in c#
Write-Output $o
}
}
这是因为远程会话 returns 序列化(也称为脱水或字符串化)对象。这些不保持对原始对象的完全保真度。通常,这被描述为方法的移除,但它可以不止于此。通常,复杂的对象会有些扁平化。以这种情况为例,在安装并正确加载管理工具的 Exchange 管理 Shell 控制台中,ForwardingAddress 属性 的类型为 [Microsoft.Exchange.Data.Directory.ADObjectId]
.
但是,在使用以下命令建立的远程会话中:
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "http://<serverName>/powershell" -Authentication Kerberos
Import-PSSession -Session $session
然后转发地址将是一个格式为规范名称的简单字符串。这通常与通过 .ToString()
方法 运行 宁全保真对象相同。
我还没有通过 C# 完成任何这些,但是,这是一个大问题。我们倾向于在安装了完整工具链的环境中进行开发,然后部署到没有安装的环境中。我有两种方法解决了这个问题。
- 破例同环境下发展
您计划部署到的环境。
- 在您的代码中构建逻辑以检测对象类型并采取行动
不同的是,如下所示:
If( $ForwardingAddress.GetType().Fullname -is [String] ) {
# Do Something...
}
Else {
# Do something different...
}
#1显然更简单
#2 更适合继续开发,因为您可以 运行 并在本地进行测试。然而,这也可能会失控,因为您的程序变得更加复杂并且您有其他对象要处理等等......更不用说甚至在容纳它们之前检查对象也会产生开销。
我有以下用于 Exchange 2010 的 powershell 脚本来获取转发电子邮件地址
$fwds = get-mailbox | Where-Object { $_.ForwardingAddress -ne $null } | select Name, ForwardingAddress
foreach ($fwd in $fwds)
{
$fwd | add-member -membertype noteproperty -name "ContactAddress" -value (Get-ADObject -Identity $(($fwd.ForwardingAddress).DistinguishedName) -Properties mail).mail
if($fwd.ContactAddress)
{
#Maakt objecten aan die in C# uit te lezen zijn
$properties = @{
Name = $fwd.Name
ContactAddress = $fwd.ContactAddress
}
$o = New-Object psobject -Property $properties;
# Dit zet het object bruikbaar als object in c#
Write-Output $o
}
}
当我在 Exchange Management Shell (2010) 中 运行 它工作正常.. 昨天我也能够通过 C# 中的 Powershell 运行 这个。
我打开一个运行空格
后使用下面的代码连接 PSCommand commandExchangePSSession = new PSCommand();
commandExchangePSSession.AddCommand("New-PSSession");
commandExchangePSSession.AddParameter("ConfigurationName", "Microsoft.Exchange");
commandExchangePSSession.AddParameter("ConnectionUri", argUri);
commandExchangePSSession.AddParameter("Credential", creds);
commandExchangePSSession.AddParameter("Authentication", "Kerberos");
PSSessionOption sessionOption = new PSSessionOption();
sessionOption.SkipCACheck = true;
sessionOption.SkipCNCheck = true;
sessionOption.SkipRevocationCheck = true;
commandExchangePSSession.AddParameter("SessionOption", sessionOption);
然后我使用 Get-Session
命令,然后是 Import-Session
。之后,我使用 PowerShell.Create()
创建一个新的 PowerShell 对象,将脚本添加到 with:
var powershellExecScript = PowerShell.Create();
powershellExecScript.Commands.AddScript(tempTotalScript);
powershellExecScript.Runspace = runspace;
Collection<PSObject> results = powershellExecScript.Invoke();
其中 tempTotalScript
是上述脚本...但是当我 运行 它时,我得到错误,Identity can't be NULL.
Exception: System.Management.Automation.ParameterBindingValidationException: Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try running the command again.
所以我将问题缩小到 $(($fwd.ForwardingAddress).DistinguishedName
$fwd.ForwardingAddress
有效,它 returns 通过 C# 的有效值。所以这也意味着我的 powershell 连接代码不是无效的。但是 DistinguishedName
没有,它 returns 为空。这就是我通过 C# 编译代码时出现错误 运行 的原因。
当我在 Exchange Management Shell 中尝试相同的代码时...DistinguishedName
属性 不为空并显示正确的可分辨名称..
所以我的问题是,为什么我通过C# Powershell运行代码时,$fwd.ForwardingAddress里面的DistinguishedName属性没有填充值?
编辑:这不是正确答案。
似乎 Get-ADObject
在 Exchange 2010 中不起作用。我不得不使用 get-contact
#Exchange 2010 Script
$fwds = get-mailbox | Where-Object { $_.ForwardingAddress -ne $null } | select Name, ForwardingAddress, DeliverToMailboxAndForward
foreach ($fwd in $fwds)
{
$ErrorActionPreference = "SilentlyContinue"
$fwd | add-member -membertype noteproperty -name "ContactAddress" -value (get-contact $fwd.ForwardingAddress).WindowsEmailAddress
$ErrorActionPreference = "Continue"
#Maakt objecten aan die in C# uit te lezen zijn
if($fwd.ContactAddress)
{
$properties = @{
Name = $fwd.Name
ContactAddress = $fwd.ContactAddress
DeliverToMailboxAndForward = $fwd.DeliverToMailboxAndForward
}
$o = New-Object psobject -Property $properties;
# Dit zet het object bruikbaar als object in c#
Write-Output $o
}
}
这是因为远程会话 returns 序列化(也称为脱水或字符串化)对象。这些不保持对原始对象的完全保真度。通常,这被描述为方法的移除,但它可以不止于此。通常,复杂的对象会有些扁平化。以这种情况为例,在安装并正确加载管理工具的 Exchange 管理 Shell 控制台中,ForwardingAddress 属性 的类型为 [Microsoft.Exchange.Data.Directory.ADObjectId]
.
但是,在使用以下命令建立的远程会话中:
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "http://<serverName>/powershell" -Authentication Kerberos
Import-PSSession -Session $session
然后转发地址将是一个格式为规范名称的简单字符串。这通常与通过 .ToString()
方法 运行 宁全保真对象相同。
我还没有通过 C# 完成任何这些,但是,这是一个大问题。我们倾向于在安装了完整工具链的环境中进行开发,然后部署到没有安装的环境中。我有两种方法解决了这个问题。
- 破例同环境下发展 您计划部署到的环境。
- 在您的代码中构建逻辑以检测对象类型并采取行动 不同的是,如下所示:
If( $ForwardingAddress.GetType().Fullname -is [String] ) {
# Do Something...
}
Else {
# Do something different...
}
#1显然更简单
#2 更适合继续开发,因为您可以 运行 并在本地进行测试。然而,这也可能会失控,因为您的程序变得更加复杂并且您有其他对象要处理等等......更不用说甚至在容纳它们之前检查对象也会产生开销。