2010-10-13 39 views
14

Tôi có một ứng dụng (dịch vụ Windows) được cài đặt vào một thư mục trong thư mục Program Files. Cùng với ứng dụng này là một ứng dụng WinForms khác được sử dụng để cấu hình dịch vụ (trong số những thứ khác). Khi nó cấu hình, nó lưu các thay đổi vào một tập tin cấu hình sống cùng với dịch vụ.Cách đúng để xử lý UAC trong C#

Khi chạy trên Vista/Win7, UAC ngăn người dùng lưu tệp cấu hình. Những gì tôi muốn làm là:

  • đặt biểu tượng cái khiên bên cạnh các mục trình đơn sử dụng để cấu hình
  • lời nhắc về quyền UAC khi mục này được chọn
  • chỉ hiển thị các biểu tượng/dấu nhắc khi trên một hệ điều hành mà đòi hỏi nó
  • chỉ hiển thị các biểu tượng/dấu nhắc khi quyền được yêu cầu (ví dụ. nếu ứng dụng được cài đặt ở đâu đó mà không yêu cầu UAC phép)

tôi không thực sự muốn chạy toàn bộ ứng dụng với tư cách là quản trị viên, vì nó cũng được sử dụng cho các mục đích khác không yêu cầu quyền UAC (do đó, thiết lập tệp kê khai ứng dụng không phải là giải pháp chính xác). Tôi cũng giả định (sửa tôi nếu tôi sai) rằng một khi các điều khoản UAC đã được cấp, quy trình hiện tại của tôi không thể thực hiện hành động và tôi sẽ cần phải bắt đầu một quy trình mới.

Làm cách nào để đạt được điều này tốt nhất?

+0

Tôi phải làm một chút nhảy qua hoops để mã này lên một cách chính xác, nhưng nhờ Matthew tôi đã có một cái gì đó tương tự như những gì tôi mô tả ở trên. – adrianbanks

+0

Tốt để nghe. UAC đôi khi làm cho mọi thứ trở nên đau đớn, nhưng phần mềm của bạn thực sự tốt hơn cho nó. –

Trả lời

21

Điều này khá dễ dàng. Đặt biểu tượng cái khiên trên nút lưu thay đổi vào tệp cấu hình, thay vì mục menu. Điều này tuân theo hành vi của Windows không yêu cầu quyền UAC cho đến giây phút cuối cùng. Nút này thực sự sẽ khởi động lại tệp thực thi của bạn với tư cách là quản trị viên với dòng lệnh đặc biệt (bạn quyết định) để thực hiện lưu tệp cấu hình. Sử dụng một đường ống có tên (đảm bảo cung cấp cho nó quyền chính xác) để chuyển dữ liệu cấu hình đến thể hiện thứ hai của bạn nếu bạn không muốn sử dụng dòng lệnh để truyền dữ liệu.

Đối tung ra thực thi của bạn:

ProcessStartInfo info = new ProcessStartInfo(); 
info.FileName = "YOUR EXE"; 
info.UseShellExecute = true; 
info.Verb = "runas"; // Provides Run as Administrator 
info.Arguments = "YOUR SPECIAL COMMAND LINE"; 

if (Process.Start(info) != null) 
{ 
    // The user accepted the UAC prompt. 
} 

này cũng hoạt động khi UAC không tồn tại (Windows XP), bởi vì nó sẽ chỉ đơn giản là chạy as administrator nếu có thể, hoặc đòi hỏi quyền hạn. Bạn có thể kiểm tra xem hệ điều hành có yêu cầu UAC hay không bằng cách thực hiện Environment.OSVersion.Version.Major == 6. 6 là cả Windows Vista và 7. Bạn có thể đảm bảo rằng bạn đang sử dụng Windows bằng cách xem Environment.OSVersion.Platform.

Đối với việc phát hiện cho dù bạn đang ứng dụng đã được admin, bạn có thể làm điều này:

public static bool IsAdministrator() 
{ 
    WindowsIdentity identity = WindowsIdentity.GetCurrent(); 

    if (identity != null) 
    { 
     WindowsPrincipal principal = new WindowsPrincipal(identity); 
     return principal.IsInRole(WindowsBuiltInRole.Administrator); 
    } 

    return false; 
} 
+0

YOu sẽ phát hiện nếu người dùng hiện đang chạy dưới dạng quản trị viên. Nếu có, bạn có thể muốn hành xử khác nhau (ví dụ: không khởi chạy một phiên bản riêng biệt và có thể bỏ qua biểu tượng cái khiên). – Brian

+0

@Brian, Như ông đã chỉ ra, ông không muốn toàn bộ ứng dụng chạy với tư cách quản trị viên, vì vậy trong tình huống này, không có gì để phát hiện. Trừ khi bạn đang đề cập đến tài khoản Administrator thực sự, nơi mà ngay cả Windows vẫn sử dụng lá chắn. –

+0

@Matthew: Vâng, tôi biết OP không muốn ứng dụng chạy với tư cách quản trị viên. Điều đó không có nghĩa là người dùng sẽ không chạy nó dưới dạng quản trị viên, ví dụ: vì người dùng đang sử dụng Windows XP, cố tình sử dụng nhấp chuột phải chạy dưới dạng quản trị viên hoặc người dùng đã tắt UAC. – Brian

9

Matthew Ferreira's answer đi vào chi tiết về lý do tại sao bạn cần phải khởi động lại toàn bộ ứng dụng và phải làm gì khi khởi động lại nó Tuy nhiên, anh không bao gồm cách thể hiện biểu tượng cái khiên. Dưới đây là một số mã tôi sử dụng (tôi nghĩ tôi ban đầu đã nhận nó từ câu trả lời khác ở đâu đó trên trang web này) sẽ chỉ hiển thị biểu tượng cái khiên khi chương trình không được nâng lên

/// <summary> 
/// Is a button with the UAC shield 
/// </summary> 
public partial class ElevatedButton : Button 
{ 
    /// <summary> 
    /// The constructor to create the button with a UAC shield if necessary. 
    /// </summary> 
    public ElevatedButton() 
    { 
     FlatStyle = FlatStyle.System; 
     if (!IsElevated()) ShowShield(); 
    } 


    [DllImport("user32.dll")] 
    private static extern IntPtr 
     SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 

    private uint BCM_SETSHIELD = 0x0000160C; 

    private bool IsElevated() 
    { 
     WindowsIdentity identity = WindowsIdentity.GetCurrent(); 
     WindowsPrincipal principal = new WindowsPrincipal(identity); 
     return principal.IsInRole(WindowsBuiltInRole.Administrator); 
    } 


    private void ShowShield() 
    { 
     IntPtr wParam = new IntPtr(0); 
     IntPtr lParam = new IntPtr(1); 
     SendMessage(new HandleRef(this, Handle), BCM_SETSHIELD, wParam, lParam); 
    } 
} 

Các kiểm tra nút khi nó đang được xây dựng nếu nó nằm trong bối cảnh quản trị và nếu nó không phải là nó vẽ biểu tượng cái khiên trên nút.

Nếu bạn muốn cửa sổ biểu tượng cái khiên sử dụng, here is a sneaky trick trả về biểu tượng cái khiên làm đối tượng Bitmap.

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