├── .gitattributes ├── .gitignore ├── CMClient.psd1 ├── CMClient.psm1 ├── Clear-CMClientCache.ps1 ├── Get-CMClientBaselineEvaluation.ps1 ├── Get-CMClientCache.ps1 ├── Get-CMClientComputerByLoggedOnUser.ps1 ├── Get-CMClientDeviceCollectionMembership.ps1 ├── Get-CMClientPackage.ps1 ├── Get-CMClientPendingUpdates.ps1 ├── Get-CMClientUpdates.ps1 ├── Get-CMClientVersion.ps1 ├── Invoke-CMClientAction.ps1 ├── Invoke-CMClientAdvancedFunctions.ps1 ├── Invoke-CMClientApplicationDeploymentEvaluation.ps1 ├── Invoke-CMClientBaselineEvaluation.ps1 ├── Invoke-CMClientComplianceEvaluation.ps1 ├── Invoke-CMClientDiscoveryDataCycle.ps1 ├── Invoke-CMClientHardwareInventory.ps1 ├── Invoke-CMClientJob.ps1 ├── Invoke-CMClientMachinePolicyDownload.ps1 ├── Invoke-CMClientSoftwareInventory.ps1 ├── Invoke-CMClientUpdateDeploymentEvaluation.ps1 ├── Invoke-CMClientUpdateScan.ps1 └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /CMClient.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adbertram/CMClient/ceb72ac6ff90f2334b412945192d8e0d68ef8955/CMClient.psd1 -------------------------------------------------------------------------------- /CMClient.psm1: -------------------------------------------------------------------------------- 1 | <# 2 | =========================================================================== 3 | Created with: SAPIEN Technologies, Inc., PowerShell Studio 2014 v4.1.58 4 | Created on: 6/9/2014 1:57 PM 5 | Created by: Adam Bertram 6 | Filename: CMClient.psm1 7 | Modified: 8/17/2015 03:02:23 PM 8 | Modified by: Jason Wasser @wasserja 9 | ------------------------------------------------------------------------- 10 | Module Name: CMClient 11 | =========================================================================== 12 | #> 13 | 14 | 15 | # Source all ps1 files from module directory. 16 | # https://becomelotr.wordpress.com/2017/02/13/expensive-dot-sourcing/ 17 | foreach ($file in Get-ChildItem $PSScriptRoot\*.ps1) { 18 | $ExecutionContext.InvokeCommand.InvokeScript( 19 | $false, 20 | ( 21 | [scriptblock]::Create( 22 | [io.file]::ReadAllText( 23 | $file.FullName, 24 | [Text.Encoding]::UTF8 25 | ) 26 | ) 27 | ), 28 | $null, 29 | $null 30 | ) 31 | } -------------------------------------------------------------------------------- /Clear-CMClientCache.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Clear the cache content on SCCM clients. 4 | 5 | .DESCRIPTION 6 | Clear the cache content on SCCM clients using the COM object. 7 | 8 | .PARAMETER ComputerName 9 | Enter a computer name 10 | 11 | .PARAMETER CacheAgeinDays 12 | Enter a number in days of the last time cache was referenced. 13 | 14 | .PARAMETER Force 15 | Clears persisted cache items. 16 | 17 | .EXAMPLE 18 | Clear-CMClientCache -ComputerName DESKTOP01 19 | 20 | Clears all SCCM client non-persistent cache content 21 | 22 | .EXAMPLE 23 | Clear-CMClientCache -ComputerName DESKTOP01,DESKETOP01 -CacheAgeinDays 30 -Force 24 | 25 | Clears all SCCM client cache content that hasn't been referenced in 30 days including persistent cache items. 26 | .NOTES 27 | Created by: Jason Wasser @wasserja 28 | Modified: 7/11/2017 11:43:18 AM 29 | #> 30 | function Clear-CMClientCache { 31 | [CmdletBinding(SupportsShouldProcess = $true)] 32 | param ( 33 | [string[]]$ComputerName = $env:COMPUTERNAME, 34 | [int]$CacheAgeinDays = 0, 35 | [switch]$Force 36 | ) 37 | 38 | begin { 39 | function Clean-ClientCache { 40 | param ( 41 | [int]$CacheAgeinDays, 42 | [bool]$WhatIf, 43 | [bool]$Force 44 | ) 45 | $VerbosePreference = 'Continue' 46 | Write-Verbose "Beginning clearing of SCCM Cache older than $CacheAgeinDays days" 47 | $UIResourceMgr = New-Object -ComObject UIResource.UIResourceMgr 48 | $Cache = $UIResourceMgr.GetCacheInfo() 49 | $CacheElements = $Cache.GetCacheElements() | Where-Object -FilterScript {$_.LastReferenceTime -lt (Get-Date).AddDays( - $CacheAgeInDays)} 50 | if ($CacheElements) { 51 | if ($CacheElements.Count) { 52 | Write-Verbose -Message "Found $($CacheElements.Count) cache elements on $($env:COMPUTERNAME) continuing to clear the elements in the cache." 53 | } 54 | else { 55 | Write-Verbose -Message "Found a cache element on $($env:COMPUTERNAME) continuing to clear the elements in the cache." 56 | } 57 | 58 | foreach ($Element in $CacheElements) { 59 | if ($WhatIf) { 60 | if ($Force) { 61 | Write-Verbose "What if: Forcing deletion of CacheElement with PackageID $($Element.ContentID) from $($Element.Location)" 62 | } 63 | else { 64 | Write-Verbose "What if: Deleting CacheElement with PackageID $($Element.ContentID) from $($Element.Location)" 65 | } 66 | 67 | } 68 | else { 69 | if ($Force) { 70 | Write-Verbose "Forcing deletion of CacheElement with PackageID $($Element.ContentID) from $($Element.Location)" 71 | $Cache.DeleteCacheElementEx($Element.CacheElementID, $true) 72 | } 73 | else { 74 | Write-Verbose "Deleting CacheElement with PackageID $($Element.ContentID) from $($Element.Location)" 75 | $Cache.DeleteCacheElement($Element.CacheElementID) 76 | } 77 | 78 | } 79 | } 80 | } 81 | else { 82 | Write-Verbose -Message "No cache elements found on $($env:COMPUTERNAME)" 83 | } 84 | } 85 | } 86 | 87 | process { 88 | 89 | foreach ($Computer in $ComputerName) { 90 | Write-Verbose -Message "Attempting to clear SCCM client cache on $Computer older than $CacheAgeinDays days" 91 | if ($PSBoundParameters.ContainsKey('WhatIf')) { 92 | Write-Verbose 'WhatIf detected' 93 | $WhatIf = $true 94 | if ($Force) { 95 | Write-Verbose 'Force detected' 96 | $Force = $true 97 | Invoke-Command -ComputerName $Computer -ScriptBlock ${function:Clean-ClientCache} -ArgumentList $CacheAgeinDays, $WhatIf, $Force 98 | } 99 | else { 100 | Invoke-Command -ComputerName $Computer -ScriptBlock ${function:Clean-ClientCache} -ArgumentList $CacheAgeinDays, $WhatIf 101 | } 102 | 103 | } 104 | else { 105 | Write-Verbose 'WhatIf not detected' 106 | $WhatIf = $false 107 | if ($Force) { 108 | Write-Verbose -Message 'Force detected' 109 | $Force = $true 110 | Invoke-Command -ComputerName $Computer -ScriptBlock ${function:Clean-ClientCache} -ArgumentList $CacheAgeinDays, $WhatIf, $Force 111 | } 112 | else { 113 | Invoke-Command -ComputerName $Computer -ScriptBlock ${function:Clean-ClientCache} -ArgumentList $CacheAgeinDays 114 | } 115 | 116 | } 117 | } 118 | } 119 | 120 | end { 121 | } 122 | } -------------------------------------------------------------------------------- /Get-CMClientBaselineEvaluation.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Get the status of Configuration Manager client configuration baselines. 4 | 5 | .DESCRIPTION 6 | Get the status of Configuration Manager client configuration baselines. 7 | .NOTES 8 | Created by: Jason Wasser @wasserja 9 | Modified: 5/17/2017 04:05:12 PM 10 | 11 | .EXAMPLE 12 | Get-CMClientBaselineEvaluation 13 | 14 | ComputerName : SERVER01 15 | BaselineName : SMB1 Disabled 16 | Version : 2 17 | EvaluationStatus : Idle 18 | Compliance : Compliant 19 | LastEvaluationTime : 5/17/2017 7:46:44 PM 20 | 21 | .EXAMPLE 22 | Get-CMClientBaselineEvaluation -ComputerName SERVER01,SERVER02 23 | 24 | ComputerName : SERVER01 25 | BaselineName : SMB1 Disabled 26 | Version : 2 27 | EvaluationStatus : Idle 28 | Compliance : Compliant 29 | LastEvaluationTime : 5/17/2017 7:46:44 PM 30 | 31 | ComputerName : SERVER02 32 | BaselineName : SMB1 Disabled 33 | Version : 2 34 | EvaluationStatus : Idle 35 | Compliance : Compliant 36 | LastEvaluationTime : 5/17/2017 7:46:37 PM 37 | 38 | #> 39 | function Get-CMClientBaselineEvaluation 40 | { 41 | [CmdletBinding()] 42 | param ( 43 | [Parameter(Mandatory=$false, 44 | ValueFromPipelineByPropertyName=$true, 45 | ValueFromPipeline=$true, 46 | Position=0)] 47 | [string[]]$ComputerName=$env:COMPUTERNAME 48 | ) 49 | begin { 50 | $ComplianceHash = [hashtable]@{ 51 | "0" = 'Non-Compliant' 52 | "1" = 'Compliant' 53 | "2" = 'Submitted' 54 | "3" = 'Unknown' 55 | "4" = 'Detecting' 56 | "5" = 'Not Evaluated' 57 | } 58 | $EvalHash = [hashtable]@{ 59 | "0" = 'Idle' 60 | "1" = 'Evaluated' 61 | "5" = 'Not Evaluated' 62 | } 63 | 64 | } 65 | process { 66 | foreach ($Computer in $ComputerName) { 67 | # Get a list of baseline objects assigned to the remote computer 68 | $Baselines = Get-WmiObject -ComputerName $Computer -Namespace root\ccm\dcm -Class SMS_DesiredConfiguration 69 | 70 | # For each (%) baseline object, call SMS_DesiredConfiguration.TriggerEvaluation, passing in the Name and Version as params 71 | foreach ($Baseline in $Baselines) { 72 | if ($Baseline.LastEvalTime -eq '00000000000000.000000+000') { 73 | $LastEvalTime = 'N/A' 74 | } 75 | else { 76 | $LastEvalTime = $Baseline.ConvertToDateTime($Baseline.LastEvalTime) 77 | } 78 | $BaselineStatusProperties = [ordered]@{ 79 | ComputerName = $Baseline.PSComputerName 80 | BaselineName = $Baseline.DisplayName 81 | Version = $Baseline.Version 82 | EvaluationStatus = $EvalHash[$Baseline.Status.tostring()] 83 | Compliance = $ComplianceHash[$Baseline.LastComplianceStatus.tostring()] 84 | LastEvaluationTime = $LastEvalTime 85 | } 86 | $BaselineStatus = New-Object -TypeName pscustomobject -Property $BaselineStatusProperties 87 | $BaselineStatus 88 | } 89 | } 90 | } 91 | end {} 92 | 93 | } -------------------------------------------------------------------------------- /Get-CMClientCache.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Get the cache content on SCCM clients. 4 | 5 | .DESCRIPTION 6 | Get the cache content on SCCM clients using the COM object. 7 | 8 | .PARAMETER ComputerName 9 | Enter a computer name 10 | 11 | .PARAMETER CacheAgeinDays 12 | Enter a number in days of the last time cache was referenced. 13 | 14 | .EXAMPLE 15 | Get-CMClientCache -ComputerName DESKTOP01 16 | 17 | Gets all SCCM client cache content 18 | 19 | .EXAMPLE 20 | Get-CMClientCache -ComputerName DESKTOP01,DESKETOP01 -CacheAgeinDays 30 21 | 22 | Gets all SCCM client cache content that hasn't been referenced in 30 days. 23 | .NOTES 24 | General notes 25 | #> 26 | #requires -RunAsAdministrator 27 | function Get-CMClientCache { 28 | [CmdletBinding()] 29 | param ( 30 | [string[]]$ComputerName = $env:COMPUTERNAME, 31 | [int]$CacheAgeinDays = 0 32 | ) 33 | 34 | begin { 35 | function Get-ClientCache { 36 | param ( 37 | [int]$CacheAgeinDays, 38 | [bool]$WhatIf 39 | ) 40 | $VerbosePreference = 'Continue' 41 | Write-Verbose "Beginning gathering of SCCM Cache older than $CacheAgeinDays days" 42 | $UIResourceMgr = New-Object -ComObject UIResource.UIResourceMgr 43 | $Cache = $UIResourceMgr.GetCacheInfo() 44 | $CacheElements = $Cache.GetCacheElements() | Where-Object -FilterScript {$_.LastReferenceTime -lt (Get-Date).AddDays( - $CacheAgeInDays)} 45 | if ($CacheElements) { 46 | if ($CacheElements.Count) { 47 | Write-Verbose -Message "Found $($CacheElements.Count) cache elements on $($env:COMPUTERNAME)." 48 | } 49 | else { 50 | Write-Verbose -Message "Found a cache element on $($env:COMPUTERNAME)." 51 | } 52 | 53 | foreach ($Element in $CacheElements) { 54 | Write-Verbose "CacheElement with PackageID $($Element.ContentID) with location $($Element.Location)" 55 | Write-Output $Element 56 | 57 | } 58 | } 59 | else { 60 | Write-Verbose -Message "No cache elements found on $($env:COMPUTERNAME)" 61 | } 62 | } 63 | } 64 | 65 | process { 66 | 67 | foreach ($Computer in $ComputerName) { 68 | Write-Verbose -Message "Attempting to get SCCM client cache on $Computer older than $CacheAgeinDays days" 69 | Invoke-Command -ComputerName $Computer -ScriptBlock ${function:Get-ClientCache} -ArgumentList $CacheAgeinDays 70 | } 71 | } 72 | 73 | end { 74 | } 75 | } -------------------------------------------------------------------------------- /Get-CMClientComputerByLoggedOnUser.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Get a list of computers where a specified user has last logged on. 4 | 5 | .DESCRIPTION 6 | This function performs a WMI SQL query against the SCCM database to determine to 7 | which computers a specified user account has last logged. 8 | 9 | .PARAMETER UserName 10 | Provide a username. 11 | 12 | .PARAMETER SiteServer 13 | Specify the name or FQDN of your SCCM site server. By default it gathers the site server 14 | from the computer from which the function is called. 15 | 16 | .PARAMETER SiteCode 17 | Specify the site code of your SCCM environment. By default it gathers the site code 18 | from the computer from which the function is called. 19 | 20 | .PARAMETER Credential 21 | Provide a credential object for accessing the site server. 22 | 23 | .EXAMPLE 24 | Get-CMClientComputerByLoggedOnUser -Username jsmith 25 | 26 | Get the list of computers where jsmith last logged on. 27 | 28 | .NOTES 29 | Created by: Jason Wasser @wasserja 30 | Modified: 7/5/2017 01:13:57 PM 31 | #> 32 | function Get-CMClientComputerByLoggedOnUser { 33 | [CmdletBinding()] 34 | param ( 35 | [Parameter(Mandatory = $true)] 36 | [Alias('SamAccountName')] 37 | [string]$UserName, 38 | [string]$SiteServer = (Get-WmiObject -Namespace root\ccm -ClassName SMS_Authority).CurrentManagementPoint, 39 | [string]$SiteCode = (Get-WmiObject -Namespace root\ccm -ClassName SMS_Authority).Name.Split(':')[1], 40 | [System.Management.Automation.PSCredential]$Credential = [System.Management.Automation.PSCredential]::Empty 41 | ) 42 | 43 | begin {} 44 | process { 45 | foreach ($User in $UserName) { 46 | Write-Verbose -Message "Gathering computers from where $User last logged on from Site Server $SiteServer using Site Code $SiteCode." 47 | $Query = "SELECT SMS_R_System.LastLogonUserName, SMS_R_System.Name, SMS_R_System.LastLogonTimestamp from SMS_R_System where LastLogonUserName='$User'" 48 | $Computers = Get-WmiObject -ComputerName $SiteServer -Namespace root/SMS/site_$SiteCode -Credential $Credential -Query $Query 49 | if ($Computers) { 50 | Write-Verbose 'Query has results.' 51 | foreach ($Computer in $Computers) { 52 | Write-Verbose -Message "Username: $($Computer.LastLogonUsername)" 53 | Write-Verbose -Message "Computer: $($Computer.Name)" 54 | Write-Verbose -Message "LastLogonTimeStamp: $($Computer.LastLogonTimeStamp)" 55 | $ComputerByLoggedOnUserProperties = [ordered]@{ 56 | 'Username' = $Computer.LastLogonUserName 57 | 'ComputerName' = $Computer.Name 58 | 'LastLogonTimeStamp' = [datetime]::ParseExact($Computer.LastLogonTimeStamp.Split('.')[0],'yyyyMMddHHmmss',[System.Globalization.CultureInfo]::InvariantCulture) 59 | } 60 | $ComputerByLoggedOnUser = New-Object -TypeName PSCustomObject -Property $ComputerByLoggedOnUserProperties 61 | $ComputerByLoggedOnUser 62 | } 63 | 64 | } 65 | else { 66 | Write-Verbose -Message "No computers found for user $User" 67 | } 68 | } 69 | } 70 | end {} 71 | } -------------------------------------------------------------------------------- /Get-CMClientDeviceCollectionMembership.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Get the collection membership of a configuration manager client device or computer. 4 | 5 | .DESCRIPTION 6 | Get the collection membership of a configuration manager client device or computer. 7 | This function will query System Center Configuration manager for a given computer name 8 | and return the collections for which it is a member. 9 | 10 | .PARAMETER ComputerName 11 | Provide a computer name. 12 | 13 | .PARAMETER SiteServer 14 | Specify the name or FQDN of your SCCM site server. By default it gathers the site server 15 | from the computer from which the function is called. 16 | 17 | .PARAMETER SiteCode 18 | Specify the site code of your SCCM environment. By default it gathers the site code 19 | from the computer from which the function is called. 20 | 21 | .PARAMETER Credential 22 | Provide a credential object for accessing the site server. 23 | 24 | .EXAMPLE 25 | Get-CMClientDeviceCollectionMembership 26 | 27 | Gets the collection membership of the local host. 28 | 29 | .EXAMPLE 30 | Get-CMClientDeviceCollectionMembership -Computer DESKTOP01 31 | 32 | Gets the collection membership of DESKTOP01 33 | 34 | .EXAMPLE 35 | Get-CMClientDeviceCollectionMembership -Computer DESKTOP01 -Summary 36 | 37 | Gets the collection membership of DESKTOP01 in a summary format. 38 | 39 | .NOTES 40 | Created by: Jason Wasser @wasserja 41 | Modified: 6/8/2017 10:49:50 AM 42 | #> 43 | function Get-CMClientDeviceCollectionMembership { 44 | [CmdletBinding()] 45 | param ( 46 | [string]$ComputerName = $env:COMPUTERNAME, 47 | [string]$SiteServer = (Get-WmiObject -Namespace root\ccm -ClassName SMS_Authority).CurrentManagementPoint, 48 | [string]$SiteCode = (Get-WmiObject -Namespace root\ccm -ClassName SMS_Authority).Name.Split(':')[1], 49 | [switch]$Summary, 50 | [System.Management.Automation.PSCredential]$Credential = [System.Management.Automation.PSCredential]::Empty 51 | ) 52 | 53 | begin {} 54 | process { 55 | Write-Verbose -Message "Gathering collection membership of $ComputerName from Site Server $SiteServer using Site Code $SiteCode." 56 | $Collections = Get-WmiObject -ComputerName $SiteServer -Namespace root/SMS/site_$SiteCode -Credential $Credential -Query "SELECT SMS_Collection.* FROM SMS_FullCollectionMembership, SMS_Collection where name = '$ComputerName' and SMS_FullCollectionMembership.CollectionID = SMS_Collection.CollectionID" 57 | if ($Summary) { 58 | $Collections | Select-Object -Property Name,CollectionID 59 | } 60 | else { 61 | $Collections 62 | } 63 | 64 | } 65 | end {} 66 | } -------------------------------------------------------------------------------- /Get-CMClientPackage.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | This function gets a list of advertised packages for a SCCM client. 4 | .DESCRIPTION 5 | This function gets a list of advertised packages for a SCCM client. 6 | .PARAMETER Computername 7 | Enter a name of a computer or list of computers. 8 | .PARAMETER Details 9 | Outputs the full WMI object rather than just a summary. 10 | .EXAMPLE 11 | PS C:\> Get-CMClientPackage -Computername 'SERVER01' 12 | .EXAMPLE 13 | PS C:\> Get-CMClientPackage -Computername 'SERVER01' -Details 14 | .NOTES 15 | Created by: Jason Wasser @wasserja 16 | #> 17 | function Get-CMClientPackage { 18 | [CmdletBinding()] 19 | param ( 20 | [Parameter(Mandatory = $true, 21 | ValueFromPipeline = $true, 22 | ValueFromPipelineByPropertyName = $true)] 23 | [string[]]$ComputerName, 24 | [switch]$Details 25 | ) 26 | 27 | begin {} 28 | process { 29 | 30 | foreach ($Computer in $ComputerName) { 31 | Write-Verbose -Message "Checking for advertised packages on $Computer" 32 | if ($Computer -eq $env:COMPUTERNAME) { 33 | $SccmPackages = Get-WmiObject -Namespace 'ROOT\ccm\SoftMgmtAgent' -Class CCM_ExecutionRequestEx 34 | } 35 | else { 36 | $SccmPackages = Get-WmiObject -Namespace 'ROOT\ccm\SoftMgmtAgent' -Class CCM_ExecutionRequestEx -ComputerName $Computer 37 | } 38 | if ($Details) { 39 | $SccmPackages 40 | } 41 | else { 42 | $SccmPackages | Select-Object -Property PSComputerName,ProgramID,ContentID,State,@{label='ReceivedTime';expression={$_.ConvertToDateTime($_.ReceivedTime)}} 43 | } 44 | } 45 | } 46 | end {} 47 | } 48 | -------------------------------------------------------------------------------- /Get-CMClientPendingUpdates.ps1: -------------------------------------------------------------------------------- 1 | #region Get-CMClientPendingUpdates 2 | <# 3 | .SYNOPSIS 4 | This function gets a list of pending software updates for a SCCM client. 5 | .DESCRIPTION 6 | 7 | .PARAMETER Computername 8 | The name of the system you'd like to invoke the action on 9 | .EXAMPLE 10 | PS C:\> Get-CMClientPendingUpdates -Computername 'SERVER01' 11 | .EXAMPLE 12 | PS C:\> Get-CMClientPendingUpdates -Computername 'SERVER01' -Summary 13 | .NOTES 14 | 15 | #> 16 | function Get-CMClientPendingUpdates { 17 | [CmdletBinding()] 18 | param ( 19 | [Parameter(Mandatory = $true, 20 | ValueFromPipeline = $true, 21 | ValueFromPipelineByPropertyName = $true)] 22 | [string[]]$ComputerName = $env:COMPUTERNAME, 23 | [switch]$Summary 24 | ) 25 | 26 | begin {} 27 | process { 28 | 29 | foreach ($Computer in $ComputerName) { 30 | if ($Computer -eq $env:COMPUTERNAME) { 31 | $SccmPendingUpdates = Get-WmiObject -Namespace root\ccm\clientsdk -Class CCM_SoftwareUpdate 32 | } 33 | else { 34 | $SccmPendingUpdates = Get-WmiObject -Namespace root\ccm\clientsdk -Class CCM_SoftwareUpdate -ComputerName $Computer 35 | } 36 | if ($Summary) { 37 | $SccmPendingUpdates | Select-Object -Property PSComputerName,ArticleID,@{label=’Deadline’;expression={$_.ConvertToDateTime($_.Deadline)}},Name 38 | } 39 | else { 40 | $SccmPendingUpdates 41 | } 42 | } 43 | } 44 | end {} 45 | } 46 | #endregion 47 | -------------------------------------------------------------------------------- /Get-CMClientUpdates.ps1: -------------------------------------------------------------------------------- 1 | #region Get-CMClientUpdates 2 | <# 3 | .SYNOPSIS 4 | This function gets a list of software updates for a SCCM client. 5 | .DESCRIPTION 6 | 7 | .PARAMETER Computername 8 | The name of the system you'd like to invoke the action on 9 | .EXAMPLE 10 | PS C:\> Get-CMClientUpdates -Computername 'SERVER01' 11 | .EXAMPLE 12 | PS C:\> Get-CMClientUpdates -Computername 'SERVER01' -Summary 13 | .NOTES 14 | 15 | #> 16 | function Get-CMClientUpdates { 17 | 18 | [CmdletBinding()] 19 | param ( 20 | [Parameter(Mandatory = $true, 21 | ValueFromPipeline = $true, 22 | ValueFromPipelineByPropertyName = $true)] 23 | [string[]]$ComputerName = $env:COMPUTERNAME, 24 | [switch]$Summary 25 | ) 26 | 27 | begin {} 28 | process { 29 | 30 | foreach ($Computer in $ComputerName) { 31 | if ($Computer -eq $env:COMPUTERNAME) { 32 | $SccmUpdates = Get-WmiObject -Namespace root\ccm\SoftwareUpdates\UpdatesStore -Class CCM_UpdateStatus 33 | } 34 | else { 35 | $SccmUpdates = Get-WmiObject -Namespace root\ccm\SoftwareUpdates\UpdatesStore -Class CCM_UpdateStatus -ComputerName $Computer 36 | } 37 | if ($Summary) { 38 | $SccmUpdates | Select-Object -Property PSComputerName,Article,@{label=’ScanTime’;expression={$_.ConvertToDateTime($_.ScanTime)}},Status,Title 39 | } 40 | else { 41 | $SccmUpdates 42 | } 43 | } 44 | } 45 | end {} 46 | } 47 | #endregion 48 | -------------------------------------------------------------------------------- /Get-CMClientVersion.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | This function gets the SCCM client version. 4 | .DESCRIPTION 5 | This function gets the SCCM client version. 6 | .PARAMETER Computername 7 | Enter a name of a computer or list of computers. 8 | .EXAMPLE 9 | Get-CMClientVersion -Computername 'SERVER01' 10 | .EXAMPLE 11 | Get-CMClienVersion -Computername 'SERVER01','WORKSTATION02' 12 | .NOTES 13 | Created by: Jason Wasser @wasserja 14 | #> 15 | function Get-CMClientVersion { 16 | [CmdletBinding()] 17 | param ( 18 | [Parameter(Mandatory = $false, 19 | ValueFromPipeline = $true, 20 | ValueFromPipelineByPropertyName = $true)] 21 | [string[]]$ComputerName = $env:COMPUTERNAME 22 | ) 23 | 24 | begin {} 25 | process { 26 | 27 | foreach ($Computer in $ComputerName) { 28 | Write-Verbose -Message "Checking SCCM Client version on $Computer" 29 | if ($Computer -eq $env:COMPUTERNAME) { 30 | $SccmClientVersion = Get-WmiObject -Namespace 'ROOT\ccm' -Class Ccm_InstalledComponent -Filter "Name = 'SmsClient'" 31 | } 32 | else { 33 | $SccmClientVersion = Get-WmiObject -Namespace 'ROOT\ccm' -Class Ccm_InstalledComponent -Filter "Name = 'SmsClient'" -ComputerName $Computer 34 | } 35 | $SccmClientVersion | Select-Object -Property PSComputerName, Version 36 | } 37 | } 38 | end {} 39 | } -------------------------------------------------------------------------------- /Invoke-CMClientAction.ps1: -------------------------------------------------------------------------------- 1 | #region Invoke-CMClientAction 2 | <# 3 | .SYNOPSIS 4 | This is a helper function that initiates many ConfigMgr client actions. 5 | .DESCRIPTION 6 | 7 | .PARAMETER Computername 8 | The system you'd like to initate the action on. 9 | .PARAMETER AsJob 10 | A switch parameter that initates a job in the background 11 | .PARAMETER ClientAction 12 | The client action to initiate. 13 | .EXAMPLE 14 | PS C:\> Invoke-CMClientAction -Computername 'Value1' -AsJob 15 | This example shows how to call the Invoke-CMClientAction function with named parameters. 16 | .NOTES 17 | #> 18 | function Invoke-CMClientAction { 19 | [CmdletBinding()] 20 | param 21 | ( 22 | [Parameter(Mandatory = $true, 23 | ValueFromPipelineByPropertyName=$true, 24 | Position=0)] 25 | [string]$Computername, 26 | [Parameter(Mandatory = $true)] 27 | [ValidateSet('MachinePolicy', 28 | 'DiscoveryData', 29 | 'ComplianceEvaluation', 30 | 'AppDeployment', 31 | 'HardwareInventory', 32 | 'UpdateDeployment', 33 | 'UpdateScan', 34 | 'SoftwareInventory')] 35 | [string]$ClientAction, 36 | [Parameter()] 37 | [switch]$AsJob 38 | ) 39 | 40 | Begin { 41 | 42 | try { 43 | $ScheduleIDMappings = @{ 44 | 'MachinePolicy' = '{00000000-0000-0000-0000-000000000021}'; 45 | 'DiscoveryData' = '{00000000-0000-0000-0000-000000000003}'; 46 | 'ComplianceEvaluation' = '{00000000-0000-0000-0000-000000000071}'; 47 | 'AppDeployment' = '{00000000-0000-0000-0000-000000000121}'; 48 | 'HardwareInventory' = '{00000000-0000-0000-0000-000000000001}'; 49 | 'UpdateDeployment' = '{00000000-0000-0000-0000-000000000108}'; 50 | 'UpdateScan' = '{00000000-0000-0000-0000-000000000113}'; 51 | 'SoftwareInventory' = '{00000000-0000-0000-0000-000000000002}'; 52 | } 53 | $ScheduleID = $ScheduleIDMappings[$ClientAction] 54 | } catch { 55 | Write-Error $_.Exception.Message 56 | } 57 | 58 | } 59 | Process { 60 | try { 61 | ## $args[0] represents the computername and $args[1] represents the scheduleID 62 | $ActionScriptBlock = { 63 | [void] ([wmiclass] "\\$($args[0])\root\ccm:SMS_Client").TriggerSchedule($args[1]); 64 | if (!$?) { 65 | throw "Failed to initiate a $ClientAction on $($args[0])" 66 | } 67 | } 68 | 69 | if ($AsJob.IsPresent) { 70 | $Params = @{ 71 | 'Computername' = $Computername; 72 | 'OriginatingFunction' = $ClientAction; 73 | 'ScriptBlock' = $ActionScriptBlock; 74 | 'ScheduleID' = $ScheduleID 75 | } 76 | Initialize-CMClientJob @Params 77 | } else { 78 | Write-Verbose "Initializing $ClientAction on $Computername." 79 | Invoke-Command -ScriptBlock $ActionScriptBlock -ArgumentList $Computername,$ScheduleID 80 | } 81 | } catch { 82 | Write-Error $_.Exception.Message 83 | } 84 | 85 | } 86 | End { 87 | 88 | } 89 | } 90 | #endregion -------------------------------------------------------------------------------- /Invoke-CMClientAdvancedFunctions.ps1: -------------------------------------------------------------------------------- 1 | ## Modify these function as advanced functions 2 | <# 3 | Function Set-CMClientBusinessHours ($ComputerName, $StartTime = 3, $EndTime = 7, $WorkingDays) { 4 | ## The first digit is the start time (7am), the second digit is the end time (7pm) and the third digit is the days of the week. 5 | ## The days of the week are calculated using the table below, so Monday – Friday is calculated as 2+4+8+16+32 = 62. 6 | ## Sunday - 1, Monday - 2, Tuesday - 4, Wednesday - 8, Thursday - 16, Friday - 32, Saturday - 64 7 | 8 | try { 9 | Write-Debug "Initiating the $($MyInvocation.MyCommand.Name) function..."; 10 | 11 | $cmClientUserSettings = [WmiClass]"\\$ComputerName\ROOT\ccm\ClientSDK:CCM_ClientUXSettings" 12 | $businessHours = $cmClientUserSettings.PSBase.GetMethodParameters("SetBusinessHours") 13 | $businessHours.StartTime = $StartTime 14 | $businessHours.EndTime = $EndTime 15 | $businessHours.WorkingDays = $WorkingDays 16 | 17 | $result = $cmClientUserSettings.PSBase.InvokeMethod("SetBusinessHours", $businessHours, $Null) 18 | 19 | if ($result.ReturnValue -eq 0) { 20 | $mResult = $true 21 | } else { 22 | $mResult = $false; 23 | } 24 | 25 | return $mResult 26 | 27 | } catch [System.Exception] { 28 | Write-Error $_.Exception.Message; 29 | }##endtry 30 | }##endfunction 31 | 32 | Function Get-CMClientBusinessHours ($ComputerName) { 33 | ## The first digit is the start time (7am), the second digit is the end time (7pm) and the third digit is the days of the week. 34 | ## The days of the week are calculated using the table below, so Monday – Friday is calculated as 2+4+8+16+32 = 62. 35 | ## Sunday - 1, Monday - 2, Tuesday - 4, Wednesday - 8, Thursday - 16, Friday - 32, Saturday - 64 36 | 37 | try { 38 | Write-Debug "Initiating the $($MyInvocation.MyCommand.Name) function..."; 39 | 40 | $cmClientUserSettings = [WmiClass]"\\$ComputerName\ROOT\ccm\ClientSDK:CCM_ClientUXSettings" 41 | $businessHours = $cmClientUserSettings.GetBusinessHours() 42 | $businessHoursCI = [string]$businessHours.StartTime + "," + [string]$businessHours.EndTime + "," + [string]$businessHours.WorkingDays 43 | 44 | return $businessHoursCI 45 | 46 | } catch [System.Exception] { 47 | Write-Error $_.Exception.Message; 48 | }##endtry 49 | }##endfunction 50 | 51 | Function Disable-CMClientBusinessHours ($ComputerName) { 52 | try { 53 | ## Change the "automatic install or uninstall required software and restart the computer only outside of the specified business hours 54 | 55 | return $mResult 56 | 57 | } catch [System.Exception] { 58 | Write-Error $_.Exception.Message; 59 | }##endtry 60 | }##endfunction 61 | 62 | Function Get-SccmApplicationState ($ComputerName,$Name = $null,[switch]$IncludeDetails) { 63 | try { 64 | Write-Debug "Initiating the $($MyInvocation.MyCommand.Name) function..."; 65 | 66 | $eval_states = @{0 = 'No state information is available'; 67 | 1 = 'Application is enforced to desired/resolved state'; 68 | 2 = 'Application is not required on the client'; 69 | 3 = 'Application is available for enforcement (install or uninstall based on resolved state). Content may/may not have been downloaded'; 70 | 4 = 'Application last failed to enforce (install/uninstall)'; 71 | 5 = 'Application is currently waiting for content download to complete'; 72 | 6 = 'Application is currently waiting for content download to complete'; 73 | 7 = 'Application is currently waiting for its dependencies to download'; 74 | 8 = 'Application is currently waiting for a service (maintenance) window'; 75 | 9 = 'Application is currently waiting for a previously pending reboot'; 76 | 10 = 'Application is currently waiting for serialized enforcement'; 77 | 11 = 'Application is currently enforcing dependencies'; 78 | 12 = 'Application is currently enforcing'; 79 | 13 = 'Application install/uninstall enforced and soft reboot is pending'; 80 | 14 = 'Application installed/uninstalled and hard reboot is pending'; 81 | 15 = 'Update is available but pending installation'; 82 | 16 = 'Application failed to evaluate'; 83 | 17 = 'Application is currently waiting for an active user session to enforce'; 84 | 18 = 'Application is currently waiting for all users to logoff'; 85 | 19 = 'Application is currently waiting for a user logon'; 86 | 20 = 'Application in progress, waiting for retry'; 87 | 21 = 'Application is waiting for presentation mode to be switched off'; 88 | 22 = 'Application is pre-downloading content (downloading outside of install job)'; 89 | 23 = 'Application is pre-downloading dependent content (downloading outside of install job)'; 90 | 24 = 'Application download failed (downloading during install job)'; 91 | 25 = 'Application pre-downloading failed (downloading outside of install job)'; 92 | 26 = 'Download success (downloading during install job)'; 93 | 27 = 'Post-enforce evaluation'; 94 | 28 = 'Waiting for network connectivity'; 95 | } 96 | 97 | if ($Name -and $IncludeDetails.IsPresent) { 98 | $aApps = Request-Wmi -ComputerName $ComputerName -Namespace 'root\ccm\clientsdk' -Query "SELECT * FROM CCM_Application WHERE FullName = '$Name'" 99 | } elseif ($Name -and !$IncludeDetails.IsPresent) { 100 | $aApps = Request-Wmi -ComputerName $ComputerName -Namespace 'root\ccm\clientsdk' -Query "SELECT * FROM CCM_Application WHERE FullName = '$Name'" | Select-Object PSComputerName,FullName,InstallState,ErrorCode,EvaluationState,@{label='StartTime';expression={$_.ConvertToDateTime($_.StartTime)}} 101 | } elseif (!$Name -and $IncludeDetails.IsPresent) { 102 | $aApps = Request-Wmi -ComputerName $ComputerName -Namespace 'root\ccm\clientsdk' -Query "SELECT * FROM CCM_Application" 103 | } elseif (!$Name -and !$IncludeDetails.IsPresent) { 104 | $aApps = Request-Wmi -ComputerName $ComputerName -Namespace 'root\ccm\clientsdk' -Query "SELECT * FROM CCM_Application" | Select-Object PSComputerName,FullName,InstallState,ErrorCode,EvaluationState,@{label='StartTime';expression={$_.ConvertToDateTime($_.StartTime)}} 105 | } 106 | 107 | if (!$aApps) { 108 | $mResult = "$($MyInvocation.MyCommand.Name): WMI query failed"; 109 | } else { 110 | $mResult = $aApps | Sort-Object FullName; 111 | }##endif 112 | 113 | return $mResult; 114 | 115 | } catch [System.Exception] { 116 | Write-Error $_.Exception.Message; 117 | }##endtry 118 | }##endfunction 119 | 120 | Function Get-CMClientUpdateDeploymentState() { 121 | 122 | } 123 | #> -------------------------------------------------------------------------------- /Invoke-CMClientApplicationDeploymentEvaluation.ps1: -------------------------------------------------------------------------------- 1 | #region Invoke-CMClientApplicationDeploymentEvaluation 2 | <# 3 | .SYNOPSIS 4 | This function invokes an application deployment eval on a ConfigMgr client 5 | .DESCRIPTION 6 | 7 | .PARAMETER Computername 8 | The name of the system you'd like to invoke the action on 9 | .PARAMETER AsJob 10 | Specify this parameter if you'd like to run this as a background job. 11 | .EXAMPLE 12 | PS C:\> Invoke-CMClientApplicationDeploymentEvaluation -Computername 'Value1' -AsJob 13 | .NOTES 14 | 15 | #> 16 | function Invoke-CMClientApplicationDeploymentEvaluation { 17 | [CmdletBinding()] 18 | param 19 | ( 20 | [Parameter(Mandatory = $true, 21 | ValueFromPipeline = $true, 22 | ValueFromPipelineByPropertyName = $true)] 23 | [string[]]$Computername, 24 | [Parameter()] 25 | [switch]$AsJob 26 | ) 27 | 28 | Begin { 29 | 30 | } 31 | Process { 32 | foreach ($Computer in $Computername) { 33 | $Params = @{ 34 | 'Computername' = $Computer; 35 | 'ClientAction' = 'AppDeployment'; 36 | 'AsJob' = $AsJob.IsPresent 37 | } 38 | Invoke-CMClientAction @Params 39 | } 40 | } 41 | End { 42 | 43 | } 44 | } 45 | #endregion -------------------------------------------------------------------------------- /Invoke-CMClientBaselineEvaluation.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Initiate the evaluation of Configuration Manager client configuration baselines. 4 | 5 | .DESCRIPTION 6 | Initiate the evaluation of Configuration Manager client configuration baselines. 7 | 8 | .NOTES 9 | Created by: Jason Wasser @wasserja 10 | Modified: 5/17/2017 04:09:20 PM 11 | 12 | .EXAMPLE 13 | Invoke-CMClientBaselineEvaluation 14 | 15 | __GENUS : 1 16 | __CLASS : __PARAMETERS 17 | __SUPERCLASS : 18 | __DYNASTY : __PARAMETERS 19 | __RELPATH : __PARAMETERS 20 | __PROPERTY_COUNT : 2 21 | __DERIVATION : {} 22 | __SERVER : SERVER01 23 | __NAMESPACE : ROOT\ccm\dcm 24 | __PATH : \\SERVER01\ROOT\ccm\dcm:__PARAMETERS 25 | JobId : {70CC8CE2-1349-4B2A-9D6C-030DE174D269} 26 | ReturnValue : 0 27 | PSComputerName : SERVER01 28 | 29 | .EXAMPLE 30 | Invoke-CMClientBaselineEvaluation -ComputerName SERVER01,SERVER02 31 | 32 | __GENUS : 1 33 | __CLASS : __PARAMETERS 34 | __SUPERCLASS : 35 | __DYNASTY : __PARAMETERS 36 | __RELPATH : __PARAMETERS 37 | __PROPERTY_COUNT : 2 38 | __DERIVATION : {} 39 | __SERVER : SERVER01 40 | __NAMESPACE : ROOT\ccm\dcm 41 | __PATH : \\SERVER01\ROOT\ccm\dcm:__PARAMETERS 42 | JobId : {70CC8CE2-1349-4B2A-9D6C-030DE174D269} 43 | ReturnValue : 0 44 | PSComputerName : SERVER01 45 | 46 | __GENUS : 1 47 | __CLASS : __PARAMETERS 48 | __SUPERCLASS : 49 | __DYNASTY : __PARAMETERS 50 | __RELPATH : __PARAMETERS 51 | __PROPERTY_COUNT : 2 52 | __DERIVATION : {} 53 | __SERVER : SERVER02 54 | __NAMESPACE : ROOT\ccm\dcm 55 | __PATH : \\SERVER02\ROOT\ccm\dcm:__PARAMETERS 56 | JobId : {1D92D42D-B1B4-4256-B8AE-24F7CC382578} 57 | ReturnValue : 0 58 | PSComputerName : SERVER02 59 | 60 | #> 61 | function Invoke-CMClientBaselineEvaluation 62 | { 63 | [CmdletBinding()] 64 | param ( 65 | [Parameter(Mandatory=$false, 66 | ValueFromPipelineByPropertyName=$true, 67 | ValueFromPipeline=$true, 68 | Position=0)] 69 | [string[]]$ComputerName=$env:COMPUTERNAME 70 | ) 71 | begin {} 72 | process { 73 | foreach ($Computer in $ComputerName) { 74 | # Get a list of baseline objects assigned to the remote computer 75 | $Baselines = Get-WmiObject -ComputerName $Computer -Namespace root\ccm\dcm -Class SMS_DesiredConfiguration 76 | 77 | # For each (%) baseline object, call SMS_DesiredConfiguration.TriggerEvaluation, passing in the Name and Version as params 78 | $Baselines | foreach { ([wmiclass]"\\$Computer\root\ccm\dcm:SMS_DesiredConfiguration").TriggerEvaluation($_.Name, $_.Version) } 79 | } 80 | } 81 | end {} 82 | 83 | } -------------------------------------------------------------------------------- /Invoke-CMClientComplianceEvaluation.ps1: -------------------------------------------------------------------------------- 1 | #region Invoke-CMClientComplianceEvaluation 2 | <# 3 | .SYNOPSIS 4 | This function invokes a compliance evaluation on a ConfigMgr client 5 | .DESCRIPTION 6 | 7 | .PARAMETER Computername 8 | The name of the system you'd like to invoke the action on 9 | .PARAMETER AsJob 10 | Specify this parameter if you'd like to run this as a background job. 11 | .EXAMPLE 12 | PS C:\> Invoke-CMClientComplianceEvaluation -Computername 'Value1' -AsJob 13 | .NOTES 14 | 15 | #> 16 | function Invoke-CMClientComplianceEvaluation { 17 | [CmdletBinding()] 18 | param 19 | ( 20 | [Parameter(Mandatory = $true, 21 | ValueFromPipeline = $true, 22 | ValueFromPipelineByPropertyName = $true)] 23 | [string[]]$Computername, 24 | [Parameter()] 25 | [switch]$AsJob 26 | ) 27 | 28 | Begin { 29 | 30 | } 31 | Process { 32 | foreach ($Computer in $Computername) { 33 | $Params = @{ 34 | 'Computername' = $Computer; 35 | 'ClientAction' = 'ComplianceEvaluation'; 36 | 'AsJob' = $AsJob.IsPresent 37 | } 38 | Invoke-CMClientAction @Params 39 | } 40 | } 41 | End { 42 | 43 | } 44 | } 45 | #endregion -------------------------------------------------------------------------------- /Invoke-CMClientDiscoveryDataCycle.ps1: -------------------------------------------------------------------------------- 1 | #region Invoke-CMClientDiscoveryDataCycle 2 | <# 3 | .SYNOPSIS 4 | This function invokes a DDR cycle on a ConfigMgr client 5 | .DESCRIPTION 6 | 7 | .PARAMETER Computername 8 | The name of the system you'd like to invoke the action on 9 | .PARAMETER AsJob 10 | Specify this parameter if you'd like to run this as a background job. 11 | .EXAMPLE 12 | PS C:\> Invoke-CMClientDiscoveryDataCycle -Computername 'Value1' -AsJob 13 | .NOTES 14 | 15 | #> 16 | function Invoke-CMClientDiscoveryDataCycle { 17 | [CmdletBinding()] 18 | param 19 | ( 20 | [Parameter(Mandatory = $true, 21 | ValueFromPipeline = $true, 22 | ValueFromPipelineByPropertyName = $true)] 23 | [string[]]$Computername, 24 | [Parameter()] 25 | [switch]$AsJob 26 | ) 27 | 28 | Begin { 29 | 30 | } 31 | Process { 32 | foreach ($Computer in $Computername) { 33 | $Params = @{ 34 | 'Computername' = $Computer; 35 | 'ClientAction' = 'DiscoveryData'; 36 | 'AsJob' = $AsJob.IsPresent 37 | } 38 | Invoke-CMClientAction @Params 39 | } 40 | } 41 | End { 42 | 43 | } 44 | } 45 | #endregion -------------------------------------------------------------------------------- /Invoke-CMClientHardwareInventory.ps1: -------------------------------------------------------------------------------- 1 | #region Invoke-CMClientHardwareInventory 2 | <# 3 | .SYNOPSIS 4 | This function invokes a hardware inventory cycle on a ConfigMgr client 5 | .DESCRIPTION 6 | 7 | .PARAMETER Computername 8 | The name of the system you'd like to invoke the action on 9 | .PARAMETER AsJob 10 | Specify this parameter if you'd like to run this as a background job. 11 | .EXAMPLE 12 | PS C:\> Invoke-CMClientHardwareInventory -Computername 'Value1' -AsJob 13 | .NOTES 14 | 15 | #> 16 | function Invoke-CMClientHardwareInventory { 17 | [CmdletBinding()] 18 | param 19 | ( 20 | [Parameter(Mandatory = $true, 21 | ValueFromPipeline = $true, 22 | ValueFromPipelineByPropertyName = $true)] 23 | [string[]]$Computername, 24 | [Parameter()] 25 | [switch]$AsJob 26 | ) 27 | 28 | Begin { 29 | 30 | } 31 | Process { 32 | foreach ($Computer in $Computername) { 33 | $Params = @{ 34 | 'Computername' = $Computer; 35 | 'ClientAction' = 'HardwareInventory'; 36 | 'AsJob' = $AsJob.IsPresent 37 | } 38 | Invoke-CMClientAction @Params 39 | } 40 | } 41 | End { 42 | 43 | } 44 | } 45 | #endregion -------------------------------------------------------------------------------- /Invoke-CMClientJob.ps1: -------------------------------------------------------------------------------- 1 | #region Initialize-CMClientJob 2 | <# 3 | .SYNOPSIS 4 | This is a helper function that starts and manages background jobs for the all 5 | functions in this module. 6 | .DESCRIPTION 7 | 8 | .PARAMETER OriginatingFunction 9 | The function where the job request came from. This is used to keep track of 10 | which background jobs were started by which function. 11 | .PARAMETER ScriptBlock 12 | This is the scriptblock that is passed to the system. 13 | .PARAMETER Computername 14 | The computer name that the function is connecting to. This is used to keep track 15 | of the functions initiated on computers. 16 | .PARAMETER ScheduleID 17 | This is the schedule ID to designate which client action to initiate. This is needed 18 | because it has to be sent to the background job scriptblock. 19 | .EXAMPLE 20 | 21 | .NOTES 22 | #> 23 | function Initialize-CMClientJob { 24 | [CmdletBinding()] 25 | param 26 | ( 27 | [Parameter(Mandatory = $true)] 28 | [string]$OriginatingFunction, 29 | [Parameter(Mandatory = $true)] 30 | [scriptblock]$ScriptBlock, 31 | [Parameter(Mandatory = $true)] 32 | [string]$Computername, 33 | [Parameter(Mandatory = $true)] 34 | [string]$ScheduleID 35 | ) 36 | 37 | Begin { 38 | ## The total number of jobs that can be concurrently running 39 | $MaxJobThreads = 75 40 | ## How long to wait when the max job threads has been met to start another job 41 | $JobWaitSecs = 1 42 | } 43 | Process { 44 | try { 45 | Write-Verbose "Starting job `"$ComputerName - $OriginatingFunction`"..." 46 | Start-Job -ScriptBlock $ScriptBlock -Name "$ComputerName - $OriginatingFunction" -ArgumentList $Computername, $ScheduleID | Out-Null 47 | While ((Get-Job -state running).count -ge $MaxJobThreads) { 48 | Write-Verbose "Maximum job threshold has been met. Waiting $JobWaitSecs second(s) to try again..."; 49 | Start-Sleep -Seconds $JobWaitSecs 50 | } 51 | } catch { 52 | Write-Error $_.Exception.Message 53 | } 54 | } 55 | End { 56 | 57 | } 58 | } 59 | #endregion -------------------------------------------------------------------------------- /Invoke-CMClientMachinePolicyDownload.ps1: -------------------------------------------------------------------------------- 1 | #region Invoke-CMClientMachinePolicyDownload 2 | <# 3 | .SYNOPSIS 4 | This function invokes a machine policy download on a ConfigMgr client 5 | .DESCRIPTION 6 | 7 | .PARAMETER Computername 8 | The name of the system you'd like to invoke the machine policy download on 9 | .PARAMETER AsJob 10 | Specify this parameter if you'd like to run this as a background job. 11 | .EXAMPLE 12 | PS C:\> Invoke-CMClientMachinePolicyDownload -Computername 'Value1' -AsJob 13 | .NOTES 14 | 15 | #> 16 | function Invoke-CMClientMachinePolicyDownload { 17 | [CmdletBinding()] 18 | param 19 | ( 20 | [Parameter(Mandatory = $true, 21 | ValueFromPipeline = $true, 22 | ValueFromPipelineByPropertyName = $true)] 23 | [alias('Name')] 24 | [string[]]$Computername, 25 | [Parameter()] 26 | [switch]$AsJob 27 | ) 28 | 29 | Begin { 30 | 31 | } 32 | Process { 33 | foreach ($Computer in $Computername) { 34 | $Params = @{ 35 | 'Computername' = $Computer; 36 | 'ClientAction' = 'MachinePolicy'; 37 | 'AsJob' = $AsJob.IsPresent 38 | } 39 | Invoke-CMClientAction @Params 40 | } 41 | } 42 | End { 43 | 44 | } 45 | } 46 | #endregion -------------------------------------------------------------------------------- /Invoke-CMClientSoftwareInventory.ps1: -------------------------------------------------------------------------------- 1 | #region Invoke-CMClientSoftwareInventory 2 | <# 3 | .SYNOPSIS 4 | This function invokes a software inventory scan on a ConfigMgr client 5 | .DESCRIPTION 6 | 7 | .PARAMETER Computername 8 | The name of the system you'd like to invoke the action on 9 | .PARAMETER AsJob 10 | Specify this parameter if you'd like to run this as a background job. 11 | .EXAMPLE 12 | PS C:\> Invoke-CMClientSoftwareInventory -Computername 'Value1' -AsJob 13 | .NOTES 14 | 15 | #> 16 | function Invoke-CMClientSoftwareInventory { 17 | [CmdletBinding()] 18 | param 19 | ( 20 | [Parameter(Mandatory = $true, 21 | ValueFromPipeline = $true, 22 | ValueFromPipelineByPropertyName = $true)] 23 | [string[]]$Computername, 24 | [Parameter()] 25 | [switch]$AsJob 26 | ) 27 | 28 | Begin { 29 | 30 | } 31 | Process { 32 | foreach ($Computer in $Computername) { 33 | $Params = @{ 34 | 'Computername' = $Computer; 35 | 'ClientAction' = 'SoftwareInventory'; 36 | 'AsJob' = $AsJob.IsPresent 37 | } 38 | Invoke-CMClientAction @Params 39 | } 40 | } 41 | End { 42 | 43 | } 44 | } 45 | #endregion -------------------------------------------------------------------------------- /Invoke-CMClientUpdateDeploymentEvaluation.ps1: -------------------------------------------------------------------------------- 1 | #region Invoke-CMClientUpdateDeploymentEvaluation 2 | <# 3 | .SYNOPSIS 4 | This function invokes an update deployment eval on a ConfigMgr client 5 | .DESCRIPTION 6 | 7 | .PARAMETER Computername 8 | The name of the system you'd like to invoke the action on 9 | .PARAMETER AsJob 10 | Specify this parameter if you'd like to run this as a background job. 11 | .EXAMPLE 12 | PS C:\> Invoke-CMClientUpdateDeploymentEvaluation -Computername 'Value1' -AsJob 13 | .NOTES 14 | 15 | #> 16 | function Invoke-CMClientUpdateDeploymentEvaluation { 17 | [CmdletBinding()] 18 | param 19 | ( 20 | [Parameter(Mandatory = $true, 21 | ValueFromPipeline = $true, 22 | ValueFromPipelineByPropertyName = $true)] 23 | [string[]]$Computername, 24 | [Parameter()] 25 | [switch]$AsJob 26 | ) 27 | 28 | Begin { 29 | 30 | } 31 | Process { 32 | foreach ($Computer in $Computername) { 33 | $Params = @{ 34 | 'Computername' = $Computer; 35 | 'ClientAction' = 'UpdateDeployment'; 36 | 'AsJob' = $AsJob.IsPresent 37 | } 38 | Invoke-CMClientAction @Params 39 | } 40 | } 41 | End { 42 | 43 | } 44 | } 45 | #endregion -------------------------------------------------------------------------------- /Invoke-CMClientUpdateScan.ps1: -------------------------------------------------------------------------------- 1 | #region Invoke-CMClientUpdateScan 2 | <# 3 | .SYNOPSIS 4 | This function invokes an update scan eval on a ConfigMgr client 5 | .DESCRIPTION 6 | 7 | .PARAMETER Computername 8 | The name of the system you'd like to invoke the action on 9 | .PARAMETER AsJob 10 | Specify this parameter if you'd like to run this as a background job. 11 | .EXAMPLE 12 | PS C:\> Invoke-CMClientUpdateScan -Computername 'Value1' -AsJob 13 | .NOTES 14 | 15 | #> 16 | function Invoke-CMClientUpdateScan { 17 | [CmdletBinding()] 18 | param 19 | ( 20 | [Parameter(Mandatory = $true, 21 | ValueFromPipeline = $true, 22 | ValueFromPipelineByPropertyName = $true)] 23 | [string[]]$Computername, 24 | [Parameter()] 25 | [switch]$AsJob 26 | ) 27 | 28 | Begin { 29 | 30 | } 31 | Process { 32 | foreach ($Computer in $Computername) { 33 | $Params = @{ 34 | 'Computername' = $Computer; 35 | 'ClientAction' = 'UpdateScan'; 36 | 'AsJob' = $AsJob.IsPresent 37 | } 38 | Invoke-CMClientAction @Params 39 | } 40 | } 41 | End { 42 | 43 | } 44 | } 45 | #endregion -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CMClient 2 | 3 | Use this module to kick off many common client triggers like Machine Policy Download, Discovery Data Cycle, Compliance Evaluation, Application Deployment Evaluation, Hardware Inventory, Software Inventory, Update Deployment Evaluation and Update Scan. 4 | 5 | This module has something a lot of the other modules I've seen don't have which is -AsJob support. This means you don't have to wait around on each of your clients to invoke whatever action they'r doing. Instead, you can use the -AsJob parameter which will invoke each action as a PowerShell job so you can run lots of actions asynchronously. 6 | 7 |
8 | PS C:\> Get-Command -Module CMClient 9 | 10 | CommandType Name Version Source 11 | ----------- ---- ------- ------ 12 | Function Get-CMClientBaselineEvaluation 1.7.2 CMClient 13 | Function Get-CMClientComputerByLoggedOnUser 1.7.2 CMClient 14 | Function Get-CMClientDeviceCollectionMembership 1.7.2 CMClient 15 | Function Get-CMClientPackage 1.7.2 CMClient 16 | Function Get-CMClientPendingUpdates 1.7.2 CMClient 17 | Function Get-CMClientUpdates 1.7.2 CMClient 18 | Function Get-CMClientVersion 1.7.2 CMClient 19 | Function Invoke-CMClientApplicationDeploymentEvaluation 1.7.2 CMClient 20 | Function Invoke-CMClientBaselineEvaluation 1.7.2 CMClient 21 | Function Invoke-CMClientComplianceEvaluation 1.7.2 CMClient 22 | Function Invoke-CMClientDiscoveryDataCycle 1.7.2 CMClient 23 | Function Invoke-CMClientHardwareInventory 1.7.2 CMClient 24 | Function Invoke-CMClientMachinePolicyDownload 1.7.2 CMClient 25 | Function Invoke-CMClientUpdateDeploymentEvaluation 1.7.2 CMClient 26 | Function Invoke-CMClientUpdateScan 1.7.2 CMClient 27 | Function Get-CMClientCache 1.7.2 CMClient 28 | Function Clear-CMClientCache 1.7.2 CMClient 29 |--------------------------------------------------------------------------------