从Exchange 2010中的C#代码访问Exchange管理工具的命令是什么

时间:2010-08-27 12:46:33

标签: c# .net asp.net powershell exchange-server

在Exchange 2007中,这行代码用于加载Exchange Poweshell命令snapin:

PSSnapInInfo info = rsConfig.AddPSSnapIn(
  "Microsoft.Exchange.Management.PowerShell.Admin",
  out snapInException);

但是,这在Exchange 2010中不存在,我正试图找出如何从C#代码访问Exchange Powershell命令。 Microsoft.Exchange.Management.PowerShell.Admin在Exchange Server上的任何地方都不存在,我在Google上找不到任何关于等效代码行的内容。

如何从Exchange 2010中的C#代码访问Exchange管理工具?

下面是我的完整代码供参考,在我添加代码行之前一切正常:

                //Creating and Opening a Runspace
            RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
            PSSnapInException snapInException = null;
            PSSnapInInfo info = rsConfig.AddPSSnapIn(
               "Microsoft.Exchange.Management.PowerShell.Admin",
               out snapInException);
            Runspace myRunSpace = RunspaceFactory.CreateRunspace(rsConfig);
            myRunSpace.Open();

            //How Do I Run a Cmdlet?
            //create a new instance of the Pipeline class 
            Pipeline pipeLine = myRunSpace.CreatePipeline();

            //create an instance of the Command class
            // by using the name of the cmdlet that you want to run
            Command myCommand = new Command(txtCommand.Text);

            //add the command to the Commands collection of the pipeline
            pipeLine.Commands.Add(myCommand);

            Collection<PSObject> commandResults = pipeLine.Invoke();

            // iterate through the commandResults collection
            // and get the name of each cmdlet
            txtResult.Text = "start ....";
            foreach (PSObject cmdlet in commandResults)
            {
                string cmdletName = cmdlet.Properties["Name"].Value.ToString();
                System.Diagnostics.Debug.Print(cmdletName);
                txtResult.Text += "cmdletName: " + cmdletName;
            }
            txtResult.Text += ".... end";

3 个答案:

答案 0 :(得分:1)

我不确定,但Exchange 2010 powershell可能会实现为powershell 2.0模块,它以不同的方式加载。要查找,请转到具有Exchange管理外壳的系统,然后启动它。接下来,运行:

ps> get-module

这将列出已加载的v2模块。如果你已经启动了专用的Exchange管理shell,我希望交换机能够出现。如果您加载了常规的PowerShell控制台,请尝试:

ps> get-module -list

这将列出可加载的所有模块。如果你发现正确的那个,那么你需要针对v2 system.management.automation dll构建你的代码。由于超出本回复范围的原因,v2 powershell的程序集具有与v1相同的强名称,因此您无法在同一台计算机上轻松拥有两个版本的powershell。从安装了v2 powershell的计算机构建它:

InitialSessionState initial = InitialSessionState.CreateDefault();
initialSession.ImportPSModule(new[] { *modulePathOrModuleName* });
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
RunspaceInvoke invoker = new RunspaceInvoke(runspace);
Collection<PSObject> results = invoker.Invoke(*myScript*);

希望这有帮助,

-Oisin

答案 1 :(得分:1)

经过大量的反复试验,我终于弄明白了。上面代码的问题是它在针对Exchange 2007运行时运行良好,但在Exchange 2010中发生了变化。而不是名为“Microsoft.Exchange.Management.PowerShell.Admin”的管理单元,请使用此管理单元“Microsoft.Exchange.Management .PowerShell.E2010" 。

从C#运行Powershell命令的完整代码如下所示。希望这有助于其他人尝试这样做。

您还需要引用System.Management.Automation.Runspaces,System.Collections.ObjectModel和System.Management.Automation。

我发现必须使用notepad手动将对System.Management.Automation的引用添加到ItemGroup部分的csproj文件中:

  <Reference Include="System.Management.Automation" />

以下代码:

private class z_test
{
    //set up
    private RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
    private PSSnapInException snapInException = null;
    private Runspace runSpace;

    private void RunPowerShell()
    {
        //create the runspace
        runSpace = RunspaceFactory.CreateRunspace(rsConfig);
        runSpace.Open();
        rsConfig.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out snapInException);

        //set up the pipeline to run the powershell command 
        Pipeline pipeLine = runSpace.CreatePipeline();

        //create the script to run
        String sScript = "get-mailbox -identity 'rj'";

        //invoke the command
        pipeLine.Commands.AddScript(sScript);

        Collection<PSObject> commandResults = pipeLine.Invoke();

