public TokenSwitchRenderer(Connection connection, ElevationRequest elevationRequest) { if (Settings.SecurityEnforceUacIsolation && !elevationRequest.NewWindow) { throw new Exception("TokenSwitch mode not supported when SecurityEnforceUacIsolation is set."); } _connection = connection; _elevationRequest = elevationRequest; Environment.SetEnvironmentVariable("prompt", Environment.ExpandEnvironmentVariables(elevationRequest.Prompt)); ProcessApi.CreateProcessFlags dwCreationFlags = ProcessApi.CreateProcessFlags.CREATE_SUSPENDED; if (elevationRequest.NewWindow) { dwCreationFlags |= ProcessApi.CreateProcessFlags.CREATE_NEW_CONSOLE; } string exeName, args; if (elevationRequest.IntegrityLevel == IntegrityLevel.MediumPlus && ArgumentsHelper.UnQuote(elevationRequest.FileName.ToUpperInvariant()) != Environment.GetEnvironmentVariable("COMSPEC").ToUpperInvariant()) { // Now, we have an issue with this method: The process launched with the new token throws Access Denied if it tries to read its own token. // Kind of dirty workaround is to wrap the call with a "CMD.exe /c ".. this intermediate process will then // launching the command with a fresh new (desired) token and we know cmd wont try to read it's substitute token (throwing Access Denied). exeName = Environment.GetEnvironmentVariable("COMSPEC"); args = $"/s /c \"{elevationRequest.FileName} {elevationRequest.Arguments}\""; } else { // Hack not needed if we are already calling CMD exeName = elevationRequest.FileName; args = elevationRequest.Arguments; } _process = ProcessFactory.CreateProcessAsUserWithFlags(exeName, args, dwCreationFlags, out _processInformation); elevationRequest.TargetProcessId = _processInformation.dwProcessId; if (!elevationRequest.NewWindow) { ConsoleApi.SetConsoleCtrlHandler(ConsoleHelper.IgnoreConsoleCancelKeyPress, true); } }