[C#] Windowsサービスからcmd.exeでbatファイルを起動した時の作業フォルダを設定する方法


はじめに

Windowsサービスからあるbatファイルを起動する際に、そのbatファイルの実行ディレクトリをそのbatファイルないで取得するために「%~dp0」でパスを取得した際、本来はbatファイルと同じフォルダパスになって欲しいのですが、下記の結果となりました。

var path = "C:¥Work¥test.bat";
var process = new Process 
{
    StartInfo = new ProcessStartInfo
    {
        FileName = Environment.GetEnvironmentVariable("ComSpec"),
        CreateNoWindow = true,
        UseShellExecute = false,
        Arguments = $"/c ¥"{path}¥" ¥"arg1¥""
    }
};

process.Start();
process.WaitForExit();

rem C#から実行されたbatファイル
rem C:¥Work¥test.bat "arg1"

echo %1
echo %~dp0
arg1
C:¥Windows¥System32

「C:¥Work」となることを期待していたのですが、cmd.exeの実行パスとなっていました。

対策

ProcessStartInfoにはオプションとして「WorkingDirectory」が用意されていて、この設定をしてあげることで、好きな作業ディレクトリを設定することができます。

たとえば、「C:¥Work」を作業ディレクトリとしたい場合は下記のように設定します。

var path = "C:¥Work¥test.bat";
var process = new Process 
{
    StartInfo = new ProcessStartInfo
    {
        FileName = Environment.GetEnvironmentVariable("ComSpec"),
        CreateNoWindow = true,
        UseShellExecute = false,
        Arguments = $"/c ¥"{path}¥" ¥"arg1¥"",
        // *****************************************
        // 下記を追加
        // *****************************************
        WorkingDirectory = "C:¥Work"
    }
};

process.Start();
process.WaitForExit();

上記を実行してみた結果が下記の通りです。

rem C#から実行されたbatファイル
rem C:¥Work¥test.bat "arg1"

echo %1
echo %~dp0
arg1
C:¥Work

最後に

少しハマりましたが、C#アプリケーションからbatファイルを呼び出す場合には、作業ディレクトリを決めておくと、良いかと思います。

C#アプリケーションと同じパスで処理したい場合は、下記のように設定しておくと良いかと思います。

using system.Reflection;
using system.IO;

〜〜〜
WorkingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
〜〜〜