none
WMI remote query returns emtpy column RRS feed

  • Question

  • Hi forum,

    I try to query WMI remotely with a non-admin user, which basically works fine. I have added the user to the groups "Performance Monitor Users" and "Distributed COM Users" as described in many blogs. I added the required remote enable permissions in WMI control.

    I want to get the LastUseTime from Win32_UserProfile. I run this command:

    $Computer = "computername"
    $cred = Get-Credential
    
    Get-WmiObject -Namespace "root\cimv2" -Class Win32_UserProfile -Impersonation 3 -Credential $cred -ComputerName $Computer | Where{$_.LocalPath -Like "*username*"}

    when I run it as the non-admin user I get the result with LastUseTime empty. If I add this user to local admins then I get the correct timestamp.

    __GENUS           : 2
    __CLASS           : Win32_UserProfile
    __SUPERCLASS      : 
    __DYNASTY         : Win32_UserProfile
    __RELPATH         : Win32_UserProfile.SID="S-1-5-21-1289385845-471110988-4091671220-8383"
    __PROPERTY_COUNT  : 12
    __DERIVATION      : {}
    __SERVER          : COMPUTERNAME
    __NAMESPACE       : root\cimv2
    __PATH            : \\COMPUTERNAME\root\cimv2:Win32_UserProfile.SID="S-1-5-21-1289385845-471110988-4091671220-8383"
    LastDownloadTime  : 
    LastUploadTime    : 
    LastUseTime       : 
    Loaded            : True
    LocalPath         : C:\Users\username
    RefCount          : 2
    RoamingConfigured : False
    RoamingPath       : 
    RoamingPreference : 
    SID               : S-1-5-21-1289385845-471110988-4091671220-8383
    Special           : False
    Status            : 0
    PSComputerName    : COMPUTERNAME

    I have been googling this now for quite a while. I didn't find anything that helped.

    Any other hints?

    KR
    Alex

    Tuesday, June 20, 2017 9:03 AM

Answers

  • It turned out that I was querying the wrong namespace. I needed the currently logged on user, not the last logon from every or a specific user.

    Anyways in Win32_ComputerSystem column UserName I had the same issue. Result shows when the user is an admin and empty if he isn't. After many tests I found out that the non-admin user can read this column when he is member of the "Remote Desktop Users" group. I have no idea why, but with that it works.

    • Marked as answer by Alex Vary Wednesday, June 21, 2017 12:27 PM
    Wednesday, June 21, 2017 12:27 PM

