จะยกระดับสิทธิ์เฉพาะเมื่อจำเป็นได้อย่างไร?


85

คำถามนี้ใช้ได้กับ Windows Vista!

ฉันมีแอปพลิเคชันที่ใช้งานได้โดยไม่มีสิทธิ์ระดับผู้ดูแลระบบ มีกิจกรรมหนึ่งที่ต้องการสิทธิ์ระดับผู้ดูแลระบบ แต่ฉันไม่ต้องการเริ่มแอปพลิเคชันด้วยตัวเองด้วยสิทธิ์ที่สูงขึ้นเมื่อฉันรู้ว่าผู้ใช้ส่วนใหญ่จะไม่ได้ใช้คุณลักษณะนั้น

ฉันกำลังคิดถึงวิธีการบางอย่างที่ฉันสามารถยกระดับสิทธิ์ของแอปพลิเคชันในบางเหตุการณ์ (เช่นการกดปุ่ม) ตัวอย่าง:

หากผู้ใช้คลิกปุ่มนี้เขาจะได้รับแจ้งพร้อมกล่องโต้ตอบ UAC หรือคำยินยอม ฉันจะทำเช่นนี้ได้อย่างไร?

คำตอบ:


58

ฉันไม่เชื่อว่าจะสามารถยกระดับกระบวนการที่กำลังทำงานอยู่ได้ มีอยู่ใน Windows Vista ซึ่งสิทธิ์ของผู้ดูแลระบบจะมอบให้กับกระบวนการเมื่อเริ่มต้นทำงานตามที่ฉันเข้าใจ หากคุณดูโปรแกรมต่างๆที่ใช้ UAC คุณจะเห็นว่าพวกเขาเปิดกระบวนการแยกต่างหากทุกครั้งที่ต้องดำเนินการด้านการดูแลระบบ (ตัวจัดการงานคือหนึ่ง Paint.NET เป็นอีกโปรแกรมหนึ่งซึ่งเป็นแอปพลิเคชัน. NET ในความเป็นจริง ).

วิธีแก้ปัญหาโดยทั่วไปสำหรับปัญหานี้คือการระบุอาร์กิวเมนต์บรรทัดคำสั่งเมื่อเรียกใช้กระบวนการที่ยกระดับ (คำแนะนำของ abatishchev เป็นวิธีหนึ่งในการดำเนินการนี้) เพื่อให้กระบวนการที่เรียกใช้ทราบเฉพาะการแสดงกล่องโต้ตอบบางกล่องจากนั้นจึงออกหลังจากการดำเนินการนี้ เสร็จสมบูรณ์ ดังนั้นผู้ใช้จึงแทบไม่ควรสังเกตเห็นว่ามีการเปิดตัวกระบวนการใหม่แล้วออกไปและค่อนข้างจะดูเหมือนว่ามีการเปิดกล่องโต้ตอบใหม่ภายในแอปเดียวกัน (โดยเฉพาะอย่างยิ่งหากคุณแฮ็กเกอร์สร้างหน้าต่างหลักของ ยกระดับกระบวนการลูกของกระบวนการหลัก) หากคุณไม่ต้องการ UI สำหรับการเข้าถึงแบบยกระดับยิ่งดี

สำหรับการสนทนาเต็มรูปแบบของ UAC บน Vista ฉันขอแนะนำให้คุณอ่านบทความนี้ในหัวข้อนี้ (ตัวอย่างโค้ดอยู่ใน C ++ แต่ฉันสงสัยว่าคุณจะต้องใช้ WinAPI และ P / Invoke เพื่อทำสิ่งต่างๆใน C # อย่างไรก็ตาม). หวังว่าอย่างน้อยตอนนี้คุณจะเห็นแนวทางที่ถูกต้องแม้ว่าการออกแบบโปรแกรมที่สอดคล้องกับ UAC นั้นยังห่างไกลจากเรื่องเล็กน้อย ...


4
มีการเปลี่ยนแปลงใด ๆ กับ Windows 7 หรือไม่คำตอบ "ไม่ใช้กระบวนการใหม่" ค้างไว้? ขอบคุณ ...
Radim Vansa

2
ไม่มีการเปลี่ยนแปลงกับ Windows 7 ฉันกลัวขอโทษ (เท่าที่ฉันรู้และฉันเป็นผู้ใช้ / ผู้พัฒนาบน Win7 เป็นประจำ)
Noldorin

2
นี่คือวิธีที่ตัวจัดการงานทำ เมื่อคุณคลิกปุ่มเพื่อแสดงงานสำหรับผู้ใช้ทั้งหมดมันมีอยู่ตัวจัดการงานปัจจุบันจากนั้นเรียกใช้ตัวจัดการงานอื่นที่มีสิทธิ์ของผู้ดูแลระบบ
Natalie Adams

3
@NathanAdams ในทางเทคนิคจะเปิดตัวจัดการงานใหม่ก่อน มิฉะนั้นการเปิดจะทำอะไร? :-)
wizzwizz4

