| File: DiagnosticsIpc\ProcessInfo.cs | Web Access |
| Project: src\diagnostics\src\Microsoft.Diagnostics.NETCore.Client\Microsoft.Diagnostics.NETCore.Client.csproj (Microsoft.Diagnostics.NETCore.Client) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Buffers.Binary; namespace Microsoft.Diagnostics.NETCore.Client { /** * ==ProcessInfo== * The response payload to issuing the GetProcessInfo command. * * 8 bytes - PID (little-endian) * 16 bytes - CLR Runtime Instance Cookie (little-endian) * # bytes - Command line string length and data * # bytes - Operating system string length and data * # bytes - Process architecture string length and data * * ==ProcessInfo2== * The response payload to issuing the GetProcessInfo2 command. * * 8 bytes - PID (little-endian) * 16 bytes - CLR Runtime Instance Cookie (little-endian) * # bytes - Command line string length and data * # bytes - Operating system string length and data * # bytes - Process architecture string length and data * # bytes - Managed entrypoint assembly name * # bytes - CLR product version string (may include prerelease labels) * * * The "string length and data" fields are variable length: * 4 bytes - Length of string data in UTF-16 characters * (2 * length) bytes - The data of the string encoded using Unicode * (includes null terminating character) */ internal class ProcessInfo { private const int GuidSizeInBytes = 16; /// <summary> /// Parses a ProcessInfo payload. /// </summary> internal static ProcessInfo ParseV1(byte[] payload) { int index = 0; return ParseCommon(payload, ref index); } /// <summary> /// Parses a ProcessInfo2 payload. /// </summary> internal static ProcessInfo ParseV2(byte[] payload) { int index = 0; return ParseCommon2(payload, ref index); } /// <summary> /// Parses a ProcessInfo3 payload. /// </summary> internal static ProcessInfo ParseV3(byte[] payload) { int index = 0; // The ProcessInfo3 command is intended to allow the addition of new fields in future versions so // long as the version field is incremented; prior fields shall not be changed or removed. // Read the version field, parse the common payload, and dynamically parse the remainder depending on the version. uint version = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan<byte>(payload, index, 4)); index += sizeof(uint); ProcessInfo processInfo = ParseCommon2(payload, ref index); if (version >= 1) { processInfo.PortableRuntimeIdentifier = IpcHelpers.ReadString(payload, ref index); } return processInfo; } private static ProcessInfo ParseCommon(byte[] payload, ref int index) { ProcessInfo processInfo = new(); processInfo.ProcessId = BinaryPrimitives.ReadUInt64LittleEndian(new ReadOnlySpan<byte>(payload, index, 8)); index += sizeof(ulong); byte[] cookieBuffer = new byte[GuidSizeInBytes]; Array.Copy(payload, index, cookieBuffer, 0, GuidSizeInBytes); processInfo.RuntimeInstanceCookie = new Guid(cookieBuffer); index += GuidSizeInBytes; processInfo.CommandLine = IpcHelpers.ReadString(payload, ref index); processInfo.OperatingSystem = IpcHelpers.ReadString(payload, ref index); processInfo.ProcessArchitecture = IpcHelpers.ReadString(payload, ref index); return processInfo; } internal bool TryGetProcessClrVersion(out Version version, out bool isPrerelease) { version = null; isPrerelease = true; if (string.IsNullOrEmpty(ClrProductVersionString)) { return false; } // The version is of the SemVer2 form: <major>.<minor>.<patch>[-<prerelease>][+<metadata>] // Remove the prerelease and metadata version information before parsing. ReadOnlySpan<char> versionSpan = ClrProductVersionString.AsSpan(); int metadataIndex = versionSpan.IndexOf('+'); if (-1 == metadataIndex) { metadataIndex = versionSpan.Length; } ReadOnlySpan<char> noMetadataVersion = versionSpan.Slice(0, metadataIndex); int prereleaseIndex = noMetadataVersion.IndexOf('-'); if (-1 == prereleaseIndex) { isPrerelease = false; prereleaseIndex = metadataIndex; } return Version.TryParse(noMetadataVersion.Slice(0, prereleaseIndex).ToString(), out version); } private static ProcessInfo ParseCommon2(byte[] payload, ref int index) { ProcessInfo processInfo = ParseCommon(payload, ref index); processInfo.ManagedEntrypointAssemblyName = IpcHelpers.ReadString(payload, ref index); processInfo.ClrProductVersionString = IpcHelpers.ReadString(payload, ref index); return processInfo; } public ulong ProcessId { get; private set; } public Guid RuntimeInstanceCookie { get; private set; } public string CommandLine { get; private set; } public string OperatingSystem { get; private set; } public string ProcessArchitecture { get; private set; } public string ManagedEntrypointAssemblyName { get; private set; } public string ClrProductVersionString { get; private set; } public string PortableRuntimeIdentifier { get; private set; } } }