Làm thế nào để nâng cao đặc quyền chỉ khi được yêu cầu?


85

Câu hỏi này áp dụng cho Windows Vista!

Tôi có một ứng dụng thường hoạt động mà không có đặc quyền quản trị. Có một hoạt động cần đặc quyền quản trị nhưng tôi không muốn tự khởi động ứng dụng với các đặc quyền cao hơn khi tôi biết rằng hầu hết thời gian người dùng thậm chí sẽ không sử dụng tính năng đó.

Tôi đang suy nghĩ về một số phương pháp mà tôi có thể nâng cao các đặc quyền của ứng dụng trong một số sự kiện (chẳng hạn như nhấn nút). Thí dụ:

Nếu người dùng nhấp vào nút này thì họ sẽ được nhắc bằng hộp thoại UAC hoặc sự đồng ý. Tôi có thể làm cái này như thế nào?

Câu trả lời:


58

Tôi không tin rằng có thể nâng cao quy trình hiện đang chạy. Theo tôi hiểu, nó được tích hợp vào Windows Vista mà các đặc quyền của quản trị viên được cấp cho một quy trình khi khởi động. Nếu bạn nhìn vào các chương trình khác nhau sử dụng UAC, bạn sẽ thấy rằng chúng thực sự khởi chạy một quy trình riêng biệt mỗi khi một hành động quản trị cần được thực hiện (Task Manager là một, Paint.NET là một, thực tế là ứng dụng .NET ).

Giải pháp điển hình cho vấn đề này là chỉ định các đối số dòng lệnh khi khởi chạy một quy trình nâng cao (gợi ý của abatishchev là một cách để thực hiện điều này), để quy trình được khởi chạy chỉ biết hiển thị một hộp thoại nhất định và sau đó thoát sau khi hành động này đã được thực hiện. đã hoàn thành. Do đó, người dùng khó có thể nhận thấy rằng một quy trình mới đã được khởi chạy và sau đó thoát ra, và sẽ xuất hiện như thể một hộp thoại mới trong cùng một ứng dụng đã được mở (đặc biệt nếu bạn có một số hack để tạo cửa sổ chính của tiến trình nâng lên một con của tiến trình mẹ). Nếu bạn không cần giao diện người dùng cho quyền truy cập nâng cao, thậm chí tốt hơn.

Để có một cuộc thảo luận đầy đủ về UAC trên Vista, tôi khuyên bạn nên xem điều này rất thông qua bài viết về chủ đề này (ví dụ về mã là trong C ++, nhưng tôi nghi ngờ bạn sẽ cần sử dụng WinAPI và P / Invoke để thực hiện hầu hết mọi thứ trong C # dù sao). Hy vọng rằng bây giờ bạn ít nhất đã thấy được cách tiếp cận phù hợp để thực hiện, mặc dù việc thiết kế một chương trình tuân thủ UAC còn xa vời ...


4
Có bất kỳ thay đổi nào với Windows 7 hay câu trả lời "không, sử dụng quy trình mới" không? Cảm ơn ...
Radim Vansa

2
Tôi e rằng không có thay đổi nào với Windows 7. (Theo như tôi biết, và tôi là một người sử dụng thường xuyên / nhà phát triển trên Win7.)
Noldorin

2
Đây chính xác là cách trình quản lý tác vụ thực hiện. Khi bạn nhấp vào nút để hiển thị nhiệm vụ cho tất cả người dùng, nó tồn tại trình quản lý tác vụ hiện tại, sau đó gọi trình quản lý tác vụ khác có quyền quản trị.
Natalie Adams

3
@NathanAdams Về mặt kỹ thuật, nó sẽ mở trình quản lý tác vụ mới trước tiên. Nếu không, mở màn là gì? :-)
wizzwizz

16

Như đã nói ở đó :

Process.StartInfo.UseShellExecute = true;
Process.StartInfo.Verb = "runas";

sẽ chạy quy trình với tư cách là quản trị viên để thực hiện bất kỳ điều gì bạn cần với sổ đăng ký, nhưng quay lại ứng dụng của bạn với các đặc quyền bình thường.


