Connectez-vous à Microsoft Exchange PowerShell en C #

J’essaie de me connecter à PowerShell à distance à partir de l’application C # .NET WinForms. Mon objective est de créer ma propre version de Microsoft PowerShell ISE. J’ai donc besoin d’un moyen d’exécuter les scripts PowerShell à partir de mon application sur des ordinateurs distants. J’ai créé plusieurs méthodes et testé sur la machine locale à partir de mon application. Si je n’utilise pas WSManConnectionInfo et que j’utilise (Runspace remoteRunspace = RunspaceFactory.CreateRunspace ()), je peux exécuter des scripts localement comme s’il s’agissait de true powershell (petits scripts, utilisation de variables, données de sortie à l’aide de ft , fl , faire beaucoup de Le problème commence lorsque j’ajoute WSManConnectionInfo et que je le signale à mon serveur Exchange au lieu d’utiliser une connexion locale. Il semble qu’il soit capable d’exécuter des tâches de base telles que “get-mailbox”, mais dès que j’essaie de diriger les choses , utilise des fonctionnalités de script telles que $ variables, elle rompt en disant qu’elle n’est pas prise en charge.

De même, je dois désactiver powershell.AddCommand (“out-ssortingng”); lorsque vous ne l’utilisez pas localement.

Une exception non gérée du type ‘System.Management.Automation.RemoteException’ s’est produite dans System.Management.Automation.dll.

Informations complémentaires: Le terme ‘Out-Ssortingng’ n’est pas reconnu en tant que nom d’une applet de commande, d’une fonction, d’un fichier de script ou d’un programme utilisable. Vérifiez l’orthographe du nom ou, si un chemin a été inclus, vérifiez que le chemin est correct et réessayez.

La même erreur n’apparaît pas si je ne force pas la connexion à distance mais le fais simplement localement. Il semble que SchemaUri rend très ssortingcte l’exécution de commandes de base. J’ai vu d’autres exemples où des personnes utilisaient des informations très directes telles que nous:

powershell.AddCommand("Get-Users"); powershell.AddParameter("ResultSize", count); 

Mais avec cette approche, je devrais définir beaucoup d’options possibles et je ne voudrais pas aller à travers la définition de parameters et d’autres choses. Je voudrais simplement charger “script” et l’exécuter comme dans la fenêtre PowerShell. Voici un exemple de ce que j’utilise maintenant.

  public static WSManConnectionInfo PowerShellConnectionInformation(ssortingng serverUrl, PSCredential psCredentials) { var connectionInfo = new WSManConnectionInfo(new Uri(serverUrl), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", psCredentials); //var connectionInfo = new WSManConnectionInfo(new Uri(serverUrl), "http://schemas.microsoft.com/powershell", psCredentials); connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Basic; connectionInfo.SkipCACheck = true; connectionInfo.SkipCNCheck = true; connectionInfo.SkipRevocationCheck = true; connectionInfo.MaximumConnectionRedirectionCount = 5; connectionInfo.OperationTimeout = 150000; return connectionInfo; } public static PSCredential SecurePassword(ssortingng login, ssortingng password) { SecureSsortingng ssLoginPassword = new SecureSsortingng(); foreach (char x in password) { ssLoginPassword.AppendChar(x); } return new PSCredential(login, ssLoginPassword); } public static ssortingng RunScriptPs(WSManConnectionInfo connectionInfo, ssortingng scriptText) { SsortingngBuilder ssortingngBuilder = new SsortingngBuilder(); // Create a remote runspace using the connection information. //using (Runspace remoteRunspace = RunspaceFactory.CreateRunspace()) using (Runspace remoteRunspace = RunspaceFactory.CreateRunspace(connectionInfo)) { // Establish the connection by calling the Open() method to open the runspace. // The OpenTimeout value set previously will be applied while establishing // the connection. Establishing a remote connection involves sending and // receiving some data, so the OperationTimeout will also play a role in this process. remoteRunspace.Open(); // Create a PowerShell object to run commands in the remote runspace. using (PowerShell powershell = PowerShell.Create()) { powershell.Runspace = remoteRunspace; powershell.AddScript(scriptText); //powershell.AddCommand("out-ssortingng"); powershell.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output); Collection results = powershell.Invoke(); foreach (PSObject result in results) { ssortingngBuilder.AppendLine(result.ToSsortingng()); } } // Close the connection. Call the Close() method to close the remote // runspace. The Dispose() method (called by using primitive) will call // the Close() method if it is not already called. remoteRunspace.Close(); } // convert the script result into a single ssortingng return ssortingngBuilder.ToSsortingng(); } 

Avez-vous des conseils sur les raisons pour lesquelles cela se produit et comment contourner le problème pour qu’il se comporte de la même manière? J’ai vu beaucoup de blogs comme celui-ci, mais définir chaque commande simple n’a aucun sens pour moi. J’ai également vu une option pour créer une connexion locale et ensuite exécuter une connexion à distance à l’intérieur de celle-ci, mais cela doit être utilisé en dernier recours, car elle repose sur de nombreux autres facteurs.

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

L’expérience de gestion fournie par Exchange 2010 via PowerShell a été déplacée de local à distant. […] Seules les applets de commande d’échange fonctionneront dans ce scénario distant, vous ne pourrez pas exécuter la plupart des applets de commande powershell . […] Oui, cela signifie que vous ne pourrez pas exécuter d’applets de commande comme les scripts Where-Object et .PS1 dans l’espace d’exécution distant .

Est-ce une limitation? Je ne pense pas. Nous pouvons très facilement le contourner en créant une nouvelle session et en l’important .


Donc vous aurez besoin de faire quelque chose comme ça :

 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 result = powershell.Invoke(); 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 

À partir d’Exchange Server 2010, vous devez utiliser une session PowerShell distante au lieu d’append directement le composant logiciel enfichable Exchange PowerShell (en raison de l’utilisation de RBAC au lieu de ACL dans Exchange 2010). Vous devez donc créer une nouvelle session PowerShell (à l’aide de New-PSSession), puis l’importer (à l’aide de Import-PSSession). Vous pouvez utiliser un code comme celui-ci pour exécuter vos commandes PowerShell à distance:

 void ExecutePowerShellUsingRemotimg() { RunspaceConfiguration runspaceConfig = RunspaceConfiguration.Create(); PSSnapInException snapInException = null; Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfig); runspace.Open(); Pipeline pipeline = runspace.CreatePipeline(); ssortingng serverFqdn = "FQDN of you server"; pipeline.Commands.AddScript(ssortingng.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-Ssortingng"); Collection results = pipeline.Invoke(); runspace.Close(); SsortingngBuilder sb = new SsortingngBuilder(); if (pipeline.Error != null && pipeline.Error.Count > 0) { // Read errors succeeded = false; Collection errors = pipeline.Error.ReadToEnd(); foreach (object error in errors) sb.Append(error.ToSsortingng()); } else { // Read output foreach (PSObject obj in results) sb.Append(obj.ToSsortingng()); } runspace.Dispose(); pipeline.Dispose(); } 

Il semble que vous renconsortingez des problèmes d’authentification à double saut, mais j’ai eu les mêmes problèmes lorsque j’essayais de le faire.

Après avoir déconné, j’ai fini par installer les compléments Exchange Powershell localement et les ai utilisés pour se connecter à distance au serveur Exchange.

Exemple approximatif:

  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; ssortingng script = ssortingng.Format(@"Get-Mailbox -Server {0} -Identity {1}", serverName, identity); powershell.AddScript(script); powershell.Invoke(); // Do something with the output }