/// <summary> /// Creates new remote PS session if neccesary, and returns unique session identifier /// </summary> public string Connect(PSConnection options, out object state) { var connectionHash = GetConnectionHash(options); var sessionStateVars = new Dictionary <string, object>(); // state vars as result from InitConnection var newLazy = new Lazy <object>(() => InitConnection(options, sessionStateVars)); var lazyFromCache = (Lazy <object>)sessions.AddOrGetExisting(connectionHash, newLazy, runspacePolicy); try { // force lazy initialization var connection = (lazyFromCache ?? newLazy).Value; } catch (Exception) { sessions.Remove(connectionHash); throw; } var stateDict = ((ConcurrentDictionary <string, object>)sessionState .GetOrAdd(connectionHash, _ => new ConcurrentDictionary <string, object>())); stateDict.AddOrUpdate(RefCounterKey, 1, (key, current) => (int)current + 1); foreach (var sesVars in sessionStateVars) { stateDict.TryAdd(sesVars.Key, sesVars.Value); } string newSession = Guid.NewGuid().ToString(); sessions.Add(newSession, connectionHash, options.ShortTimeConnection ? shortTimeSessionPolicy : sessionPolicy); // session refers to shared connection state = stateDict; return(newSession); }
private object InitConnection(PSConnection options, Dictionary <string, object> sessionStateVars) { Uri connectTo = null; string hostName = options.ComputerName; if (hostName != null && hostName.IndexOf(':') == -1) { hostName += ":5985"; } connectTo = new Uri(String.Format("http://{0}/wsman", hostName)); var user = options.UserName; if (!user.Contains("\\")) { user = "******" + user; } var connection = new WSManConnectionInfo(connectTo, null, new PSCredential(user, options.Password)); connection.AuthenticationMechanism = options.Authentication; Runspace runspace; if (options.InteractiveTerminal) { var factory = new PsFactory(); var interactiveHost = new WmBridge.Web.Terminal.Host(factory); if (options.Options != null) { dynamic size; if (options.Options.TryGetValue("BufferSize", out size)) { interactiveHost.Terminal.BufferSize = new System.Management.Automation.Host.Size(Convert.ToInt32(size.Width), Convert.ToInt32(size.Height)); } if (options.Options.TryGetValue("WindowSize", out size)) { interactiveHost.Terminal.WindowSize = new System.Management.Automation.Host.Size(Convert.ToInt32(size.Width), Convert.ToInt32(size.Height)); } } runspace = RunspaceFactory.CreateRunspace(interactiveHost, connection); factory.Runspace = runspace; sessionStateVars.Add(PSSessionManager.PSHostClientKey, interactiveHost); } else { runspace = RunspaceFactory.CreateRunspace(connection); } logger.InfoFormat("Opening runspace: {0}", runspace.ConnectionInfo.ComputerName); try { runspace.Open(); logger.InfoFormat("Runspace opened: {0}; InstanceId: {1}", runspace.ConnectionInfo.ComputerName, runspace.InstanceId); } catch (Exception ex) { logger.Error(string.Format("Failed to open runspace: {0} - {1}", runspace.ConnectionInfo.ComputerName, ex.Message)); throw; } var eap = ""; using (var ps = PowerShell.Create()) { ps.Runspace = runspace; string script = options.InteractiveTerminal ? "" : "$ErrorActionPreference = 'stop';"; if (!string.IsNullOrEmpty(options.ExecutionPolicy)) { script += "Set-ExecutionPolicy $args[0] -Scope Process -Force;"; } script += "$PSVersionTable.PSVersion; $ErrorActionPreference;"; ps.AddScript(script); ps.AddArgument(options.ExecutionPolicy); var psResult = ps.Invoke(); if (psResult.Count == 2) { sessionStateVars.Add(PSSessionManager.PSVersionKey, psResult[0].BaseObject as Version); eap = psResult[1].ToString(); } } if (!string.IsNullOrEmpty(options.Script)) { using (var ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddScript($"$ErrorActionPreference = 'stop'; {options.Script}; $ErrorActionPreference = '{eap}';"); ps.Invoke(); } } if (!string.IsNullOrEmpty(options.ClientVersion)) { Version ver; if (Version.TryParse(options.ClientVersion, out ver)) { sessionStateVars.Add(PSSessionManager.ClientVersionKey, ver); } } return(runspace); }
string GetConnectionHash(PSConnection connection) { using (MD5 md5 = MD5.Create()) return(System.Convert.ToBase64String(md5.ComputeHash(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(connection))))); }