return s_isWindowsElevated == 1;
}
}
+
+ public static bool IsWindowsAndNotElevated
+ => IsWindows && !IsWindowsAndElevated;
}
}
{
if (_processName == null)
{
- EnsureState(State.HaveNonExitedId);
// If we already have the name via a populated ProcessInfo
// then use that one.
if (_processInfo?.ProcessName != null)
}
else
{
- // If we don't have a populated ProcessInfo, then get and cache the process name.
+ // Ensure that the process is not yet exited
+ EnsureState(State.HaveNonExitedId);
_processName = ProcessManager.GetProcessName(_processId, _machineName);
+ // Fallback to slower ProcessInfo implementation if optimized way did not return a
+ // process name (e.g. in case of missing permissions for Non-Admin users)
if (_processName == null)
{
- throw new InvalidOperationException(SR.NoProcessInfo);
+ EnsureState(State.HaveProcessInfo);
+ _processName = _processInfo!.ProcessName;
}
}
}
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Collections.Generic;
-using System.Text;
+using System.ComponentModel;
+using System.Security.Principal;
using System.Threading.Tasks;
using Xunit.Sdk;
p.Dispose();
}
}
+
+ public static string? GetProcessUserName(Process p)
+ {
+ try
+ {
+ if (Interop.OpenProcessToken(p.SafeHandle, 0x8u, out var handle))
+ {
+ if (Interop.ProcessTokenToSid(handle, out var sid))
+ {
+ string userName = sid.Translate(typeof(NTAccount)).ToString();
+ int indexOfDomain = userName.IndexOf('\\');
+ if (indexOfDomain != -1)
+ userName = userName.Substring(indexOfDomain + 1);
+
+ return userName;
+ }
+ }
+ }
+ catch (Win32Exception) { } // Process.SafeHandle can throw unauthorized since it uses OpenProcess with PROCESS_ALL_ACCESS.
+
+ return null;
+ }
}
}
throw new SkipTestException($"{p.StartInfo.FileName} has been locked by some other process");
}
- if (Interop.OpenProcessToken(p.SafeHandle, 0x8u, out handle))
- {
- SecurityIdentifier sid;
- if (Interop.ProcessTokenToSid(handle, out sid))
- {
- string actualUserName = sid.Translate(typeof(NTAccount)).ToString();
- int indexOfDomain = actualUserName.IndexOf('\\');
- if (indexOfDomain != -1)
- actualUserName = actualUserName.Substring(indexOfDomain + 1);
- bool isProfileLoaded = GetNamesOfUserProfiles().Any(profile => profile.Equals(username));
+ Assert.Equal(username, Helpers.GetProcessUserName(p));
+ bool isProfileLoaded = GetNamesOfUserProfiles().Any(profile => profile.Equals(username));
+ Assert.True(isProfileLoaded);
- Assert.Equal(username, actualUserName);
- Assert.True(isProfileLoaded);
- }
- }
}
finally
{
}
}
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsWindowsAndNotElevated))]
+ public void NonElevatedUser_QueryProcessNameOfSystemProcess()
+ {
+ const string Services = "services";
+
+ string currentProcessUser = Helpers.GetProcessUserName(Process.GetCurrentProcess());
+ Assert.NotNull(currentProcessUser);
+
+ Process? systemOwnedServices = null;
+
+ foreach (var p in Process.GetProcessesByName(Services))
+ {
+ // returns the username of the owner of the process or null if the username can't be queried.
+ // for services.exe, this will be null.
+ string? servicesUser = Helpers.GetProcessUserName(p);
+
+ // this isn't really verifying that services.exe is owned by SYSTEM, but we are sure it is not owned by the current user.
+ if (servicesUser != currentProcessUser)
+ {
+ systemOwnedServices = p;
+ break;
+ }
+ }
+
+ Assert.NotNull(systemOwnedServices);
+ Assert.Equal(Services, systemOwnedServices.ProcessName);
+
+ systemOwnedServices = Process.GetProcessById(systemOwnedServices.Id);
+ Assert.Equal(Services, systemOwnedServices.ProcessName);
+ }
+
private IReadOnlyList<Process> CreateProcessTree()
{
(Process Value, string Message) rootResult = ListenForAnonymousPipeMessage(rootPipeHandleString =>