Connect to Microsoft Exchange PowerShell within C#

ぐ巨炮叔叔 提交于 2019-12-01 03:35:28

Check https://blogs.msdn.microsoft.com/akashb/2010/03/25/how-to-migrating-exchange-2007-powershell-managed-code-to-work-with-exchange-2010/:

The management experience given by Exchange 2010 through PowerShell has been moved all the way from Local to Remote. [...] Only exchange cmdlets will work in this remoting scenario, you will not be able to run most of the powershell cmdlets. [...] Yes, this does mean that you will not be able to run cmdlets like Where-Object and .PS1 scripts in the Remote Runspace.

Is that a limitation? I don’t think so. We can very easily get around it by create a new Session and Importing it.


So you'll need to do something like this:

PSCredential creds = new PSCredential(userName, securePassword);
System.Uri uri = new Uri("http://Exchange-Server/powershell?serializationLevel=Full");

Runspace runspace = RunspaceFactory.CreateRunspace();

PowerShell powershell = PowerShell.Create();
PSCommand command = new PSCommand();
command.AddCommand("New-PSSession");
command.AddParameter("ConfigurationName", "Microsoft.Exchange");
command.AddParameter("ConnectionUri", uri);
command.AddParameter("Credential", creds);
command.AddParameter("Authentication", "Default");
powershell.Commands = command;
runspace.Open(); powershell.Runspace = runspace;
Collection<PSSession> result = powershell.Invoke<PSSession>();

powershell = PowerShell.Create();
command = new PSCommand();
command.AddCommand("Set-Variable");
command.AddParameter("Name", "ra");
command.AddParameter("Value", result[0]);
powershell.Commands = command;
powershell.Runspace = runspace;
powershell.Invoke();

powershell = PowerShell.Create();
command = new PSCommand();
command.AddScript("Import-PSSession -Session $ra");
powershell.Commands = command;
powershell.Runspace = runspace;
powershell.Invoke();

# now you can use remote PS like it's local one

Starting from Exchange Server 2010 you need to use remote PowerShell session instead of adding exchange PowerShell snapin directly (due to using RBAC instead of ACL in exchange 2010). So you need to create new PowerShell session (using New-PSSession) and then import it (using Import-PSSession). You can use code like this to execute you PowerShell commands remote:

void ExecutePowerShellUsingRemotimg()
{
    RunspaceConfiguration runspaceConfig = RunspaceConfiguration.Create();
    PSSnapInException snapInException = null;

    Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfig);
    runspace.Open();

    Pipeline pipeline = runspace.CreatePipeline();


    string serverFqdn = "FQDN of you server";
    pipeline.Commands.AddScript(string.Format("$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://{0}/PowerShell/ -Authentication Kerberos", serverFqdn));
    pipeline.Commands.AddScript("Import-PSSession $Session");
    pipeline.Commands.AddScript("your PowerShell script text");
    pipeline.Commands.Add("Out-String");
    Collection<PSObject> results = pipeline.Invoke();
    runspace.Close();

    StringBuilder sb = new StringBuilder();

    if (pipeline.Error != null && pipeline.Error.Count > 0)
    {
        // Read errors
        succeeded = false;
        Collection<object> errors = pipeline.Error.ReadToEnd();
        foreach (object error in errors)
            sb.Append(error.ToString());
    }
    else
    {
        // Read output
        foreach (PSObject obj in results)
            sb.Append(obj.ToString());
    }

    runspace.Dispose();
    pipeline.Dispose();
}

It looks like your running into double hop authentication problems, I've had the very same issues when trying to this.

After messing around I ended up installing the Exchange Powershell addins locally and used them to connect remotely to the Exchange server.

Rough example:

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

    Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
    runspace.Open();

    using (PowerShell powershell = PowerShell.Create())
    {
        powershell.Runspace = runspace;

        string script = string.Format(@"Get-Mailbox -Server {0} -Identity {1}", serverName, identity);
        powershell.AddScript(script);

        powershell.Invoke();

       // Do something with the output

    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!