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

在使用New-CimSessioncmdlet成功打开CIM会话并在PowerShell中查询WMI数据后,我try 使用C#中的CimSession.Create完成相同的操作.

然而,当try 使用C#查询相同的数据时,我收到了一个Access Denied错误,代码为0x80070005. 根据Microsoft文档(https://learn.microsoft.com/en-us/windows/win32/wmisdk/wmi-troubleshooting),这是由DCOM引起的.

到目前为止,我一直无法想出一个不同的解决方案,我觉得奇怪的是,在使用PowerShell时,基本上同样的try 可以很好地工作.

一些一般信息:

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

PowerShell中的成功try :

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

在不传递显式身份验证参数的情况下try 使用登录到运行应用程序的服务器的Windows用户的same credentials的代码示例:

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

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

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的不同方法,但对于我的用例来说,使用CimSessionQueryInstances方法似乎是最直接的.尽管如此,我找到的所有其他代码示例都导致了相同的错误.

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

更新

正如@IanKemp所指出的,我知道在Web应用程序中运行需要管理员权限的操作是不好的做法.然而,我只是想弄清楚如何在C#中运行基本的WMI查询,以及哪些问题可能会导致我得到所描述的Access Denied错误,而使用PowerShell则完全可以正常工作.

更新 V2

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

如果您正在try 访问WMI,则有两种协议可用:DCOM和WinRM.您使用的协议将取决于所使用的工具或API.例如,当您使用PowerShell时,‘较旧’的Get-WmiObject cmdlet使用DCOM,而‘较新’的Get-CimInstance cmdlet使用WinRM.

这可以解释为什么PowerShell在我的例子中表现不同,但我仍然没有找到一个解决方案来让它在C#中工作

推荐答案

经过反复试验,我找到了解决问题的办法.

正如我在《更新V2》中提到的,这篇文章指向我的解决方案:https://serverfault.com/a/1105113

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

  1. 我在服务器故障的帖子中提到,我在WMI控制下授予了我的用户‘Remote Enable’权限

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

Csharp相关问答推荐

为什么在GuardationRule的收件箱函数中,decode.TryParse(valueString,out valueParsed)在给出1.0.1时返回true?

使用yaml将Azure函数代码部署到FunctionApp插槽时出现问题(zip未找到)

`Task`只有在C#中等待时才会运行吗?

Int和uint相乘得到LONG?

将字节转换为 struct 并返回

如何在用户在线时限制令牌生成?

避免只读记录 struct 中的防御副本

在Docker容器中运行API项目时,无法本地浏览到index.html

.NET 6:如何防止系统生成的日志(log)?

泛型参数在.NET 8 AOT中没有匹配的批注

用C#从XML内部元素中获取特定值

在等待OnGetAsync时打开Razor Page显示微调器

C#Microsoft.CodeAnalysis.CSharp.Scriiting不等待并行.对于

在C#/ASP.NET Core 7中,什么可能导致POST请求作为GET请求发送

如果所有";async任务方法()";调用都返回Task.FromResult()-是否同步执行?

如何保存具有多个重叠图片框的图片框?

处理方法内部过滤与外部过滤

有没有更好的方法来使用LINQ获取整行的计算组

不寻常的C#语法

XmlSerializer在遇到XML属性(命名空间)时崩溃