internal ProcessInfo GetProcessInfo()
{
+ // Attempt to get ProcessInfo v3
+ ProcessInfo processInfo = TryGetProcessInfo3();
+ if (null != processInfo)
+ {
+ return processInfo;
+ }
+
// Attempt to get ProcessInfo v2
- ProcessInfo processInfo = TryGetProcessInfo2();
+ processInfo = TryGetProcessInfo2();
if (null != processInfo)
{
return processInfo;
internal async Task<ProcessInfo> GetProcessInfoAsync(CancellationToken token)
{
+ // Attempt to get ProcessInfo v3
+ ProcessInfo processInfo = await TryGetProcessInfo3Async(token).ConfigureAwait(false);
+ if (null != processInfo)
+ {
+ return processInfo;
+ }
+
// Attempt to get ProcessInfo v2
- ProcessInfo processInfo = await TryGetProcessInfo2Async(token).ConfigureAwait(false);
+ processInfo = await TryGetProcessInfo2Async(token).ConfigureAwait(false);
if (null != processInfo)
{
return processInfo;
return TryGetProcessInfo2FromResponse(response2, nameof(GetProcessInfoAsync));
}
+ private ProcessInfo TryGetProcessInfo3()
+ {
+ IpcMessage request = CreateProcessInfo3Message();
+ using IpcResponse response2 = IpcClient.SendMessageGetContinuation(_endpoint, request);
+ return TryGetProcessInfo3FromResponse(response2, nameof(GetProcessInfo));
+ }
+
+ private async Task<ProcessInfo> TryGetProcessInfo3Async(CancellationToken token)
+ {
+ IpcMessage request = CreateProcessInfo3Message();
+ using IpcResponse response2 = await IpcClient.SendMessageGetContinuationAsync(_endpoint, request, token).ConfigureAwait(false);
+ return TryGetProcessInfo3FromResponse(response2, nameof(GetProcessInfoAsync));
+ }
+
private static byte[] SerializePayload<T>(T arg)
{
using (MemoryStream stream = new())
return new IpcMessage(DiagnosticsServerCommandSet.Process, (byte)ProcessCommandId.GetProcessInfo2);
}
+ private static IpcMessage CreateProcessInfo3Message()
+ {
+ return new IpcMessage(DiagnosticsServerCommandSet.Process, (byte)ProcessCommandId.GetProcessInfo3);
+ }
+
private static IpcMessage CreateResumeRuntimeMessage()
{
return new IpcMessage(DiagnosticsServerCommandSet.Process, (byte)ProcessCommandId.ResumeRuntime);
return ProcessInfo.ParseV2(response.Message.Payload);
}
+ private static ProcessInfo TryGetProcessInfo3FromResponse(IpcResponse response, string operationName)
+ {
+ if (!ValidateResponseMessage(response.Message, operationName, ValidateResponseOptions.UnknownCommandReturnsFalse))
+ {
+ return null;
+ }
+
+ return ProcessInfo.ParseV3(response.Message.Payload);
+ }
+
internal static bool ValidateResponseMessage(IpcMessage responseMessage, string operationName, ValidateResponseOptions options = ValidateResponseOptions.None)
{
switch ((DiagnosticsServerResponseId)responseMessage.Header.CommandId)
internal static ProcessInfo ParseV2(byte[] payload)
{
int index = 0;
- ProcessInfo processInfo = ParseCommon(payload, ref index);
+ return ParseCommon2(payload, ref index);
+ }
- processInfo.ManagedEntrypointAssemblyName = IpcHelpers.ReadString(payload, ref index);
- processInfo.ClrProductVersionString = IpcHelpers.ReadString(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;
}
return processInfo;
}
+ 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 ProcessArchitecture { get; private set; }
public string ManagedEntrypointAssemblyName { get; private set; }
public string ClrProductVersionString { get; private set; }
+ public string PortableRuntimeIdentifier { get; private set; }
}
}