        //loop through the results of the command and load the SamAccountName into the list
        foreach (PSObject results in commandResults)
        {
            Console.WriteLine(results.Properties["SamAccountName"].Value.ToString());
        }

        pipeLine.Dispose();

        runSpace.Close();
    }
}

答案 2 :(得分:0)

这就是我在做的事情:

$sessionOptionsTimeout=180000

$sessionOptionsTimeout=180000

$so = New-PSSessionOption -OperationTimeout $sessionOptionsTimeout -IdleTimeout $sessionOptionsTimeout -OpenTimeout $sessionOptionsTimeout

$connectionUri="http://$fqdn/powershell?serializationLevel=Full;ExchClientVer=14.3.91.1"


$s = New-PSSession -ConnectionURI "$connectionUri" -ConfigurationName Microsoft.Exchange -SessionOption $so

$s | Enter-PSSession

PS&GT;得到-mailboxserver

EncryptionRequired        AutoDatabaseMountDial        DatabaseCopyAutoActivationPo
                                                       licy
------------------        ---------------------        ----------------------------
e                         GoodAvailability             Unrestricted
e                         GoodAvailability             Unrestricted

现在,将上面的内容转换为.net(c#)应该很容易......

基本上是一个例外:“C:\ Program Files \ Microsoft \ Exchange Server \ V14 \ Bin \ ConnectFunctions.ps1”

请参阅以下功能:

function _NewExchangeRunspace([String]$fqdn, 
                [System.Management.Automation.PSCredential] 
$credential=$null, 

                [bool]$UseWIA=$true, 

                [bool]$SuppressError=$false,

                $ClientApplication=$null,

                $AllowRedirection=$false)

{
    $hostFQDN = _GetHostFqdn

    if (($fqdn -ne $null) -and ($hostFQDN -ne $null) -and ($hostFQDN.ToLower() -eq $fqdn.ToLower()))

    {
        $ServicesRunning = _CheckServicesStarted

        if ($ServicesRunning -eq $false)
        {
            return
        }
    }

    Write-Verbose ($ConnectFunctions_LocalizedStrings.res_0005 -f $fqdn)

    $so = New-PSSessionOption -OperationTimeout $sessionOptionsTimeout -IdleTimeout $sessionOptionsTimeout -OpenTimeout $sessionOptionsTimeout;
    $setupRegistryEntry = get-itemproperty HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\Setup -erroraction:silentlycontinue
    if ( $setupRegistryEntry -ne $null)
    {
        $clientVersion = "{0}.{1}.{2}.{3}" -f $setupRegistryEntry.MsiProductMajor, $setupRegistryEntry.MsiProductMinor, $setupRegistryEntry.MsiBuildMajor, $setupRegistryEntry.MsiBuildMinor
        $connectionUri = "http://$fqdn/powershell?serializationLevel=Full;ExchClientVer=$clientVersion"
    }
    else
    {
        $connectionUri = "http://$fqdn/powershell?serializationLevel=Full"
    }

    if ($ClientApplication -ne $null)
    {
        $connectionUri = $connectionUri + ";clientApplication=$ClientApplication"
    }

    write-host -fore Yellow ("connectionUri: " + $connectionUri)

    $contents = 'New-PSSession -ConnectionURI "$connectionUri" -ConfigurationName Microsoft.Exchange -SessionOption $so'

    if (-not $UseWIA)
    {
        $contents = $contents + ' -Authentication Kerberos -Credential $credential'
    }
    if ($SuppressError)
    {
        $contents = $contents + ' -erroraction silentlycontinue'
    }
    if ($AllowRedirection)
    {
        $contents = $contents + ' -AllowRedirection'
    }

    write-host -fore Yellow ("contents: " + $contents)
    write-host -fore Yellow ("join n contents: " + [string]::join("`n", $contents))


    [ScriptBlock] $command = $executioncontext.InvokeCommand.NewScriptBlock([string]::join("`n", $contents))
    $session=invoke-command -Scriptblock $command

  if (!$?)
    {
      # ERROR_ACCESS_DENIED = 5
      # ERROR_LOGON_FAILURE = 1326
      if (!(5 -eq $error[0].exception.errorcode) -and
          !(1326 -eq $error[0].exception.errorcode))
      {
            #Write-Verbose ($ConnectFunctions_LocalizedStrings.res_0006 -f $fqdn)
            return
      }
      else
      {
        # no retries if we get 5 (access denied) or 1326 (logon failure)
        #$REVIEW$ connectedFqdn is not set. Is it okay?
        break connectScope
      }
    }
  $session
}