VISTA/Win7下的程序编程我们往往比较注意两个问题——“我的程序真的具有管理员权限了吗?”,“我的程序如何实现权限切换?”。
这两个问题一直困扰了我很久。最后终于在CodeProject上找到了答案,现在发上来大家一起共享。
首先我们来看看怎么检查自己的程序是不是管理员权限,这个代码相对简单。(special thanks to hackman3vilGuy fromCodeProject)
我们经常看见UAC下请求ADMIN的程序都有一个小盾,证明此程序需要ADMIN权限。那么如何给自己的button添加一个UAC标记以实现权限切换呢?这需要导入一个API函数。
接下来的代码就是要实现UAC下的程序权限切换了——
这两个问题一直困扰了我很久。最后终于在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权限,否则则是受限模式。
/// <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);
}
我们经常看见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的好处。
{
[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);
}
接下来的代码就是要实现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();
}
/// 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的方法,或者不提升程序权限而只提升某个线程来执行管理员代码(????)。