W Powershell 2.0 mamy możliwość zdalnego wykonywania poleceń. Powershell domyślnie też umożliwia odwołania z kodu C# do comandletów Powershellowych. Jednak połączenie remotingu Powershella oraz C# nie jest prostym zadaniem – brakuje po prostu przykładów. Nawet google jest w tym wypadku bezradny.
Po wnikliwej lekturze SDK do Powershell-a, możemy znaleźć klasę RunspaceConnectionInfo, ale niestety ta klasa ma prywatny konstruktor. Na szczęście jest klasa WSManConnection Info.
Jak więc zacząć? Zacznijmy od wymaganych klas:
using System.Collections.Generic; using System.Management.Automation; using System.Collections.ObjectModel; using System.Management.Automation.Runspaces;
Przy czym odwołanie do System.Management.Automation; wymaga referencji do klasy System.Management.Automation.dll. Domyślnie klasa nie jest wrzucana do GAC, więc ręcznie musimy przeszukać katalog %WinDir% i ją sobie wyciągnąć.
Remote powershell ma ogrniczenie co do ilości sesji, więc musimy gdzieś przechowywać informacje o sesji. Tu na przykład przechowuję informację o tworzeniu sesji w globalnych zmiennych aplikacji:
/// <summary> /// Opens remote runspace /// </summary> /// <param name="uri">Uri to connect to, for example https://pod51002psh.outlook.com/powershell/"</param> /// <param name="schema">Schema of connection, for example http://schemas.microsoft.com/powershell/Microsoft.Exchange</param> /// <param name="username">Username</param> /// <param name="password">Secure pasword</param> /// <returns></returns> public void openRunspace(string uri, string schema, string username, string livePass) { System.Security.SecureString password = new System.Security.SecureString(); foreach (char c in livePass.ToCharArray()) { password.AppendChar(c); } PSCredential psc = new PSCredential(username, password); WSManConnectionInfo rri = new WSManConnectionInfo(new Uri(uri), schema, psc); rri.AuthenticationMechanism = AuthenticationMechanism.Basic; Runspace runspace = RunspaceFactory.CreateRunspace(rri); runspace.Open(); Application["runspace"] = runspace; } A inicjalizacja takiej funkcji by wyglądała np tak:
/// <summary>
/// Opens remote runspace
/// </summary>
/// <param name="uri">Uri to connect to, for example https://pod51002psh.outlook.com/powershell/"</param>
/// <param name="schema">Schema of connection, for example http://schemas.microsoft.com/powershell/Microsoft.Exchange</param>
/// <param name="username">Username</param>
/// <param name="password">Secure pasword</param>
/// <returns></returns>
public void openRunspace(string uri, string schema, string username, string livePass)
{
System.Security.SecureString password = new System.Security.SecureString();
foreach (char c in livePass.ToCharArray())
password.AppendChar(c);
}
PSCredential psc = new PSCredential(username, password);
WSManConnectionInfo rri = new WSManConnectionInfo(new Uri(uri), schema, psc);
rri.AuthenticationMechanism = AuthenticationMechanism.Basic;
Runspace runspace = RunspaceFactory.CreateRunspace(rri);
runspace.Open();
Application["runspace"] = runspace;
protected void Application_Start(object sender, EventArgs e) { string psremoteserver = "https://pod51002psh.outlook.com/powershell/"; string liveLogin = "liveadmin@domain.fqdn"; string livePass = "Pass"; string schema = "http://schemas.microsoft.com/powershell/Microsoft.Exchange"; if (Application["runspace"] == null) openRunspace(psremoteserver, schema, liveLogin, livePass); }
protected void Application_Start(object sender, EventArgs e)
string psremoteserver = "https://pod51002psh.outlook.com/powershell/";
string liveLogin = "liveadmin@domain.fqdn";
string livePass = "Pass";
string schema = "http://schemas.microsoft.com/powershell/Microsoft.Exchange";
if (Application["runspace"] == null)
openRunspace(psremoteserver, schema, liveLogin, livePass);
Nie zapomnijmy o zamykaniu sesji:
protected void Application_End(object sender, EventArgs e) { if (Application["runspace"] != null) { Runspace rs = (Runspace)Application["runspace"]; rs.Close(); } } protected void Application_Error(object sender, EventArgs e) { if (Application["runspace"] != null) { Runspace rs = (Runspace)Application["runspace"]; rs.Close(); } }
protected void Application_End(object sender, EventArgs e)
if (Application["runspace"] != null)
Runspace rs = (Runspace)Application["runspace"];
rs.Close();
protected void Application_Error(object sender, EventArgs e)
Po stworzeniu połączenia nie pozostaje nam nic innego jak go użyć. Np tak:
/// <summary> /// Opens remote runspace /// </summary> /// <param name="uri">Uri to connect to, for example https://pod51002psh.outlook.com/powershell/"</param> /// <param name="schema">Schema of connection, for example http://schemas.microsoft.com/powershell/Microsoft.Exchange</param> /// <param name="username">Username</param> /// <param name="password">Secure pasword</param> /// <returns></returns> public void openRunspace(string uri, string schema, string username, string livePass) { System.Security.SecureString password = new System.Security.SecureString(); foreach (char c in livePass.ToCharArray()) { password.AppendChar(c); } PSCredential psc = new PSCredential(username, password); WSManConnectionInfo rri = new WSManConnectionInfo(new Uri(uri), schema, psc); rri.AuthenticationMechanism = AuthenticationMechanism.Basic; Runspace runspace = RunspaceFactory.CreateRunspace(rri); runspace.Open(); Application["runspace"] = runspace; } private Runspace getRunSpace() { Runspace runspace = (Runspace)Application["runspace"]; if (runspace.RunspaceStateInfo.State != RunspaceState.Opened) runspace.Open(); return runspace; } /// <summary> /// Invokes any powershell script /// </summary> /// <param name="scriptText">script to invoke</param> /// <returns></returns> public Collection<PSObject> RunScript(string scriptText) { Runspace runspace = getRunSpace(); // create a pipeline and feed it the script text Pipeline pipeline = runspace.CreatePipeline(); pipeline.Commands.AddScript(scriptText); // execute the script Collection<PSObject> results = new Collection<PSObject>(); results = pipeline.Invoke(); return results; } /// <summary> /// Invoke simple command /// Ex. /// Collection<PSObject> col = RunCommand("Get-Mailbox"); /// </summary> /// <param name="command">Command Name</param> /// <returns></returns> public Collection<PSObject> RunCommand(string command) { Command myCommand = new Command(command); Pipeline pipeLine = getRunSpace().CreatePipeline(); pipeLine.Commands.Add(myCommand); return pipeLine.Invoke(); } /// <summary> /// Invoke command with single paramtere /// </summary> /// <param name="command">Command</param> /// <param name="param">Command parameter</param> /// <returns></returns> public Collection<PSObject> RunCommand(string command, string param) { Command myCommand = new Command(command); myCommand.Parameters.Add(param); Pipeline pipeLine = getRunSpace().CreatePipeline(); pipeLine.Commands.Add(myCommand); return pipeLine.Invoke(); } /// <summary> /// Invoke command with single named parameter /// Ex. /// Collection<PSObject> col = RunCommand("Get-Mailbox","Identity","usr@iscg.eu"); /// </summary> /// <param name="command">Command to invoke</param> /// <param name="param">Parameter Name</param> /// <param name="paramValue">Parameter value</param> /// <returns></returns> public Collection<PSObject> RunCommand(string command, string param, object paramValue) { Command myCommand = new Command(command); myCommand.Parameters.Add(new CommandParameter(param, paramValue)); Pipeline pipeLine = getRunSpace().CreatePipeline(); pipeLine.Commands.Add(myCommand); return pipeLine.Invoke(); } /// <summary> /// Invokes command with collection of paramters /// Ex. /// Collection<CommandParameter> cpc = new Collection<CommandParameter>(); /// cpc.Add(new CommandParameter("Identity", "user@iscg.eu")); /// Collection<PSObject> col = RunCommand("Get-Mailbox",cpc); /// </summary> /// <param name="command"></param> /// <param name="param"></param> /// <returns></returns> public Collection<PSObject> RunCommand(string command, Collection<CommandParameter> param) { Command myCommand = new Command(command); foreach (CommandParameter cp in param) myCommand.Parameters.Add(cp); Pipeline pipeLine = getRunSpace().CreatePipeline(); pipeLine.Commands.Add(myCommand); return pipeLine.Invoke(); } public string translatePSObject(Collection<PSObject> input) { StringBuilder stringBuilder = new StringBuilder(); foreach (PSObject obj in (input)) { stringBuilder.AppendLine(obj.ToString() + obj.GetType() + obj.ImmediateBaseObject.GetType()); } return stringBuilder.ToString(); }
private Runspace getRunSpace()
Runspace runspace = (Runspace)Application["runspace"];
if (runspace.RunspaceStateInfo.State != RunspaceState.Opened)
return runspace;
/// Invokes any powershell script
/// <param name="scriptText">script to invoke</param>
public Collection<PSObject> RunScript(string scriptText)
Runspace runspace = getRunSpace();
// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
// execute the script
Collection<PSObject> results = new Collection<PSObject>();
results = pipeline.Invoke();
return results;
/// Invoke simple command
/// Ex.
/// Collection<PSObject> col = RunCommand("Get-Mailbox");
/// <param name="command">Command Name</param>
public Collection<PSObject> RunCommand(string command)
Command myCommand = new Command(command);
Pipeline pipeLine = getRunSpace().CreatePipeline();
pipeLine.Commands.Add(myCommand);
return pipeLine.Invoke();
/// Invoke command with single paramtere
/// <param name="command">Command</param>
/// <param name="param">Command parameter</param>
public Collection<PSObject> RunCommand(string command, string param)
myCommand.Parameters.Add(param);
/// Invoke command with single named parameter
/// Collection<PSObject> col = RunCommand("Get-Mailbox","Identity","usr@iscg.eu");
/// <param name="command">Command to invoke</param>
/// <param name="param">Parameter Name</param>
/// <param name="paramValue">Parameter value</param>
public Collection<PSObject> RunCommand(string command, string param, object paramValue)
myCommand.Parameters.Add(new CommandParameter(param, paramValue));
/// Invokes command with collection of paramters
/// Collection<CommandParameter> cpc = new Collection<CommandParameter>();
/// cpc.Add(new CommandParameter("Identity", "user@iscg.eu"));
/// Collection<PSObject> col = RunCommand("Get-Mailbox",cpc);
/// <param name="command"></param>
/// <param name="param"></param>
public Collection<PSObject> RunCommand(string command, Collection<CommandParameter> param)
foreach (CommandParameter cp in param)
myCommand.Parameters.Add(cp);
public string translatePSObject(Collection<PSObject> input)
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in (input))
stringBuilder.AppendLine(obj.ToString() + obj.GetType() + obj.ImmediateBaseObject.GetType());
return stringBuilder.ToString();
Remember Me