C:\Windows\System32\WFS.exeを起動したい

タグの編集
投稿者 エピ  (社会人) 投稿日時 2023/12/29 10:30:32
Process.Start("C:\Windows\System32\WFS.exe") 
Windows FAXとスキャンを起動したいのですが上記で実行すると
指定したファイルが見つかりませんとなってしまいます。
WFS.exeは存在しています。

どうすれば起動できるのか教えていただけないでしょうか
notepad.exeなどは起動します
投稿者 るきお  (社会人) 投稿日時 2023/12/29 14:23:52
試しに Visual Basic のコンソールアプリケーション(.NET 8)で下記プログラムを実行してみましたが、私の環境では無事 Windows Faxとスキャン が起動しました。

Imports System

Module Program
    Sub Main(args As String())
        Process.Start("C:\Windows\System32\WFS.exe")
    End Sub
End Module


エピさんの環境では、「指定されたファイルが見つかりません。」というエラーになるということですが、私が思いつく原因はあまりないのです。2つほど挙げてみます。

1.本当にファイルが存在しない。

「WFS.exeは存在しています。」とのことですが、本当に存在するのか、Windows + R で「ファイル名を指定して実行」ダイアログを表示して「C:\Windows\System32\WFS.exe」と入力して、OKで起動できるか念のため確認してみてください。

2.プログラムを実行している環境が、エピさんが想定している環境ではない。

たとえば、実行するときに WSL で実行していませんか?
または、どこかにデプロイしてクラウドやWebサーバーで実行している、コンテナ内で実行している、何かのエミュレーターの中で実行しているなどということはないでしょうか?

解決しないようであれば、1の確認の結果と、実際に動かしているエラーになるプログラムを共有いただき、あわせて、そのプログラムをどうやって実行しているかも教えてください。


投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/12/29 16:17:06
x86 ビルドで実行されているのではありませんか?
Process.Start("C:\Windows\SysNative\WFS.exe")
投稿者 エピ  (社会人) 投稿日時 2023/12/29 16:42:38
るきおさん、魔界の仮面弁士さん ありがとうございます。

コンソールアプリケーションでは起動できました。

ビルドはコンパイルのターゲットCPUでしょうか AnyCPUになっています。
投稿者 とくま  (社会人) 投稿日時 2024/1/4 09:34:02
>ビルドはコンパイルのターゲットCPUでしょうか AnyCPUになっています。
そうです。

「x86 x64」でweb検索すれば分かると思いますが、
過去、パソコンの基本性能が32ビットから64ビットへ移行した時代に
それぞれに対応したDLLが2種類存在した名残です。
実はパソコンは裏でその2種類をうまく切り替えていました。

最近のPCは64ビットなので、AnyCPUかx64にするのですが、
その名残は今でも残っていて、対象のドライバが古かったり、うまく判断できないと
プログラム上からは見つけられない判定になる場合があります。

x86→32ビット
x64→64ビット

とりあえず、EXEをx86とx64のビルド版、2種類作って、どちらかで起動するか確認してはどうでしょうか?

プロジェクトの[プロパティ]-[ビルド]-[32ビットを優先]
のチェックありなしも関係します。チェックは外しておいて下さい。

https://qiita.com/mima_ita/items/57d7c1101543e214b1d6

投稿者 エピ  (社会人) 投稿日時 2024/1/4 11:04:10
とくまさんありがとうございます。

x64,AnyCPU 32ビットを優先のチェックを外す
これで起動できました。
投稿者 とくま  (社会人) 投稿日時 2024/1/4 14:48:58
エピ さん
解決して良かったです。


★有識者の方へ
>x64,AnyCPU 32ビットを優先のチェックを外す
この設定、64ビットしかコマンドが通らないって解釈してますが、合ってますでしょうか?

この質問で思い出したことがありまして、
プラットホームターゲット:AnyCPU
ビルド環境・実行環境:Windows 10 Pro(64 ビット オペレーティング システム)
Process.Start
で実行すると
>指定されたファイルが見つかりません。

process.StandardError
で取ると
>'C:\windows\system32\ie4uinit.exe' は、内部コマンドまたは外部コマンド、
>操作可能なプログラムまたはバッチ ファイルとして認識されていません。
とのエラーが出るコマンドがありまして

私は、他にも実行しているコマンドが沢山あったので、影響範囲が最小になるように本体EXEは変更せず
本体EXE(AnyCPU、32ビットを優先のチェックあり)呼び出し→別EXE(AnyCPU、32ビットを優先のチェック★無し)呼び出し→"ie4uinit.exe"
の形で逃げたのですが、どうするのが良い形なのかご意見を伺えたらと思いました。


using System;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;

