2009-09-08 6 views
5

Zapytałem o to w CreateDesktop() with Vista UAC (C Windows) Ustawiłem nagrodę, ale próbując zagłosować jedyną odpowiedzią, przez pomyłkę naciśnięto "zaakceptuj" (czułem się więcej niż 48 godzin). więc proszę o to ponownie.CreateDesktop() z vista i UAC na (C, Windows)

Używam CreateDesktop(), aby utworzyć tymczasowy pulpit, na którym uruchomiona zostanie aplikacja, wykonać akcję czyszczącą (pozostając na uboczu) i zakończyć działanie. Zamykam ten pulpit, gdy aplikacja zniknie. Wszystko jest w porządku podczas korzystania z systemu Windows XP, a nawet Vista. Problem pojawia się, gdy włączysz (denerwujący) UAC.

Wszystko jest w porządku po utworzeniu pulpitu, ale po wywołaniu CreateProcess() w celu otwarcia programu na tym komputerze powoduje on awarię uruchomionej aplikacji z wyjątkiem na User32.dll.

Czytałem dużo o różnych komputerach i warstwach w systemie Windows i ograniczeniach pamięci. Jednak większość programów, które otwieram (jako scenariusze testowe) jest w porządku, ale kilka (jak IE, Notepad, Calc i moja własna aplikacja) powoduje awarię.

Ktoś ma pojęcie, dlaczego tak się dzieje w systemie Vista z UAC, a dokładniej z tymi konkretnymi programami? i jak to naprawić?

Ktoś ma dobry przykład na to, jak utworzyć pulpit i otworzyć tam aplikację bez przełączania się na nią w systemie Vista z UAC na?

Kod jest mile widziany.

Dzięki

Kod stosowany jest

SECURITY_ATTRIBUTES sa; 

HDESK dOld; 
HDESK dNew; 

BOOL switchdesk, switchdesk2, closedesk; 
int AppPid; 

sa.bInheritHandle = TRUE; 
sa.lpSecurityDescriptor = NULL; 
sa.nLength = sizeof(SECURITY_ATTRIBUTES); 

//Get handle to current desktop 
dOld = OpenDesktopA("default", 0, TRUE, DESKTOP_SWITCHDESKTOP| 
             DESKTOP_WRITEOBJECTS| 
             DESKTOP_READOBJECTS| 
             DESKTOP_ENUMERATE| 
             DESKTOP_CREATEWINDOW| 
             DESKTOP_CREATEMENU); 
if(!dOld) 
{ 
    printf("Failed to get current desktop handle !!\n\n"); 
    return 0; 
} 

//Make a new desktop 
dNew = CreateDesktopA("kaka", 0, 0, 0, DESKTOP_SWITCHDESKTOP| 
              DESKTOP_WRITEOBJECTS| 
              DESKTOP_READOBJECTS| 
              DESKTOP_ENUMERATE| 
              DESKTOP_CREATEWINDOW| 
              DESKTOP_CREATEMENU, &sa); 

if(!dNew) 
{ 
    printf("Failed to create new desktop !!\n\n"); 
    return 0; 
} 

AppPid = PerformOpenApp(SomeAppPath); 
if(AppPid == 0) 
{ 
    printf("failed to open app, err = %d\n", GetLastError()); 
} 
else 
{ 
    printf("App pid = %d\n", AppPid); 
} 


closedesk = CloseDesktop(dNew); 

if(!closedesk) 
{ 
    printf("Failed to close new desktop !!\n\n"); 
    return 0; 
} 


return 0; 
+0

Czy robisz to w wątku UI? – Isaac

+0

Czyli? Mam na myśli, nazywam CreateDesktop z głównego wątku aplikacji – wonderer

+0

Śledzenie stosu byłoby całkiem pomocne również – jcopenha

Odpowiedz

4

Wygląda na to jest natknąć się na błąd w IE, jak współdziała z UAC. Jeśli tryb chroniony jest włączony, nie można uruchamiać IE jako zwykłego użytkownika na żadnym pulpicie oprócz domyślnego. Aby uruchomić IE na alternatywnym pulpicie, musisz być uruchomiony jako administrator lub mieć wyłączony tryb chroniony. Dotyczy to Vista, W2K8 i Win7.

Jeśli chodzi o inne programy, których nie możesz uruchomić, niestety nic nie mogę potwierdzić. Wypróbowałem ponad trzydzieści różnych programów, w tym notatnik, calc, wszystkie aplikacje biurowe, wizualne studio 2005, 2008 i 2010, pomoc MSDN i wiele innych i wszystko działało zgodnie z oczekiwaniami z wyjątkiem IE. Czy jest coś niezwykłego w Twojej aplikacji, które może sprawić, że będzie się zachowywać w nieoczekiwany sposób?

Jedna uwaga - jeśli spróbujesz uruchomić aplikację podobną do tej, która potrzebuje podniesienia (np. Regedit itp.), To się nie uda w CreateProcess z ostatnim błędem ustawionym na ERROR_ELEVATION_REQUIRED.

Dla odniesienia, w przypadku robię coś innego od was, kod użyłem to:

#ifndef _WIN32_WINNT   // Specifies that the minimum required platform is Windows Vista. 
#define _WIN32_WINNT 0x0600  // Change this to the appropriate value to target other versions of Windows. 
#endif 

#include <stdio.h> 
#include <tchar.h> 

#include "windows.h" 

