2011-10-18 43 views
3

取消我經歷的ShellExecuteEx啓動EXE:如何檢測是否通過的ShellExecuteEx推出由UAC

tstring sPath = _T("C:\\Test\\MyApp.exe"); 
tstring sArgs = _T("/S"); 
SHELLEXECUTEINFO lpExecInfo = {0,}; 
lpExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); 
lpExecInfo.lpFile = sPath.c_str(); 
lpExecInfo.fMask=SEE_MASK_NOASYNC ;  
lpExecInfo.hwnd = NULL; 
lpExecInfo.lpVerb = NULL; 
lpExecInfo.lpParameters = sArgs.c_str(); 
lpExecInfo.lpDirectory = NULL; 
lpExecInfo.nShow = SW_SHOWNORMAL; 

if (!ShellExecuteEx(&lpExecInfo)) { 
    // handle the error 
    throw CException("Cannot launch an application"); 
} 

int nRes = (int)lpExecInfo.hInstApp; // nRes = 42 
DWORD dwErr = GetLastError(); // dwErr = 0 

我怎樣才能檢測是否啓動由UAC取消?在這種情況下ShellExecuteEx成功(hInstApp = 42,GetLastError返回0)。

感謝

+0

維塔利,當有問題後作爲評論發佈(如這一個)或編輯您的原始文章。如果它仍然是一個問題,請不要將其作爲答案發布。 – RedX

回答

2

如果ShellExecuteEx()沒有返回一個錯誤,那麼就沒有什麼可以做,以檢測UAC地取消正在發生ShellExecuteEx's控制之外。

你應該做的是使用CreateProcess()來代替。如果UAC拒絕新流程,這將返回一個錯誤。不要使用ShellExecuteEx()來啓動.exe文件,除非您使用「runas」動詞強制UAC提示。

+6

如果子進程需要提升,CreateProcess()只會失敗(帶有ERROR_ELEVATION_REQUIRED)。您必須使用其他API(例如ShellExecute())才能獲得提示。 – Luke

+0

然後簡短的回答是 - 如果API不直接向您報告,則無法檢測取消。 –

+0

您可能可以通過在fMask字段中設置SEE_MASK_NOCLOSEPROCESS標誌來完成此操作,但我不確定它是否會爲高級進程返回一個句柄。值得一看,但。 – Luke

1

現在的問題是CreateProcess在兩種情況下都成功,當啓動取消並且不被取消。問題是如何檢測它何時被取消?

可能無法檢測提升啓動成功還是失敗是安全功能。否則,您可以探測系統中已安裝的軟件,您不應該知道。

2

FAR Manager即使在使用ShellExecuteEx時也能夠檢測到UAC取消。

╔════════════ Error ═════════════╗ 
    ║  Operation cancelled  ║ 
    ║   Cannot execute   ║ 
    ║ D:\Downloads\fiddler4setup.exe ║ 
    ║    OK    ║ 
    ╚════════════════════════════════╝ 

我檢查下調試器會發生什麼和這裏的結構是如何的樣子:

lpVerb = "open"; 
lpFile = <path to the .exe>; 
lpParameters = ""; 
lpDirectory = <current directory>; 
nShow = SW_SHOWNORMAL; 
fMask = SEE_MASK_NOCLOSEPROCESS|SEE_MASK_NOASYNC| 
    SEE_MASK_FLAG_NO_UI|SEE_MASK_NOZONECHECKS; // 0x800540 

您可以檢查他們the source code做全魔。

相關問題