- Hardware Inventory Cycle (Delta)
- Hardware Inventory Cycle (Full)
- Software Inventory Cycle (Delta)
- Software Inventory Cycle (Full)
- Discovery Data Collection Cycle (Delta)
- Discovery Data Collection Cycle (Full)
- File Collection Cycle (Delta)
- File Collection Cycle (Full)
- Software Updates Deployment Evaluation Cycle
- Software Updates Scan Cycle
An interesting piece of the code is this:
$wmiQuery = "\\$srv\root\ccm\invagt:InventoryActionStatus.InvetoryActionID=$fscheduleID"
$checkdelete = ([wmi]$wmiQuery).Delete()
Why is this important? Because there are cases when you try to troubleshoot why HW or SW inventory data is not flowing into the SCCM database and the best way to do that is enforcing the client to perform a full inventory and look at the logs (like the InventoryAgent.log on the client or the DataTransferService.log on the Management Point...etc.)
$SMSCli = [wmiclass] \\$srv\root\ccm:SMS_Client
This is for binding the SCCM Client's WMI class, if it's done, then we can invoke the TriggerSchedule method to start an action.
switch ($action) {
...
}
In this section, depending on what action is selected with the -action switch, we set up 2 variables, one is the identifier of the WMI instance which identifies the particular action. The other one is just for displaying the friendly name of the action for the user.
$hostlist = @($Input)
if($($hostlist.length) -gt 0){
foreach ($srv in $hostlist) {
if(!$srv){
executeSCCMAction $srv $action $scheduleID
}
}
}
Get the list of hosts from the pipe into an array, go through the array and call the executeSCCMAction function to create and/or delete the necessary WMI instance.
Clipboard friendly code:
param ( [string] $action = "")
function executeSCCMAction ([string]$srv, [string]$action, $fscheduleID){
#Binding SMS_Client wmi class remotely....
$SMSCli = [wmiclass] "\\$srv\root\ccm:SMS_Client"
if($SMSCli){
if($action -imatch "full"){
#Clearing HW or SW inventory delta flag...
$wmiQuery = "\\$srv\root\ccm\invagt:InventoryActionStatus.InventoryActionID=$fscheduleID"
$checkdelete = ([wmi]$wmiQuery).Delete()
}
#Invoking $action ...
Write-Host "$srv, Invoking action $script:actionName"
$check = $SMSCli.TriggerSchedule($fscheduleID)
}
else{
# could not get SCCM WMI Class
Write-Host "$srv, could not get SCCM WMI Class"
}
}
switch ($action) {
"hw" {
$scheduleID = "{00000000-0000-0000-0000-000000000001}"
$script:actionName = "Hardware Inventory Cycle (Delta)"
}
"hwfull" {
$scheduleID = "{00000000-0000-0000-0000-000000000001}"
$script:actionName = "Hardware Inventory Cycle (Full)"
}
"sw" {
$scheduleID = "{00000000-0000-0000-0000-000000000002}"
$script:actionName = "Software Inventory Cycle (Delta)"
}
"swfull" {
$scheduleID = "{00000000-0000-0000-0000-000000000002}"
$script:actionName = "Software Inventory Cycle (Full)"
}
"datadisc" {
$scheduleID = "{00000000-0000-0000-0000-000000000003}"
$script:actionName = "Discovery Data Collection Cycle (Delta)"
}
"datadiscfull" {
$scheduleID = "{00000000-0000-0000-0000-000000000003}"
$script:actionName = "Discovery Data Collection Cycle (Full)"
}
"filecollect" {
$scheduleID = "{00000000-0000-0000-0000-000000000010}"
$script:actionName = "File Collection Cycle (Delta)"
}
"filecollectfull" {
$scheduleID = "{00000000-0000-0000-0000-000000000010}"
$script:actionName = "File Collection Cycle (Full)"
}
"swupdatedeploy" {
$scheduleID = "{00000000-0000-0000-0000-000000000108}"
$script:actionName = "Software Updates Deployment Evaluation Cycle"
}
"swupdatescan" {
$scheduleID = "{00000000-0000-0000-0000-000000000113}"
$script:actionName = "Software Updates Scan Cycle"
}
default {
Write-Host -ForegroundColor 'red' "No valid Action is specified. Exiting..."
exit
}
}
#getting hostlist from pipe i.e.: PS C:\> gc list.txt | script.ps1
$hostlist = @($Input)
if($($hostlist.length) -gt 0){
foreach ($srv in $hostlist) {
if($srv){
executeSCCMAction $srv $action $scheduleID
}
}
}
else{
# No hostname or hostlist is specified
}
t
awesome, this was perfect. good for tagging on other sccm packages or stand alone.
ReplyDeleteDo you recommend running this in its entirety, or choose which Actions to run? I'm thinking of putting this at the end of an OSD Task Sequence so that users get other assigned applications quicker.
ReplyDeleteDepends on how you want to do it. I usually have one script with multiple actions and just use the switches as applicable. It's easier in terms of code management. However, if something is a one-liner, it's easier to put it into the Task Sequence as one step running a command
DeleteGreat script, but do you have a similar one which works for SCCM 2012 sp1? I have tried this for triggering a forced Software Updates Scan but no joy... I was hoping to make an unattended script for use during the OSD task sequence (replacing the text file input string $srv with $pcname = $env:computername)... Am I doing something wrong - pretty new to PowerShell.
ReplyDelete=================================================================
SCCM 2012 probably has a different inventory code for Software Updates Scan.
DeleteKick it off on an host via GUI and check the InventoryAgent.log of the SCCM client. It will have an inventory ID, something like {00000000-0000-0000-0000-000000000113}.
Put that into this script replacing the line:
$scheduleID = "{00000000-0000-0000-0000-000000000113}"
How do I launch it?
ReplyDeleteIf I use gc list.txt | script.ps1, I get The term 'script.ps1' is not recognized as the name of a cmdlet.
if I use gc list.txt | .\script.ps1, I get "No valid Action is specified. Exiting..."
this is just one of the "limitations" of PS, if the script is in the current folder, you need to explicitly refer to it like .\script.ps1 or with full path as you just said above.
DeleteThe script needs the -action switch to be specified, so e.g.:
gc list.txt | .\script.ps1 0action hwfull
it can be, hw, hwfull, sw, policy...etc, as you can see it in the code
Also, you misspelled Inventory in Line 8
ReplyDeleteThanks, fixed
DeleteGreat script, but I only got it really working, when I took "!" away in row "if(!$srv)"
ReplyDeleteWow, I left it there from the original script, nice catch. Thanks.
ReplyDeletet
$wmiQuery = "\\$srv\root\ccm\invagt:InventoryActionStatus.InventoryActionID=$fscheduleID"
ReplyDeletedoes not work, should be (I think)
$wmiQuery = "\\"+$srv+"\root\ccm\invagt:InventoryActionStatus.InventoryActionID="+$fscheduleID
I have this error:
ReplyDeleteCannot convert value "\\hostname\root\ccm\invagt:InventoryActionStatus.InventoryActionID={00000000-0000-0000-0000-000000000002}" to
type "System.Management.ManagementObject". Error: "Invalid object path "
At C:\Users\user\Desktop\script\test.ps1:19 char:9
+ $checkdelete = ([wmi]$wmiQuery).Delete()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastToWMI
hostname, Invoking action Software Inventory Cycle (Full)
is you SCCM server name called "hostname"?" \\hostname\root\ccm\invagt:InventoryActionStatus
DeleteI think the parameters are not lined up when you are running the script and the real server name is not taken by the script.