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

发布于 2024-09-16 09:36:08 字数 1967 浏览 1 评论 0原文

在 Exchange 2007 中,这行代码用于加载 Exchange Poweshell 命令管理单元:

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

In Exchange 2007 this line of code is used to load the Exchange Poweshell commands snapin:

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

However, this does not exist in Exchange 2010 and I am pulling my hair out trying to find out how to access the Exchange Powershell commands from C# code. Microsoft.Exchange.Management.PowerShell.Admin does not exist anywhere on the Exchange Server and I can find nothing on Google that talks about an equivalent line of code.

How do I access Exchange Management Tools from C# code in Exchange 2010?

Below is my complete code for reference, it all works until I add the line of code:

                //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";

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

三生殊途 2024-09-23 09:36:08

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

ps> get-module

这将列出已加载的 v2 模块。如果您启动了专用的交换管理外壳,我希望交换一会出现。如果您加载了常规 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

I don't know for sure, but Exchange 2010 powershell might be implemented as a powershell 2.0 module, which is loaded in a different manner. To find out, go to a system with the exchange management shell on it, and fire it up. Next, run:

ps> get-module

This will list the loaded v2 modules. I would expect the exchange one to appear if you have started the dedicated exchange management shell. If you loaded the regular powershell console, try:

ps> get-module -list

This will list all modules available to load. If you spot the right one, then you'll need to build your code against the v2 system.management.automation dll. For reasons beyond the scope of this reply, v2 powershell's assembly has the same strong name as v1's, so you cannot easily have both versions of powershell on the same machine. Build this from a machine with v2 powershell installed:

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

Hope this helps,

-Oisin

久而酒知 2024-09-23 09:36:08

经过多次尝试和错误,我终于弄清楚了这一点。上述代码的问题是,在 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。

我发现必须使用记事本将 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();
    }
}

After a lot of trial and error, I finally figured this out. The problem with the code above is it works great when run against Exchange 2007 but things have changed in Exchange 2010. Instead of the snapin called "Microsoft.Exchange.Management.PowerShell.Admin", use this snapin, "Microsoft.Exchange.Management.PowerShell.E2010".

The complete code to run a Powershell command from C# looks like this. Hope this helps someone else trying to do this.

You will need references to System.Management.Automation.Runspaces, System.Collections.ObjectModel and System.Management.Automation also.

I found that the reference to System.Management.Automation had to be manually added to the csproj file itself in the ItemGroup section using notepad like this:

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

code below:

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();
    }
}
七颜 2024-09-23 09:36:08

这就是我正在做的事情:

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

This is what I am doing:

$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>get-mailboxserver

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

Now, converting above to .net (c#) should be easy...

Essentially an exerpt from: "C:\Program Files\Microsoft\Exchange Server\V14\Bin\ConnectFunctions.ps1"

Please refer to the following function:

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文