/// <summary> /// Starts a new <see cref="Process" /> with the start info provided and with the same rights as the mentioned /// <see cref="Process" /> /// </summary> /// <param name="process">The <see cref="Process" /> to copy rights from</param> /// <param name="startInfo">Contains the information about the <see cref="Process" /> to be started</param> /// <returns>Returns the newly started <see cref="Process" /></returns> /// <exception cref="InvalidOperationException">This method needs administrative access rights.-or-UAC is not enable</exception> /// <exception cref="NotSupportedException">Current version of Windows does not meets the needs of this method</exception> public static Process StartAndCopyProcessPermission(Process process, ProcessStartInfo startInfo) { if (!string.IsNullOrWhiteSpace(startInfo.UserName)) { throw new InvalidOperationException(Resources.Error_StartWithUsername); } if (!IsElevated) { throw new InvalidOperationException(Resources.Error_AccessDenied); } Tokens.EnablePrivilegeOnProcess(Process.GetCurrentProcess(), SecurityEntities.SeImpersonatePrivilege); using (var primaryToken = Tokens.DuplicatePrimaryToken(process)) { var lockTaken = false; try { Monitor.Enter(startInfo, ref lockTaken); var unicode = Environment.OSVersion.Platform == PlatformID.Win32NT; var creationFlags = startInfo.CreateNoWindow ? ProcessCreationFlags.CreateNoWindow : ProcessCreationFlags.None; if (unicode) { creationFlags |= ProcessCreationFlags.UnicodeEnvironment; } var commandLine = IOPath.BuildCommandLine(startInfo.FileName, startInfo.Arguments); var workingDirectory = string.IsNullOrEmpty(startInfo.WorkingDirectory) ? Environment.CurrentDirectory : startInfo.WorkingDirectory; var startupInfo = StartupInfo.GetOne(); var gcHandle = new GCHandle(); try { gcHandle = GCHandle.Alloc( IOPath.EnvironmentBlockToByteArray(startInfo.EnvironmentVariables, unicode), GCHandleType.Pinned); var environmentPtr = gcHandle.AddrOfPinnedObject(); var logonFlags = startInfo.LoadUserProfile ? LogonFlags.LogonWithProfile : LogonFlags.None; ProcessInformation processInfo; bool processCreationResult; if (IsUACSupported) // Vista + { processCreationResult = AdvancedAPI.CreateProcessWithTokenW(primaryToken, logonFlags, null, commandLine, creationFlags, environmentPtr, workingDirectory, ref startupInfo, out processInfo); } else { Tokens.EnablePrivilegeOnProcess(Process.GetCurrentProcess(), SecurityEntities.SeIncreaseQuotaPrivilege); processCreationResult = AdvancedAPI.CreateProcessAsUserW(primaryToken, null, commandLine, IntPtr.Zero, IntPtr.Zero, false, creationFlags, environmentPtr, workingDirectory, ref startupInfo, out processInfo); } if (!processCreationResult) { throw new Win32Exception(); } SafeNativeHandle.CloseHandle(processInfo.Thread); SafeNativeHandle.CloseHandle(processInfo.Process); if (processInfo.ProcessId <= 0) { throw new InvalidOperationException(Resources.Error_Unknown); } return(Process.GetProcessById(processInfo.ProcessId)); } catch (EntryPointNotFoundException) { throw new NotSupportedException(); } finally { if (gcHandle.IsAllocated) { gcHandle.Free(); } } } finally { if (lockTaken) { Monitor.Exit(startInfo); } } } }