如果程式不是以管理者身份運作,操作本地檔案會提示:System.UnauthorizedAccessException異常。
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。
下面是修改後的配置檔案:
<?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 後,程式才可以繼續運作,并且獲得系統管理者的權限。
下面再來看看程式如何知道目前運作在系統管理者權限還是非系統管理者權限:
using System.Security.Principal;
public static bool IsAdministrator()
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
這段代碼可以用于判斷目前程式是否運作在系統管理者權限下。如果配置為 asInvoker,在win7 下,這個函數會傳回 false ,如果是 requireAdministrator 則傳回 true。