16

ตามที่กล่าวไว้ที่นั่น :

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

จะเรียกใช้กระบวนการในฐานะผู้ดูแลระบบเพื่อทำสิ่งที่คุณต้องการกับรีจิสทรี แต่กลับไปที่แอปของคุณด้วยสิทธิ์ปกติ


ซึ่งเกี่ยวข้องกับการขยายกระบวนการใหม่ ขวา? ฉันกำลังมองหาการยกระดับสิทธิพิเศษของกระบวนการปัจจุบันเอง
Hemant

ลองใช้กับ Process.GetCurrentProcess ()
abatishchev

27
คุณไม่สามารถยกระดับกระบวนการที่กำลังทำงานอยู่ได้
Jacob Proffitt

1
นี่ไม่เป็นความจริง. คุณสามารถเปลี่ยน Owner ของกระบวนการและตั้งค่า DACL และ ACL สำหรับผู้ใช้ที่ให้อำนาจในการดูแลระบบ ....
Nightforce2

4
@ nightforce2: สิ่งนี้จะใช้ได้ผลก็ต่อเมื่อคุณมีสิทธิ์ระดับผู้ดูแลระบบอยู่แล้ว ไม่เช่นนั้น AdjustTokenPrivileges และอื่น ๆ ก็จะล้มเหลวไม่?
Ben Schwehn

13

บทความ MSDN KB ต่อไปนี้ 981778 อธิบายวิธีการ 'ยกระดับตนเอง' แอปพลิเคชัน:

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

ประกอบด้วยตัวอย่างที่ดาวน์โหลดได้ใน Visual C ++, Visual C #, Visual Basic.NET

วิธีนี้ทำให้จำเป็นต้องเริ่มกระบวนการแยกต่างหาก แต่ในความเป็นจริงมันเป็นแอปพลิเคชันดั้งเดิมที่เริ่มต้นใหม่ทำงานในฐานะผู้ใช้ระดับสูง อย่างไรก็ตามสิ่งนี้อาจยังมีประโยชน์อย่างมากในบางบริบทที่ไม่สามารถทำโค้ดซ้ำในไฟล์ปฏิบัติการแยกต่างหากได้

ในการลบระดับความสูงคุณต้องออกจากแอปพลิเคชัน


1
มีประโยชน์สำหรับปุ่ม แต่เมื่อคุณต้องการสิ่งเดียวกันสำหรับรายการเมนูคุณก็อยู่ในความยุ่งเหยิงที่ซับซ้อนจริงๆ
Nyerguds

3
@Todd คุณสามารถค้นหารหัสได้ที่นี่: https://code.msdn.microsoft.com/windowsapps/CSUACSelfElevation-644673d3
Matthiee

ลิงก์ของคำตอบนั้นไม่สามารถใช้งานได้และลิงก์ของความคิดเห็นชี้ไปที่รายการยาว 2608
DonBoitnott

คุณสามารถพบได้ที่นี่
Mirh


2

บางทีอาจมีใครบางคนเข้ามามีประโยชน์ในตัวอย่างง่ายๆนี้:

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

ฉันรู้ว่านี่เป็นโพสต์เก่า แต่นี่เป็นการตอบสนองต่อใครก็ตามที่พบข้อเสนอแนะของ MarcP โพสต์ msdn ที่เขาอ้างถึงจะรีสตาร์ทแอปพลิเคชันในตัวอย่างโค้ดทั้งหมด ตัวอย่างโค้ดใช้runasคำกริยาที่เสนอไว้แล้วในคำแนะนำอื่น ๆ

ฉันดาวน์โหลดรหัสเพื่อให้แน่ใจ แต่นี่มาจากบทความ msdn ดั้งเดิม:

4. คลิกใช่เพื่ออนุมัติระดับความสูง จากนั้นแอปพลิเคชันเดิมจะรีสตาร์ทโดยทำงานในฐานะผู้ดูแลระบบที่ได้รับการยกระดับ
5. ปิดแอปพลิเคชัน


1
คุณสามารถเพิ่มลิงค์ MSDN ที่เป็นปัญหาได้หรือไม่? ฉันไม่พบผู้ใช้ชื่อ MarcP
Alf
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.