談談c# 以管理員方式啟動實現過程

談談c# 以管理員方式啟動實現過程

以管理員方式不只是簡單的啟動一個進程,在實際開發過程中遇到的情況可能會複雜的多。

最后更新 2024/3/10 下午10:05
nobody
预计阅读 5 分钟
分类
.NET
标签
.NET C# 管理員

前言

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

以管理員方式不只是簡單的啟動一個進程,在實際開發過程中遇到的情況可能會複雜的多。比如用戶打開應用程式就是以管理員方式啟動的,那這個時候就不需要再以管理員方式自啟;比如用戶是在無人值守的情況下使用,就需要考慮管理員提權的提示行為,只有在”不提示,直接提升“的情況下才以管理員方式啟動;比如管理員啟動方式會進行傳遞,比如應用 a 以管理員方式啟動,那應用 a 啟動應用 b 通常情況下,應用 b 默認獲取了應用 a 的管理員權限等。

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

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

需要注意的是,如果用戶提權行為非”不提示,直接提升“,而一定要以管理員方式啟動,就一定要更改提權行為。可以通過運行”gpedit.msc“→ 計算機配置 →windows 設置 → 安全設置 → 本地策略 → 安全選項 → 用戶帳戶控制: 在管理審批模式下管理員的提升提示行為 來進行更改。

實現步驟

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

  1. 判斷當前應用程式是否是以管理員方式啟動,代碼如下:
public static bool IsRunAsAdmin()
{
    WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();
    WindowsPrincipal windows = new WindowsPrincipal(windowsIdentity);
    if (windows.IsInRole(WindowsBuiltInRole.Administrator))
    {
        return true;
    }
    return false;
}

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

  1. 以管理員方式啟動, 這個是最基本的代碼,代碼如下:
public static void RunAsAdmin()
{
    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 表示當前用戶有管理員權限,代碼如下:
public static bool IsUACEnabled()
{
    //注册表项
    RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", false);
    if (key != null)
    {
        //获取子键EnableLUA的值,1表示开启了UAC
        object value = key.GetValue("EnableLUA");
        if (value != null && value.ToString() == "1")
        {
            return true;
        }
    }
    return false;
}
  1. 判斷當前用戶是否在管理員權限組,代碼如下:
public static bool IsInAdminGroup()
{
    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 管理員提升權限提示行為,這裡需要判斷行為是否為“不提示,直接提升”,代碼如下:
public static bool IsUpPermissionWithOutTip()
{
    //注册表项
    RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", false);
    if (key != null)
    {
        //获取子键ConsentPromptBehaviorAdmin的值,0表示开启了不提示直接提升,就不会造成阻断
        object value = key.GetValue("ConsentPromptBehaviorAdmin");
        if (value != null && value.ToString() == "0")
        {
            return true;
        }
    }
    return false;
}

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

總結

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

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 2026/2/7

aot使用經驗總結

從項目創建伊始,就應養成良好的習慣,即只要添加了新功能或使用了較新的語法,就及時進行 aot 發布測試。

继续阅读