The latest script I am writing requires me to initiate both a software updates scan cycle and a software updates deployment evaluation cycle before continuing with the script. The actions needed to be completed before the script can continue, which is what started me on the path to writing this script. I figured if I was going to write two functions for those actions, I would write functions for the rest of the actions. I do realize there are more actions out there that I could include, but for now, I only included the ones in the Actions tab of the Configuration Manager Properties. Thanks to Eswar Knoeti's blog post, I had a reference to refer to on what log files to scan for the action being taken.
The way these scripts work, they kick off an action and then monitor the log file associated with that action until the completion/failed message appears. I have also included a 5 minute maximum wait time if something goes wrong and the action does not complete successfully, and a new message appears. I have noticed that some actions will not initiate if they have been initiated recently. For those, the status will return as failed.
I was going to originally include parameters so that you could select which functions to execute at command line. I chose not to because I figured that functions will likely be taken from this script to be included in other scripts and it is just as easy to comment out ones you do not want to execute between lines 446 and 456.
This has worked great in my environment. There maybe new messages in the log files that you may encounter that cause the function to not read the log file correctly. If so, please write a comment about that in the blog so that I can update the script. Thanks in advance.
With the help of Sapien's PowerShell Studio, I wrote the following script. You can download the script from here.
The way these scripts work, they kick off an action and then monitor the log file associated with that action until the completion/failed message appears. I have also included a 5 minute maximum wait time if something goes wrong and the action does not complete successfully, and a new message appears. I have noticed that some actions will not initiate if they have been initiated recently. For those, the status will return as failed.
I was going to originally include parameters so that you could select which functions to execute at command line. I chose not to because I figured that functions will likely be taken from this script to be included in other scripts and it is just as easy to comment out ones you do not want to execute between lines 446 and 456.
This has worked great in my environment. There maybe new messages in the log files that you may encounter that cause the function to not read the log file correctly. If so, please write a comment about that in the blog so that I can update the script. Thanks in advance.
With the help of Sapien's PowerShell Studio, I wrote the following script. You can download the script from here.
1: <#
2: .SYNOPSIS
3: Initiate SCCM actions
4:
5: .DESCRIPTION
6: This script will initiate SCCM actions and wait until the action is complete before continuing.
7:
8: .EXAMPLE
9: powershell.exe -executionpolicy bypass -file SCCMActions.ps1
10:
11: .NOTES
12: ===========================================================================
13: Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.122
14: Created on: 5/20/2016 2:28 PM
15: Created by: Mick Pletcher
16: Organization:
17: Filename: SCCMActions.ps1
18: ===========================================================================
19: #>
20: [CmdletBinding()]
21: param ()
22:
23: function Get-CurrentDate {
24: <#
25: .SYNOPSIS
26: Get the current date and return formatted value
27:
28: .DESCRIPTION
29: Return the current date in the following format: mm-dd-yyyy
30:
31: .NOTES
32: Additional information about the function.
33: #>
34:
35: [CmdletBinding()][OutputType([string])]
36: param ()
37:
38: $CurrentDate = Get-Date
39: $CurrentDate = $CurrentDate.ToShortDateString()
40: $CurrentDate = $CurrentDate -replace "/", "-"
41: If ($CurrentDate[2] -ne "-") {
42: $CurrentDate = $CurrentDate.Insert(0, "0")
43: }
44: If ($CurrentDate[5] -ne "-") {
45: $CurrentDate = $CurrentDate.Insert(3, "0")
46: }
47: Return $CurrentDate
48: }
49:
50: function Invoke-ApplicationDeploymentEvaluationCycle {
51: $Completed = $false
52: $StartTime = Get-Date -UFormat %R
53: $CurrentDate = Get-CurrentDate
54: Write-Host "Running Application Deployment Evaluation Cycle....." -NoNewline
55: Start-ConfigurationManagerClientScan -ScheduleID "00000000-0000-0000-0000-000000000121"
56: Do {
57: Start-Sleep -Seconds 1
58: $CurrentTime = Get-Date -UFormat %R
59: $TimeDifference = New-TimeSpan -Start $StartTime -End $CurrentTime
60: $Log = Get-Content $env:windir"\ccm\logs\DCMReporting.log"
61: $Count = $Log.count
62: $Count = $Count - 1
63: $Log = $Log[$Count]
64: $LogTable = $Log.split("<")[-1]
65: $LogTable = $LogTable.Substring(0, $LogTable.length - 1) -replace ' ', ';'
66: $LogTable = "@{$($LogTable)}" | Invoke-Expression
67: $LogTime = $LogTable.time.Substring(0, 5)
68: [datetime]$StringTime = $LogTable.time
69: If (($Log -like "*FinalRelease*") -and ($CurrentDate -eq $LogTable.date) -and ($LogTime -ge $StartTime)) {
70: Write-Host "Completed" -ForegroundColor Yellow
71: $Completed = $true
72: }
73: If ($TimeDifference.Minutes -ge 5) {
74: Write-Host "Failed" -ForegroundColor Yellow
75: $Completed = $true
76: }
77: } while ($Completed -eq $false)
78: }
79:
80: function Invoke-DiscoveryDataCollectionCycle {
81: $Completed = $false
82: $StartTime = Get-Date -UFormat %R
83: $CurrentDate = Get-CurrentDate
84: Write-Host "Running Discovery Data Collection Cycle....." -NoNewline
85: Start-ConfigurationManagerClientScan -ScheduleID "00000000-0000-0000-0000-000000000003"
86: Do {
87: Start-Sleep -Seconds 1
88: $CurrentTime = Get-Date -UFormat %R
89: $TimeDifference = New-TimeSpan -Start $StartTime -End $CurrentTime
90: $Log = Get-Content $env:windir"\ccm\logs\InventoryAgent.log"
91: $Count = $Log.count
92: $Count = $Count - 1
93: $Log = $Log[$Count]
94: $LogTable = $Log.split("<")[-1]
95: $LogTable = $LogTable.Substring(0, $LogTable.length - 1) -replace ' ', ';'
96: $LogTable = "@{$($LogTable)}" | Invoke-Expression
97: $LogTime = $LogTable.time.Substring(0, 5)
98: [datetime]$StringTime = $LogTable.time
99: If (($Log -like "*End of message processing*") -and ($CurrentDate -eq $LogTable.date) -and ($LogTime -ge $StartTime)) {
100: Write-Host "Completed" -ForegroundColor Yellow
101: $Completed = $true
102: }
103: If ($TimeDifference.Minutes -ge 5) {
104: Write-Host "Failed" -ForegroundColor Yellow
105: $Completed = $true
106: }
107: } while ($Completed -eq $false)
108: }
109:
110: function Invoke-FileCollectionCycle {
111: $Completed = $false
112: $StartTime = Get-Date -UFormat %R
113: $CurrentDate = Get-CurrentDate
114: Write-Host "Running File Collection Cycle....." -NoNewline
115: Start-ConfigurationManagerClientScan -ScheduleID "00000000-0000-0000-0000-000000000010"
116: Do {
117: Start-Sleep -Seconds 1
118: $CurrentTime = Get-Date -UFormat %R
119: $TimeDifference = New-TimeSpan -Start $StartTime -End $CurrentTime
120: $Log = Get-Content $env:windir"\ccm\logs\InventoryAgent.log"
121: $Count = $Log.count
122: $Count = $Count - 1
123: $Log = $Log[$Count]
124: $LogTable = $Log.split("<")[-1]
125: $LogTable = $LogTable.Substring(0, $LogTable.length - 1) -replace ' ', ';'
126: $LogTable = "@{$($LogTable)}" | Invoke-Expression
127: $LogTime = $LogTable.time.Substring(0, 5)
128: [datetime]$StringTime = $LogTable.time
129: If ((($Log -like "*Action completed*") -or ($Log -like "*Exiting as no items to collect*")) -and ($CurrentDate -eq $LogTable.date) -and ($LogTime -ge $StartTime)) {
130: Write-Host "Completed" -ForegroundColor Yellow
131: $Completed = $true
132: }
133: If ($TimeDifference.Minutes -ge 5) {
134: Write-Host "Failed" -ForegroundColor Yellow
135: $Completed = $true
136: }
137: } while ($Completed -eq $false)
138: }
139:
140: function Invoke-HardwareInventoryCycle {
141: $Completed = $false
142: $StartTime = Get-Date -UFormat %R
143: $CurrentDate = Get-CurrentDate
144: Write-Host "Running Hardware Inventory Cycle....." -NoNewline
145: Start-ConfigurationManagerClientScan -ScheduleID "00000000-0000-0000-0000-000000000001"
146: Do {
147: Start-Sleep -Seconds 1
148: $CurrentTime = Get-Date -UFormat %R
149: $TimeDifference = New-TimeSpan -Start $StartTime -End $CurrentTime
150: $Log = Get-Content $env:windir"\ccm\logs\InventoryAgent.log"
151: $Count = $Log.count
152: $Count = $Count - 1
153: $Log = $Log[$Count]
154: $LogTable = $Log.split("<")[-1]
155: $LogTable = $LogTable.Substring(0, $LogTable.length - 1) -replace ' ', ';'
156: $LogTable = "@{$($LogTable)}" | Invoke-Expression
157: $LogTime = $LogTable.time.Substring(0, 5)
158: [datetime]$StringTime = $LogTable.time
159: If (($Log -like "*End of message processing*") -and ($CurrentDate -eq $LogTable.date) -and ($LogTime -ge $StartTime)) {
160: Write-Host "Completed" -ForegroundColor Yellow
161: $Completed = $true
162: }
163: If (($Log -like "*already in queue. Message ignored.*") -and ($CurrentDate -eq $LogTable.date) -and ($LogTime -ge $StartTime)) {
164: Write-Host "Ignored" -ForegroundColor Red
165: $Completed = $true
166: }
167: If ($TimeDifference.Minutes -ge 5) {
168: Write-Host "Failed" -ForegroundColor Yellow
169: $Completed = $true
170: }
171: } while ($Completed -eq $false)
172: }
173:
174: function Invoke-MachinePolicyEvaluationCycle {
175: $Completed = $false
176: $StartTime = Get-Date -UFormat %r
177: $StartTime = $StartTime.Split(' ')
178: $StartTime = $StartTime[0]
179: $StartTime = $StartTime.Substring(0, $StartTime.Length - 3)
180: $CurrentDate = Get-CurrentDate
181: Write-Host "Running Machine Policy Evaluation Cycle....." -NoNewline
182: Start-ConfigurationManagerClientScan -ScheduleID "00000000-0000-0000-0000-000000000022"
183: Do {
184: Start-Sleep -Seconds 1
185: $CurrentTime = Get-Date -UFormat %R
186: $TimeDifference = New-TimeSpan -Start $StartTime -End $CurrentTime
187: $Log = Get-Content $env:windir"\ccm\logs\PolicyEvaluator.log"
188: $Count = $Log.count
189: $LogTime = $Log[$Count - 6]
190: $LogTime = $LogTime.Split('"')
191: $LogTime = $LogTime[1]
192: $LogTime = [management.managementdatetimeconverter]::ToDateTime($LogTime)
193: $LogDate = $LogTime
194: $LogTime = $LogTime.ToShortTimeString()
195: $LogTime = $Logtime.Split(' ')
196: $LogTime = $LogTime[0]
197: If ($LogTime[2] -ne ":") {
198: $LogTime = $LogTime.Insert(0, "0")
199: }
200: $LogDate = $LogDate.ToShortDateString()
201: $LogDate = Get-CurrentDate
202: $LogStatus = $Log[$Count - 9]
203: If (($LogStatus -like "*instance of CCM_PolicyAgent_PolicyEvaluationComplete*") -and ($CurrentDate -eq $LogDate) -and ($LogTime -ge $StartTime)) {
204: Write-Host "Completed" -ForegroundColor Yellow
205: $Completed = $true
206: }
207: If ($TimeDifference.Minutes -ge 5) {
208: Write-Host "Failed" -ForegroundColor Yellow
209: $Completed = $true
210: }
211: } while ($Completed -eq $false)
212: }
213:
214: function Invoke-MachinePolicyRetrievalCycle {
215: $Completed = $false
216: $StartTime = Get-Date -UFormat %r
217: $StartTime = $StartTime.Split(' ')
218: $StartTime = $StartTime[0]
219: $StartTime = $StartTime.Substring(0, $StartTime.Length - 3)
220: $CurrentDate = Get-CurrentDate
221: Write-Host "Running Machine Policy Retrieval Cycle....." -NoNewline
222: Start-ConfigurationManagerClientScan -ScheduleID "00000000-0000-0000-0000-000000000021"
223: Do {
224: Start-Sleep -Seconds 1
225: $CurrentTime = Get-Date -UFormat %R
226: $TimeDifference = New-TimeSpan -Start $StartTime -End $CurrentTime
227: $Log = Get-Content $env:windir"\ccm\logs\PolicyEvaluator.log"
228: $Count = $Log.count
229: $LogTime = $Log[$Count - 6]
230: $LogTime = $LogTime.Split('"')
231: $LogTime = $LogTime[1]
232: $LogTime = [management.managementdatetimeconverter]::ToDateTime($LogTime)
233: $LogDate = $LogTime
234: $LogTime = $LogTime.ToShortTimeString()
235: $LogTime = $Logtime.Split(' ')
236: $LogTime = $LogTime[0]
237: If ($LogTime[2] -ne ":") {
238: $LogTime = $LogTime.Insert(0, "0")
239: }
240: $LogDate = $LogDate.ToShortDateString()
241: $LogDate = Get-CurrentDate
242: $LogStatus = $Log[$Count - 9]
243: If (($LogStatus -like "*instance of CCM_PolicyAgent_PolicyEvaluationComplete*") -and ($CurrentDate -eq $LogDate) -and ($LogTime -ge $StartTime)) {
244: Write-Host "Completed" -ForegroundColor Yellow
245: $Completed = $true
246: }
247: If ($TimeDifference.Minutes -ge 5) {
248: Write-Host "Failed" -ForegroundColor Yellow
249: $Completed = $true
250: }
251: } while ($Completed -eq $false)
252: }
253:
254: function Invoke-SoftwareInventoryCycle {
255: $Completed = $false
256: $StartTime = Get-Date -UFormat %R
257: $CurrentDate = Get-CurrentDate
258: Write-Host "Running Software Inventory Cycle....." -NoNewline
259: Start-ConfigurationManagerClientScan -ScheduleID "00000000-0000-0000-0000-000000000002"
260: Do {
261: Start-Sleep -Seconds 1
262: $CurrentTime = Get-Date -UFormat %R
263: $TimeDifference = New-TimeSpan -Start $StartTime -End $CurrentTime
264: $Log = Get-Content $env:windir"\ccm\logs\InventoryAgent.log"
265: $Count = $Log.count
266: $Count = $Count - 1
267: $Log = $Log[$Count]
268: $LogTable = $Log.split("<")[-1]
269: $LogTable = $LogTable.Substring(0, $LogTable.length - 1) -replace ' ', ';'
270: $LogTable = "@{$($LogTable)}" | Invoke-Expression
271: $LogTime = $LogTable.time.Substring(0, 5)
272: [datetime]$StringTime = $LogTable.time
273: If (($Log -like "*Initialization completed in*") -and ($CurrentDate -eq $LogTable.date) -and ($LogTime -ge $StartTime)) {
274: Write-Host "Completed" -ForegroundColor Yellow
275: $Completed = $true
276: }
277: If ($TimeDifference.Minutes -ge 5) {
278: Write-Host "Failed" -ForegroundColor Yellow
279: $Completed = $true
280: }
281: } while ($Completed -eq $false)
282: }
283:
284: function Invoke-SoftwareMeteringUsageReportCycle {
285: $Completed = $false
286: $StartTime = Get-Date -UFormat %R
287: $CurrentDate = Get-CurrentDate
288: Write-Host "Running Software Metering Usage Report Cycle....." -NoNewline
289: Start-ConfigurationManagerClientScan -ScheduleID "00000000-0000-0000-0000-000000000031"
290: Do {
291: Start-Sleep -Seconds 1
292: $CurrentTime = Get-Date -UFormat %R
293: $TimeDifference = New-TimeSpan -Start $StartTime -End $CurrentTime
294: $Log = Get-Content $env:windir"\ccm\logs\SWMTRReportGen.log"
295: $Count = $Log.count
296: $Count = $Count - 1
297: $Log = $Log[$Count]
298: $LogTable = $Log.split("<")[-1]
299: $LogTable = $LogTable.Substring(0, $LogTable.length - 1) -replace ' ', ';'
300: $LogTable = "@{$($LogTable)}" | Invoke-Expression
301: $LogTime = $LogTable.time.Substring(0, 5)
302: [datetime]$StringTime = $LogTable.time
303: If ((($Log -like "*No usage data found to generate software metering report*") -or ($Log -like "*Successfully generated report header*") -or ($Log -like "*Message ID of sent message*")) -and ($CurrentDate -eq $LogTable.date) -and ($LogTime -ge $StartTime)) {
304: Write-Host "Completed" -ForegroundColor Yellow
305: $Completed = $true
306: }
307: If ($TimeDifference.Minutes -ge 5) {
308: Write-Host "Failed" -ForegroundColor Yellow
309: $Completed = $true
310: }
311: } while ($Completed -eq $false)
312: }
313:
314: function Invoke-SoftwareUpdatesDeploymentEvaluationCycle {
315: <#
316: .SYNOPSIS
317: Scan for software updates that are out of compliance
318:
319: .DESCRIPTION
320: Initiates a scan for software updates compliance. Before client computers can scan for software update compliance, the software updates environment must be configured.
321:
322: .NOTES
323: Additional information about the function.
324: #>
325:
326: [CmdletBinding()]
327: param ()
328:
329: $Completed = $false
330: $StartTime = Get-Date -UFormat %R
331: $CurrentDate = Get-CurrentDate
332: Write-Host "Running Software Updates Deployment Evaluation Cycle....." -NoNewline
333: Start-ConfigurationManagerClientScan -ScheduleID "00000000-0000-0000-0000-000000000108"
334: Do {
335: Start-Sleep -Seconds 1
336: $CurrentTime = Get-Date -UFormat %R
337: $TimeDifference = New-TimeSpan -Start $StartTime -End $CurrentTime
338: $Log = Get-Content $env:windir"\ccm\logs\ScanAgent.log"
339: $Count = $Log.count
340: $Count = $Count - 1
341: $Log = $Log[$Count]
342: $LogTable = $Log.split("<")[-1]
343: $LogTable = $LogTable.Substring(0, $LogTable.length - 1) -replace ' ', ';'
344: $LogTable = "@{$($LogTable)}" | Invoke-Expression
345: $LogTime = $LogTable.time.Substring(0, 5)
346: [datetime]$StringTime = $LogTable.time
347: If (($Log -like "*Calling back to client on Scan request complete*") -and ($CurrentDate -eq $LogTable.date) -and ($LogTime -ge $StartTime)) {
348: Write-Host "Completed" -ForegroundColor Yellow
349: $Completed = $true
350: }
351: If ($TimeDifference.Minutes -ge 5) {
352: Write-Host "Failed" -ForegroundColor Yellow
353: $Completed = $true
354: }
355: } while ($Completed -eq $false)
356: }
357:
358: function Invoke-SoftwareUpdatesScanCycle {
359: $Completed = $false
360: $StartTime = Get-Date -UFormat %R
361: $CurrentDate = Get-CurrentDate
362: Write-Host "Running Software Updates Scan Cycle....." -NoNewline
363: Start-ConfigurationManagerClientScan -ScheduleID "00000000-0000-0000-0000-000000000113"
364: Do {
365: Start-Sleep -Seconds 1
366: $CurrentTime = Get-Date -UFormat %R
367: $TimeDifference = New-TimeSpan -Start $StartTime -End $CurrentTime
368: $Log = Get-Content $env:windir"\ccm\logs\scanagent.log"
369: $Count = $Log.count
370: $Count = $Count - 1
371: $Log = $Log[$Count]
372: $LogTable = $Log.split("<")[-1]
373: $LogTable = $LogTable.Substring(0, $LogTable.length - 1) -replace ' ', ';'
374: $LogTable = "@{$($LogTable)}" | Invoke-Expression
375: $LogTime = $LogTable.time.Substring(0, 5)
376: [datetime]$StringTime = $LogTable.time
377: If (($Log -like "*scan completion received*") -and ($CurrentDate -eq $LogTable.date) -and ($LogTime -ge $StartTime)) {
378: Write-Host "Completed" -ForegroundColor Yellow
379: $Completed = $true
380: }
381: If ($TimeDifference.Minutes -ge 5) {
382: Write-Host "Failed" -ForegroundColor Yellow
383: $Completed = $true
384: }
385: } while ($Completed -eq $false)
386: }
387:
388: function Invoke-WindowsInstallerSourceListUpdateCycle {
389: $Completed = $false
390: $StartTime = Get-Date -UFormat %R
391: $CurrentDate = Get-CurrentDate
392: Write-Host "Running Windows Installer Source List Update Cycle....." -NoNewline
393: Start-ConfigurationManagerClientScan -ScheduleID "00000000-0000-0000-0000-000000000032"
394: Do {
395: Start-Sleep -Seconds 1
396: $CurrentTime = Get-Date -UFormat %R
397: $TimeDifference = New-TimeSpan -Start $StartTime -End $CurrentTime
398: $Log = Get-Content $env:windir"\ccm\logs\SrcUpdateMgr.log"
399: $Count = $Log.count
400: $Count = $Count - 1
401: $Log = $Log[$Count]
402: $LogTable = $Log.split("<")[-1]
403: $LogTable = $LogTable.Substring(0, $LogTable.length - 1) -replace ' ', ';'
404: $LogTable = "@{$($LogTable)}" | Invoke-Expression
405: $LogTime = $LogTable.time.Substring(0, 5)
406: [datetime]$StringTime = $LogTable.time
407: If (($Log -like "*MSI update source list task finished successfully*") -and ($CurrentDate -eq $LogTable.date) -and ($LogTime -ge $StartTime)) {
408: Write-Host "Completed" -ForegroundColor Yellow
409: $Completed = $true
410: }
411: If ($TimeDifference.Minutes -ge 5) {
412: Write-Host "Failed" -ForegroundColor Yellow
413: $Completed = $true
414: }
415: } while ($Completed -eq $false)
416: }
417:
418: function Start-ConfigurationManagerClientScan {
419: <#
420: .SYNOPSIS
421: Initiate Configuration Manager Client Scan
422:
423: .DESCRIPTION
424: This will initiate an SCCM action
425:
426: .PARAMETER ScheduleID
427: GUID ID of the SCCM action
428:
429: .NOTES
430: Additional information about the function.
431: #>
432:
433: [CmdletBinding()]
434: param
435: (
436: [ValidateSet('00000000-0000-0000-0000-000000000121', '00000000-0000-0000-0000-000000000003', '00000000-0000-0000-0000-000000000010', '00000000-0000-0000-0000-000000000001', '00000000-0000-0000-0000-000000000021', '00000000-0000-0000-0000-000000000022', '00000000-0000-0000-0000-000000000002', '00000000-0000-0000-0000-000000000031', '00000000-0000-0000-0000-000000000108', '00000000-0000-0000-0000-000000000113', '00000000-0000-0000-0000-000000000111', '00000000-0000-0000-0000-000000000026', '00000000-0000-0000-0000-000000000027', '00000000-0000-0000-0000-000000000032')]$ScheduleID
437: )
438:
439: $WMIPath = "\\" + $env:COMPUTERNAME + "\root\ccm:SMS_Client"
440: $SMSwmi = [wmiclass]$WMIPath
441: $Action = [char]123 + $ScheduleID + [char]125
442: [Void]$SMSwmi.TriggerSchedule($Action)
443: }
444:
445: Clear-Host
446: Invoke-SoftwareUpdatesScanCycle
447: Invoke-SoftwareUpdatesDeploymentEvaluationCycle
448: Invoke-ApplicationDeploymentEvaluationCycle
449: Invoke-DiscoveryDataCollectionCycle
450: Invoke-FileCollectionCycle
451: Invoke-HardwareInventoryCycle
452: Invoke-MachinePolicyEvaluationCycle
453: Invoke-MachinePolicyRetrievalCycle
454: Invoke-SoftwareInventoryCycle
455: Invoke-SoftwareMeteringUsageReportCycle
456: Invoke-WindowsInstallerSourceListUpdateCycle
457:
0 comments:
Post a Comment