【问题标题】:What is the difference between Process.Start() and running manually?Process.Start() 和手动运行有什么区别?
【发布时间】:2013-09-11 23:16:44
【问题描述】:

我正在为我工​​作的公司创建一个应用程序,它将为我们提供的某些软件备份数据。它可以选择将 SQL 数据库、文件夹、文件和注册密钥添加到备份作业中,然后将其放入 Zip 文件中。还有一些选项可以在需要时恢复备份。

我在注册表备份和还原方面遇到问题。我已经尝试过多次尝试使其正常工作,但我已经以最能说明我的问题的方式对其进行了简化,希望有人能提供帮助。

基本上我是通过使用带有命令行参数的 regedit.exe 来导入“.reg”文件。我尝试通过使用 ProcessStartInfo() 构建它来做到这一点,但它不起作用。因此,为了测试问题,我创建了一个批处理文件并按如下方式运行它:

    File.WriteAllText("ImportReg.bat", "regedit /s /i MyRegFile.reg");
    Process.Start("ImportReg.bat");

但这不起作用。

批处理文件创建成功,REG文件有效。这两个文件都与 EXE 位于相同的位置,所以我认为问题不应该在于正在使用的目录。如果我自己从这个位置运行批处理文件,它会成功导入注册表文件。我是我正在测试的机器上的完整管理员。

我也遇到了从注册表导出的问题。注册表的某些部分可以正常导出,而其他部分则不能。但是,如果我像上面的导入一样将导出设置为批处理文件,那么它每次都可以工作。

有人可以帮忙吗?我看不到为什么我的批处理文件有效,但当它通过 Process.Start 运行时却看不到。任何建议将不胜感激。

【问题讨论】:

  • 您是否验证了进程的退出代码?您可以通过调查 Process 返回的退出代码来弄清楚发生了什么。
  • 如果你这样做Process.Start("regedit.exe", "/s /i MyRegFile.reg");会起作用吗?
  • 感谢您的回复。从 Process.Start 直接运行 regedit.exe 是我最初开始使用它的方式,但在尝试找到问题时,我开始使用批处理文件来排除引号或反斜杠过多/过少的任何拼写问题。它也不起作用。如果我直接从运行框中使用该命令,它就可以正常工作。
  • 退出代码成功返回零。如果我在批处理文件中放了一个暂停,我可以看到命令窗口打开并在关闭之前等待我的输入。
  • 当你这样做时,无法诊断的故障太多了。使用 /s 选项当然也无济于事。请改用 .NET RegistryKey 类。

标签: c# windows process.start regedit


【解决方案1】:

可能是权限问题?

当您双击它时,Regedit 会自动提升。但是当运行你的程序时,它不是。也许这就是为什么它允许您导出注册表的某些部分,而不是其他部分。

【讨论】:

  • 我不确定。我试图导出的注册表的两个部分位于同一个子项中,并且是由我公司自己的软件创建的 - 一个有效,一个无效。知道如何测试吗?此外,我可以从应用程序导出的密钥与我无法通过应用程序导入的密钥相同。
【解决方案2】:

当程序运行时,即使登录用户是管理员,它也不会以提升的权限运行。 选项 A) 更改 Process.Start 以使用 'runas' 提升创建的进程

...
using System.Diagnostics;
...

System.Diagnostics.Process proc = new System.Diagnostics.Process();
  proc.StartInfo.FileName        = "C:\\Windows\\system32\\notepad.exe";
  proc.StartInfo.Verb            = "runas"; // Elevate the application
  proc.StartInfo.UseShellExecute = true;
proc.Start();

选项 B) 通过添加清单文件来提升权限

http://msdn.microsoft.com/en-us/library/bb384691.aspx

在 Visual Studio 开发环境中设置此链接器选项

  1. 打开项目的“属性页”对话框。有关详细信息,请参阅如何:打开项目属性页。
  2. 展开配置属性节点。
  3. 展开链接器节点。
  4. 选择清单文件属性页。
  5. 修改启用用户帐户控制 (UAC)、UAC 执行级别和 UAC 绕过 UI 保护属性。

清单文件看起来像这样

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <v3:trustInfo xmlns:v3="urn:schemas-microsoft-com:asm.v3">
        <v3:security>
            <v3:requestedPrivileges>
                <v3:requestedExecutionLevel level="requireAdministrator"/>
            </v3:requestedPrivileges>
        </v3:security>
    </v3:trustInfo>
</assembly>

选项 C),添加以下代码(它使用动词 runas,使用它的参数重新生成程序以提升重复的子进程) Windows 7 and Vista UAC - Programmatically requesting elevation in C#

【讨论】:

  • 但是调用进程也需要提升,所以也需要一个清单,或者使用其他2个选项
  • 为什么调用进程需要提升? Explorer 不是并且设法启动 regedit。
  • Explorer 不仅仅使用 Process.Start()。例如。 Explorer 使用 shell 注册表来执行一些事情,(即使是为了遗留目的,它也会加载与 Windows3.11 兼容的 DDE 内容)——这就是为什么您可以单击各种文件,而不仅仅是可执行文件。将您编写的用于启动进程的任何代码与资源管理器打开操作进行比较是不现实的,您不想编写任何效率低下或如此复杂的东西
  • 废话。最终,资源管理器进程调用 CreateProcess。然后加载程序读取附加到 regedit.exe 的清单并处理它。该清单为请求的执行级别指定了最高可用。编写一个简单的 C++ 程序,通过 regedit.exe 调用 CreateProcess。在没有提升的情况下运行此 C++ 程序。观察为 regedit 显示的 UAC 对话框。
  • 1) 这不是废话,explorer 做的不仅仅是 CreateProcess。这个博客blogs.msdn.com/b/oldnewthing 经常谈论自成立以来做作的探索者是如何成为的。 2)CreateProcess 包含 UseShellExecute 标志,以提供更多“浏览器”功能,例如读取 shell 关联表,但它不包含许多兼容性补丁。 3)如果你的进程已经被提升,那么对话框不会第二次产生,所以如果你想控制 UAC,你必须在你的进程中进行,因为你不能拦截清单 UAC。
【解决方案3】:

您可能传递了"regedit /s /i MyRegFile.reg" 作为可执行文件名。传递"regedit.exe" 和参数"/s /i MyRegFile.reg"

【讨论】:

    猜你喜欢
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    • 2013-10-24
    • 2022-01-26
    • 2021-09-08
    • 2014-10-05
    • 1970-01-01
    • 2022-09-30
    相关资源
    最近更新 更多