一、通過設定檔實現以管理員身份運行程式
Vista 和 Windows 7 作業系統為了加強安全,增加了 UAC(使用者賬戶控制) 的機制,如果 UAC 被開啟,使用者即使是以管理員權限登入,其應用程式預設情況下也無法對系統目錄,系統註冊表等可能影響系統啟動並執行設定進行寫操作。這個機制大大增強了系統的安全性,但對應用程式開發人員來說,我們不能強迫使用者去關閉UAC,但有時我們開發的應用程式又需要以 Administrator 的方式運行,即 Win7 中 以 as administrator 方式運行,那麼我們怎麼來實現這樣的功能呢?
我們在 win7 下運行一些安裝程式時,會發現首先彈出一個對話方塊,讓使用者確認是否同意允許這個程式改變你的電腦配置,但我們編寫的應用程式預設是不會彈出這個提示的,也無法以管理員權限運行。本文介紹了 C# 程式如何設定來提示使用者以管理員權限運行。
首先在項目中增加一個 Application Manifest File
預設的配置如下:
<?xml version="1.0" encoding="utf-8"?><asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"
xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> <security> <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> <!-- UAC Manifest Options If you want to change the Windows User Account Control level replace the requestedExecutionLevel node with one of the following. <requestedExecutionLevel level="asInvoker" uiAccess="false" /> <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> If you want to utilize File and Registry Virtualization for backward compatibility then delete the requestedExecutionLevel node. --> <requestedExecutionLevel level="asInvoker" uiAccess="false" /> </requestedPrivileges> </security> </trustInfo></asmv1:assembly>
我們可以看到這個配置中有一個 requestedExecutionLevel 項,這個項用於配置當前應用請求的執行權限等級。這個項有3個值可供選擇,如下表所示:
Value |
Description |
Comment |
asInvoker |
The application runs with the same access token as the parent process. |
Recommended for standard user applications. Do refractoring with internal elevation points, as per the guidance provided earlier in this document. |
highestAvailable |
The application runs with the highest privileges the current user can obtain. |
Recommended for mixed-mode applications. Plan to refractor the application in a future release. |
requireAdministrator |
The application runs only for administrators and requires that the application be launched with the full access token of an administrator. |
Recommended for administrator only applications. Internal elevation points are not needed. The application is already running elevated. |
asInvoker : 如果選這個,應用程式就是以當前的許可權運行。
highestAvailable: 這個是以目前使用者可以獲得的最高許可權運行。
requireAdministrator: 這個是僅以系統管理員許可權運行。
預設情況下是 asInvoker。
highestAvailable 和 requireAdministrator 這兩個選項都可以提示使用者擷取系統管理員許可權。那麼這兩個選項的區別在哪裡呢?
他們的區別在於,如果我們不是以管理員帳號登入,那麼如果應用程式設定為 requireAdministrator ,那麼應用程式就直接運行失敗,無法啟動。而如果設定為 highestAvailable,則應用程式可以運行成功,但是是以當前帳號的許可權運行而不是系統管理員許可權運行。如果我們希望程式在非管理員帳號登入時也可以運行(這種情況下應該某些功能受限制) ,那麼建議採用 highestAvailable 來配置。
關於requestedExecutionLevel 設定的權威文檔請參考下面連結:
Create and Embed an Application Manifest (UAC)
下面是修改後的設定檔:
<?xml version="1.0" encoding="utf-8"?><asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"
xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> <security> <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> <!-- UAC Manifest Options If you want to change the Windows User Account Control level replace the requestedExecutionLevel node with one of the following. <requestedExecutionLevel level="asInvoker" uiAccess="false" /> <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> If you want to utilize File and Registry Virtualization for backward compatibility then delete the requestedExecutionLevel node. --> <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> </requestedPrivileges> </security> </trustInfo></asmv1:assembly>
設定檔修改後,我們運行應用程式,就會首先彈出這樣一個提示框,點 Yes 後,程式才可以繼續運行,並且獲得系統管理員的許可權。
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
下面再來看看程式如何知道當前運行在系統管理員許可權還是非系統管理員許可權:
public static bool IsAdministrator() { WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); return principal.IsInRole(WindowsBuiltInRole.Administrator); }
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
這段代碼可以用於判斷當前程式是否運行在系統管理員許可權下。如果配置為 asInvoker,在win7 下,這個函數會返回 false ,如果是 requireAdministrator 則返回 true。
二、通過編程以管理員身份運行程式
在讀寫註冊表“HKEY_LOCAL_MACHINE\SOFTWARE\”下的項時,明明註冊表中有,但程式OpenSubKey始終返回Null,考慮到可能是因為許可權的原因,於是我以管理員身份運行了一次,結果測試成功!原來真的是許可權的問題,於是就在程式裡面加入了預設以管理員身份啟動並執行代碼。下面讓我們看看是怎麼實現的吧!
程式預設以管理員身份運行
static void Main(string[] Args) { /** * 目前使用者是管理員的時候,直接啟動應用程式 * 如果不是管理員,則使用啟始物件啟動程式,以確保使用管理員身份運行 */ //獲得當前登入的Windows使用者標示 System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent(); //建立Windows使用者主題 Application.EnableVisualStyles(); System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal(identity); //判斷當前登入使用者是否為管理員 if (principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator)) { //如果是管理員,則直接運行 Application.EnableVisualStyles(); Application.Run(new Form1()); } else { //建立啟始物件 System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); //設定運行檔案 startInfo.FileName = System.Windows.Forms.Application.ExecutablePath; //設定啟動參數 startInfo.Arguments = String.Join(" ", Args); //設定啟動動作,確保以管理員身份運行 startInfo.Verb = "runas"; //如果不是管理員,則啟動UAC System.Diagnostics.Process.Start(startInfo); //退出 System.Windows.Forms.Application.Exit(); } }
開啟程式集裡的Program.cs檔案,並將其中Main方法中的代碼替換為以上代碼即可實現程式預設以管理員身份運行。