20110726

VS2010 – 解決ServiceController權限不足的問題

說明

Windows從Vista開始引進UAC (User Account Control),這是一項不錯的機制,雖然有點煩人,但是至少可以通知使用者目前的動作是會影響到系統的「安全性」。但是對我們這些寫程式的人來說,UAC可就是常常出問題的點了。

例如下面「呼叫特定Windows Service」的程式碼:

  1:         // WindowsServiceStart: 啟動視窗服務
  2:         #region
  3:         public static bool WindowsServiceStart(string strServiceName)
  4:         {
  5:             // 回傳值
  6:             bool bln = true;
  7: 
  8:             // 服務管理員
  9:             ServiceController svc = new ServiceController();
 10: 
 11:             // 取得服務啟動之Timeout
 12:             TimeSpan timeout = TimeSpan.FromMilliseconds(int.Parse(Program.SettingRead(LL.Setting_Service_Timeout)));
 13: 
 14:             try
 15:             {
 16:                 // 設定ServiceName
 17:                 svc.ServiceName = strServiceName;
 18: 
 19:                 // 檢查目前狀態,若不在執行中,或是啟動中,則啟動之
 20:                 if ((svc.Status != ServiceControllerStatus.Running) && (svc.Status != ServiceControllerStatus.StartPending))
 21:                 {
 22:                     svc.Start();
 23:                     svc.WaitForStatus(ServiceControllerStatus.Running, timeout);
 24:                 }
 25: 
 26:                 bln = (svc.Status == ServiceControllerStatus.Running);
 27:             }
 28:             catch (InvalidOperationException)
 29:             {
 30:                 bln = false;
 31:             }
 32: 
 33:             return bln;
 34:         }
 35:         #endregion
 36: 

在Windows XP中運作正常,但是放到了Windows 7的環境中,就會出現以下的錯誤:


20110726-VS2010-01-W


只要看到了圖中的「存取被拒」,問題點在哪兒,心中已有了答案。反正不是權限不足,就是被UAC給擋住了。

就算目前的使用者是屬於「Administrators」群組,只要您不是透過以下二種方式執行程式,那麼,預設您就是沒有修改「Windows Service」的權限:


  • 右點捷徑選取「以系統管理員身份執行」

20110726-VS2010-02-W



  • 點選「UAC」確認視窗

 


解決方法

但是我們是程式設計師,需要以程式來解決這項問題。解法有二:


  • 利用Manifest檔,自動跳出UAC確認視窗,讓使用者在繼續程式前,先行確認 (建議作法)



  • 利用程式,自動重新執行一個可經過使用者授權之程式 (會多出一個程式實體)

1. 在Program.cs中加入以下程式碼

  1:         // IsRunAsAdministrator: 是否以Administrator權限執行
  2:         #region
  3:         public static bool IsRunAsAdministrator()
  4:         {
  5:             // 取得目前執行之使用者權限
  6:             WindowsIdentity wi = WindowsIdentity.GetCurrent();
  7: 
  8:             // 檢查是否為Null
  9:             if (wi == null)
 10:             {
 11:                 return false;
 12:             }
 13:             else
 14:             {
 15:                 return (new WindowsPrincipal(wi)).IsInRole(WindowsBuiltInRole.Administrator);
 16:             }
 17:         }
 18:         #endregion
 19: 
 20:         // ProgramElevateToAdministrator: 詢問使用者是否可將目前程序提昇至Administrator身份 
 21:         #region
 22:         public static void ProgramElevateToAdministrator()
 23:         {
 24:             // 檢查是否已用Admin身份執行
 25:             if (!IsRunAsAdministrator())
 26:             {
 27:                 // 將此程序改為以Admin身份執行
 28:                 ProcessStartInfo prc = new ProcessStartInfo();
 29:                 prc.UseShellExecute = true;
 30:                 prc.WorkingDirectory = Environment.CurrentDirectory;
 31:                 prc.FileName = Application.ExecutablePath;
 32:                 // 指定「runas」屬性
 33:                 prc.Verb = "runas";
 34: 
 35:                 try
 36:                 {
 37:                     // 將會跳出UAC詢問視窗
 38:                     Process.Start(prc);
 39:                 }
 40:                 catch
 41:                 {
 42:                     // 若使用者拒絕,跳出
 43:                     return;
 44:                 }
 45:             }
 46:         }
 47:         #endregion

 

2. 在程式中加入以下程式碼,用以執行新的程式實體 (例如按鈕的事件,或是工具列的事件)

  1:         // SystemUAC: 進行UAC確認
  2:         #region
  3:         private void SystemUAC()
  4:         {
  5:             // 檢查是否為Vista或以上之系統,若是則進行UAC確認
  6:             if (Environment.OSVersion.Version.Major >= 6)
  7:             {
  8:                 Program.ProgramElevateToAdministrator();
  9:             }
 10:         }
 11:         #endregion
 12: 

 


參考


http://stackoverflow.com/questions/3892088/servicecontroller-permissions-in-windows-7

http://www.enusbaum.com/blog/2007/08/26/how-to-run-your-c-application-as-administrator-in-windows-vista/

http://stackoverflow.com/questions/916714/how-to-run-c-application-with-admin-creds

http://www.codeproject.com/KB/cs/cpimpersonation1.aspx

http://csharptuning.blogspot.com/2007/06/impersonation-in-c.html

http://msdn.microsoft.com/en-us/library/1w45z383(vs.71).aspx

http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/28f84724-af3e-4fa1-bd86-b0d1499eaefa#x_FAQAnswer91

http://social.msdn.microsoft.com/Forums/da-DK/winforms/thread/db6647a3-85ca-4dc4-b661-fbbd36bd561f

http://gelis-dotnet.blogspot.com/2009/06/manifestvista.html

沒有留言: