1. 程式人生 > >C#正確方式讓程式以管理員許可權啟動

C#正確方式讓程式以管理員許可權啟動

  應用程式可能執行在各個windows版:windowsXp,win7-32bit,win7-64bit,win8-32bit,win8-64bit.由於windows各個版本的使用者許可權的限制不同,同一個開發環境編譯出來的應用程式,拿到各個系統中執行的效果是用差別的。其主要原因還是win7、win8加強了對應用程式操作許可權的限制。

一、一個明顯的例子:

image

圖1.1 Win8 普通使用者下的cmd

image

圖1.2  win8管理員下的cmd

pcmd

圖1.3 win7執行CMD介面

    上面兩個圖中,win7 win8都是以Administrator登入的。但是,win7上直接在[執行]->CMD,直接是以管理員許可權啟動;而Win8直接在[執行]->CMD,進入的是普通許可權的CMD介面,必須右鍵[以管理員身份執行]才能出現圖1.2介面。

   網上的神人對於這個問題是這樣回答的:

image

圖1.4

二、許可權限制在程式中使用命令列時中引發的問題

2.1、使用普通使用者命令列去開啟一些服務

image

圖2.1

2.2、程式中以普通使用者形式去開啟一些服務:

image

圖2.2

    2.1 和2.2的操作都失敗了,原因就是應用程式的操作許可權級數不夠。

    這些問題該如何處理?

    有些解決方案是在我們呼叫到CMD的地方,直接使用下面的方式去呼叫管理員來啟動CMD來執行相關命令列的命令:


  1. ProcessStartInfo startInfo = new ProcessStartInfo(); 
  2.                 startInfo.
    FileName = "cmd.exe"; 
  3.                 startInfo.Arguments = "/c C:\\Windows\\System32\\cmd.exe"; 
  4.                 startInfo.RedirectStandardInput = true; 
  5.                 startInfo.RedirectStandardOutput = true; 
  6.                 startInfo.RedirectStandardError = true; 
  7.                 startInfo.UseShellExecute =
    false ; 
  8.                 startInfo.Verb = "RunAs"; 
  9.                 Process process = new Process(); 
  10.                 process.StartInfo = startInfo; 
  11.                 process.Start(); 
  12.                 process.StandardInput.WriteLine("bcdedit"); 
  13.                 process.StandardInput.WriteLine("exit"); 
  14.                 string strRst = process.StandardOutput.ReadToEnd(); 
  15.                 Bootinitext.AppendText("\n"+strRst ); 
  16.                 process.WaitForExit();

    實踐證明,這種方法的在模組所在的應用程式不是以管理員許可權啟動時它是沒什麼作用的,它仍然是出現圖2.2的結果。故解決方法應該是直接將應用程式的啟動許可權提升到管理員級別,主要參考下面程式碼:

在program.cs如下操作(案例)


  1. static void Main(string[] Args) 
  2.         { 
  3.             /** 
  4.              * 當前使用者是管理員的時候,直接啟動應用程式 
  5.              * 如果不是管理員,則使用啟動物件啟動程式,以確保使用管理員身份執行 
  6.              */ 
  7.             //獲得當前登入的Windows使用者標示 
  8.             System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent(); 
  9.             //建立Windows使用者主題 
  10.             Application.EnableVisualStyles(); 
  11.             System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal(identity); 
  12.             //判斷當前登入使用者是否為管理員 
  13.             if (principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator)) 
  14.             { 
  15.                 //如果是管理員,則直接執行 
  16.                 Application.EnableVisualStyles(); 
  17.                 Application.Run(new Form1()); 
  18.             } 
  19.             else 
  20.             { 
  21.                 //建立啟動物件 
  22.                 System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); 
  23.                 //設定執行檔案 
  24.                 startInfo.FileName = System.Windows.Forms.Application.ExecutablePath; 
  25.                 //設定啟動引數 
  26.                 startInfo.Arguments = String.Join(" ", Args); 
  27.                 //設定啟動動作,確保以管理員身份執行 
  28.                 startInfo.Verb = "runas"; 
  29.                 //如果不是管理員,則啟動UAC 
  30.                 System.Diagnostics.Process.Start(startInfo); 
  31.                 //退出 
  32.                 System.Windows.Forms.Application.Exit(); 
  33.             } 
  34.         }

