You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C#程序中嵌入授权凭据执行PowerShell命令的问题咨询

问题描述

我用VS C#编写了一个Windows应用程序,点击Button3时会执行一段PowerShell命令,用于获取远程机器的开机时长。右键以管理员身份运行(输入授权用户信息)时命令可正常执行,但以无PowerShell执行权限的普通标准用户身份运行时会报错。想知道能否在程序中嵌入授权用户名和密码,无需右键以管理员身份运行即可正常执行该命令?

原代码如下:

private void button3_Click_2(object sender, EventArgs e)
{
    string command = string.Concat(@"$wmi = Get-WmiObject -class Win32_OperatingSystem -computer ", txb_pc.Text.Trim(), "\n", "$LBTime = $wmi.ConvertToDateTime($wmi.Lastbootuptime)","\n", "[TimeSpan]$uptime = New-TimeSpan $LBTime $(get-date)","\n", "\"$($uptime.days) Gun $($uptime.hours) Saat $($uptime.minutes) Dakika\"");

    using (PowerShell powerShell = PowerShell.Create())
    {
        powerShell.AddScript(command);
        powerShell.AddCommand("Out-String");
        Collection<PSObject> PSOutput = powerShell.Invoke();
        StringBuilder stringBuilder = new StringBuilder();
        foreach (PSObject pSObject in PSOutput)
            stringBuilder.AppendLine(pSObject.ToString());
       txb_islemmonitoru.Text = stringBuilder.ToString();
    }
}
解决方案

可以通过在PowerShell执行上下文注入管理员凭据的方式实现,无需手动以管理员身份运行程序。以下是两种可行方案:

方案1:在PowerShell命令中直接传入凭据

修改PowerShell命令,加入-Credential参数,同时在C#代码中构建管理员凭据并注入命令:

private void button3_Click_2(object sender, EventArgs e)
{
    // 替换为实际管理员账号信息(域账号格式:DOMAIN\AdminUser,本地账号:MachineName\AdminUser)
    string adminUsername = "DOMAIN\\AdminUser";
    string adminPassword = "YourAdminPassword";

    // 构建带凭据的PowerShell命令
    string command = string.Concat(
        "$securePassword = ConvertTo-SecureString '", adminPassword, "' -AsPlainText -Force\n",
        "$credential = New-Object System.Management.Automation.PSCredential('", adminUsername, "', $securePassword)\n",
        "$wmi = Get-WmiObject -class Win32_OperatingSystem -computer ", txb_pc.Text.Trim(), " -Credential $credential\n",
        "$LBTime = $wmi.ConvertToDateTime($wmi.Lastbootuptime)\n",
        "[TimeSpan]$uptime = New-TimeSpan $LBTime $(get-date)\n",
        "\"$($uptime.days) Gun $($uptime.hours) Saat $($uptime.minutes) Dakika\"");

    using (PowerShell powerShell = PowerShell.Create())
    {
        powerShell.AddScript(command);
        powerShell.AddCommand("Out-String");
        Collection<PSObject> PSOutput = powerShell.Invoke();

        // 处理执行错误
        if (powerShell.HadErrors)
        {
            StringBuilder errorBuilder = new StringBuilder();
            foreach (var error in powerShell.Streams.Error)
            {
                errorBuilder.AppendLine("错误:" + error.ToString());
            }
            txb_islemmonitoru.Text = errorBuilder.ToString();
            return;
        }

        StringBuilder stringBuilder = new StringBuilder();
        foreach (PSObject pSObject in PSOutput)
            stringBuilder.AppendLine(pSObject.ToString());
        txb_islemmonitoru.Text = stringBuilder.ToString();
    }
}

方案2:通过C#直接创建PSCredential绑定到PowerShell会话

这种方式更符合C#编程习惯,避免在字符串中拼接敏感信息:

private void button3_Click_2(object sender, EventArgs e)
{
    string adminUsername = "DOMAIN\\AdminUser";
    string adminPassword = "YourAdminPassword";
    string targetComputer = txb_pc.Text.Trim();

    // 创建安全字符串形式的密码
    SecureString securePassword = new SecureString();
    foreach (char c in adminPassword)
    {
        securePassword.AppendChar(c);
    }
    PSCredential credential = new PSCredential(adminUsername, securePassword);

    using (PowerShell powerShell = PowerShell.Create())
    {
        // 添加WMI命令及参数
        powerShell.AddCommand("Get-WmiObject")
                  .AddParameter("Class", "Win32_OperatingSystem")
                  .AddParameter("ComputerName", targetComputer)
                  .AddParameter("Credential", credential);

        Collection<PSObject> wmiResults = powerShell.Invoke();

        // 处理错误
        if (powerShell.HadErrors)
        {
            StringBuilder errorBuilder = new StringBuilder();
            foreach (var error in powerShell.Streams.Error)
            {
                errorBuilder.AppendLine("错误:" + error.ToString());
            }
            txb_islemmonitoru.Text = errorBuilder.ToString();
            return;
        }

        // 计算并显示开机时长
        if (wmiResults.Count > 0)
        {
            var wmiObj = wmiResults[0];
            DateTime lastBootTime = System.Management.ManagementDateTimeConverter.ToDateTime(
                wmiObj.Properties["LastBootUpTime"].Value.ToString()
            );
            TimeSpan uptime = DateTime.Now - lastBootTime;
            txb_islemmonitoru.Text = $"{uptime.Days} Gun {uptime.Hours} Saat {uptime.Minutes} Dakika";
        }
        else
        {
            txb_islemmonitoru.Text = "未获取到目标机器的开机时间信息";
        }
    }
}

关键安全注意事项

  • 禁止明文存储密码:示例中为演示使用了明文密码,实际开发中必须对密码进行加密存储(如使用DPAPI加密、Windows凭据管理器存储),运行时再解密使用,防止管理员账号信息泄露。
  • 确认权限配置:确保所用的管理员账号拥有访问目标机器WMI服务的权限,否则即使传入正确凭据也会执行失败。

内容的提问来源于stack exchange,提问作者Hakan DAŞTAN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 16:50:55