VISTA下的程序编程我们往往比较注意两个问题——“我的程序真的具有管理员权限了吗?”,“我的程序如何实现权限切换?”。
    这两个问题一直困扰了我很久。最后终于在CodeProject上找到了答案,现在发上来大家一起共享。

    首先我们来看看怎么检查自己的程序是不是管理员权限,这个代码相对简单。(special thanks to hackman3vilGuy from CodeProject
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, 
00xFFFFFFFF);
        }
    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的方法,或者不提升程序权限而只提升某个线程来执行管理员代码。

Copyright © 2024 Samson小天
Powered by .NET 9.0 on Kubernetes