Skip navigation

Category Archives: General Discussion

Everything that goes on here.

Since I posted anything personal on here that a non-techie person could read.  I’ve had a lot of things going on to me, and around me; so it’s about time to spill it.

Let’s start with some of the good things going on.


Maggie.

She’s getting stronger, and her confidence is growing.

2011-11-07_18-14-42_776[1]

Most people may not realize how huge seeing her sitting up on her own in a shopping cart is to her mother and I.  Is she behind?  Sure, but she’s making progress, and for that we are thankful.

Now, she’s also becoming more and more aware of things she wants to do and realizing she can’t do them (so it would seem) and she gets increasingly more frustrated and that breaks our hearts to witness.  So moments like this where she’s sitting like a big girl, elicits a very proud and triumphant smile from her beautiful little face.


Will.

He keeps growing, and he’s developing such a strong sense of right and wrong.  He’s also got a great sense of humor and a huge heart.

2011-10-27_18-06-51_374[1]

He’s as high energy as ever, and continues to push boundaries though mind you.  Asking questions and wearing his emotions on his sleeve.  He’ll be going into speech therapy soon, more for conversational reasons than his inability to pronounce single words.  With his high energy comes his blurt speaking as I like to think of it.  Essentially he has a million thoughts in his head and his mouth will only go so fast to convey that message.  With all that being said though, every day he does something to test my ire, yet cause an absolute swelling of pride over him.  A 3 year old in true form (soon to be 4, which he is certainly excited about).


Amanda.

There isn’t really a whole lot to say that she doesn’t say on her own blog, but we continue to grow together as well.  Everyday, a day at a time.  She’s my earthly joy, and the one I seek for guidance and approval.  Aside from being an amazing mother and wife, she’s taken to doing a lot of crafts lately (sewing, embroidery, and scrapbooking), lately of course being for the past year or so.  It continues to amaze me the level of quality stuff she’s been making.  I’m being serious here, it’s really neat to see the way she takes such obscure random things, visualizes something, then in a few hours or a few days has this absolutely impressive piece of work.

I also love the fact she has a hobby now.  I’ve always kind of been one to be into something.  Coding, studying obscure subjects, collecting anime, playing video games, tweaking hardware, building networks, etc.  Amanda has always had things she’s into I guess, but never really had the time/money/equipment/support/motivation to follow through on it but now she has and it excites me to see her pouring herself into it.


Me.

So the current situation for me is pretty, interesting.  My company was bought out a few weeks ago in what is (admittedly) a great deal for the shareholders.  The only kicker is, it could be bad for me, as in lose my job bad.  I’m not presently assuming that, but the reality is there.  I can’t really disclose any more then that at this time, but it’s a matter of concern.

I’m not really sure what else there is to say, I’ve been coding a lot, studying a lot, and (with all the games coming out) gaming a lot.  There never seems to be a shortage of things that need to be done, or things I want done.  Par for the course I guess, and that sums up what’s been going on lately. 

If only things were always this simple.

cde cde cbnhjtgvffffffffffffffffffffffrffffffffffrcde cde cde ftrh,.                                 vggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg

gggggggggggggggggggggffffcggggggggggggggvv n bbbhhhhhhhhhhhhhhhhhhhhhnhjHoffcccccccccvvqtgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfg

fgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgf

gfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgf

gfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgf

gfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgf

gfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfh6

vfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfv

fvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfvfb     

So I ran into a rather straight forward script request recently that turned into a ton of research for what is a very simple solution in the end. I needed to disable anonymous FTP on multiple XP machines. Now normally this wouldn’t have been an issue except that they are using version 5.1 of IIS.

Why is that a problem?

Well it wasn’t until IIS version 6.0 that WMI components were added.  Generally finding support information for these types of tasks can be the lion share of the work anyway, and in this case; that was most certainly the outcome.

