Пример #1
0
        /// <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);
                    }
                }
            }
        }