2013-06-12 50 views
0

我正在重写一个小型的VB6应用程序/工具,其工作是安装一些传统VB6应用程序的最新版本。传统的VB6应用程序是一个构建并打包到可执行安装程序中的ActiveX DLL(某些Inno Setup脚本通过名称companynameSetup.exe构建安装程序)。C#进程vs VB6 Shell vs UAC

旧版VB6应用程序被改写:

  • 杀死消耗的ActiveX DLL(在所有已登录的用户)
  • 卸载当前的ActiveX DLL
  • 安装的ActiveX DLL的新版本的所有进程
  • 可以与禁用UI

重写的一个命令行参数来执行C#应用程序也完成了以上所有内容。唯一的区别(从全新的外观分开),是不论有/无用户界面,VB6的代码不会触发任何UAC提示:

但这种代码确实带来了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 }; 
+0

这是很清楚你想解决什么问题。如果是“我不想要UAC提示”,那么,不,这不是一个选项。如果是“我不需要管理员权限”,那么您的程序名称就很重要。如果它包含诸如“setup”或“upgrade”之类的词,那么Windows将猜测它是那种可能需要提升并且显示UAC提示的程序。你通过包含一个使用“asInvoker”的清单来避免这种情况。如果它是“我在无人看管的操作中获得UAC提示”,那么您可以使用计划任务解决该问题。 –

+0

@HansPassant对不起,如果我不够清楚:“我不想UAC提示”,的确如此。如果它不是一个选项,那么VB6代码如何在不触发UAC提示符下运行相同的可执行文件的情况下运行?如果必须的话,我会在VB6中编写流程启动部分,并在'unsafe'块中调用它。但是如果UAC没有办法,那么*我怎么没有从运行完全相同的可执行文件的VB6代码获得UAC提示?就UAC而言,VB6是否处于雷达之下? –

+0

VB6程序被视为传统程序,因为它没有清单。它所做的一切都是*重定向*,所以它不会造成任何麻烦。注册表写入HKLM将重定向到HKCU。文件写入受保护的目录被重定向到一个孤立的目录。如果这个程序真的有效,那么你实际需要的UAC提升的可能性非常低。 –

回答

1

就像在框架的大多数事情,NET的ProcessStartInfo类是...代码一个相当大的一堆。它包装了大量的Win32结构和调用。

经典的VB的Shell()函数是一个围绕WinExec() In Kernel32的轻量级包装,而这又是在32位和64位Windows中围绕CreateProcess() In Kernel32的薄包装。

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

  • 添加一个清单,以本次计划将其标记为“Vista的认识”内经:<requestedExecutionLevel level="asInvoker" uiAccess="false"/>

  • 告诉它不要使用ShellExecute()但首先设定,而非CreateProcess()Process.UseShellExecute = false;

和 “是弗吉尼亚州,一个VB6程序可以(也应该)有一个证明。”

我的C#被锈蚀,建议你可以去文档:ProcessStartInfo.UseShellExecute Property

+0

Woot-woot! 'UseShellExecute = false;'只需要花费!太感谢了! –

+0

'ShellExecute()'也是'CreateProcess()'的一个包装,但是包含了几层之间的脂肪 - 包括传统的安装程序检测。很高兴这是你所需要的。 – Bob77