.NET/C# 獲取一個正在運行的進程的命令行參數

  • 2020 年 2 月 10 日
  • 筆記

在自己的進程內部,我們可以通過 Main 函數傳入的參數,也可以通過 Environment.GetCommandLineArgs 來獲取命令行參數。

但是,可以通過什麼方式來獲取另一個運行著的程式的命令行參數呢?


進程內部獲取傳入參數的方法,可以參見我的另一篇部落格:.NET 命令行參數包含應用程式路徑嗎?

.NET Framework / .NET Core 框架內部是不包含獲取其他進程命令行參數的方法的,但是我們可以在任務管理器中看到,說明肯定存在這樣的方法。

實際上方法是有的,不過這個方法是 Windows 上的專屬方法。

對於 .NET Framework,需要引用程式集 System.Management;對於 .NET Core 需要引用 Microsoft.Windows.Compatibility 這個針對 Windows 系統準備的兼容包(不過這個兼容包目前還是預覽版本)。

<ItemGroup Condition="$(TargetFramework) == 'netcoreapp2.1'">      <PackageReference Include="Microsoft.Windows.Compatibility" Version="2.1.0-preview.19073.11" />  </ItemGroup>  <ItemGroup Condition="$(TargetFramework) == 'net472'">      <Reference Include="System.Management" />  </ItemGroup>

然後,我們使用 ManagementObjectSearcherManagementBaseObject 來獲取命令行參數。

為了簡便,我將其封裝成一個擴展方法,其中包括對於一些異常的簡單處理。

using System;  using System.Diagnostics;  using System.Linq;  using System.Management;    namespace Walterlv  {      /// <summary>      /// 為 <see cref="Process"/> 類型提供擴展方法。      /// </summary>      public static class ProcessExtensions      {          /// <summary>          /// 獲取一個正在運行的進程的命令行參數。          /// 與 <see cref="Environment.GetCommandLineArgs"/> 一樣,使用此方法獲取的參數是包含應用程式路徑的。          /// 關於 <see cref="Environment.GetCommandLineArgs"/> 可參見:          /// .NET 命令行參數包含應用程式路徑嗎?https://blog.walterlv.com/post/when-will-the-command-line-args-contain-the-executable-path.html          /// </summary>          /// <param name="process">一個正在運行的進程。</param>          /// <returns>表示應用程式運行命令行參數的字元串。</returns>          public static string GetCommandLineArgs(this Process process)          {              if (process is null) throw new ArgumentNullException(nameof(process));                try              {                  return GetCommandLineArgsCore();              }              catch (Win32Exception ex) when ((uint) ex.ErrorCode == 0x80004005)              {                  // 沒有對該進程的安全訪問許可權。                  return string.Empty;              }              catch (InvalidOperationException)              {                  // 進程已退出。                  return string.Empty;              }                string GetCommandLineArgsCore()              {                  using (var searcher = new ManagementObjectSearcher(                      "SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id))                  using (var objects = searcher.Get())                  {                      var @object = objects.Cast<ManagementBaseObject>().SingleOrDefault();                      return @object?["CommandLine"]?.ToString() ?? "";                  }              }          }      }  }

使用此方法得到的命令行參數是一個字元串,而不是我們通常使用字元串時的字元串數組。如果你需要將其轉換為字元串數組,可以使用我在另一篇部落格中使用的方法:


參考資料

本文會經常更新,請閱讀原文: https://blog.walterlv.com/post/get-command-line-for-a-running-process.html ,以避免陳舊錯誤知識的誤導,同時有更好的閱讀體驗。

本作品採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名 呂毅 (包含鏈接: https://blog.walterlv.com ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發布。如有任何疑問,請 與我聯繫 ([email protected])