2.3、使程式以管理員許可權啟動的實際案例程式碼如下:


  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Linq; 
  4. using System.Windows.Forms; 
  5. using System.Runtime.InteropServices; 
  6. using System.IO; 
  7. using System.Text; 
  8. using System.Diagnostics; 
  9. using System.Threading; 
  10. namespace DatabaseCreate 
  11. { 
  12.     static class Program 
  13.     { 
  14.         #region Setting from ini document 
  15.         [DllImport("kernel32")] 
  16.         private static extern long WritePrivateProfileString(string Section, string key, string val, string filePath); 
  17.         [DllImport("kernel32")] 
  18.         private static extern int GetPrivateProfileString(string Section, string key, string def, /*StringBuilder reVal原來用StringBuilder*/byte[]buffer/*現在使用byte串*/, int Usize, string filePath); 
  19.         [DllImport("kernel32")] 
  20.         private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath); 
  21.         #endregion 
  22.         ///
  23.         /// The main entry point for the application. 
  24.         /// 
  25.         [STAThread] 
  26.         static void Main(string[] Args) 
  27.         { 
  28.             Application.EnableVisualStyles(); 
  29.             Application.SetCompatibleTextRenderingDefault(false); 
  30.             //獲取當前登入的Windows使用者的標識 
  31.             System.Security.Principal.WindowsIdentity wid = System.Security.Principal.WindowsIdentity.GetCurrent(); 
  32.             System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal(wid); 
  33.             // 判斷當前使用者是否是管理員 
  34.             if (principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator)) 
  35.             { 
  36.                 byte[] bufferContent = new byte[255]; 
  37.                 string LanguageInfoPath = Application.StartupPath + "\\DayaSystemInfo.ini"; 
  38.                 FileInfo fileInfo = new FileInfo(LanguageInfoPath); 
  39.                 string section = "Setting"; 
  40.                 string key = "Language"; 
  41.                 int returnNum = 0; 
  42.                 /* 讀取顯示語言及處理 */ 
  43.                 if (fileInfo.Exists) 
  44.                     returnNum = GetPrivateProfileString(section, key, "", bufferContent, (int)bufferContent.Length, fileInfo.ToString().Trim()); 
  45.                 string lanResult = ""; 
  46.                 int languageIndex = 0; 
  47.                 if (returnNum != 0) 
  48.                 { 
  49.                     lanResult = Encoding.Default.GetString(bufferContent, 0, 1); 
  50.                     if ((lanResult.Trim().Equals("1")) || (lanResult.Trim().Equals("0"))) 
  51.                     { 
  52.                         languageIndex = Convert.ToInt32(lanResult); 
  53.                     } 
  54.                 } 
  55.                 Application.Run(new Form1(languageIndex)); 
  56.             } 
  57.             else // 用管理員使用者執行 
  58.             { 
  59.                 System.Diagnostics.ProcessStartInfo startInfo = new ProcessStartInfo(); 
  60.                 startInfo.FileName = Application.ExecutablePath; 
  61.                 startInfo.Arguments = string.Join(" ", Args); 
  62.                 startInfo.Verb = "runas"; 
  63.                 System.Diagnostics.Process.Start(startInfo); 
  64.                 System.Windows.Forms.Application.Exit(); 
  65.             } 
  66.         } 
  67.     } 
  68. }

參考文件:

C#2010在Windows8—64系統,寫的程式可以訪問電腦(其他軟體)的服務狀態,但不能開啟或關閉該服務

C#預設以管理員身份執行程式