Điều đó liên quan đến việc mở rộng một quy trình mới. đúng? Tôi đang tìm kiếm các đặc quyền nâng cao của chính quy trình hiện tại.
Hemant

Hãy thử sử dụng Process.GetCurrentProcess ()
abatishchev

27
Bạn không thể nâng cấp một quy trình hiện đang chạy.
Jacob Proffitt

1
Đây không phải là sự thật. Bạn có thể thay đổi chủ sở hữu của quá trình và thiết lập các giá trị DACL và ACL cho người sử dụng đem lại cho họ quyền lực hành chính ....
Nightforce2

4
@ nightforce2: chắc chắn điều này sẽ chỉ hoạt động, nếu bạn đã có quyền quản trị (tức là bạn đã được nâng cấp). Nếu không thì AdjustTokenPrivileges, v.v. sẽ đơn giản là không thành công, phải không?
Ben Schwehn

13

Bài viết MSDN KB 981778 sau đây mô tả cách 'tự nâng cấp' ứng dụng:

http://support.microsoft.com/kb/981778

Nó chứa các mẫu có thể tải xuống trong Visual C ++, Visual C #, Visual Basic.NET.

Cách tiếp cận này giải quyết được nhu cầu bắt đầu một quy trình riêng biệt, nhưng trên thực tế, ứng dụng gốc được khởi động lại, chạy với tư cách người dùng nâng cao. Tuy nhiên, điều này vẫn có thể rất hữu ích trong một số ngữ cảnh mà việc sao chép mã trong một tệp thực thi riêng biệt là không thực tế.

Để xóa độ cao, bạn cần thoát khỏi ứng dụng.


1
Tiện dụng cho một nút, nhưng khi bạn muốn điều tương tự cho một mục menu, bạn đang ở trong một mớ hỗn độn thực sự phức tạp.
Nyerguds

3
@Todd Bạn có thể tìm thấy mã ở đây: https://code.msdn.microsoft.com/windowsapps/CSUACSelfElevation-644673d3
Matthiee

Liên kết của câu trả lời đã chết và liên kết của bình luận trỏ đến một danh sách dài 2608 mục.
DonBoitnott

Bạn có thể tìm thấy nó ở đây
mirh


2

Có lẽ ai đó có ích ví dụ đơn giản này:

using System;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
using System.Security.Principal;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    internal static class Program
    {
        private class Form1 : Form
        {
            internal Form1()
            {
                var button = new Button{ Dock = DockStyle.Fill };
                button.Click += (sender, args) => RunAsAdmin();
                Controls.Add(button);

                ElevatedAction();
            }
        }

        [STAThread]
        internal static void Main(string[] arguments)
        {
            if (arguments?.Contains("/run_elevated_action") == true)
            {
                ElevatedAction();
                return;
            }

            Application.Run(new Form1());
        }

        private static void RunAsAdmin()
        {
            var path = Assembly.GetExecutingAssembly().Location;
            using (var process = Process.Start(new ProcessStartInfo(path, "/run_elevated_action")
            {
                Verb = "runas"
            }))
            {
                process?.WaitForExit();
            }
        }

        private static void ElevatedAction()
        {
            MessageBox.Show($@"IsElevated: {IsElevated()}");
        }

        private static bool IsElevated()
        {
            using (var identity = WindowsIdentity.GetCurrent())
            {
                var principal = new WindowsPrincipal(identity);

                return principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
        }

    }
}

1

Tôi biết đây là một bài viết cũ, nhưng bài viết này là để đáp lại bất kỳ ai khác gặp phải đề xuất của MarcP. Bài đăng trên msdn mà anh ấy tham chiếu thực sự không khởi động lại các ứng dụng trong tất cả các ví dụ mã. Các mẫu mã sử dụng runasđộng từ được đề xuất đã có trong các đề xuất khác.

Tôi đã tải xuống mã để đảm bảo, nhưng đây là từ bài viết gốc trên msdn:

4. Nhấp vào Có để phê duyệt độ cao. Sau đó, ứng dụng gốc khởi động lại, chạy với tư cách quản trị viên cấp cao.
5. Đóng ứng dụng.


1
Bạn có thể thêm liên kết MSDN được đề cập không? Tôi không thể tìm thấy người dùng có tên là MarcP.
Alf
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.