In the end I found a comprehensive list of IIS metabase properties (the original list read as if they were only accessible via WMI which I found later to be untrue) and I was free to begin exploring them all individually and building some very simple scripts to modify our server properties.

First, lets disable anonymous FTP since that’s what started us on this:

Set oFtpServer = GetObject("IIS://localhost/MSFtpsvc")
	oFtpServer.Put "AllowAnonymous", 0 
	oFtpServer.SetInfo

 

Now for our VDs I’d like to disable anonymous while utilizing the integrated windows authentication instead.

Set oWebServer = GetObject("IIS://localhost/W3SVC")
	owebserver.put "authflags", 4
	owebserver.setinfo

 

Simple enough, instantiate the object, put a property change in, then commit the change.  In these examples I’m setting the changes at the root, but it’s possible to drill them down to specific VDs by finishing the full path when instantiating.

Thankfully technet saved my behind after some digging, but here’s the list of Metabase Properties for anyone reading this who might find themselves at a point of frustration over dealing with legacy IIS installs.

Be sure to also familiarize yourself with the data types etc if this is new to you.

Alright, so I received a pretty loaded technical topic from my good friend Matthew.  Mind you I asked for a technical topic to write about, and he did provide one but the question was:

What is an API and why/when would you use one?

Now seeing as how I already stated that is a loaded question, it deserves a bit of programming fundamentals.  I promise to keep this high level, but with enough detail that a novice programmer could glean a bit of workable information from it.

First I want to explain some basic program flow and design (paradigms).  I’m going to provide some very basic examples of procedural programming and object oriented programming using php (high level).  Lets begin with a very basic example of procedural code.

Put simply procedural programming is just building things to run in a sequence but dividing it up into functions or subroutines.  I’ve demonstrated examples of this in previous posts, but here’s a simple example:


<?php
	example("functions");
	echo '<br />';
	endthis("example");

function example($arg)
{
	echo "This is a very simple example of $arg";
}

function endthis($arg)
{
	echo "This is the end of our $arg";
}
?>

Ok, so what do we have here?

We have a prescribed run order, with a fixed goal in mind.  We are calling the function example with the argument string “functions”, echoing a break, then calling the function endthis with the string argument “example”. 

Simple enough, now why is this important?

Well it’s important to see the way I am passing arguments INTO the function in order for it to produce an output.

Now in more complex applications the best thing to do is to break apart your code and build it into objects (a collection of functions and variables) that perform like tasks and tie them together.  This is object oriented programming.

Lets just take a quick look at a sample object and how it works (stick with me, this is will become relevant to APIs I promise):


<?php
	$object = New SaySomething;
	
$object->set_words("jimmy crack corn and I don't care");

echo $object->get_words();

class SaySomething {
	var $words;
		
		function set_words($new_name) {
			$this->words = $new_name;
		}
		
		function get_words() {
			return $this->words;
		}
}
?>

Ok, we instantiated the object we created, passed a string to it, then retrieved the sting.

Think of it like this, we have a program, we are loading it.  Once we have that program loaded we can begin to tell it what to do.  You can have as many instances of this object or other objects as your memory can handle. 

This paradigm affords us a massive amount of flexibility by giving us a standalone object for completing multiple like tasks.  It’s also easily extensible, allowing us to create child objects that inherit the functionality of their parent without having to modify the parent.  That will allow us over time to build a framework so to speak that we could use to quickly develop new applications on.

So, what does this all have to do with an API?

Looking at how the OOP paradigm communicates with each individual part, instantiating and then passing and receiving content.  An API isn’t much different than that.  The API simply exposes an application for communication.  It allows for interoperability from one application to another by passing messages to each other.

An example of common social networking APIs allow you to call for user information, as well as passing user information back.  Let’s use Twitter for an example. 

I want to post something to twitter, but from a custom application I’ve made.  I need a way to pass that information from my application to twitter.  The API is the interface point to allow that communication.  In a sense, twitter becomes my applications twitter object by virtue of calling and using the API (there are some stark differences, but generally this is a true statement).

