Search code examples
c#powershellwmi

Access Denied trying to gather WMI information using C# ASP.NET but works in powershell


I am trying to query hardware data of computers on my local domain using WMI in a C# ASP.NET Application running on a server using IIS.

After successfully opening a cim session using the New-CimSession cmdlet and querying WMI data in powershell I tried to acomplish the same thing using CimSession.Create in C#.

However when trying to query the same data using C# I receive an Access Denied error with code 0x80070005. According to the microsoft documentation (https://learn.microsoft.com/en-us/windows/win32/wmisdk/wmi-troubleshooting) this is caused by DCOM.

So far I have been unable to come up with a different solution and I find it weird that essentially the same attempt works fine when using powershell.

Some general information:

  • My account has local administrator permissions on the remote machine (as required when using a cim session to execute wmi queries)
  • I already looked into firewall and connectivity issues and tried running my application outside of IIS

Successful attempt in powershell:

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

Code example trying to use the same credentials from the windows user logged in on the server running the application without passing explicit authentication parameters:

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

This should work as is but to make sure I also tried passing explicit authentication parameters which also results in the same error:

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");

I have seen many different approaches on WMI in C# but using CimSession with the QueryInstances method seemed to be the most straight forward for my use case. Nonetheless all other code examples I found resulted in the same error.

Any help would be greatly appreciated - thanks!

Update

As pointed out by @IanKemp I understand that it's bad practice to run operations requiring administrator permissions in a web application. However I am just trying to figure out how to run a basic WMI query in C# and what issues could lead to me getting the described Access Denied error whereas it works perfectly fine using powershell.

Update V2

I have found an interesting answer on serverfault: https://serverfault.com/a/1105113

If you are trying to access WMI there are two protocols available: DCOM and WinRM. Which protocol you are using will depend on the tools or API being used. For example, when you are using PowerShell, the 'older' Get-WmiObject cmdlet uses DCOM, whereas the 'newer' Get-CimInstance cmdlet uses WinRM.

This could explain why powershell behaves differently in my case but I still had no luck finding a solution to get it to work in C#


Solution

  • After a bit of trial and error I have found a solution to my problem.

    As mentioned in my "Update V2" this post lead to my solution: https://serverfault.com/a/1105113

    Two things that resolved my problem:

    1. I granted my user 'Remote Enable' permissions under WMI control as mentioned in the post on serverfault

    2. In development I have to run Visual Studio as Administrator (don't know why but this resolved any Access Denied issues I encountered earlier even though I authenticated as administrator in code)

    Edit: I posted a new post about using wmi without admin permissions Running wmi queries as a non-admin user on a remote machine using C#