尝试使用 C# ASP.NET 收集 WMI 信息时访问被拒绝,但可以在 powershell 中使用

问题描述 投票:0回答:1

我正在尝试使用 IIS 在服务器上运行的 C# ASP.NET 应用程序中使用 WMI 查询本地域中计算机的硬件数据。

使用

New-CimSession
cmdlet 成功打开 cim 会话并在 powershell 中查询 WMI 数据后,我尝试在 C# 中使用
CimSession.Create
完成相同的操作。

但是,当尝试使用 C# 查询相同数据时,我收到一个

Access Denied
错误,代码为
0x80070005
。 根据微软文档(https://learn.microsoft.com/en-us/windows/win32/wmisdk/wmi-troubleshooting)这是由DCOM引起的。

到目前为止,我一直无法想出不同的解决方案,而且我觉得很奇怪,在使用 powershell 时,本质上相同的尝试工作得很好。

一些一般信息:

  • 我的帐户在远程计算机上具有本地管理员权限(根据使用 cim 会话执行 wmi 查询时的需要)
  • 我已经研究了防火墙和连接问题,并尝试在 IIS
  • 之外运行我的应用程序

在powershell中尝试成功:

$CimSession = New-CimSession -ComputerName "PC-HOSTNAME" -Credential (Get-Credential)
Get-CimInstance -CimSession $CimSession -ClassName Win32_ComputerSystem

尝试使用登录到运行应用程序的服务器的 Windows 用户的相同凭据的代码示例,而不传递显式身份验证参数:

CimSession session = CimSession.Create("PC-HOSTNAME");
// The next line results in the error
var response = session.QueryInstances(@"root\cimv2", "WQL", "SELECT * FROM Win32_ComputerSystem");

这应该按原样工作,但为了确保我也尝试传递显式身份验证参数,这也会导致相同的错误:

DComSessionOptions dComOptions = new DComSessionOptions();
dComOptions.Impersonation = ImpersonationType.Impersonate;

//Build secure string from plain text for representation
var somePasswordString = "password"
var password = new SecureString();
somePasswordString.ToList().ForEach(x => password.AppendChar(x));

dComOptions.AddDestinationCredentials(new CimCredential(PasswordAuthenticationMechanism.Default, "mydomain.local", "myusername", password));
        
CimSession session = CimSession.Create("PC-HOSTNAME");
// The next line results in the error
var response = session.QueryInstances(@"root\cimv2", "WQL", "SELECT * FROM Win32_ComputerSystem");

我在 C# 中见过许多不同的 WMI 方法,但使用

CimSession
QueryInstances
方法似乎对我的用例来说是最直接的。尽管如此,我发现的所有其他代码示例都导致了相同的错误。

任何帮助将不胜感激 - 谢谢!

更新

正如 @IanKemp 所指出的,我知道在 Web 应用程序中运行需要管理员权限的操作是不好的做法。不过,我只是想弄清楚如何在 C# 中运行基本的 WMI 查询,以及哪些问题可能会导致我收到所描述的

Access Denied
错误,而使用 powershell 则可以正常工作。

更新V2

我在 serverfault 上找到了一个有趣的答案:https://serverfault.com/a/1105113

如果您尝试访问 WMI,有两种可用协议:DCOM 和 WinRM。您使用哪种协议取决于所使用的工具或 API。例如,当您使用 PowerShell 时,“较旧”的 Get-WmiObject cmdlet 使用 DCOM,而“较新”的 Get-CimInstance cmdlet 使用 WinRM。

这可以解释为什么 powershell 在我的情况下表现不同,但我仍然没有找到解决方案让它在 C# 中工作

c# powershell wmi
1个回答
0
投票

经过一番尝试和错误,我找到了解决问题的方法。

正如我的“更新 V2”中提到的,这篇文章导致了我的解决方案:https://serverfault.com/a/1105113

有两件事解决了我的问题:

  1. 我在 WMI 控制下授予了我的用户“远程启用”权限,如 serverfault 上的帖子中所述

  2. 在开发过程中,我必须以管理员身份运行 Visual Studio(不知道为什么,但这解决了我之前遇到的任何访问被拒绝的问题,即使我在代码中以管理员身份进行了身份验证)

编辑:我发布了一篇关于在没有管理员权限的情况下使用 wmi 的新帖子使用 C# 在远程计算机上以非管理员用户身份运行 wmi 查询

© www.soinside.com 2019 - 2024. All rights reserved.