The difference is, using the API doesn’t require intimate knowledge of what is going on behind the scenes.  I won’t be modifying anything within the application.  I’m simply sending and receiving information through the API.  The same is true for building an API, less is often more.  As you can imagine exposing your applications to external input and output can be a dangerous game; but that’s a much larger subject. 

The general take a way here is that although the application may consist of multiple functions and/or objects the API simply allows you to interlink one or more applications via messages.

A friend of mine Tom Miller put it rather well in a conversation we had over the subject.  “An API is a lot like a remote control”

I want the TV to change channels, I pick up the remote, press the channel up button, and the channel changes.  The remote IS the API.  My hand is the program communicating to it, and the TV is the program receiving the signal.  At no point do I need to understand how the remote works, or how the TV changed it’s channel. 

Ok, so when/why would I use an API?

That’s generally a design thing, but in most cases when you are building a platform or an application you want to improve it’s usability and not limit it.  Extensibility is the name of the game, so it makes sense to make something that would allow users to integrate other things with your application.

It’s good design because it achieves two major things towards (what I would consider) application design success.

1) It opens your platform up to the imagination of it’s user which can produce some really neat things.

2) It creates an operating environment for users with applications that depend on your platform which increases usage.

Hopefully this hasn’t left you completely confused, but like I said, it was a loaded question.

 

yea, I am that guy

Ok, so as I stated at the tail end of my last post, here’s your PowerShell to export data from Active Directory to a MSSQL Database.  This code can be easily modified to pull whatever AD info you want and to insert it.  I make use of the System.Data.SqlClient namespace, so it’s worth mentioning that you can also use MySql.Data.MySqlClient or System.Data.OracleClient for your needs.  You can examine what I’m using via the SqlClient namespace and easily correlate it back to your respective need.

 


<#
Script: AD to DB
Author: Daniel Belcher
#>
#$ErrorActionPreference = "silentlycontinue"
$CHECK = Get-Module ActiveDirectory
IF(!$CHECK) {
	Write-Host -ForegroundColor Red `
	"Can't find the ActiveDirectory module, please insure it's installed.`n"
	Break}
ELSE {Import-Module ActiveDirectory}

#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
<#Variable String values for customizing
	the DB and to write to and OU to lookup against
		as well as the time range in days#>
<#DataBase Name:#>
$DB = "Data"
<#SQL Server Name:#>
$SQLSRVR = "localhost\sqlexpress"
<#Table to Create:#>
$TABLE = "ADExport"	
<#Days old based on activity according to passwordlastset:#>
$DAYS = 180
<#Root OU to Search:#>
$ORGUNIT = "Root OU to Search"
<#Table Create String#>
$CREATE = "CREATE TABLE $TABLE (AD_Machine varchar(150) not null PRIMARY KEY, `
	OU varchar(100),DistinguishedName varchar(max),PasswordLastSet datetime, `
	OS varchar(100),ServicePack varchar(100))"
#/////////////////////////////////////////////////////////
<#Setting up object variables
	to be used for AD lookup#>
	$TIME = [datetime]::today.adddays(-$DAYS)
$LOOKUP = (Get-ADOrganizationalUnit -LDAPFilter "(Name=$ORGUNIT)")
	$ADARRAY = (Get-ADComputer -SearchBase $lookup.DistinguishedName -properties `
			name,passwordlastset,operatingsystem,operatingsystemservicepack `
			-Filter 'passwordlastset -ge $TIME')  
<#Setting up object variables
	to be used for AD lookup#>
	$TIME = [datetime]::today.adddays(-$DAYS)
$LOOKUP = (Get-ADOrganizationalUnit -LDAPFilter "(Name=$ORGUNIT)")
	$ADARRAY = (Get-ADComputer -SearchBase $lookup.DistinguishedName -properties `
			name,passwordlastset,operatingsystem,operatingsystemservicepack `
			-Filter 'passwordlastset -ge $TIME')  
<#Connect and cleanup the AD table
	Connection remains open for writting#>
$SQLCON = New-Object System.Data.SqlClient.SqlConnection("Data Source=$SQLSRVR; `
			Initial Catalog=$DB;Integrated Security=SSPI")
	$SQLCON.open()
		$SQL = $SQLCON.CreateCommand() 
			$SQL.CommandText ="DROP TABLE $TABLE"
				$SQL.ExecuteNonQuery() > $null
		$SQL.CommandText = $CREATE
			$SQL.ExecuteNonQuery() > $null