HANDLE PerformOpenApp(TCHAR* appPath); 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    HDESK dNew; 
    BOOL closedesk; 
    HANDLE hApp; 

    //Make a new desktop 
    dNew = CreateDesktop(_T("kaka"), 0, 0, 0, DESKTOP_SWITCHDESKTOP| 
               DESKTOP_WRITEOBJECTS| 
               DESKTOP_READOBJECTS| 
               DESKTOP_ENUMERATE| 
               DESKTOP_CREATEWINDOW| 
               DESKTOP_CREATEMENU, NULL); 

    if(!dNew) 
    { 
     _tprintf(_T("Failed to create new desktop !!\n\n")); 
     return 0; 
    } 

    TCHAR path[MAX_PATH]; 
    _putts(_T("Enter the path of a program to run in the new desktop:\n")); 
    _getts(path); 

    while(_tcslen(path) > 0) 
    { 
     hApp = PerformOpenApp(path); 
     if(hApp == 0) 
     { 
      _tprintf(_T("Failed to open app, err = %d\n"), GetLastError()); 
     } 
     else 
     { 
      _tprintf(_T("App pid = %d\n"), GetProcessId(hApp)); 
      _putts(_T("Press any key to close the app.\n")); 
      _gettchar(); 
      TerminateProcess(hApp, 0); 
      CloseHandle(hApp); 
     } 
     _putts(_T("Enter the path of a program to run in the new desktop:\n")); 
     _getts(path); 
    } 

    closedesk = CloseDesktop(dNew); 

    if(!closedesk) 
    { 
     _tprintf(_T("Failed to close new desktop !!\n\n")); 
     return 0; 
    } 
    return 0; 
} 

HANDLE PerformOpenApp(TCHAR* appPath) 
{ 
    STARTUPINFO si = {0}; 
    PROCESS_INFORMATION pi; 

    si.cb = sizeof(si); 
    si.lpDesktop = _T("kaka"); 

    BOOL retVal = CreateProcess(NULL, appPath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, 
     NULL, &si, &pi); 

    if (retVal) 
    { 
     CloseHandle(pi.hThread); 
    } 
    return pi.hProcess; 
} 
+0

To dziwne, ponieważ nie mam problemu z Windows 7, nie IE, nie moja aplikacja nie ma żadnej aplikacji z pełnym UAC NA – wonderer

+0

Podwójnie sprawdziłem Win7 z kilkoma różnymi konfiguracjami i nadal nie mogłem uruchomić IE na innym pulpicie. Jednak na Win7 proces po prostu zniknął, nie było żadnego okna dialogowego awarii ani wpisu zdarzenia awarii aplikacji. –

+0

W celu uzupełnienia tego pytania automatycznie udzielono odpowiedzi. To NIE jest odpowiedź. Nie ustawiłem go jako odpowiedzi. – wonderer

9

Prawidłowe rozwiązanie jest podane jako krótkim komentarzem przez ChristianWimmer powyżej:

Pulpit musi mieć deskryptor zabezpieczeń, który umożliwia dostęp do niższego poziomu integralności, takiego jak IE. W przeciwnym razie interfejs GUI nie będzie mógł uzyskać dostępu do pulpitu.- ChristianWimmer 22 lipca '10 o 17:00

Ponieważ odpowiedź jest trochę ukryty i nie ma przykładowy kod źródłowy, pozwól mi stwierdzić jasno tutaj:

Jeśli IE działa w trybie chronionym następnie zakładki przeglądarki są tworzone jako procesy o niskiej integralności. Proces zakładki niskiej integralności nie zostanie zainicjowany, jeśli na pulpicie nie ma etykiety obowiązkowej niskiej integralności.

W konsekwencji główny proces IE również się kończy. Interesującą obserwacją jest to, że jeśli uruchomisz IE dostarczając URL linii poleceń ze strefy bezpiecznej, to IE się uda, ponieważ tryb chroniony jest domyślnie wyłączony dla strefy bezpiecznej.

Sprawdziłem poziom integralności domyślnego pulpitu i rzeczywiście udało mi się sprawdzić, czy domyślny pulpit ma niski poziom integralności! Najłatwiejszym rozwiązaniem tego problemu jest (1) stworzenie nowego pulpitu, (2) pobranie obowiązkowej etykiety z domyślnego pulpitu i (3) skopiowanie jej na nowy pulpit. For (2) i (3), można użyć następującego kodu

PACL pSacl; 
PSECURITY_DESCRIPTOR pSecurityDescriptor; 
DWORD dwResult; 

dwResult = GetSecurityInfo(hDefaultDesktop, SE_WINDOW_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, &pSacl, &pSecurityDescriptor); 

if (dwResult == ERROR_SUCCESS) { 
    if (pSacl != NULL) { 
     dwResult = SetSecurityInfo(hNewDesktop, SE_WINDOW_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, pSacl); 

     if (dwResult != ERROR_SUCCESS) 
      _tprintf(_T("SetSecurityInfo(hNewDesktop) failed, error = %d"), dwResult); 
    } 

    LocalFree(pSecurityDescriptor); 
} else { 
    _tprintf(_T("GetSecurityInfo(hDefaultDesktop) failed, error = %d"), dwResult); 
} 

@CristianWimmer: Dzięki za dostarczenie wskazówkę do prawidłowego rozwiązania. To oszczędzało mi dużo czasu !!

Powiązane problemy