執行外部EXE檔案時考量逾時、路徑錯置、檔案資源釋放之方法

每次遭遇到必須利用C#執行外部檔案,而這個外部檔案寫的奇差無比,狀況連連罄竹難書,所以乾脆把以前的知識集結在此篇整理成一個統一方法,日後遇到狀況再隨時修補更新,供後續參考用。

運行外部執行檔案時可能會遭遇的問題

運用System.Diagnostics.Process處理外部檔案時,常常會遭遇到下列問題:

public static (bool bIsError, string cMessage) Execute(string cPath, string cExeFileName, string cResultFileName, int iWaitingExecuteSeconds = 6_000)
{
  var oResult = (bIsError: true, cMessage: string.Empty);
  var tEventHandled = new System.Threading.Tasks.TaskCompletionSource<bool>();
  using var oProcess = new System.Diagnostics.Process()
  {
    StartInfo = new System.Diagnostics.ProcessStartInfo()
    { //設定確實的執行檔運行路徑
      WorkingDirectory = cPath,
      FileName = System.IO.Path.Combine(cPath, cExeFileName),
      //防止利用DLL Hook運行其他認知之外的檔案
      UseShellExecute = false,
      //背景執行
      CreateNoWindow = true,
    },
    EnableRaisingEvents = true,
  };
  oProcess.Exited += (s, e) =>
  {
    var oSender = (System.Diagnostics.Process)s;
    var dExecuteStart = oSender.StartTime;
    oProcess.Close();
    var dCheckFileStart = System.DateTime.Now;
    while ((System.DateTime.Now - dCheckFileStart).TotalMilliseconds < iWaitingExecuteSeconds)
    {
      try
      { //能夠開啟代表檔案資源已經釋放
        using var oFile = new System.IO.FileStream(System.IO.Path.Combine(cPath, cResultFileName), System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.None);
        break;
      }
      catch
      { System.Threading.Thread.Sleep(500); } //防止執行緒壅塞
    }
    //回傳執行緒運行狀況
    oResult.cMessage = $@"執行成功,運行時間{System.Math.Round((System.DateTime.Now - dExecuteStart).TotalMilliseconds)}ms";
    tEventHandled.TrySetResult(true);
  };

  try
  { //執行EXE檔案
    oProcess.Start();
    //超過預設的時間就不等了
    if (!tEventHandled.Task.Wait(iWaitingExecuteSeconds))
    { throw new System.Exception($"執行超過{iWaitingExecuteSeconds}毫秒"); }
    //成功訊息
    oResult.bIsError = false;
  }
  catch (System.Exception oEx)
  { //失敗訊息
    oResult.bIsError = true;
    oResult.cMessage = $"執行錯誤|{oEx.Message}";
    oProcess.Close();
  }
  return oResult;
}

方法包裝大概長得像這樣,至於是哪間噁心的公司寫出這種API執行檔我就不講了,多說都是淚,只能祝福那個開發噁心執行檔的開發者離職後,有一天被自己寫的程式碼婊,That's all。

相關參考

.NetFramework C# CallEXE CallExecute DetectHadFinish DetectHadExit WaitingTime DataExchange FileExchange FileReleased ResourceReleased