Process.GetCurrentProcess().ProcessName 返回当前进程映像名(不含扩展名),如 MyApp;若以 dotnet MyApp.dll 启动则返回 dotnet,此时应改用 Environment.ProcessPath(.NET 5+)或 MainModule.FileName。

怎么用 Process.GetCurrentProcess().ProcessName 获取当前进程名
直接调用 Process.GetCurrentProcess().ProcessName 就能拿到当前 exe 的文件名(不含扩展名),比如 MyApp 而不是 MyApp.exe。这是最常用也最轻量的方式。
注意:它返回的是进程映像名,不是主窗口标题,也不是程序集名称;如果程序是通过 dotnet MyApp.dll 启动的,ProcessName 会是 dotnet,不是你的项目名——这时候得换方法。
- 若需完整路径,改用
Process.GetCurrentProcess().MainModule.FileName(但可能抛Win32Exception,尤其在受限上下文如服务或沙箱中) - 若用 .NET Core / .NET 5+,推荐搭配
Environment.ProcessPath(.NET 5+ 才有),它更可靠,且返回带扩展名的完整路径 - 不要依赖
Assembly.GetExecutingAssembly().GetName().Name来当进程名——它返回的是程序集名,和实际启动的进程名可能不一致(比如发布为单文件时)
判断本程序是否已运行:用互斥体(Mutex)最稳妥
靠查进程列表(比如 Process.GetProcessesByName())容易误判:同名不同程序、权限不足读不到其他用户进程、UWP/沙盒环境限制多。真正健壮的做法是用 Mutex 做启动互斥。
核心逻辑是:程序启动时尝试创建一个命名互斥体,成功说明是首个实例;失败且 WaitOne(0) 返回 false,说明已有实例在跑。
- 命名要带唯一性,建议加公司名或 GUID 前缀,避免和其他程序冲突,例如
"Global\MyCompany_MyApp_SingleInstance" - 必须用
Global\前缀才能跨会话(如 Windows 服务 vs 普通用户桌面),否则默认是会话本地的 - 记得在
finally或Dispose中释放Mutex,否则重启后可能残留导致后续启动失败 - 如果程序崩溃退出没释放,.NET 的
Mutex通常会被系统自动清理,但别依赖这个行为
Process.GetProcessesByName() 的坑:为什么有时查不到自己
常见现象:代码里写 Process.GetProcessesByName("MyApp"),结果返回空数组,哪怕程序明明在跑。这不是 bug,而是名字没对上。
- 传入的名字是进程的
ProcessName,即不含路径和扩展名的文件名;如果启动的是MyApp.exe,就查"MyApp";如果是MyApp.Console.exe,就得查"MyApp.Console" - 在 .NET 6+ 单文件发布模式下,
ProcessName是dotnet,除非你用PublishTrimmed=true+IncludeNativeLibrariesForSelfExtract=true等组合强制生成原生 exe - Windows 权限限制:非管理员进程无法枚举系统级进程,反过来,低权限进程也可能被高权限进程“看不见”——尤其是跨用户会话时
- 调试器附加时(如 VS 调试),某些场景下
ProcessName可能临时变成conhost或其他,不建议用于关键判断逻辑
性能与兼容性提醒:别在高频路径里查进程
Process.GetProcessesByName() 是个相对重的操作,每次调用都会触发一次完整的系统进程枚举,Win32 层开销不小。放在定时器、UI 刷新或网络回调里反复调,很快会拖慢响应。
- 如果只是启动时做单次检查,用
Mutex比查进程快一个数量级,且无权限问题 - .NET Framework 4.8 和 .NET 5+ 对
Process类的行为基本一致,但Environment.ProcessPath在 .NET Core 3.1 不可用,得降级用MainModule.FileName并捕获异常 - Linux/macOS 下
Process.GetCurrentProcess().ProcessName行为一致,但Mutex的跨平台语义有限——.NET 6+ 支持NamedMutex在 Unix 上用文件锁模拟,但需确保 tmp 目录可写
真正麻烦的从来不是“怎么写”,而是“什么时候不该写”——比如把进程名硬编码进配置、拿进程名当身份凭证、或者在没有互斥需求的地方强行加 Mutex。这些地方一松劲,后面排查起来比写十遍逻辑还费劲。










