Demo-WmiCim.ps1


<#PSScriptInfo
 
.VERSION 1.0.0.0
 
.GUID bda77019-6f07-45aa-a496-bee004da35dc
 
.AUTHOR Frits van Drie (3-Link.nl)
 
.COMPANYNAME 3-Link Opleidingen
 
.COPYRIGHT free to use and distribute without modifications
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
First release
 
.PRIVATEDATA
 
#>


<#
 
.DESCRIPTION
 Developed by 3-Link Opleidingen for training purposes only
 
#>
 

Param()


# Filename: Demo-WmiCim.ps1
# Author: Frits van Drie (3-Link.nl)
# Date: 2022-04-13

<#
.NOTES
 
    DMTF (Distributed Management Task Force)
        Organization that defines management standards for different platforms and vendors
 
    WBEM (Web-Based Enterprise Management)
        One of the standards defined by DMTF
 
    WMI
        (older) implementation of WBEM, based on older standards and MS technology
 
    CIM
        (newer) implementation of WBEM, based on open cross-platform standards
 
    WMI Repository
        a common information store with management information that you can query or manipulate
        The repo is organized in Namespaces, which contain Classes for hard/software components
 
    Namespace
        a folder in the repository that groups related items; it organizes the Classes that you can query
        Namespaces contain Classes
 
    Class
        represents a manageable software or hardware component
 
    Instance
        Object is an Instance
        an actual occurrence of a Class
        (e.g.: 2 cpu's ==> 2 instances of the processor class)
 
    Properties
        describe the attributes of an Instance
 
    Methods
        tell an Instance to do something
 
    COM
        a MS Protocol for connectivity between software components (local),
 
    DCOM
        a MS Protocol for connectivity between software components (remote),
        using dynamic ports and RPC
 
    WS-MAN
        web-based protocol for connectivity, defined by DMTF
        using port TCP-5985/TCP-5986
        Provided by WinRM-service
 
    New Common Information Model (CIM) cmdlets, introduced in Windows PowerShell 3.0, perform the same tasks as the WMI cmdlets.
    The CIM cmdlets comply with WS-Management (WSMan) standards and with the CIM standard, which enables the cmdlets to use the same
    techniques to manage Windows computers and those running other operating systems.
    Instead of using 'Invoke-WmiMethod', consider using 'Invoke-CimMethod' (../cimcmdlets/invoke-cimmethod.md).
 
 
    WMI-cmdlets
        Connections:
            - Local
            - Ad-hoc ( using -ComputerName parameter )
        Requirements:
            - WMI service
            - firewall - DisplayGroup 'Windows Managed Instrumentarium'
 
 
    CIM-cmdlets
        Connections:
            - Local
            - Ad-hoc ( using -ComputerName parameter )
            - Session ( using New-CimSession)
        Requirements:
            - PS or PSRemoting on remote computer not needed (e.g. Linux)
            - WS-MAN support on remote computer is required
 
 
    https://devblogs.microsoft.com/powershell/introduction-to-cim-cmdlets/
    https://technet.microsoft.com/en-us/library/ee692772.aspx
    https://blogs.technet.microsoft.com/heyscriptingguy/2014/01/31/comparing-powershell-pssessions-and-cim-sessions/
     
    WMI Monitor:
    http://www.solarwinds.com/register/index.aspx?Program=937&c=70150000000P9ds&CMP=BIZ-TAD-COMPPERF-APPS-WMI_PS-DL-2011
    https://www.varonis.com/blog/wmi-windows-management-instrumentation/
 
.LINK
    Demo-PSRemoting.ps1
 
 
#>


# gwmi ==> Get-WmiObject
# gcim ==> Get-CimInstance


#region: List Namespaces

    Get-WmiObject -Namespace root -List | Sort Name
    Get-CimClass  -Namespace root       | sort CimClassName    # e.g. __Namespace
    Get-CimClass  -Namespace root -ClassName __Namespace

    # top-level namespaces (all instances of class/type __Namespace below the root)
    Get-CimInstance -Namespace root -ClassName __Namespace     # e.g. CIMV2

#endregion

#region: List Classes

    Get-CimClass    -Namespace root\CIMv2 | ogv                # e.g. Win32_OperatingSystem, Win32_BIOS

    Get-CimInstance -Namespace root\cimv2 -ClassName Win32_OperatingSystem |fl *
    Get-CimClass    -Namespace root\cimv2 -ClassName Win32_OperatingSystem |fl *

    Get-CimInstance -Namespace root\cimv2 -ClassName Win32_BIOS |fl *


#endregion

#region: List Instances

    Get-WmiObject   -Class Win32_LogicalDisk | ft

    Get-CimInstance -Class Win32_LogicalDisk

    $className = (Get-CimClass -Namespace root\CIMv2 | Sort CimClassName | ogv -OutputMode Single).CimClassName # e.g. Win32_DiskPartition, Win32_Processor, Win32_BIOS
    Get-CimInstance -Class $className



#endregion

#region: Filter Instances

    Get-WmiObject   -Class Win32_LogicalDisk -Filter "DriveType=3"  # '=' is comparison

    Get-CimInstance -Class Win32_LogicalDisk
    Get-CimInstance -Class Win32_LogicalDisk -Filter "DriveType=3"

    Get-CimInstance -Class Win32_DiskPartition -Filter "PrimaryPartition=True"
    


    # Filter with WQL (WQL is subset of SQL)
    $wqlQuery = "SELECT * FROM Win32_LogicalDisk WHERE DriveType = 3"
    $wqlQuery = "SELECT * FROM Win32_NetworkAdapter"

    Get-WmiObject   -Query $wqlQuery
    Get-CimInstance -Query $wqlQuery

    $wqlQuery = "SELECT * FROM Win32_DiskPartition WHERE PrimaryPartition=True"
    Get-CimInstance -Query $wqlQuery


#endregion

#region: Find Methods

    Get-CimInstance -ClassName Win32_Service | Get-Member -MemberType Method
    Get-CimClass    -Class     Win32_Service | select -ExpandProperty CimClassMethods




#endregion

#region: Demo-PSRemoting

    Get-WmiObject   Win32_Product |select Name  # lists all products/packages installed by Windows Installer
    Get-CimInstance Win32_Product |select Name  # lists all products/packages installed by Windows Installer

    (Get-WmiObject   Win32_ComputerSystem).Domain
    (Get-CimInstance Win32_ComputerSystem).Domain

    $remotePC = Read-Host "Enter ComputerName"

    Get-Alias gcim, gwmi

    $os           = gwmi -ComputerName $remotePC -Query  "SELECT * FROM Win32_OperatingSystem"
    $cpuLoad      = gwmi -ComputerName $remotePC -Query  "SELECT * FROM Win32_Processor"
    $tSessions    = gwmi -ComputerName $remotePC -Query  "SELECT * FROM Win32_TerminalService"
    $ima          = gwmi -ComputerName $remotePC -Query  "SELECT * FROM Win32_Service WHERE name='imaservice'"
    $mfcom        = gwmi -ComputerName $remotePC -Query  "SELECT * FROM Win32_Service WHERE name='mfcom'"
    $ctxPrintMgr  = gwmi -ComputerName $remotePC -Query  "SELECT * FROM Win32_Service WHERE name='cpsvc'"
    $msmqstatus   = gwmi -ComputerName $remotePC -Query  "SELECT * FROM Win32_Service WHERE name='msmq'"

    $cDrive       = gcim -ComputerName $remotePC -Query  "SELECT * FROM Win32_Logicaldisk WHERE deviceid='c:'"
    $dDrive       = gcim -ComputerName $remotePC -Query  "SELECT * FROM Win32_Logicaldisk WHERE deviceid='d:'" 

    $os 
    $cpuLoad 
    $tSessions
    $ima 
    $mfcom 
    $ctxPrintMgr 
    $msmqstatus 
    $cDrive 
    $dDrive 



#endregion

#region: Remoting

    # Requirements:
        # Services:
        # Firewall: Windows Management Instrumentation (WMI) (WMI: TCP / DCOM: TCP 135)



    # CIM by default uses WSMAN for Remote Sessions

    Get-CimInstance  -ComputerName $remotePC -ClassName Win32_OperatingSystem                # OK

    # Start Process
    1..5 | % { Invoke-CimMethod -ComputerName $remotePC -ClassName Win32_Process -MethodName "Create" -Arguments @{ CommandLine = 'notepad.exe'; CurrentDirectory = "C:\windows\system32" } }   # OK
    Invoke-Command -ComputerName $remotePC { Get-Process 'notepad' }

    $filter = 'name like "notepad%"'
    Get-CimInstance  -ComputerName $remotePC -ClassName Win32_Process -Filter $filter # OK


    # Terminate Process
    Invoke-CimMethod -ComputerName $remotePC -Query "select * from Win32_Process where $filter" -MethodName "Terminate" # OK
    Get-CimInstance  -ComputerName $remotePC -ClassName Win32_Process -Filter $filter # OK






    ## PREPARE
    $displayGroup = "Windows Management Instrumentation (WMI)"
    Invoke-Command $remotePC { Set-NetFirewallRule -DisplayGroup $Using:displayGroup -Profile Domain -Enabled true -Action Block }

    ## PROBLEM
    Get-WmiObject   -ComputerName $remotePC -Class Win32_LogicalDisk | ft          # FAILED


    ## SOLUTION
    $displayGroup = "Windows Management Instrumentation (WMI)"
    Invoke-Command $remotePC { Get-NetFirewallRule -DisplayGroup $using:displayGroup | Select Name, displayGroup, Enabled, Action | ft}
    Invoke-Command $remotePC { Set-NetFirewallRule -DisplayGroup $Using:displayGroup -Profile Domain -Action Allow -Enabled true }

    ## DEMO
    Get-WmiObject   -ComputerName $remotePC -Class Win32_LogicalDisk | ft



#endregion: Remoting

#region: start Process
    
    # Deprecated : cmd.exe >> wmic -?

    # !! wmic is cmd-command
    wmic process call create �notepad.exe�
    

#endregion

#region: Performance
    # Find file on drive C:

    # Get-ChildItem
    Measure-Command {
        gci C:\powershell.exe -File -Recurse -ErrorAction SilentlyContinue
    } | ft minutes, seconds




    # Cim
    Measure-Command {
        Get-CimInstance `
            -ClassName CIM_Logicalfile `
            -Filter "filename='powershell' AND extension = 'exe' AND drive='C:'"
    } | ft minutes, seconds




    (Get-CimInstance -ClassName CIM_Logicalfile).count


#endregion

#region: Check USB devices at shutdown

    $usbDrives = GET-WMIOBJECT win32_diskdrive | Where { $_.InterfaceType �eq �USB� }
    $devices = @()
    foreach($usb in $usbDrives){
        $devices += $usb.Model + ". "
    }

    $input = [System.Windows.MessageBox]::Show("There are USB devices connected, $($devices | Out-String)`nWould you like to proceed logging off?","Warning","YesNoCancel","Error")
        if($input -eq "Yes"){
            shutdown -L
        }
        elseif($input -eq "No"){
            shutdown -A
        }
        else{
            break    
        }


#endregion

#region: Remote Logged on user

    Get-CimClass -PropertyName Win32_LoggedOnUser -ComputerName 'DC1'| Select Antecedent -Unique

#endregion

#region: Change ServiceAccountPassword
    $serviceName            = 'bits'
    $serviceAccountName     = 'sure\administrator' 
    $serviceAccountPassword = 'Pa55w.rd'

    $ret = Invoke-CimMethod `
        -Query "SELECT * FROM Win32_Service WHERE Name=`'$serviceName`'" `
        -MethodName Change `
        -Arguments @{'StartName'    =$serviceAccountName;
                     'StartPassword'=$serviceAccountPassword
                    }

#endregion