MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Management.Automation.Internal;5 6using Dbg = System.Management.Automation.Diagnostics;7 8namespace System.Management.Automation.Runspaces9{10 /// <summary>11 /// Computer target type.12 /// </summary>13 public enum TargetMachineType14 {15 /// <summary>16 /// Target is a machine with which the session is based on networking.17 /// </summary>18 RemoteMachine,19 20 /// <summary>21 /// Target is a virtual machine with which the session is based on Hyper-V socket.22 /// </summary>23 VirtualMachine,24 25 /// <summary>26 /// Target is a container with which the session is based on Hyper-V socket (Hyper-V27 /// container) or named pipe (windows container)28 /// </summary>29 Container30 }31 32 /// <summary>33 /// Class that exposes read only properties and which conveys information34 /// about a remote runspace object to the user. The class serves the35 /// following purpose:36 /// 1. Exposes useful information to the user as properties37 /// 2. Shields the remote runspace object from directly being exposed38 /// to the user. This way, the user will not be able to directly39 /// act upon the object, but instead will have to use the remoting40 /// cmdlets. This will prevent any unpredictable behavior.41 /// </summary>42 public sealed class PSSession43 {44 #region Private Members45 46 private RemoteRunspace _remoteRunspace;47 private string _transportName;48 49 /// <summary>50 /// Static variable which is incremented to generate id.51 /// </summary>52 private static int s_seed = 0;53 54 #endregion Private Members55 56 #region Public Properties57 58 /// <summary>59 /// Type of the computer target.60 /// </summary>61 public TargetMachineType ComputerType { get; set; }62 63 /// <summary>64 /// Name of the computer target.65 /// </summary>66 public string ComputerName67 {68 get69 {70 return _remoteRunspace.ConnectionInfo.ComputerName;71 }72 }73 74 /// <summary>75 /// Id of the container target.76 /// </summary>77 public string ContainerId78 {79 get80 {81 if (ComputerType == TargetMachineType.Container)82 {83 ContainerConnectionInfo connectionInfo = _remoteRunspace.ConnectionInfo as ContainerConnectionInfo;84 return connectionInfo.ContainerProc.ContainerId;85 }86 else87 {88 return string.Empty;89 }90 }91 }92 93 /// <summary>94 /// Name of the virtual machine target.95 /// </summary>96 public string VMName97 {98 get99 {100 if (ComputerType == TargetMachineType.VirtualMachine)101 {102 return _remoteRunspace.ConnectionInfo.ComputerName;103 }104 else105 {106 return string.Empty;107 }108 }109 }110 111 /// <summary>112 /// Guid of the virtual machine target.113 /// </summary>114 public Guid? VMId115 {116 get117 {118 if (ComputerType == TargetMachineType.VirtualMachine)119 {120 VMConnectionInfo connectionInfo = _remoteRunspace.ConnectionInfo as VMConnectionInfo;121 return connectionInfo.VMGuid;122 }123 else124 {125 return null;126 }127 }128 }129 130 /// <summary>131 /// Shell which is executed in the remote machine.132 /// </summary>133 public string ConfigurationName { get; }134 135 /// <summary>136 /// InstanceID that identifies this runspace.137 /// </summary>138 public Guid InstanceId139 {140 get141 {142 return _remoteRunspace.InstanceId;143 }144 }145 146 /// <summary>147 /// SessionId of this runspace. This is unique only across148 /// a session.149 /// </summary>150 public int Id { get; }151 152 /// <summary>153 /// Friendly name for identifying this runspace.154 /// </summary>155 public string Name { get; set; }156 157 /// <summary>158 /// Indicates whether the specified runspace is available159 /// for executing commands.160 /// </summary>161 public RunspaceAvailability Availability162 {163 get164 {165 return Runspace.RunspaceAvailability;166 }167 }168 169 /// <summary>170 /// Private data to be used by applications built on top of PowerShell.171 /// Optionally sent by the remote server when creating a new session / runspace.172 /// </summary>173 public PSPrimitiveDictionary ApplicationPrivateData174 {175 get176 {177 return this.Runspace.GetApplicationPrivateData();178 }179 }180 181 /// <summary>182 /// The remote runspace object based on which this information object183 /// is derived.184 /// </summary>185 /// <remarks>This property is marked internal to allow other cmdlets186 /// to get access to the RemoteRunspace object and operate on it like187 /// for instance test-runspace, close-runspace etc</remarks>188 public Runspace Runspace189 {190 get191 {192 return _remoteRunspace;193 }194 }195 196 /// <summary>197 /// Name of the transport used.198 /// </summary>199 public string Transport => GetTransportName();200 201 #endregion Public Properties202 203 #region Public Methods204 205 /// <summary>206 /// ToString method override.207 /// </summary>208 /// <returns>String.</returns>209 public override string ToString()210 {211 // PSSession is a PowerShell type name and so should not be localized.212 const string formatString = "[PSSession]{0}";213 return StringUtil.Format(formatString, Name);214 }215 216 #endregion217 218 #region Internal Methods219 220 /// <summary>221 /// Internal method to insert a runspace into a PSSession object.222 /// This is used only for Disconnect/Reconnect scenarios where the223 /// new runspace is a reconstructed runspace having the same Guid224 /// as the existing runspace.225 /// </summary>226 /// <param name="remoteRunspace">Runspace to insert.</param>227 /// <returns>Boolean indicating if runspace was inserted.</returns>228 internal bool InsertRunspace(RemoteRunspace remoteRunspace)229 {230 if (remoteRunspace == null ||231 remoteRunspace.InstanceId != _remoteRunspace.InstanceId)232 {233 return false;234 }235 236 _remoteRunspace = remoteRunspace;237 return true;238 }239 240 #endregion241 242 #region Constructor243 244 /// <summary>245 /// This constructor will be used to created a remote runspace info246 /// object with a auto generated name.247 /// </summary>248 /// <param name="remoteRunspace">Remote runspace object for which249 /// the info object need to be created</param>250 internal PSSession(RemoteRunspace remoteRunspace)251 {252 _remoteRunspace = remoteRunspace;253 254 // Use passed in session Id, if available.255 if (remoteRunspace.PSSessionId != -1)256 {257 Id = remoteRunspace.PSSessionId;258 }259 else260 {261 Id = System.Threading.Interlocked.Increment(ref s_seed);262 remoteRunspace.PSSessionId = Id;263 }264 265 // Use passed in friendly name, if available.266 if (!string.IsNullOrEmpty(remoteRunspace.PSSessionName))267 {268 Name = remoteRunspace.PSSessionName;269 }270 else271 {272 Name = "Runspace" + Id;273 remoteRunspace.PSSessionName = Name;274 }275 276 switch (remoteRunspace.ConnectionInfo)277 {278 case WSManConnectionInfo _:279 ComputerType = TargetMachineType.RemoteMachine;280 string fullShellName = WSManConnectionInfo.ExtractPropertyAsWsManConnectionInfo<string>(281 remoteRunspace.ConnectionInfo,282 "ShellUri", string.Empty);283 ConfigurationName = GetDisplayShellName(fullShellName);284 break;285 286 case VMConnectionInfo vmConnectionInfo:287 ComputerType = TargetMachineType.VirtualMachine;288 ConfigurationName = vmConnectionInfo.ConfigurationName;289 break;290 291 case ContainerConnectionInfo containerConnectionInfo:292 ComputerType = TargetMachineType.Container;293 ConfigurationName = containerConnectionInfo.ContainerProc.ConfigurationName;294 break;295 296 case SSHConnectionInfo _:297 ComputerType = TargetMachineType.RemoteMachine;298 ConfigurationName = "DefaultShell";299 break;300 301 case NewProcessConnectionInfo _:302 ComputerType = TargetMachineType.RemoteMachine;303 break;304 305 default:306 // Default for custom connection and transports.307 ComputerType = TargetMachineType.RemoteMachine;308 break;309 }310 }311 312 #endregion Constructor313 314 #region Private Methods315 316 /// <summary>317 /// Generates and returns the runspace name.318 /// </summary>319 /// <returns>Auto generated name.</returns>320 private string GetTransportName()321 {322 switch (_remoteRunspace.ConnectionInfo)323 {324 case WSManConnectionInfo _:325 return "WSMan";326 327 case SSHConnectionInfo _:328 return "SSH";329 330 case NamedPipeConnectionInfo _:331 return "NamedPipe";332 333 case ContainerConnectionInfo _:334 return "Container";335 336 case NewProcessConnectionInfo _:337 return "Process";338 339 case VMConnectionInfo _:340 return "VMBus";341 342 default:343 return string.IsNullOrEmpty(_transportName) ? "Custom" : _transportName;344 }345 }346 347 /// <summary>348 /// Returns shell configuration name with shell prefix removed.349 /// </summary>350 /// <param name="shell">Shell configuration name.</param>351 /// <returns>Display shell name.</returns>352 private static string GetDisplayShellName(string shell)353 {354 const string shellPrefix = System.Management.Automation.Remoting.Client.WSManNativeApi.ResourceURIPrefix;355 int index = shell.IndexOf(shellPrefix, StringComparison.OrdinalIgnoreCase);356 357 return (index == 0) ? shell.Substring(shellPrefix.Length) : shell;358 }359 360 #endregion Private Methods361 362 #region Static Methods363 364 /// <summary>365 /// Creates a PSSession object from the provided remote runspace object.366 /// If psCmdlet argument is non-null, then the new PSSession object is added to the367 /// session runspace repository (Get-PSSession).368 /// </summary>369 /// <param name="runspace">Runspace for the new PSSession.</param>370 /// <param name="transportName">Optional transport name.</param>371 /// <param name="psCmdlet">Optional cmdlet associated with the PSSession creation.</param>372 public static PSSession Create(373 Runspace runspace,374 string transportName,375 PSCmdlet psCmdlet)376 {377 if (runspace is not RemoteRunspace remoteRunspace)378 {379 throw new PSArgumentException(RemotingErrorIdStrings.InvalidPSSessionArgument);380 }381 382 var psSession = new PSSession(remoteRunspace)383 {384 _transportName = transportName385 };386 387 psCmdlet?.RunspaceRepository.Add(psSession);388 389 return psSession;390 }391 392 /// <summary>393 /// Generates a unique runspace id.394 /// </summary>395 /// <param name="rtnId">Returned Id.</param>396 /// <returns>Returned name.</returns>397 internal static string GenerateRunspaceName(out int rtnId)398 {399 int id = GenerateRunspaceId();400 rtnId = id;401 return "Runspace" + id.ToString();402 }403 404 /// <summary>405 /// Increments and returns a session unique runspace Id.406 /// </summary>407 /// <returns>Id.</returns>408 internal static int GenerateRunspaceId()409 {410 return System.Threading.Interlocked.Increment(ref s_seed);411 }412 413 #endregion414 }415}416 