WindowsIdentity類可以獲取當前執行者的身份信息
- /// <summary>
- /// 遞歸搜索文件方法
- /// </summary>
- /// <param name="path">搜索的目錄</param>
- /// <param name="name">搜索的文件名</param>
- public void GetDir(string path,string name)
- {
- DirectoryInfo di = new DirectoryInfo(path);
- DirectorySecurity s = new DirectorySecurity(path, AccessControlSections.Access);
- //判斷目錄是否 可以訪問
- if (!s.AreAccessRulesProtected)
- {
- foreach (DirectoryInfo d in di.GetDirectories())
- {
- foreach (FileInfo fi in di.GetFiles())
- {
- if (fi.Name.Contains(name))
- {
- txtInfo.AppendText("文件名:"+fi.Name + " 路徑:" + fi.FullName + " \n");
- }
- }
- GetDir(d.FullName, name);
- }
- }
- }
對執行的程序設定執行身份權限
如果程序不是以管理員身份運行,操作本地文件會提示:System.UnauthorizedAccessException異常
Vista 和 Windows 7 操作系統為了加強安全,增加了 UAC(用戶賬戶控制) 的機制,如果 UAC 被打開,用戶即使是以管理員權限登錄,其應用程序默認情況下也無法對系統目錄,系統注冊表等可能影響系統運行的設置進行寫操作。這個機制大大增強了系統的安全性,但對應用程序開發者來說,我們不能強迫用戶去關閉UAC,但有時我們開發的應用程序又需要以 Administrator 的方式運行,即 Win7 中 以 as administrator 方式運行,那么我們怎么來實現這樣的功能呢?
我們在 win7 下運行一些安裝程序時,會發現首先彈出一個對話框,讓用戶確認是否同意允許這個程序改變你的計算機配置,但我們編寫的應用程序默認是不會彈出這個提示的,也無法以管理員權限運行。本文介紹了 C# 程序如何設置來提示用戶以管理員權限運行。
首先在項目中增加一個 Application Manifest File
默認的配置如下:
<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)
下面是修改后的配置文件:
<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>
下面再來看看程序如何知道當前運行在系統管理員權限還是非系統管理員權限:
using System.Security.Principal
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
using System;
using System.Collections;
using System.IO;
using System.Security.AccessControl;
static class Tester
{
public static void Main()
{
try
{
string filename = @"f:\k"; //目標目錄
string account = @"Administrator";//用戶名
string userrights = @"RW";//權限字符串,自己定義的
AddDirectorySecurity(filename, account, userrights);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e);
Console.ReadLine();
}
}
static public void AddDirectorySecurity(string FileName, string Account, string UserRights)
{
FileSystemRights Rights = new FileSystemRights();
if (UserRights.IndexOf("R") >= 0)
{
Rights = Rights | FileSystemRights.Read;
}
if (UserRights.IndexOf("C") >= 0)
{
Rights = Rights | FileSystemRights.ChangePermissions;
}
if (UserRights.IndexOf("F") >= 0)
{
Rights = Rights | FileSystemRights.FullControl;
}
if (UserRights.IndexOf("W") >= 0)
{
Rights = Rights | FileSystemRights.Write;
}
bool ok;
DirectoryInfo dInfo = new DirectoryInfo(FileName);
DirectorySecurity dSecurity = dInfo.GetAccessControl();
InheritanceFlags iFlags = new InheritanceFlags();
iFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
FileSystemAccessRule AccessRule2 = new FileSystemAccessRule(Account, Rights, iFlags, PropagationFlags.None, AccessControlType.Allow);
dSecurity.ModifyAccessRule(AccessControlModification.Add, AccessRule2, out ok);
dInfo.SetAccessControl(dSecurity);
//列出目標目錄所具有的權限
DirectorySecurity sec = Directory.GetAccessControl(FileName, AccessControlSections.All);
foreach (FileSystemAccessRule rule in sec.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
{
Console.WriteLine("----------------------------------");
Console.WriteLine(rule.IdentityReference.Value);
if ((rule.FileSystemRights & FileSystemRights.Read) != 0)
Console.WriteLine(rule.FileSystemRights.ToString());
}
Console.Read();
}
}