static void DesktopRedrawFunc()
{
    string strCommand;
    string strStandard;
    string strError;
    int intExitCode;

    string strSystemPath = Environment.GetFolderPath(Environment.SpecialFolder.System);
    string strCommandPath = Path.Combine(strSystemPath, "ie4uinit.exe");

    //プロジェクトのプロパティで「32bitを優先」のチェックを外さないと実行できない⇒終了コード 1 となる

    // Windowsアイコンキャッシュ再構築(Win7)
    //strCommand = @"""" + strSystemPath + @"\ie4uinit.exe"" -ClearIconCache"; //Process.Startの時は引数付けた時点でエラーになるかも↓引数なしコマンドで通る
    ////strCommand = @"""C:\WINDOWS\system32\ie4uinit.exe""";
    ////strCommand = @"""C:\Program Files (x86)\Microsoft Office\Office16\EXCEL.EXE""";
    ////strCommand = @"ipconfig /all >> c:\ipconfigAllTest.txt";
    strCommand = @"""" + strCommandPath + @""" -ClearIconCache";
    //Process.Start(strCommand);
    ExecBatProcess(strCommand, out strStandard, out strError, out intExitCode);

    if (strStandard != string.Empty)
    { MessageBox.Show("標準出力      :" + strStandard); Console.WriteLine("標準出力      :" + strStandard); }
    if (strError != string.Empty)
    { MessageBox.Show("標準エラー出力:" + strError); Console.WriteLine("標準エラー出力:" + strError); }
    MessageBox.Show("終了コード    :" + intExitCode.ToString());

    // Windowsアイコンキャッシュ再構築(Win10)
    //strCommand = @"""" + strSystemPath + @"\ie4uinit.exe"" -show";
    strCommand = @"""" + strCommandPath + @""" -show";
    //Process.Start(strCommand);
    ExecBatProcess(strCommand, out strStandard, out strError, out intExitCode);

    if (strStandard != string.Empty)
    { MessageBox.Show("標準出力      :" + strStandard); Console.WriteLine("標準出力      :" + strStandard); }
    if (strError != string.Empty)
    { MessageBox.Show("標準エラー出力:" + strError); Console.WriteLine("標準エラー出力:" + strError); }
    MessageBox.Show("終了コード    :" + intExitCode.ToString());

}

/// <summary>
/// バッチコマンドを実行する
/// </summary>
/// <param name="executeCommand">コマンド文字列</param>
/// <param name="stdOut">標準出力</param>
/// <param name="stdErr">標準エラー出力</param>
/// <param name="exitCode">終了コード</param>
/// <returns>リターンコード</returns>
public static void ExecBatProcess(string executeCommand, out string stdOut, out string stdErr, out int exitCode)
{
    stdOut = string.Empty;
    stdErr = string.Empty;
    exitCode = 0;

    Process process = new Process();
    //ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd.exe", "/c " + executeCommand);
    ProcessStartInfo processStartInfo = new ProcessStartInfo(Environment.GetEnvironmentVariable("ComSpec"), "/c " + executeCommand);
    processStartInfo.CreateNoWindow = true;
    processStartInfo.UseShellExecute = false;

    processStartInfo.RedirectStandardOutput = true;
    processStartInfo.RedirectStandardError = true;

    process = Process.Start(processStartInfo);

    stdOut = process.StandardOutput.ReadToEnd().Trim();
    stdErr = process.StandardError.ReadToEnd().Trim();
    exitCode = process.ExitCode;

    // WaitForExitをReadToEndの後にしないと、親プロセスと子プロセスの両方でブロック処理が発生し、デッドロックの原因となる
    process.WaitForExit();
    process.Close();
    process.Dispose();

    //return 0;
}




投稿者 魔界の仮面弁士  (社会人) 投稿日時 2024/1/5 01:31:25
> x64,AnyCPU 32ビットを優先のチェックを外す
そっちで解決しちゃいましたか…。

SysNative というヒントを出したので、そこから WOW64 環境のファイル システム リダイレクターのことに辿り着けることを期待していました。
https://learn.microsoft.com/ja-jp/windows/win32/winprog64/file-system-redirector

Dim sysDir = Environment.GetFolderPath(Environment.SpecialFolder.System)
If Environment.Is64BitOperatingSystem AndAlso Not Environment.Is64BitProcess Then
    sysDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "SysNative")
End If
Process.Start(Path.Combine(sysDir, "WFS.exe"))


なお、WFS.exe (Windows FAX とスキャン) がインストールされていない環境もありえるので、
いずれにせよ、Try ~ Catch は配置しておいた方が必要でしょう。
投稿者 エピ  (社会人) 投稿日時 2024/1/5 11:23:46
魔界の仮面弁士さん ありがとうございます。
優先のチェックを外してプログラムを作っていたのですが
RTb = AcCon.CurrentDb.CreateTableDef****のところで以下の所でエラーが出てしまいました。
System.Runtime.InteropServices.COMException: 'タイプ ライブラリ/DLL の読み込みエラーです。 (HRESULT からの例外:0x80029C4A (TYPE_E_CANTLOADLIBRARY))'

この掲示板を見直していたところ【SysNative】の部分見落としていました
Process.Start("C:\Windows\SysNative\WFS.exe")とし両方解決することができました。
ありがとうございました。
 
'Accessのリンクテーブル作成 
        Dim RTb As TableDef : Dim OdCon As String : Dim TbName(2) As String

       OdCon = "ODBC;DSN=*****;DATABASE=*****;UID=sa;PWD=*****;Encrypt=no;TrustServerCertificate=no;" &
               "ConnectRetryCount=24;ConnectRetryInterval=5;Connection Timeout=120;"

        For i As Integer = 1 To 2
            'ODBCとSQLのTableName 
            TbName(1) = "dbo_" & TBL(i) : TbName(2) = "dbo." & TBL(i)

            RTb = AcCon.CurrentDb.CreateTableDef(TbName(1), TableDefAttributeEnum.dbAttachSavePWD, TbName(2), OdCon)

            'Tableがあれば削除して再作成 
            If AcCon.DCount("*""MSysObjects""[Name] = '" & TbName(1) & "'") > 0 Then

                acCmd.DeleteObject(Access.AcObjectType.acTable, TbName(1))
                AcCon.CurrentDb.TableDefs.Append(RTb)
            Else

                'なければ作成 
                AcCon.CurrentDb.TableDefs.Append(RTb)
            End If
        Next