標籤:
在我們一些Winform程式中,往往需要具有一些特殊的許可權才能作業系統檔案,我們可以設定運行程式具有管理員權限或者設定運行程式的目錄具有寫入的許可權,如果是在作業系統裡面,我們可以設定運行程式以管理員身份運行,或者設定Users使用者組在運行目錄中具有寫入許可權都可以解決問題,不過如果我們想通過C#代碼進行自動的處理,那麼應該如何?呢?
1、系統設定管理員權限或者目錄寫入許可權
如果我們需要讓程式以管理員身份運行,那麼可以通過設定捷徑的屬性或者應用程式的屬性為【以管理員身份運行此程式】即可實現,如下所示。
如果我們需要一些寫入檔案的許可權,如我們程式可能需要操作SQLite檔案資料庫,那麼也可以通過設定Users使用者組在運行目錄中具有寫入許可權都可以解決問題,否則可能會出現【 attempt to write a readonly database】的錯誤。
我們設定步驟如下所示:找到SQLite資料庫所在的檔案夾,單擊右鍵,屬性->安全,為Users使用者組添加寫入許可權。
2、使用C#代碼實現
上面的步驟可以解決我們實際碰到的許可權訪問問題,那麼我們如果使用C#代碼,應該如何?這些操作呢?
對於第一個以管理員身份運行程式的處理操作,我們是可以通過程式修改配置的方式實現,這樣可以避免一些Winform程式運行時刻的許可權問題:
1)在通過winform程式執行cmd命令時,某些情況下如果不是以管理員身份運行,則會提示命令無效。
2)或者通過winform程式執行Windows Service 服務時,也需要以管理員身份才能調用Service服務。
3)處理其他需要管理員身份的相關操作。
我們如果是編譯Winform程式,只需要幾步就可以在讓程式在啟動並執行時候獲得管理員身份,如下所示在我們Winform的UI項目【屬性】【安全性】裡面,勾選ClickOne的設定。
然後我們就可以看到在UI項目【Properties】目錄裡面,產生了一個app.manifest檔案。
這個app.manifest檔案是自動產生的,我們修改其中的一項設定,然後取消上面勾選ClickOne的設定就可以了。
把其中app.manifest檔案的內容:
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
改為:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
即可,這樣取消上面勾選ClickOne的設定,然後重新編譯整個程式即可。
在程式啟動並執行時候,會提示“使用者賬戶控制”來擷取管理員權限運行,點擊“是”則擷取了管理員權限。
對於需要為指定目錄設定使用者組許可權,那麼也是可以通過C#代碼進行處理的。
一般情況下,我們可以在程式安裝或者啟動的時候,對目錄進行使用者組許可權的處理,這樣程式運行起來就自然具有對應目錄的讀寫權限了。
如我們在程式啟動的時候處理,那麼我們可以在Main函數的裡面進行設定。
/// <summary> /// 應用程式的主進入點。 /// </summary> [STAThread] private static void Main() { }
為了方便處理,我們添加一個公用的函數,用來處理使用者組的目錄許可權訪問操作,C#代碼如下所示。
/// <summary> /// 為指定使用者組,授權目錄指定完整存取 /// </summary> /// <param name="user">使用者組,如Users</param> /// <param name="folder">實際的目錄</param> /// <returns></returns> private static bool SetAccess(string user, string folder) { //定義為完全控制的許可權 const FileSystemRights Rights = FileSystemRights.FullControl; //添加訪問規則到實際目錄 var AccessRule = new FileSystemAccessRule(user, Rights, InheritanceFlags.None, PropagationFlags.NoPropagateInherit, AccessControlType.Allow); var Info = new DirectoryInfo(folder); var Security = Info.GetAccessControl(AccessControlSections.Access); bool Result; Security.ModifyAccessRule(AccessControlModification.Set, AccessRule, out Result); if (!Result) return false; //總是允許再目錄上進行對象繼承 const InheritanceFlags iFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit; //為繼承關係添加訪問規則 AccessRule = new FileSystemAccessRule(user, Rights, iFlags, PropagationFlags.InheritOnly, AccessControlType.Allow); Security.ModifyAccessRule(AccessControlModification.Add, AccessRule, out Result); if (!Result) return false; Info.SetAccessControl(Security); return true; }
然後我們在Main函數裡面進行調用就可以了。
/// <summary> /// 應用程式的主進入點。 /// </summary> [STAThread] private static void Main() { //為使用者組指定對應目錄的完整存取 SetAccess("Users", Application.StartupPath); //介面漢化 System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("zh-Hans"); DevExpress.UserSkins.BonusSkins.Register(); DevExpress.Skins.SkinManager.EnableFormSkins(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); //登入介面 Login dlg = new Login(); dlg.StartPosition = FormStartPosition.CenterScreen; if (DialogResult.OK == dlg.ShowDialog()) { if (dlg.bLogin) { SplashScreen.Splasher.Show(typeof(SplashScreen.frmSplash)); gc.MainDialog = new MainForm(); gc.MainDialog.StartPosition = FormStartPosition.CenterScreen; Application.Run(gc.MainDialog); } } dlg.Dispose(); }
這樣在程式運行後,我們就可以看到對應目錄具有完全的讀寫操作許可權了,這樣對於一些如讀寫SQLite出錯的問題,也就迎刃而解了。
以上就是我對於兩種不同許可權訪問的處理經驗總結,希望給在Winform開發中的同行參考,感謝耐心的閱讀和支援。
在Winform程式中設定管理員權限及為使用者組添加寫入許可權