天天看点

在Win7的UAC下检查程序是否具有Admin权限及应用程序的权限切换

VISTA/Win7下的程序编程我们往往比较注意两个问题——“我的程序真的具有管理员权限了吗?”,“我的程序如何实现权限切换?”。

    这两个问题一直困扰了我很久。最后终于在CodeProject上找到了答案,现在发上来大家一起共享。

    首先我们来看看怎么检查自己的程序是不是管理员权限,这个代码相对简单。(special thanks to hackman3vilGuy fromCodeProject)

using  System.Security.Principal;

         /// <summary>

        /// Checks if the process is elevated

        /// </summary>

        /// <returns>If is elevated</returns>

         static   internal   bool  IsAdmin()

         {

            WindowsIdentity id = WindowsIdentity.GetCurrent();

            WindowsPrincipal p = new WindowsPrincipal(id);

            return p.IsInRole(WindowsBuiltInRole.Administrator);

        }     这段代码就返回了一个bool变量,如果是true那么程序在UAC下也是ADMIN权限,否则则是受限模式。

    我们经常看见UAC下请求ADMIN的程序都有一个小盾,证明此程序需要ADMIN权限。那么如何给自己的button添加一个UAC标记以实现权限切换呢?这需要导入一个API函数。

     public   static   class  VistaSecurity

     {

        [DllImport("user32")]

        public static extern UInt32 SendMessage(IntPtr hWnd, UInt32 msg, UInt32 wParam, UInt32 lParam);

        internal const int BCM_FIRST = 0x1600;

        internal const int BCM_SETSHIELD = (BCM_FIRST + 0x000C);

        /// <summary>

        /// Add a shield icon to a button

        /// </summary>

        /// <param name="b">The button</param>

        static internal void AddShieldToButton(Button b)

        {

            b.FlatStyle = FlatStyle.System;

            SendMessage(b.Handle, BCM_SETSHIELD, 0, 0xFFFFFFFF);

        }     button收到这个消息后会自动给自己加上标记的,大家就不用操心了。这就是API的好处。

    接下来的代码就是要实现UAC下的程序权限切换了——

         /// <summary>

        /// Restart the current process with administrator credentials

        /// </summary>

         internal   static   void  RestartElevated()

         {

            ProcessStartInfo startInfo = new ProcessStartInfo();

            startInfo.UseShellExecute = true;

            startInfo.WorkingDirectory = Environment.CurrentDirectory;

            startInfo.FileName = Application.ExecutablePath;

            startInfo.Verb = "runas";

            try

            {

                Process p = Process.Start(startInfo);

            }

            catch(System.ComponentModel.Win32Exception ex)

            {

                return; //If cancelled, do nothing

            }

            Application.Exit();

        }

    通过在ProcessStartInfo中对Verb加入"runas"信息就可以实现程序的权限切换了。这里我使用的是重启本程序已获得权限,如果不想重启程序可以通过传送arguments的方法,或者不提升程序权限而只提升某个线程来执行管理员代码(????)。