Search code examples
powershellpowershell-5.1cim

Setting new CIM instance values


I am trying to lock the local admin account on a remote computer that i'm connected to using a CIM session:

$CIMSession = New-CimSession -ComputerName ComputerOne -ErrorAction Stop
$adminCheck = Get-CimInstance -Query "SELECT * FROM Win32_UserAccount WHERE Name='AdminAccount'" -CimSession $CIMSession

When I enumerate all the available CIM class methods available for that object, only one shows up:

PS C:\windows\system32> $adminCheck.CimClass.CimClassMethods

Name   ReturnType Parameters Qualifiers                   
----   ---------- ---------- ----------                   
Rename     UInt32 {Name}     {Implemented, MappingStrings}

...figures this is due to some methods not showing completely, perhaps? So I tried setting it using Invoke-CimMethod.

  • $adminCheck | Invoke-CimMethod -MethodName Put -Arguments Lockout,$true

    • This doesn't work which I believe is syntactically incorrect, as it errors out as well.

Tried: $adminCheck.LockOut = $true, out of just trying stuff and to no surprise it doesn't work either. Which would make sense since the instance is just referenced on my computer.

So, in my last attempt I tried:

$adminCheck | Set-CimInstance -Property @{Lockout=$true}
# and
$adminCheck | Set-CimInstance -Property @{Lockout=$true} -CimSession $CIMSession

which didn't work, as well.

Question: Is there no method, to save the newly modified value for that CIM instance property?

I am basing this off of the older Get-WMIObject cmdlet which will allow you to set the property by saving it using the .put() method.

Get-WmiObject -Class Win32_UserAccount -ComputerName ComputerOne -Filter "Name='AdminAccount'" | 
    ForEach-Object -Process {
        $_.Lockout = $true;
        $_.put()
    }

just looking to switch over completely to the newer CIM cmdlets


Solution

  • Regarding the asymmetry of being able to set the Lockout property of Microsoft.Management.Infrastructure.CimInstance#root/cimv2/Win32_UserAccount instances to $false, but not to $true:

    • As Mathias suspects, a locked-out account can be unlocked ($false), but you cannot lock out an account on demand (you can only disable it) - that is something that can only happen as a result of a user repeatedly providing an incorrect password.
    • It is unfortunate that an attempt to do so ($true) is quietly ignored.

    Question: Is there no method, to save the newly modified value for that CIM instance property?

    There is no CIM method as such, but Set-CimInstance is indeed the cmdlet needed to modify properties of CIM instances (whereas calling methods on CIM instances requires Invoke-CimMethod).

    There are two idioms, both of which require running with elevation (with administrative privileges):

    • Retrieve a CIM instance and pipe it directly to Set-CimInstance, specifying the property modification(s) via a hashtable of property name-value pairs to the -Property parameter; e.g.:

       # Disables the 'Administrator' account.
       #requires -RunAsAdministrator
       Get-CimInstance Win32_UserAccount -Filter 'Name="Administrator"' | 
         Set-CimInstance -Property @{ Disabled = $true }
      
    • Retrieve and store a CIM instance in a variable, modify its properties, then pipe the modified object to Set-CimInstance without arguments:

       # Disables the 'Administrator' account.
       #requires -RunAsAdministrator
       $acct = Get-CimInstance Win32_UserAccount -Filter 'Name="Administrator"'
       $acct.Disabled = $true   # *Stage* the property modification.
       $acct | Set-CimInstance  # *Commit* it.
      
      • Note: While more verbose than the first idiom, this one has one advantage: some CIM classes, e.g., Microsoft.Management.Infrastructure.CimInstance#ROOT/Microsoft/Windows/SMB/MSFT_SmbShare (as output by Get-SmbShare), have properties that are friendly wrappers around the underlying CIM properties in that they accept enumeration (symbolic) values in lieu of the raw numbers stored in the CIM instance. E.g., the .FolderEnumerationMode property accepts values 'Unrestricted and 'AccessBased' as alternatives to 1 and 0, due to being [Microsoft.PowerShell.Cmdletization.GeneratedTypes.SmbShare.FolderEnumerationMode]-typed.
        Only this idiom makes use of these friendly wrappers, whereas properties targeted via entries in the -Property argument directly target the underlying CIM properties, and therefore only accept numeric values.