“File not found” error launching system32\winsat.exe using Process.Start()

廉价感情. 提交于 2019-12-01 16:34:17

问题


I'm trying to run the Windows System Assessment Tool (winsat.exe) using the following code:

System.Diagnostics.Process WinSPro =
    new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo WinSSInfo = 
    new System.Diagnostics.ProcessStartInfo();
WinSSInfo.FileName = "cmd.exe";
WinSSInfo.Arguments = "/k winsat.exe";
WinSPro.StartInfo = WinSSInfo;
WinSPro.Start();

This code works if I only call cmd.exe, and even if I call regedit.exe it still works. However, when I try to call winsat.exe as a argument of cmd.exe, it fails. The command prompt shows this:

'winsat.exe' is not recognized as an internal or external command, 
operable program or batch file.

I tried several ways to call winsat.exe:

  1. Call it directly by assigning "winsat.exe" to ProcessStartInfo.FileName. It fails with a Win32Exception: The system cannot find the file specified

  2. As above, using the full path - @"c:\windows\system32\winsat.exe". It fails with the same error.

  3. Run the code as the System Administrator. It still fails.

  4. Call winsat.exe as in the coded example. It failed as I explained earlier.

It's interesting that the command prompt launched from the code can only see .dll files in c:\windows\system32.

Does anyone have any idea why winsat.exe cannot be launched through System.Diagnostics.Process? Are there any limitations which I've misunderstood?

Thanks,

Rex


回答1:


winsat.exe is redirected using Windows-on Windows 64-bit redirection. What's happening is that your launch request (from a 32-bit process) is being redirected to %windir%\SysWOW64\winsat.exe. Since there's no 32-bit version of this particular executable on 64-bit installs, the launch fails. To bypass this process and allow your 32-bit process to access the native (64-bit) path, you can reference %windir%\sysnative instead:

Process WinSPro = new Process();
ProcessStartInfo WinSSInfo = new ProcessStartInfo();
WinSSInfo.FileName = @"c:\windows\sysnative\winsat.exe";
WinSPro.StartInfo = WinSSInfo;
WinSPro.Start();

Alternatively, if you build your program as x64, you can leave the path as c:\windows\system32.

Note that it's best to use Environment.GetFolderPath to get the path to the windows directory, just in case the OS is installed in a non-standard location:

WinSSInfo.FileName = Path.Combine(
    Environment.GetFolderPath(Environment.SpecialFolder.Windows),
    @"sysnative\winsat.exe");



回答2:


Based on Simon MᶜKenzie's answer, and the link he provided (thanks to soyuz for his comment) I wrote method that should work in either cases (to just copy/paste the code):

public static string GetSystem32DirectoryPath()
{
    string winDir = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
    string system32Directory = Path.Combine(winDir, "system32");
    if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
    {
        // For 32-bit processes on 64-bit systems, %windir%\system32 folder
        // can only be accessed by specifying %windir%\sysnative folder.
        system32Directory = Path.Combine(winDir, "sysnative");
    }
    return system32Directory;
}

and code to launch the process:

var pi = new ProcessStartInfo
{
    FileName = Path.Combine(GetSystem32DirectoryPath(), "winsat.exe"),
    CreateNoWindow = true,
    UseShellExecute = false
};
Process.Start(pi);


来源:https://stackoverflow.com/questions/16827229/file-not-found-error-launching-system32-winsat-exe-using-process-start

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!