<#Begin loop through the ADARRAY for
	Variables and begin inserting Rows to table#>
	$X = 0
ForEach($OBJECT in $ADARRAY){
	
	$NAME = $OBJECT.Name
		$OU = $OBJECT.DistinguishedName.ToString().Substring($OBJECT.Name.ToString().Length+4)
			$DN = $OBJECT.DistinguishedName
				$PWDLS = $OBJECT.PasswordLastSet
					$OS = $OBJECT.OperatingSystem
						$SP = $OBJECT.OperatingSystemServicePack
						
#\\\\Any Table Data to be written goes here:\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
	$INSERT = "INSERT $TABLE VALUES ('$NAME','$OU','$DN','$PWDLS','$OS','$SP')"
	$SQL.CommandText = $INSERT
#////////////////////////////////////////////////////////////////////////////////////////	
		$SQL.ExecuteNonQuery() > $null
$X = $X + 1			
}
"$X Records written to $TABLE in database $DB on server $SQLSRVR"
<#Cleanup variables and close connections#>
$SQLCON.Close()

 

Overview: 

We have 5 key variables to work from here:

  1. $DB – Name of Database to write to
  2. $SQLSRVR – Name/IP of the SQL server
  3. $TABLE – Table to build this data to
  4. $DAYS – Age of machines to pull from AD
  5. $ORGUNIT – The base OU to search through recursively

 

These of course are set to preference or need.

Now what the script does is, it figures out the date using the datetime function in .net factored by the number of days back you declare.

Then it looks up and stores the base OU we will search through then builds the object with the AD Objects it finds.

Next it instantiates the SqlClient object and makes a connection to the server and database we specified in our variables.  We drop the table specified, then recreate the table.

Now the real work begins, we loop through the AD Objects one by one and cherry pick the specific properties out that we want from the object (an area that PowerShell excels at I might add) and declare them as variables to be finally written to our database table.

And for good measure we count each loop and store that so we can see how many records were found and attempted, then cleanup all our variables used during the script.

So in my last two posts I was discussing how to build a script for forcing a SCCM client inventory and how to build a custom collection for them to deploy to.

There is still one more problem, as I stated in the first post, you need to run the script against the proper interpreter.  As more and more people begin to adopt Windows 7 x64 into their environments this issue will become more and more prevalent.  Fortunately there is a simple solution.  Build in your package source directory multiple batch files that contain the following in them:

if exist %systemroot%\SysWOW64\cscript.exe goto 64
cscript "inventory.vbs /full"
exit
:64
%systemroot%\SysWOW64\cscript.exe "inventory.vbs /full"
exit

You will want to build one for each variant of the script you will be running.  This also eliminates the need of creating double of every package>program and prevents you from having to do any advertisement restrictions, it will all be managed at run time.  Modify lines 2 and 5 of your bat file for whatever you need to be run and you are all set.

Finally, one more note of interest.

When building your advertisement, make sure the data is being downloaded before execution (default setting).  For good measure make sure it’s also enabled for unprotected distribution points under the advertisement schedule page.

download

As far as the command line is concerned it just needs to be:

batfilename.bat

That’s it for now. 


Also, I plan on posting a guide for building a Powershell script you can schedule to pull AD information to a SQL database which you can leverage for quick information gathering. Until then, have a good one.

