/// <summary> /// Creates and populates a new RunspaceDetails instance for the given runspace. /// </summary> /// <param name="runspace"> /// The runspace for which details will be gathered. /// </param> /// <param name="sessionDetails"> /// The SessionDetails for the runspace. /// </param> /// <param name="logger">An ILogger implementation used for writing log messages.</param> /// <returns>A new RunspaceDetails instance.</returns> internal static RunspaceDetails CreateFromRunspace( Runspace runspace, SessionDetails sessionDetails, ILogger logger) { Validate.IsNotNull(nameof(runspace), runspace); Validate.IsNotNull(nameof(sessionDetails), sessionDetails); var runspaceLocation = RunspaceLocation.Local; var runspaceContext = RunspaceContext.Original; var versionDetails = PowerShellVersionDetails.GetVersionDetails(runspace, logger); string connectionString = null; if (runspace.ConnectionInfo != null) { // Use 'dynamic' to avoid missing NamedPipeRunspaceConnectionInfo // on PS v3 and v4 try { dynamic connectionInfo = runspace.ConnectionInfo; if (connectionInfo.ProcessId != null) { connectionString = connectionInfo.ProcessId.ToString(); runspaceContext = RunspaceContext.EnteredProcess; } } catch (RuntimeBinderException) { // ProcessId property isn't on the object, move on. } // Grab the $host.name which will tell us if we're in a PSRP session or not string hostName = PowerShellContext.ExecuteScriptAndGetItem <string>( "$Host.Name", runspace, defaultValue: string.Empty); // hostname is 'ServerRemoteHost' when the user enters a session. // ex. Enter-PSSession, Enter-PSHostProcess if (hostName.Equals("ServerRemoteHost", StringComparison.Ordinal)) { runspaceLocation = RunspaceLocation.Remote; connectionString = runspace.ConnectionInfo.ComputerName + (connectionString != null ? $"-{connectionString}" : string.Empty); } } return (new RunspaceDetails( runspace, sessionDetails, versionDetails, runspaceLocation, runspaceContext, connectionString)); }
/// <summary> /// Creates and populates a new RunspaceDetails instance for the given runspace. /// </summary> /// <param name="runspace"> /// The runspace for which details will be gathered. /// </param> /// <param name="sessionDetails"> /// The SessionDetails for the runspace. /// </param> /// <param name="logger">An ILogger implementation used for writing log messages.</param> /// <returns>A new RunspaceDetails instance.</returns> internal static RunspaceDetails CreateFromRunspace( Runspace runspace, SessionDetails sessionDetails, ILogger logger) { Validate.IsNotNull(nameof(runspace), runspace); Validate.IsNotNull(nameof(sessionDetails), sessionDetails); var runspaceId = runspace.InstanceId; var runspaceLocation = RunspaceLocation.Local; var runspaceContext = RunspaceContext.Original; var versionDetails = PowerShellVersionDetails.GetVersionDetails(runspace, logger); string connectionString = null; if (runspace.ConnectionInfo != null) { // Use 'dynamic' to avoid missing NamedPipeRunspaceConnectionInfo // on PS v3 and v4 try { dynamic connectionInfo = runspace.ConnectionInfo; if (connectionInfo.ProcessId != null) { connectionString = connectionInfo.ProcessId.ToString(); runspaceContext = RunspaceContext.EnteredProcess; } } catch (RuntimeBinderException) { // ProcessId property isn't on the object, move on. } if (runspace.ConnectionInfo.ComputerName != "localhost") { runspaceId = PowerShellContext.ExecuteScriptAndGetItem <Guid>( "$host.Runspace.InstanceId", runspace); runspaceLocation = RunspaceLocation.Remote; connectionString = runspace.ConnectionInfo.ComputerName + (connectionString != null ? $"-{connectionString}" : string.Empty); } } return (new RunspaceDetails( runspace, sessionDetails, versionDetails, runspaceLocation, runspaceContext, connectionString)); }
/// <summary> /// Gets the PowerShell version details for the given runspace. /// </summary> /// <param name="runspace">The runspace for which version details will be gathered.</param> /// <param name="logger">An ILogger implementation used for writing log messages.</param> /// <returns>A new PowerShellVersionDetails instance.</returns> public static PowerShellVersionDetails GetVersionDetails(Runspace runspace, ILogger logger) { Version powerShellVersion = new Version(5, 0); string versionString = null; string powerShellEdition = "Desktop"; var architecture = PowerShellProcessArchitecture.Unknown; try { var psVersionTable = PowerShellContext.ExecuteScriptAndGetItem <Hashtable>("$PSVersionTable", runspace); if (psVersionTable != null) { var edition = psVersionTable["PSEdition"] as string; if (edition != null) { powerShellEdition = edition; } // The PSVersion value will either be of Version or SemanticVersion. // In the former case, take the value directly. In the latter case, // generate a Version from its string representation. var version = psVersionTable["PSVersion"]; if (version is Version) { powerShellVersion = (Version)version; } else if (version != null) { // Expected version string format is 6.0.0-alpha so build a simpler version from that powerShellVersion = new Version(version.ToString().Split('-')[0]); } var gitCommitId = psVersionTable["GitCommitId"] as string; if (gitCommitId != null) { versionString = gitCommitId; } else { versionString = powerShellVersion.ToString(); } var arch = PowerShellContext.ExecuteScriptAndGetItem <string>("$env:PROCESSOR_ARCHITECTURE", runspace); if (arch != null) { if (string.Equals(arch, "AMD64", StringComparison.CurrentCultureIgnoreCase)) { architecture = PowerShellProcessArchitecture.X64; } else if (string.Equals(arch, "x86", StringComparison.CurrentCultureIgnoreCase)) { architecture = PowerShellProcessArchitecture.X86; } } } } catch (Exception ex) { logger.Write( LogLevel.Warning, "Failed to look up PowerShell version, defaulting to version 5.\r\n\r\n" + ex.ToString()); } return(new PowerShellVersionDetails( powerShellVersion, versionString, powerShellEdition, architecture)); }