2009-09-08 33 views
5

Tôi đã hỏi điều này trong CreateDesktop() with Vista UAC (C Windows) Tôi đặt tiền thưởng nhưng cố gắng bỏ phiếu cho câu trả lời duy nhất "chấp nhận" đã bị nhầm lẫn (tôi đã tỉnh táo vì hơn 48 giờ). vì vậy tôi hỏi lại.CreateDesktop() với vista và UAC trên (C, windows)

Tôi đang sử dụng CreateDesktop() để tạo một máy tính để bàn tạm thời, nơi ứng dụng sẽ chạy, thực hiện thao tác dọn dẹp (trong khi còn lại) và chấm dứt. Tôi đóng máy tính để bàn đó khi ứng dụng đã biến mất. Mọi thứ đều ổn khi sử dụng Windows XP và thậm chí cả Vista. Vấn đề phát sinh khi bạn kích hoạt UAC (gây phiền nhiễu).

Mọi thứ đều ổn khi bạn tạo một màn hình, nhưng khi bạn gọi CreateProcess() để mở chương trình trên màn hình đó, ứng dụng đã mở bị lỗi với ngoại lệ trên User32.dll.

Tôi đã đọc rất nhiều về các máy tính để bàn và lớp khác nhau trên Windows và các hạn chế về bộ nhớ. Tuy nhiên, hầu hết các chương trình tôi mở (như các kịch bản thử nghiệm) đều OK, nhưng một vài chương trình (như IE, Notepad, Calc và ứng dụng của riêng tôi) gây ra sự cố.

Bất cứ ai cũng có ý tưởng tại sao điều này xảy ra trên Vista với UAC, hoặc cụ thể hơn cho các chương trình cụ thể đó? và cách khắc phục điều này?

Bất cứ ai cũng có một ví dụ vững chắc về cách tạo một máy tính để bàn và mở một ứng dụng ở đó mà không cần chuyển sang ứng dụng dưới Vista với UAC?

Mã được đánh giá cao.

Cảm ơn

Mã được sử dụng là

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

Bạn đang làm điều này trong một chuỗi giao diện người dùng? – Isaac

+0

Ý nghĩa? Ý tôi là, tôi đang gọi CreateDesktop từ chủ đề chính của ứng dụng – wonderer

+0

Một dấu vết ngăn xếp sẽ khá hữu ích cũng như – jcopenha

Trả lời

4

Bạn dường như đã đi qua một lỗi trong trình duyệt IE vì nó tương tác với UAC. Nếu chế độ được bảo vệ được đặt thành bật, bạn không thể chạy IE với tư cách người dùng thông thường trong bất kỳ máy tính để bàn nào ngoại trừ chế độ mặc định. Để chạy IE trên màn hình thay thế, bạn phải chạy với tư cách quản trị viên hoặc đã tắt chế độ bảo vệ. Điều này đúng với Vista, W2K8 và Win7.

Đối với các chương trình khác mà bạn không thể chạy, rất tiếc tôi không thể xác nhận bất kỳ điều gì. Tôi đã thử lên trên ba mươi chương trình khác nhau bao gồm notepad, calc, tất cả các ứng dụng văn phòng, studio trực quan 2005, 2008 và 2010, MSDN trợ giúp và một số người khác và tất cả làm việc như mong đợi với ngoại lệ được chú ý của IE. Có điều gì đó thực sự bất thường về ứng dụng của bạn có thể khiến ứng dụng hoạt động một cách bất ngờ không?

Một lưu ý - nếu bạn cố gắng chạy một ứng dụng như thế này cần độ cao (chẳng hạn như regedit, v.v.) nó sẽ thất bại trong CreateProcess với lỗi cuối được đặt thành ERROR_ELEVATION_REQUIRED.

Đối với các bạn tham khảo, trong trường hợp tôi đang làm một cái gì đó khác biệt so với bạn, mã tôi sử dụng là:

#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

Điều này thật lạ vì tôi không gặp vấn đề gì với windows 7, không phải IE, không phải ứng dụng của tôi không phải ứng dụng nào có đầy đủ UAC ON – wonderer

+0

Tôi đã kiểm tra lại Win7 với một vài cấu hình khác nhau và tôi vẫn không thể chạy IE trên máy tính khác. Mặc dù trên Win7 quá trình chỉ đơn giản biến mất, không có hộp thoại tường trình sự cố hoặc ứng dụng sự cố đăng nhập. –

+0

Chỉ vì mục đích hoàn thành, câu hỏi này đã được trả lời tự động. Nó KHÔNG phải là câu trả lời. Tôi không đặt nó làm câu trả lời. – wonderer

9

Các giải pháp đúng được đưa ra như một lời nhận xét ngắn bởi ChristianWimmer trên:

Máy tính để bàn phải có bộ mô tả bảo mật cho phép truy cập đến mức toàn vẹn thấp hơn như IE. Nếu không, GUI không thể truy cập vào màn hình nền.- ChristianWimmer 22 Tháng 7 '10 17:00

Kể từ khi câu trả lời là một chút ẩn và không có mã nguồn ví dụ, hãy để tôi nêu rõ ràng ở đây:

Nếu IE chạy trong chế độ bảo vệ sau đó các tab trình duyệt được tạo thành các quy trình toàn vẹn thấp. Quy trình tab toàn vẹn thấp sẽ không khởi tạo được nếu màn hình không có nhãn bắt buộc toàn vẹn thấp.

Kết quả là, quá trình IE chính cũng chấm dứt. Một quan sát thú vị là nếu bạn bắt đầu trình duyệt IE cung cấp một URL dòng lệnh từ vùng bảo mật, thì IE sẽ thành công để bắt đầu, bởi vì chế độ bảo vệ bị tắt theo mặc định cho vùng bảo mật.

Tôi đã kiểm tra mức toàn vẹn của màn hình nền mặc định và thực sự tôi có thể xác minh rằng máy tính để bàn mặc định có mức toàn vẹn thấp! Vì vậy, giải pháp dễ nhất cho vấn đề là (1) tạo máy tính để bàn mới, (2) lấy nhãn bắt buộc từ màn hình nền mặc định và (3) sao chép nó vào màn hình nền mới. Đối với (2) và (3), bạn có thể sử dụng mã sau đây

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: Cảm ơn bạn đã cung cấp gợi ý cho giải pháp đúng. Điều này tiết kiệm rất nhiều thời gian của tôi !!

Các vấn đề liên quan