Ok, so as I discussed in my previous post I built multiple collections that determine client inventory health.

So the end result is the ability to build collections based off of machines who haven’t reported to one or more inventory types for X number of days and have the script deployed to them auto-magically with the corresponding inventory type.

This is one of the areas where SCCM (from the console level) becomes pretty restrictive.  In MSSQL you have access to a couple of functions that make determining time frames very simple.  In this case DATEDIFF and GETDATE which combined provide a nice simple statement for determining a fixed time frame.

DATEDIFF(d, column-to-check, GETDATE()) >= 30

 

Ok, great.  So what’s the problem?  Well when building collections in SCCM you have to use WQL, and it doesn’t have such a robust function set.  Fortunately there is a way around this, and I’m going to give a few SQL queries you can use to build some inventory health collections.

Start by building a new empty collection, and during the creation process make a standard query rule and save it.  Now right click and go to properties of your new collection and copy it’s Collection ID.

Now, open up your sql management studio and connect to your site server DB.  Make sure you are connected to the proper DB and run the following query:

select QueryExpression from v_CollectionRuleQuery
where CollectionID = '(pasted collection id)'

 

What you should see is the SQL being used on the back end to present to your console.  Now what you need to do is update this column to match whatever query you need.  Bear in mind, when you are redefining things inside this query they need to match the WQL schema for the console to get the information it needs.  I’ll show you examples later.  I also want to point out, this is not supported by Microsoft, and if you don’t properly structure your Update statement you could end up hosing all your collections, so be safe.  Now here is how you do it.

Update v_CollectionRuleQuery
Set QueryExpression = ‘whatever query statement you want’
where CollectionID = ‘(pasted collection id)’

 

Now when you update membership and refresh that collection you should see results to match your query.  Ok, now here’s the kicker.  Never modify this collections query properties from inside SCCM, the changes you made will be overwritten if you do.

Now, about those queries I promised you.


--No Inventory for 30 days
SELECT SMS_R_System.ItemKey, SMS_R_System.DiscArchKey, SMS_R_System.Name0, 
   SMS_R_System.SMS_Unique_Identifier0,SMS_R_System.Resource_Domain_OR_Workgr0,
			SMS_R_System.Client0 
			FROM
				System_DISC AS SMS_R_System 
					JOIN softwareinventorystatus AS sw 
						ON 
					SMS_R_System.ItemKey = sw.ClientId 
						JOIN WorkstationStatus_DATA AS wks 
							ON
						wks.MachineID = sw.ClientId 
			WHERE
				DATEDIFF(dd,sw.LastUpdateDate,GETDATE()) > 30 
					AND
				DATEDIFF(dd,wks.LastHWScan,GETDATE()) > 30


--No Hinv 30 days
SELECT SMS_R_System.ItemKey, SMS_R_System.DiscArchKey, SMS_R_System.Name0, 
		SMS_R_System.SMS_Unique_Identifier0,
			SMS_R_System.Resource_Domain_OR_Workgr0, SMS_R_System.Client0 
		FROM System_DISC AS SMS_R_System 
		JOIN WorkstationStatus_DATA AS wks 
				ON 
			 wks.MachineID = sms_r_system.ItemKey
		WHERE 
			DATEDIFF(dd,wks.LastHWScan,GETDATE()) > 30


--No Sinv 30 days
SELECT SMS_R_System.ItemKey, SMS_R_System.DiscArchKey, SMS_R_System.Name0, 
		SMS_R_System.SMS_Unique_Identifier0, 
			SMS_R_System.Resource_Domain_OR_Workgr0, SMS_R_System.Client0 
		FROM 
		System_DISC AS SMS_R_System 
			JOIN softwareinventorystatus AS sw 
				ON
			SMS_R_System.ItemKey = sw.ClientId 
		WHERE 
			DATEDIFF(dd,sw.LastUpdateDate,GETDATE()) > 30


