如何在Windows Vista / 7/8上以编程方式启动SFC?

时间:2014-01-01 17:57:54

标签: c# windows security windows-7 uac

我一直在努力解决Chris Iverson was having in this other Stackoverflow question

的问题

我想以编程方式启动SFC系统文件检查器工具)。

适用于Windows XP:

private void RunSfc()
{
    ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "/K sfc.exe /scannow");
    System.Diagnostics.Process.Start(startInfo);
}

enter image description here

执行的其他变种在Windows XP下工作:

//Launch SFC directly
ProcessStartInfo startInfo = new ProcessStartInfo("sfc.exe", "/scannow"); 
System.Diagnostics.Process.Start(startInfo);

//Use full path to SFC
String sfcPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "sfc.exe");
ProcessStartInfo startInfo = new ProcessStartInfo(sfcPath, "/scannow"); 

Windows 7上的相同代码失败(启动程序以管理员身份运行)。出现控制台窗口,但SFC提供错误:

Windows Resource Protection could not start the repair service.

enter image description here

但是,如果我从单独的提升的命令提示符手动运行sfc /scannow,它可以正常运行:

enter image description here

因此,Windows Vista / 7/8显然会发生一些奇怪的事情。我完全不知道是什么。但它可能与UAC,UIPI,会话0 isoloation或console windows were run by CSRSS

的事实有关

但是,我仍然不明白这个问题。

解决克里斯的问题本来不错,因为我想做他所做的事情。

并记住:我的代码已经以管理员身份运行。我右键单击并以管理员身份启动

enter image description here

这并不意味着问题不是与UAC相关的其他微妙问题,但并不是因为我作为标准用户运行。

WinForms应用程序中的代码

private void button1_Click(object sender, EventArgs e)
{
    RunSfc(); 
}

32位失败

原来有一个32位版本的cmd.exe和一个32位版本的sfc.exe

  • C:\的Windows \ Syswow64资料\ cmd.exe的
  • C:\的Windows \ Syswow64资料\ SFC.EXE

如果您运行提升的32位 cmd ,则32位或64位版本的 sfc 都不会起作用。

因此,难题变成了如何从32位进程启动 64位 cmd.exe。这可能意味着难题变成如何从32位进程找到 64位版本的cmd.exe,给出:

  • 您可能不在64位计算机上
  • 您可能已经在运行64位进程
  • Windows喜欢根据流程的位置伪造System32文件夹的名称

2 个答案:

答案 0 :(得分:3)

我的实验表明该问题与WOW64模拟器有关。我在非提升的WinForms应用程序中使用此代码:

...
using System.Diagnostics;
...

ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "/K sfc.exe /scannow");
  startInfo.UseShellExecute = true;
  startInfo.Verb = "runas";
Process.Start(startInfo);

在32位WOW64进程中,此消息在控制台窗口中失败:

  

Windows资源保护无法启动修复服务。

从64位进程,上面的代码成功。

确实,我认为.net或WinForms根本不相关。如果我从SysWOW64文件夹运行32位cmd.exe,然后调用sfc,我会遇到故障。但我使用64位cmd.exe成功。

甚至根本不需要将cmd.exe引入其中。从64位进程开始,不进行提升,以下成功:

...
using System.Diagnostics;
...

ProcessStartInfo startInfo = new ProcessStartInfo("sfc.exe", "/scannow");
startInfo.UseShellExecute = true;
startInfo.Verb = "runas";
Process.Start(startInfo);

所以我猜你的问题的解决方案将涉及将主程序切换到64位(可能有点激烈),或者将64位进程拼接到链中,以便可以运行64位sfc

答案 1 :(得分:1)

在这里得到了所有的帮助,我最终得到了这个,它在8.1 x64上运行良好。 非常感谢你们!

    ...
    using System.Diagnostics;
    ...

    private void button4_Click(object sender, EventArgs e)
    {
        string docs = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        string snat = Environment.GetEnvironmentVariable("windir") + @"\sysnative\sfc.exe";

        Process a = new Process();
          a.StartInfo.FileName = snat;
          a.StartInfo.Arguments = "/SCANNOW";
          a.StartInfo.UseShellExecute = false;
          a.StartInfo.RedirectStandardOutput = true;
          a.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
          a.StartInfo.CreateNoWindow = true;
        a.Start();

        string output = a.StandardOutput.ReadToEnd();
        a.WaitForExit();

        using (StreamWriter outfile = new StreamWriter(docs + @"\Testoutput.txt"))
        {
            outfile.Write(output);
        }

        MessageBox.Show("DONE!");
    }