2024-10-27 更新说明:

此文章写于2018年,当时还是dotnet framework 4.7。如今已经是dotnet 8了,我也根据最新版本进行了增补,请放心参考。

另外,给我自己开发的软件 OneQuick 打个小广告,可以根据热键执行各种命令,欢迎试用。

ProcessStartInfo 类参数解析

UseShellExecute

指执行方式是系统执行(true)还是程序创建进程(false)。

为true时相当于用户双击文件,此时FileName不限于可执行文件(.exe),例如网址,bat文件均可;
为false时程序使用CreateProcess来创建进程,对进程的控制更多,但FileName必须是可执行文件(.exe)。

默认值:dotnet core 开始为false,dotnet framework 为true。

取舍:

需要以管理员身份执行命令,或执行的命令不是可执行文件时,此值必须为true。

需要重定向输入输出时(RedirectStandard* = true),此值必须为false。

WindowStyle

用于设置GUI程序的窗口。(对GUI程序有效)

另外,GUI程序可以主动忽略这个参数。

注:在dotnet core中,此值好像对控制台程序也有效。如果要隐藏窗口最好连同此值一起设置。

CreateNoWindow

是否创建窗口。(对控制台程序,并且 UseShellExecute = false 时有效)

在MacOS/Linux上时,也将忽略此值。

注:此值生效时(true),控制台窗口不会显示。这种方式下无法通过窗口关闭程序,所以运行的程序最好是可以自己运行完关闭的,不然需要到任务管理器中关闭。

Verb

文件的右键菜单里,除了“打开”,根据文件的不同还会出现“打印”,“编辑”,“以管理员身份运行”等选项,Verb控制的就是这个选项。

你可以通过new ProcessStartInfo(FileName).Verbs查看特定文件支持的Verb。

常见启动方式

Admin身份运行

ProcessStartInfo.Verb = "RunAs";

在Admin进程中,以普通权限运行

ProcessStartInfo.FileName = "RunAs";
ProcessStartInfo.Arguments = $"/trustlevel:0x20000 {YOUR_COMMAND}";

YOUR_COMMAND为你要运行的命令,包含空格时要用引号括住,而命令若包含引号,需要以\"代替。

注:此方法运行的权限准确的说是受限制的管理员,不是普通的用户权限。

以及由于系统BUG,在win11中这个方法无法使用: 参考链接

在CMD中运行命令

ProcessStartInfo.FileName = "cmd";
ProcessStartInfo.Arguments = $"/c {YOUR_COMMAND}";

YOUR_COMMAND与上文类似,但命令中的引号要用两个引号代替," –> ""

Explorer 定位到文件

PATH为文件时:

ProcessStartInfo.FileName = "explorer";
ProcessStartInfo.Arguments = $"/select, {PATH}";

PATH为目录时 ProcessStartInfo.Arguments = PATH;即可。

示例代码

我写了个类库 : ) XJKdotNetLibrary

此库已经不再维护,何况当年写的也挺蛋疼。以下是更简单的一些示例:

/// <summary>
/// 执行一个进程。
/// </summary>
internal static Process? StartProcess(string path, string? args = null, string? dir = null
    , bool? runAsAdmin = null, bool? hiddenWindow = null)
{
    // 这里不提供在管理员权限下执行非管理员权限的方法,有需要可自行编写测试
    // 在我自己的程序OneQuick中,因为RunAs的BUG,我使用了计划任务来实现这个功能

    // 经测试:args和dir可以为null
    var psi = new ProcessStartInfo(path, args!)
    {
        UseShellExecute = true, // 为true时CreateNoWindow无效
        CreateNoWindow = false,
        WorkingDirectory = dir!,
    };
    if (hiddenWindow == true)
    {
        psi.WindowStyle = ProcessWindowStyle.Hidden;
    }

    if (runAsAdmin == true)
    {
        psi.Verb = "runas";
    }

    var p = Process.Start(psi);
    return p;
}

/// <summary>
/// 使用文件管理器打开指定路径
/// </summary>
internal static void Explorer(string path)
{
    if (File.Exists(path))
    {
        StartProcess("explorer", "/select, " + path);
    }
    else if (Directory.Exists(path))
    {
        StartProcess("explorer", path);
    }
    else
    {
        StartProcess("explorer");
    }
}

最后再给我的 OneQuick 打个广告,根据热键可以执行各种命令 :)