--Client with no DDR
SELECT SMS_R_System.ItemKey, SMS_R_System.DiscArchKey, SMS_R_System.Name0, 
		SMS_R_System.SMS_Unique_Identifier0,
			SMS_R_System.Resource_Domain_OR_Workgr0, SMS_R_System.Client0 
			FROM System_DISC AS SMS_R_System 
				JOIN softwareinventorystatus AS sw 
					ON
				SMS_R_System.ItemKey = sw.ClientId
					JOIN WorkstationStatus_DATA AS wks 
						ON 
					wks.MachineID = sw.ClientId 
			WHERE 
				DATEDIFF(dd,sw.LastUpdateDate,GETDATE()) > 5 
					AND 
				DATEDIFF(dd,wks.LastHWScan,getdate()) > 5 
					AND 
				SMS_R_System.Client0 = 0


If you need to specify a collection for exclusion (which if you build all of these you may want to exclude machines in the NO inventory collection) append this to the end of your query.

						and
					SMS_R_System.ItemKey not in (select ResourceID from v_cm_res_coll_CollectionID)


 

And there you have it.  When writing your update line I would change these sql queries to be one line and remove the comment obviously.  There is also a LimitToCollectionID column you might want to apply any specific restrictions to.

Hopefully these past two posts help a few people looking to take an automated stance to proactively resolving inventory reporting issues on clients.  For anyone else:

  1. Hopefully you learned something about sql?
  2. You got a nice refresher on the collection query views name?

 

Have a good one.

Update: Code has been re-written from the previous post to make full use of WMI as the means of execution, and scripting dictionary to simplify reporting and controls

Alright, so I’ve got a bit of a problem.

A large volume of data_loader kick backs, and resynch requests.  The problem is, for one reason or another, the clients inventory data is being held up.  Sure, plenty of machines are only missing records for maybe 3, 4, or 5 days.  However I’ve started to see machines that aren’t getting a record in for about 15 days or more.

This shall not stand!  Mind you I’m not going to fix these one by one either.  So what now?

Script!

So I begin to dive into the CCM namespace looking for a method to force a full inventory. Which brings me to the InvAgt class.  Great!  But wait, I don’t see any method for just forcing an inventory.

This is no longer the object used in the script, but leaving here for reference:

I’ll save you the rest of the story and just get to what I found.  According to Technet, the best way to “script” the solution is to delete the InventoryActionID from the InventoryActionStatus in WMI and use the CPApplet COM automation class to invoke the rescan.

They were also nice enough to provide their own code so it was made increasingly more simple to build the following script as I already had the core functionality objects defined for me.  Now, I needed to weaponize code for deployment…. Perhaps weaponize isn’t the best term, but I needed it to deploy and do some work via SCCM.

So I decided to allow 4 arguments and 2 switches that would allow me to perform:

  1. Hardware Inventory (hinv)
  2. Software Inventory (sinv)
  3. Discovery Data (ddr)
  4. File Collection (file)

 

I also wanted to be able to fire this off in 2 methods, one to clear the old inventory instance ID information and force a full inventory or just force an inventory.  I also wanted to be able to run this in a verbose mode to check and see if all actions were being completed as requested.  So I added the following switches:

  1. /full
  2. /debug

 

So the end result is the ability to build collections based off of machines who haven’t reported to one or more inventory types for X number of days and have the script deployed to them auto-magically with the corresponding inventory type.

I also set the script so someone could use it ad-hoc on a machine by double-clicking.  The default behavior is to NOT delete the IDs but to initialize all 4 of the inventory calls.  I also provided CONST declarations at the top so anyone could add or remove what they want in there (they will however need to modify the arrays arrinvtypes and arrkeys to match as well as the select case statement to add additional arguments).

