为什么同一个脚本在Exchange Management Shell 2010中起作用,但在Powershell和Exchange Connection中不能通过C#起作用 [英] Why does the same script work in Exchange Management Shell 2010 but not through C# with Powershell and Exchange Connection

查看:110
本文介绍了为什么同一个脚本在Exchange Management Shell 2010中起作用,但在Powershell和Exchange Connection中不能通过C#起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有以下与Exchange 2010一起使用的powershell脚本,用于获取转发电子邮件地址

  $ fwds =获取邮箱|哪里对象{$ _.ForwardingAddress -ne $ null} |选择名称,ForwardingAddressforeach($ fwds中的$ fwd){$ fwd |add-member -membertype noteproperty -name"ContactAddress"值(Get-ADObject -Identity $((($ fwd.ForwardingAddress).DistinguishedName)-Properties mail).mail如果($ fwd.ContactAddress){#Maakt反对C#uit te lezen zijn中的对象$ properties = @ {名称= $ fwd.NameContactAddress = $ fwd.ContactAddress}$ o =新对象psobject -Property $ properties;#在C#中清除zet het对象bruikbaar als对象写输出$ o}} 

当我在Exchange命令行管理程序(2010)中运行此程序时,它运行正常..昨天,我也能够通过C#中的Powershell运行此程序.

打开运行空间后,我使用以下代码进行连接

  PSCommand commandExchangePSSession = new PSCommand();commandExchangePSSession.AddCommand("New-PSSession");commandExchangePSSession.AddParameter("ConfigurationName","Microsoft.Exchange");commandExchangePSSession.AddParameter("ConnectionUri",argUri);commandExchangePSSession.AddParameter("Credential",凭据);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对象,以将脚本添加到其中:

  var powershellExecScript = PowerShell.Create();powershellExecScript.Commands.AddScript(tempTotalScript);powershellExecScript.Runspace =运行空间;集合< PSObject>结果= powershellExecScript.Invoke(); 

其中 tempTotalScript 是上面所述的脚本...但是,当我运行它时,我得到的错误信息是Identity不能为NULL.

 异常:System.Management.Automation.ParameterBindingValidationException:无法验证参数"Identity"上的参数.参数为空.提供一个有效的参数值,然后尝试再次运行该命令. 

所以我将问题缩小到 $(($ fwd.ForwardingAddress).DistinguishedName

$ fwd.ForwardingAddress 有效,它通过C#返回有效值.因此这也意味着我的Powershell连接代码无效.但是 DistinguishedName 不会,它返回null.这就是我在通过C#运行代码时出错的原因.

当我在Exchange命令行管理程序中尝试相同的代码时... DistinguishedName 属性不为null,并显示正确的专有名称.

所以我的问题是,当我通过C#Powershell运行代码时,为什么$ fwd.ForwardingAddress中的DistinguishedName属性未填充值?

解决方案

这是因为远程会话返回序列化(也称为脱水或字符串化)的对象.这些不能对原始对象保持完全的保真度.通常,这被描述为方法的删除,但是它可以超出此范围.通常,复杂的对象会稍微变平.以这种情况为例,在安装并正确加载了管理工具的Exchange命令行管理程序控制台中,ForwardingAddress属性的类型为 [Microsoft.Exchange.Data.Directory.ADObjectId] ./p>

但是,在使用以下命令建立的远程会话中:

  $ session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri"http://< serverName>/powershell"-身份验证KerberosImport-PSSession-会话$ session 

然后,转发地址将是一个简单字符串,其格式设置为规范名称.这通常与通过 .ToString()方法运行完整保真度对象相同.

我还没有通过C#进行任何操作,但这是一个很大的问题.我们倾向于在安装了完整工具链的环境中进行开发,然后部署到没有此工具的环境中.我已经通过两种方法解决了这个问题.

  1. 例外,在相同的环境下发展您计划部署到的环境.
  2. 在代码中构建逻辑以检测对象类型并采取行动不同的是,如下所示:


  If($ ForwardingAddress.GetType().Fullname -is [String]){# 做一点事...}别的 {#做一些不同的事情...} 

#1显然更简单.

#2可以更好地进行持续开发,因为您可以在本地运行和测试.但是,这也可能会失控,因为您的程序变得越来越复杂,并且您还有其他对象要处理,等等.更不用说甚至在容纳对象之前都要检查这些对象.

I have the following powershell script I use with Exchange 2010 to get the forwarding email adresses

$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
    }
}

When I run this in the Exchange Management Shell (2010) it works fine.. Yesterday I also were able to run this through Powershell in C#.

I use the following code for connecting after I open a runspace

                        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);



Then I use a Get-Session command, followed by a Import-Session. After that I use PowerShell.Create() to create a new PowerShell Object to add the script into with:

                                var powershellExecScript = PowerShell.Create();
                                powershellExecScript.Commands.AddScript(tempTotalScript); 

                                powershellExecScript.Runspace = runspace;

                                Collection<PSObject> results = powershellExecScript.Invoke();

Where tempTotalScript is the script stated above... Yet when I run it I get errors that 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. 

So I narrowed the problem down to $(($fwd.ForwardingAddress).DistinguishedName

The $fwd.ForwardingAddress works, it returns a valid value through C#. So this also means my powershell connection code is not invalid. But the DistinguishedName does not, it returns null. This is the reason I am getting errors running my code through C#.

When I try the same code in the Exchange Management Shell... the DistinguishedName property is not null and showing a proper distinguished name..

So my question is, why is the DistinguishedName property inside $fwd.ForwardingAddress not filled with a value when I run the code through C# Powershell?

解决方案

This is because a remote session returns serialized (also called dehydrated or string-ified) objects. These do not maintain full fidelity to the original objects. Usually, this is described as the removal of methods, but it can go beyond that. Typically, complex objects are somewhat flattened. Using this case as an example, in an Exchange Management Shell console, where the management tools are installed and properly loaded, the ForwardingAddress property is of type [Microsoft.Exchange.Data.Directory.ADObjectId].

However, in a remote session established with the below command:

$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "http://<serverName>/powershell" -Authentication Kerberos
Import-PSSession -Session $session

Then the forwarding address will be a simple string formatted as a canonical name. This is usually the same as running the full fidelity object through the .ToString() method.

I haven't done any of this through C#, however, it is a big problem. We'll tend to develop in an environment that has our full tool-chain installed then deploy to an environment that doesn't. There are 2 ways I've dealt with the problem.

  1. Make an exception and develop under the same environmental circumstances you plan to deploy to.
  2. Build logic into your code to detect the object type and act differently, something like below:


If( $ForwardingAddress.GetType().Fullname -is [String] ) {
    # Do Something... 
} 
Else {
    # Do something different...
}

#1 is obviously more simple.

#2 is better for continued development because you can run and test locally. However, this can also get out of hand, as your program gets more complex and you have other objects to deal with, etc... Not to mention there's overhead to checking the objects even before accommodating them.

这篇关于为什么同一个脚本在Exchange Management Shell 2010中起作用,但在Powershell和Exchange Connection中不能通过C#起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