2013-06-12 49 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