For people that don’t give a hoot about SCCM (there are plenty of you, shockingly enough) feel free to examine the way the loops and conditionals are being used in this script.  They coorelate back to the fundamentals I have covered previously in my stick to the script series.

  1. Stick to the script…
  2. Stick to the script #!/BIN/BASH…
  3. Stick to the script CreateObject(“Wscript.Shell”)…
  4. Stick to the script PS C:> PowerShell…

 

Finally, the code…..

'||============================||
'||Author Daniel Belcher       ||
'||Full HInv                   ||
'||Date 9/22/2011			   ||
'||Updated 11/7/12             ||
'||============================||
'==================================================================================
'Usage: For any prefered deployment method
'This script can:
'	1) Initiate Soft, Hard, Discover, File Collection on a client PC
'	2) Clear agent inv cache and perform full collection
'
'	cscript.exe inventory.vbs
'
'It's possible to target single inventory types or cherry pick them as needed.
'Accepted arguements are:
'1) hinv (performs a hardware inventory)
'2) sinv (performs a software inventory)
'3) ddr  (performs a discovery data)
'4) file (performs a file collection)
'
'Accepted switches are:
'1) /full (blows away all inv cache for declared inventories and initiates request)
'2) /debug (runs the script verbose to check things are running)
'Using /full or /debug it's best to target an inventory type, but not required.
'
'All arguements and switches are case insensitive.
'
'|Objects, Variables, and Constants ***********************************************
'==================================================================================
'Constant strings for cleanup and initialization subroutines.
'==================================================================================
Option Explicit
Dim oWShell,oWmiLoc,oDict,Args,sArgs,nArgs
Dim Item,x,Full,DEBUGMSG
	Set Args 	= Wscript.Arguments
	Set	NArgs 	= Wscript.Arguments.Named
    Set oWShell = CreateObject("WScript.Shell")
    Set oWmiLoc = CreateObject("WbemScripting.SWbemLocator")
    Set oDict 	= CreateObject("Scripting.Dictionary")
'Add additional INV types here with IDs and update Case & dictionary key item pairs
Const sHinv = "Hardware Inventory Collection Cycle"	
	CONST Hinv = "{00000000-0000-0000-0000-000000000001}":oDict.Add sHinv, Hinv
Const sSinv = "Software Inventory Collection Cycle"
	CONST Sinv = "{00000000-0000-0000-0000-000000000002}":oDict.Add sSinv, Sinv
Const sDDR  = "Discovery Data Collection Cycle"
	CONST DDR  = "{00000000-0000-0000-0000-000000000003}":oDict.Add sDDR,  DDR
Const sFile = "Standard File Collection Cycle"
	Const File = "{00000000-0000-0000-0000-000000000010}":oDict.Add sFile, File
'|Main Run ***********************************************************************
'=================================================================================
'Checking for Named arguments
If NArgs.Exists("Full") Then
	Full = TRUE
		Else
	Full = FALSE
End If
		if NArgs.Exists("debug") Then
				DEBUGMSG = TRUE
					Else
				DEBUGMSG = FALSE
		End If
'Check for Unnamed arguments
If Args.Unnamed.Count > 0 Then
	If DEBUGMSG then wscript.echo "Unnamed arguments Found..."
	'Looping arguments looking for declared Inv types
	For Each item In Args
		Select Case lcase(item)
			Case "hinv"
				If Full Then
					DelInvActionID sHinv
						wscript.sleep 1500
				End If
					RunInvAction sHinv
			Case "sinv"
				If Full Then
					DelInvActionID sSinv
						wscript.sleep 1500
				End If
					RunInvAction sSinv
			Case "ddr"
				If Full Then
					DelInvActionID sDDR
						wscript.sleep 1500
				End If
					RunInvAction sDDR
			Case "file"
				If Full Then
					DelInvActionID sFile
						wscript.sleep 1500
				End If
					RunInvAction sFile
		End Select
	Next
