【问题标题】:C# Process vs VB6 Shell vs UACC# 进程与 VB6 Shell 与 UAC
【发布时间】:2013-06-12 13:17:59
【问题描述】:

我正在重写一个小型 VB6 应用程序/工具,其工作是安装一些旧版 VB6 应用程序的最新版本。旧版 VB6 应用程序是一个 ActiveX DLL,它被构建并打包到一个可执行安装程序中(一些 Inno Setup 脚本构建一个名为 companynameSetup.exe 的安装程序)。

正在重写的旧版 VB6 应用程序:

  • 杀死所有消耗 ActiveX DLL 的进程(跨所有登录用户)
  • 卸载当前的 ActiveX DLL
  • 安装新版本的 ActiveX DLL
  • 可以使用禁用 UI 的命令行参数执行

重写后的 C# 应用程序也完成了上述所有工作。唯一的区别(除了全新的外观),无论有无 UI,VB6 代码都不会触发任何 UAC 提示:

Shell(pathAndFileName, vbNormalFocus)

但此代码确实为安装程序可执行文件启动了 UAC(卸载程序首先运行并且不提示):

var startInfo = new ProcessStartInfo(path, args);
using (var process = Process.Start(startInfo))
{
    while (!process.HasExited && _timerTicks < _timeoutTicks) Thread.Sleep(100);

    //... (log stuff, handle timeout, etc.)
}

这是作为计划任务运行后的日志文件:

2013-06-12 21:49:00.8555 | Info | AutoDeploy.App | COMPUTER : somedomain\someadminuser | StartUp. ShowUI=False; TimeOut=100 | 
...
2013-06-12 21:50:40.4447 | Trace | AutoDeploy.App | COMPUTER : somedomain\someadminuser | Installer timer interval has elapsed (ticks: 99). | 
2013-06-12 21:50:41.4446 | Trace | AutoDeploy.App | COMPUTER : somedomain\someadminuser | Installer timer interval has elapsed (ticks: 100). | 
2013-06-12 21:50:41.4602 | Warn | AutoDeploy.App | COMPUTER : somedomain\someadminuser | Process execution has timed out. Process may be hung. | 

该过程必须使用 UAC,因为如果我使用 GUI 手动运行它,一切都会在几秒钟内运行(在确定 UAC 之后)。因此 VB6 代码可以在一夜之间无人看管地运行,而重写的、新的和改进的(实现日志记录、失败通知、所有有趣的东西!)C# 应用程序不能。那么 VB6 是如何受到关注的呢?

所以问题是,我如何安排安装程序在无人看管的情况下运行,而不会让 UAC 搞砸?如果安排任务应该修复它,那么应该如何设置任务,我需要从我的程序集中添加/删除什么特别的东西才能让它工作?

编辑

解决方法很简单:

var startInfo = new ProcessStartInfo(path, args) { UseShellExecute = False };

【问题讨论】:

  • 目前还不清楚您要解决什么问题。如果它是“我不想要 UAC 提示”,那么,不,这不是一个选项。如果是“我不需要管理员权限”,那么您的程序名称很重要。如果它包含诸如“设置”或“升级”之类的词,那么 Windows 会猜测它是一种可能需要提升并显示 UAC 提示的程序。您可以通过包含使用“asInvoker”的清单来避免这种情况。如果是“我在无人值守操作中收到 UAC 提示”,那么您可以使用计划任务来解决。
  • @HansPassant 对不起,如果我不够清楚:“我不想要 UAC 提示”,确实。如果它不是一个选项,那么 VB6 代码如何在不触发 UAC 提示运行相同的可执行文件的情况下运行?如果需要,我将在 VB6 中编写进程启动部分并在 unsafe 块中调用它。但是,如果没有办法绕过 UAC,那么为什么我没有从运行完全相同的可执行文件的 VB6 代码中获得 UAC 提示?就 UAC 而言,VB6 是否受到关注?
  • VB6 程序被视为遗留程序,因为它没有清单。它所做的一切都是重定向,因此不会造成任何麻烦。对 HKLM 的注册表写入被重定向到 HKCU。对受保护目录的文件写入被重定向到隔离目录。如果该程序确实有效,那么您实际需要 UAC 提升的几率非常低。
  • @HansPassant 等一下,我安排这个程序,特别是因为我不希望计划任务挂起等待 UAC 确认,你是说那是什么不用担心,定时任务不会提示UAC?如果是这样,那么谢谢,问题解决了(现在就试试!)-谢谢! (说 VB6 版本确实有效有点牵强,但是是的,它“有效”)

标签: c# process vb6 uac


【解决方案1】:

像框架中的大多数东西一样,.Net 的ProcessStartInfo 类是一大堆...代码。它封装了大量的 Win32 结构和调用。

经典 VB 的 Shell() 函数是对 WinExec() In Kernel32 的轻量级包装器,而在 32 位和 64 位 Windows 中,它又是对 CreateProcess() In Kernel32 的薄包装器。

我猜你真正想要的是使用 ProcessStartInfo 启动一个外部程序,而不调用 Shell32 中的旧安装程序检测启发式。我能想到的有两种选择:

  • 通过&lt;requestedExecutionLevel level="asInvoker" uiAccess="false"/&gt;

  • 向第二个程序添加一个清单,将其标记为“Vista 感知”
  • 通过第一个设置告诉它不要使用ShellExecute(),而是使用CreateProcess()Process.UseShellExecute = false;

“是的,Virginia,VB6 程序可以(并且应该)有一个清单。”

我的 C# 生锈了,你可以参考文档:ProcessStartInfo.UseShellExecute Property

【讨论】:

  • 呜呜呜! UseShellExecute = false; 就是这样!谢谢一百万!
  • ShellExecute() 也是CreateProcess() 的包装器,但在两者之间涉及多层脂肪——包括遗留安装程序检测。很高兴这能满足您的需要。
猜你喜欢
  • 2014-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 2011-08-06
  • 2011-07-02
  • 2011-09-20
  • 2011-06-12
相关资源
最近更新 更多