All replies

  • Try it like this:

    Get-WmiObject Win32_UserProfile -Credential $cred -ComputerName $Computer -Filter 'LocalPath LIKE "%username%"'


    \_(ツ)_/

    Tuesday, June 20, 2017 9:25 AM
    Moderator
  • Hi,

    Returns the same result. LastUseTime still empty.

    Tuesday, June 20, 2017 9:35 AM
  • I cannot reproduce your issue.


    \_(ツ)_/

    Tuesday, June 20, 2017 9:56 AM
    Moderator
  • Did you try with a non-admin user?
    Tuesday, June 20, 2017 10:28 AM
  • Hi,

    Your code is working fine for my test Win2012 R2 core servers.

    I used the following code to grant access for non-privileged user:

    #function to set security for namespace from https://blogs.msdn.microsoft.com/wmi/2009/07/27/scripting-wmi-namespace-security-part-3-of-3/
    function  Set-WmiNamespaceSecurity
    {
    	Param ( [parameter(Mandatory=$true,Position=0)][string] $namespace,
    		[parameter(Mandatory=$true,Position=1)][string] $operation,
    		[parameter(Mandatory=$true,Position=2)][string] $account,
    		[parameter(Position=3)][string[]] $permissions = $null,
    		[bool] $allowInherit = $false,
    		[bool] $deny = $false,
    		[string] $computerName = ".",
    		[System.Management.Automation.PSCredential] $credential = $null)
    	   
    	Process {
    		$ErrorActionPreference = "Stop"
    	 
    		Function Get-AccessMaskFromPermission($permissions) {
    			$WBEM_ENABLE            = 1
    					$WBEM_METHOD_EXECUTE = 2
    					$WBEM_FULL_WRITE_REP   = 4
    					$WBEM_PARTIAL_WRITE_REP              = 8
    					$WBEM_WRITE_PROVIDER   = 0x10
    					$WBEM_REMOTE_ACCESS    = 0x20
    					$WBEM_RIGHT_SUBSCRIBE = 0x40
    					$WBEM_RIGHT_PUBLISH      = 0x80
    			$READ_CONTROL = 0x20000
    			$WRITE_DAC = 0x40000
    		   
    			$WBEM_RIGHTS_FLAGS = $WBEM_ENABLE,$WBEM_METHOD_EXECUTE,$WBEM_FULL_WRITE_REP,`
    				$WBEM_PARTIAL_WRITE_REP,$WBEM_WRITE_PROVIDER,$WBEM_REMOTE_ACCESS,`
    				$READ_CONTROL,$WRITE_DAC
    			$WBEM_RIGHTS_STRINGS = "Enable","MethodExecute","FullWrite","PartialWrite",`
    				"ProviderWrite","RemoteAccess","ReadSecurity","WriteSecurity"
    	 
    			$permissionTable = @{}
    	 
    			for ($i = 0; $i -lt $WBEM_RIGHTS_FLAGS.Length; $i++) {
    				$permissionTable.Add($WBEM_RIGHTS_STRINGS[$i].ToLower(), $WBEM_RIGHTS_FLAGS[$i])
    			}
    		   
    			$accessMask = 0
    	 
    			foreach ($permission in $permissions) {
    				if (-not $permissionTable.ContainsKey($permission.ToLower())) {
    					throw "Unknown permission: $permission`nValid permissions: $($permissionTable.Keys)"
    				}
    				$accessMask += $permissionTable[$permission.ToLower()]
    			}
    		   
    			$accessMask
    		}
    	 
    		if ($PSBoundParameters.ContainsKey("Credential")) {
    			$remoteparams = @{ComputerName=$computer;Credential=$credential}
    		} else {
    			$remoteparams = @{ComputerName=$computerName}
    		}
    		   
    		$invokeparams = @{Namespace=$namespace;Path="__systemsecurity=@"} + $remoteParams
    	 
    		$output = Invoke-WmiMethod @invokeparams -Name GetSecurityDescriptor
    		if ($output.ReturnValue -ne 0) {
    			throw "GetSecurityDescriptor failed: $($output.ReturnValue)"
    		}
    	 
    		$acl = $output.Descriptor
    		$OBJECT_INHERIT_ACE_FLAG = 0x1
    		$CONTAINER_INHERIT_ACE_FLAG = 0x2
    	 
    		$computerName = (Get-WmiObject @remoteparams Win32_ComputerSystem).Name
    	   
    		if ($account.Contains('\')) {
    			$domainaccount = $account.Split('\')
    			$domain = $domainaccount[0]
    			if (($domain -eq ".") -or ($domain -eq "BUILTIN")) {
    				$domain = $computerName
    			}
    			$accountname = $domainaccount[1]
    		} elseif ($account.Contains('@')) {
    			$domainaccount = $account.Split('@')
    			$domain = $domainaccount[1].Split('.')[0]
    			$accountname = $domainaccount[0]
    		} else {
    			$domain = $computerName
    			$accountname = $account
    		}
    	 
    		$getparams = @{Class="Win32_Account";Filter="Domain='$domain' and Name='$accountname'"}
    	 
    		$win32account = Get-WmiObject @getparams
    	 
    		if ($win32account -eq $null) {
    			throw "Account was not found: $account"
    		}
    	 
    		switch ($operation) {
    			"add" {
    				if ($permissions -eq $null) {
    					throw "-Permissions must be specified for an add operation"
    				}
    				$accessMask = Get-AccessMaskFromPermission($permissions)
    	   
    				$ace = (New-Object System.Management.ManagementClass("win32_Ace")).CreateInstance()
    				$ace.AccessMask = $accessMask
    				if ($allowInherit) {
    					$ace.AceFlags = $OBJECT_INHERIT_ACE_FLAG + $CONTAINER_INHERIT_ACE_FLAG
    				} else {
    					$ace.AceFlags = 0
    				}
    						   
    				$trustee = (New-Object System.Management.ManagementClass("win32_Trustee")).CreateInstance()
    				$trustee.SidString = $win32account.Sid
    				$ace.Trustee = $trustee
    			   
    				$ACCESS_ALLOWED_ACE_TYPE = 0x0
    				$ACCESS_DENIED_ACE_TYPE = 0x1
    	 
    				if ($deny) {
    					$ace.AceType = $ACCESS_DENIED_ACE_TYPE
    				} else {
    					$ace.AceType = $ACCESS_ALLOWED_ACE_TYPE
    				}
    	 
    				$acl.DACL += $ace.psobject.immediateBaseObject
    			}
    		   
    			"delete" {
    				if ($permissions -ne $null) {
    					throw "Permissions cannot be specified for a delete operation"
    				}
    		   
    				[System.Management.ManagementBaseObject[]]$newDACL = @()
    				foreach ($ace in $acl.DACL) {
    					if ($ace.Trustee.SidString -ne $win32account.Sid) {
    						$newDACL += $ace.psobject.immediateBaseObject
    					}
    				}
    	 
    				$acl.DACL = $newDACL.psobject.immediateBaseObject
    			}
    		   
    			default {
    				throw "Unknown operation: $operation`nAllowed operations: add delete"
    			}
    		}
    	 
    		$setparams = @{Name="SetSecurityDescriptor";ArgumentList=$acl.psobject.immediateBaseObject} + $invokeParams
    	 
    		$output = Invoke-WmiMethod @setparams
    		if ($output.ReturnValue -ne 0) {
    			throw "SetSecurityDescriptor failed: $($output.ReturnValue)"
    		}
    	}
    }
    #groups for remote WMI
    $group_names=@("Performance Monitor User","Distributed COM Users")
    #user to grant access
    $domain="test.local"
    $user="test"
    #get local computer
    $computer = [ADSI]"WinNT://.,computer"
    #get local groups 
    $allgroups=$computer.psbase.children | ?{ $_.psbase.schemaClassName -eq "group"}
    $groups=$(foreach ($name in $group_names)
    		{
    			 $allgroups | ?{$_.path -like "*$name*"}
    		})	
    		
    #add test user to "Performance Monitor User" and "Distributed COM Users"
    $groups | %{$_.psbase.Invoke("Add",(([ADSI]"WinNT://$domain/$user").path))}
    #check that user is member of groups now
    foreach($group in $groups)
    {
    	@{($group.Name)=(([ADSI]$group.psbase.Path).psbase.Invoke("Members") | foreach 	{$_.GetType().InvokeMember("Name", 
    				"GetProperty", 
    				$null, 
    				$_, 
    				$null)}
    	)} 
    }
    #set security for cimv2
    Set-WMINamespaceSecurity -namespace root/cimv2 -operation add -account test\test -permissions MethodExecute,Enable,RemoteAccess

    Sergei

    Tuesday, June 20, 2017 1:56 PM
  • Hi Sergei,

    I had used the same Powershell Skript to deploy the WMI settings. Anyway it is the same setting them in WMI Control. I tried it anyway again, but no change the column remains empty.

    Tuesday, June 20, 2017 2:22 PM
  • Hi Alex,

    it seems that your need to give this account admin privilege.

    Even if i give the user DCOM related permission under:dcomcnfg->Mycomputer no effects.

    Besides, these two groups you mentioned , i suppose have no affects on this operation:

    Members of this group can monitor performance counters on a computer — 
    locally and from remote clients — without being a member of the Administrators group or the Performance Log Users groups.
    Members of this group are allowed to start, activate, and use DCOM objects on a computer.

    Local admin groups have rights to access related location while other groups don't have.

    Best regards,

    Andy


    Please remember to mark the replies as answers if they help.
    If you have feedback for TechNet Subscriber Support, contact tnmff@microsoft.com.

    Wednesday, June 21, 2017 4:32 AM
    Moderator
  • Hi Andy,

    actually the 2 groups have effect as they take care about dcom permissions. Without them there is access denied immediately.

    Additionally my setup gives me access to all the information that I need, except the LastUseTime. So it seems that I am very close.

    Admin permissions is no option in this case, otherwise I wouldn't make my life hard for no reason ;-)

    Wednesday, June 21, 2017 6:47 AM
  • Update:

    I found out that the issue exists only on Windows 7/ Server 2008 R2. On Windows 10 and Windows Server 2012 R2 I get the expected values.

    Wednesday, June 21, 2017 8:05 AM
  • Update:

    I found out that the issue exists only on Windows 7/ Server 2008 R2. On Windows 10 and Windows Server 2012 R2 I get the expected values.

    Ps version issues?


    Please remember to mark the replies as answers if they help.
    If you have feedback for TechNet Subscriber Support, contact tnmff@microsoft.com.

    Wednesday, June 21, 2017 8:10 AM
    Moderator
  • It turned out that I was querying the wrong namespace. I needed the currently logged on user, not the last logon from every or a specific user.

    Anyways in Win32_ComputerSystem column UserName I had the same issue. Result shows when the user is an admin and empty if he isn't. After many tests I found out that the non-admin user can read this column when he is member of the "Remote Desktop Users" group. I have no idea why, but with that it works.

    • Marked as answer by Alex Vary Wednesday, June 21, 2017 12:27 PM
    Wednesday, June 21, 2017 12:27 PM