當前位置: 妍妍網 > 碼農

談談C# 以管理員方式啟動實作過程

2024-03-10碼農

unset unset 前言 unset unset

本文由網友(@nobody)投稿,歡迎留言技術討論。

以管理員方式不只是簡單的啟動一個行程,在實際開發過程中遇到的情況可能會復雜的多。比如使用者開啟應用程式就是以管理員方式啟動的,那這個時候就不需要再以管理員方式自啟;比如使用者是在無人值守的情況下使用,就需要考慮管理員提權的提示行為,只有在」不提示,直接提升「的情況下才以管理員方式啟動;比如管理員啟動方式會進行傳遞,比如套用A以管理員方式啟動,那套用A啟動套用B通常情況下,套用B預設獲取了套用A的管理員許可權等。

本文主要介紹在無人值守情況下,以管理員方式啟動的實作過程。其他情況,只要進行靈活組合就應該能夠實作。

無人值守的主要特點是應用程式開機自啟、崩潰重新開機,程式自動執行。程式中不能有阻斷程式啟動或是執行的操作,比如彈窗提示讓使用者確認或是讓使用者輸入帳號密碼。解決無人值守的情況,主要解決思路如下圖:

需要註意的是,如果使用者提權行為非」不提示,直接提升「,而一定要以管理員方式啟動,就一定要更改提權行為。可以透過執行」gpedit.msc「→電腦配置→windows設定→安全設定→本地策略→安全選項→使用者帳戶控制: 在管理審批模式下管理員的提升提示行為 來進行更改。

unset unset 實作步驟 unset unset

下面為流程中設計的步驟程式碼實作方法:

  1. 判斷當前應用程式是否是以管理員方式啟動,程式碼如下:

publicstaticboolIsRunAsAdmin()
{
WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();
WindowsPrincipal windows = new WindowsPrincipal(windowsIdentity);
if (windows.IsInRole(WindowsBuiltInRole.Administrator))
{
returntrue;
}
returnfalse;
}

note:此程式碼是判斷使用者是否以管理員方式啟動,不是使用者是否是管理員。因為雖然使用者是管理員,但是啟動應用程式的時候,不一定是以管理員方式啟動的。網上搜尋判斷使用者是否管理員,搜尋出來的大部份都是這個程式碼。

  1. 以管理員方式啟動, 這個是最基本的程式碼,程式碼如下:

publicstaticvoidRunAsAdmin()
{
ProcessStartInfo startInfo = new ProcessStartInfo();
//設定以管理員方式啟動標記
startInfo.Verb = "runas";
//使用shell啟動行程
startInfo.UseShellExecute = true;
startInfo.FileName = Process.GetCurrentProcess().MainModule.FileName;
Process.Start(startInfo);
}

note:Verb是以管理員啟動的標識,除了設定Verb,還需要設定UseShellExecute=true,使用shell啟動行程,不然啟動時管理員許可權會進行傳遞,即如果原先的應用程式不是以管理員方式啟動的,那麽傳遞以後也不會以管理員方式啟動,以管理員方式啟動就會失敗。啟動物件還有很多內容可以設定,讀者可以自行研究。

  1. 判斷當前是否開啟UAC(使用者帳號控制),關閉UAC表示當前使用者有管理員許可權,程式碼如下:

publicstaticboolIsUACEnabled()
{
//登錄檔項
RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"false);
if (key != null)
{
//獲取子鍵EnableLUA的值,1表示開啟了UAC
objectvalue = key.GetValue("EnableLUA");
if (value != null && value.ToString() == "1")
{
returntrue;
}
}
returnfalse;
}

  1. 判斷當前使用者是否在管理員許可權組,程式碼如下:

publicstaticboolIsInAdminGroup()
{
WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();
WindowsPrincipal windowsPrincipal = new WindowsPrincipal(windowsIdentity);
var claims = windowsPrincipal.Claims;
//聲明集合中有使用者組的資訊,S-1-5-32-544代表管理員組
return claims.Any(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid" && c.Value == "S-1-5-32-544");
}

  1. 判斷UAC管理員提升許可權提示行為,這裏需要判斷行為是否為「不提示,直接提升」,程式碼如下:

publicstaticboolIsUpPermissionWithOutTip()
{
//登錄檔項
RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"false);
if (key != null)
{
//獲取子鍵ConsentPromptBehaviorAdmin的值,0表示開啟了不提示直接提升,就不會造成阻斷
objectvalue = key.GetValue("ConsentPromptBehaviorAdmin");
if (value != null && value.ToString() == "0")
{
returntrue;
}
}
returnfalse;
}

上述是根據主要流程提取出的5個方法。在實際開發過程中。可能還要考慮以管理員方式啟動失敗後無限重新開機的問題。方法中也沒考慮異常情況,使用者需要根據自己的需求,做例外處理。

unset unset 總結 unset unset

本文主要是根據作者的開發經驗整理的無人值守情況下的實作方式,讀者在開發過程中要根據實際需求進行靈活組裝,或是添加上述沒有的功能或是邏輯。作者相關知識也可能存在盲區,或是邏輯考慮不周的,歡迎指正。