else
	'If no Unnamed arguments then loop through appropriate arrays
	'based on /full or not
	If DEBUGMSG Then wscript.echo "No Unnamed Arguments found, " _
	&"checking for full switch..."
	If Full Then
		If DEBUGMSG Then wscript.echo "/Full switch used, " _
		&"clearing caches..."
		For Each item in oDict.Keys
			DelInvActionID item
				wscript.sleep 1500
		Next
	End If
		If DEBUGMSG Then wscript.echo "Initiating HINV, SINV, DDR, " _
		&"and File Collection now..."
	For Each item in oDict.Keys
		RunInvAction item
			wscript.sleep 1500
	Next
End If
Report
Wscript.Quit(0)
'SubRoutines *********************************************************************
'=================================================================================
'Sub to delete the InventoryActionID as requested
Sub DelInvActionID(guid)
		On Error Resume Next
	Set oInvAgt = oWmiLoc.ConnectServer(,"root\ccm\invagt")
			oInvAgt.Delete "InventoryActionStatus.InventoryActionID='"& _
				oDict.Item(guid)&"'"
	If DEBUGMSG Then wscript.echo "Clearing "& _
		oDict.Item(guid)&" from InventoryActionStatus"
End Sub
'*********************************************************************************
'Sub to initialize Inventory Cycle requested
Sub RunInvAction(name)
		On Error Resume Next
Dim smsclient:Set smsclient=GetObject("winmgmts://./root/ccm:sms_client")
	smsclient.triggerschedule(oDict.Item(name))
		If DEBUGMSG Then wscript.echo "Running "&name
End Sub
'**********************************************************************************
'Sub to report script completion if /debug
Sub Report
         If DEBUGMSG Then wscript.echo "Complete" 'Set for popup on script complete
End Sub
'End ******************************************************************************
'==================================================================================

I want you to think of a few things that will help you to remain mission minded. For the record, these are things I ask myself, or pose to myself on a regular basis; today has been one of those days.

 

God is sovereign, he placed you where you are.

You will be going into work, or staying home, or taking rest today because it was ordained by God. This same God knit you together in your mother’s womb, he also knit the people around you in their mother’s womb. The people you will see today are intended for you to see, they are not an accident.

Do you believe that?

 

You have nothing to fear or worry over, your food, your clothing, your social status.

Do you know what it is to be hungry? Do you know what it is to be a social pariah? Do you know what it is to be underdressed. Now ask yourself this, what did my worrying do to improve/resolve this problem? I believe when you evaluate that you realize it contributed nothing. I believe you will realize it is in God’s hands.

Do you believe that?

 

We go day in and day out, neglecting our God.

Our very hearts and minds drift from him towards desires of the flesh. Towards what will satisfy us physically and emotionally, we whore ourselves to it. Our work, our children, our church, our friends, ourselves.

Do you believe that?

 

We do not deserve one iota of respect, patience, peace, mercy, or love from the almighty being that created us.

We deserve to die, we are like dust before the lord. Apart from God and then compared to God, we don’t even register. We couldn’t even stand in his presence! We couldn’t even look at him!

Do you believe that?

 

This same God sent his only son, himself, in the flesh, to DIE for YOU.

Do you believe that?

 

We are forgiven, we are forgiven, we are forgiven, WE ARE FORGIVEN!

Do you believe that?

 

Who can stand before our God!? Who can hold back his hand!? How can anyone not be amazed by our God? If you see him, hear him, feel him, know him, then how can you not be amazed by our God?

Do you believe that?

 

From the overflow of our hearts comes praise and worship.

What is praise? If your child learns to walk, if you get a new car, if you got a great deal on clothes; how do you react? You want to tell everyone about it, if you are like me you can’t shut up about it! That is praise, how much MORE then should we praise God? What has been done for us? We are forgiven, we are loved, we are provided for, we will live forever, we are heirs to the throne, we are children of the light. Why would we not talk about it? If our God is in control, and we are forgiven even though all signs say we shouldn’t be; then why are we not on FIRE to tell people?

 

There is no feasible excuse outside of: we don’t believe.