我正在尝试使用 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 时,本质上相同的尝试工作得很好。
一些一般信息:
在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 则可以正常工作。
我在 serverfault 上找到了一个有趣的答案:https://serverfault.com/a/1105113
如果您尝试访问 WMI,有两种可用协议:DCOM 和 WinRM。您使用哪种协议取决于所使用的工具或 API。例如,当您使用 PowerShell 时,“较旧”的 Get-WmiObject cmdlet 使用 DCOM,而“较新”的 Get-CimInstance cmdlet 使用 WinRM。
这可以解释为什么 powershell 在我的情况下表现不同,但我仍然没有找到解决方案让它在 C# 中工作
经过一番尝试和错误,我找到了解决问题的方法。
正如我的“更新 V2”中提到的,这篇文章导致了我的解决方案:https://serverfault.com/a/1105113
有两件事解决了我的问题:
我在 WMI 控制下授予了我的用户“远程启用”权限,如 serverfault 上的帖子中所述
在开发过程中,我必须以管理员身份运行 Visual Studio(不知道为什么,但这解决了我之前遇到的任何访问被拒绝的问题,即使我在代码中以管理员身份进行了身份验证)
编辑:我发布了一篇关于在没有管理员权限的情况下使用 wmi 的新帖子使用 C# 在远程计算机上以非管理员用户身份运行 wmi 查询