ざこノート
2018-11-01 [C# ]

[C#] 32bitプロセスから64bitプロセスで外部ファイルを起動する

64bitのOSで起動している32bitアプリ(WOW64)から外部アプリ(任意のファイル)を起動する際に、WOW64のリダイレクトの影響を受けずずに正常に起動させる方法です。
cmd.exeを経由して外部アプリを起動するようにします。

環境

  • Windows 10 Pro 64bit 1803
  • Visual Studio Community 2017 15.8.2
  • .NET Framework 4.6.1
  • C# 7.0

結果

WOW64かどうかを問わず、cmd.exe経由で外部アプリ(path)を実行するようにします。

var wow64 = Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess;
var cmd = wow64 ? @"C:\Windows\sysnative\cmd.exe" : @"C:\Windows\system32\cmd.exe";
var args = $@"/C start """" ""{path}""";

var info = new ProcessStartInfo(cmd, args);
info.WindowStyle = ProcessWindowStyle.Hidden;
info.WorkingDirectory = Path.GetDirectoryName(path);
Process.Start(info);

WOW64ではない場合は、cmd.exeを使用せずにProcess.Start()しても問題はないと思います。

var wow64 = Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess;
if (wow64)
{
    var cmd = wow64 ? @"C:\Windows\sysnative\cmd.exe" : @"C:\Windows\system32\cmd.exe";
    var args = $@"/C start """" ""{path}""";

    var info = new ProcessStartInfo(cmd, args);
    info.WindowStyle = ProcessWindowStyle.Hidden;
    info.WorkingDirectory = Path.GetDirectoryName(path);
    Process.Start(info);
}
else
{
    var info = new ProcessStartInfo(path);
    info.WorkingDirectory = Path.GetDirectoryName(path);
    Process.Start(info);
}

WorkingDirectoryが未指定だと、呼び出し元32bitアプリのEnvironment.CurrentDirectoryが指定されてしまうので必ず指定するようにします。

実装,方法

WOW64リダイレクトを一時的に無効にする方法でも良いみたいです。(未確認)

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);

void Example()
{
    IntPtr wow64Value = IntPtr.Zero;

    try
    {
        // WOW64リダイレクトを無効
        Wow64DisableWow64FsRedirection(ref wow64Value);

        // 任意の処理 (WOW64のリダイレクトが必要な処理を行うと危険)
        var info = new ProcessStartInfo(path);
        info.WorkingDirectory = Path.GetDirectoryName(path);
        Process.Start(info);
    }
    finally
    {
        // 必ずリダイレクトを有効に戻す
        Wow64RevertWow64FsRedirection(wow64Value);
    }
}

感謝