March 3, 2015

The Update/Hotfix Cafuddle

Grumpy Admin was asked today for an “Update, and detailed information” on the Windows Patching on our small private company infrastructure. Now I take an meh approach these days to Windows Updates these days. This is due to a constant battle with updates constantly being rolled back, at random on our Hyper-Visors. I have nailed it down to a update with ID number KB2981580, but no reason why it is failing etc, I  just can’t tell why it does it what it does to me except that it hates me! So all I know is that it fails to install and causes a roll back other not. It seems to be some Redmond Magic Voodoo rather than computer science!

Untitled picture2

My small, not my customer(s) server estate have a little WSUS server and some parts of the System Centre stack installed. We have SCCM, badly configured and not really used, and VMM as well, again the configuration could be better. It kinda works 🙂 So when I first arrived in this job. I naturally married WSUS and SCCM – to get the more granular features of SCCM. I admit, it not the best install or configuration. I had to balance, the usage, the small amount of users and the very very limited resources that I have to play with. Personally I would KISS it all good bye, scrape the whole small estate and rebuild fresh. Work smart not hard but… I am not the boss… yet!

Given the limited users that we have (no domain joined clients) and the services we provide to ourselves, CRM,Sharepoint,Exchange and the supporting services, CA,DNS,ADDS,SQL,DPM etc Patch Tuesday is actually quite easy, each month, I just add that months patches to a deployed package in SCCM. Then SCCM pushes the updated package out to all my machines while I read TheRegister and Dilbert “monitor” the process.

For the most part it doesn’t grumble and pushes out the patches, I scheduled the reboots with any stakeholders via email. Normally during a
lunchtime and I go home feeling smug! That I managed to right click a few times and did what I am paid to do… lol

I am not a total cowboy or idiot, I am grumpy and have personality traits and similarities to BOFH but not an idiot. I do have a test package in SCCM and 3 slightly less important servers to test the patches from Microsoft prior to my boss slitting his wrists on the second Tuesday each month!

While I like SCCM, I do find the reporting features a bit crap! For example, I have yet to find a way of just determining which updates are on a particular machine. Maybe I am missing something or don’t have it configured correctly. Either way it makes me grumpy I can’t
find the information that I want, when I want it!

Back to the story, as we all know an important part of any IT system is the documentation, it is a living document that needs to be maintained and given love. Grumpy Admin gets grumpy when the documentation isn’t updated. How can I make decisions, and know what the hell is going on if there is documentation. When you patch a server, you should really document, what patches went on and where. It is just good manners.

Now you can imagine what I am about to say about my little internal system. Not the customers systems that we are contracted to maintain. Documentation is a myth! But what if god forbid the boss asks me to document, or find out information like he did. What patches are installed where. Without documentation I can’t answer the questions purposed to me now can I?

but what if there was some magic interface that could help us to extract this information from a server and allow me to export it to a file if only…. “oh hello there Mr. Powershell, how are we today?“…. “under used and not valued you say“…. “hang on… do you know a way of“…. “not directly but you think you can help? Really tell me more“…

So what we want to tell Powershell to do is, get a list of all installed updates on a machine telling me the KB number and the date it was installed.

Being a skilled and all knowing and experienced systems administrator this really does sound like something Windows Management Instrumentation can do. We know we have access to the namespace – using the Get-WmiObject – so a quick google and you will come across this

http://social.technet.microsoft.com/wiki/contents/articles/4197.how-to-list-all-of-the-windows-and-software-updates-applied-to-a-computer.aspx
I like the simple answer from that blog of using WMIC – I have used that before to poke around the WMI namespace 🙂

So a command like

wmic qfe list

will provide the output required. Simple 🙂 Job done, but it is not in a nice format…. This makes me grumpy! Ok lets try their second method via powershell Powershell method as I could do something with that maybe

So I lift their code right from the blog –

Get-WmiObject -Class “win32_quickfixengineering” | Select-Object -Property “Description”, “HotfixID”, @{Name=”InstalledOn”; Expression={([DateTime]($_.InstalledOn)).ToLocalTime()}}

If you going to steal/borrow/reuse code, apart from the acknowledgement of the original author (not giving credit,makes me grumpy! There is a theme for this blog you know!!!). You should at least make the effort to read the code and understand it. So here
goes…

Line One: using the Get-WmiObject cmdlet we collect the objects from the win32_quickfixengineering class.
Line Two: we select certain objects which we want to display using the -property argument – so we want to use description, hotfixid
and installedon

The install date is being modified by using Expression to convert the Date/time to localtime.

If you want a more detailed list of what properties you could use in your select object check out the MSDN post on the QFE class.

https://msdn.microsoft.com/en-us/library/aa394391%28v=vs.85%29.aspx

effectivly the properties are these assuming you are too lazy to follow the link –

string Caption;
string CSName;
string Description;
string FixComments;
string HotFixID;
datetime InstallDate;
string InstalledBy;
string InstalledOn;
string Name;
string ServicePackInEffect;
string Status;

Right so now we have this code, let run it and see if it does what it says on the tin…. I don’t know about you but none of my installon dates results turned in the output, up only one or two, most were blank…. Meh! This of course makes me grumpy. But I guess if that information
isn’t captured or returned then so be it! But I am after this information after all its for change management… so we need to find
a better method I think… I know the information is there somewhere!

To prove this if I do a WMIC QFE list full

Untitled picture6 Untitled picture7

Look there are entries which give us the InstalledOn property – why isn’t it being returned in my environment!? I really don’t know… this is
makes me grumpy! Not knowing is a sure way of making me grumpy!

So we know we can get the information that we really want from using WMIC – but this is not a Powershell object – but it does return output – so we can use that, combine it with some string handling perhaps and maybe grumpy admin can knock something up that will allow me to get the following information for my documentation. I expect by now I could of sorted the reporting features of SCCM out and got a nice report, but this had made me grumpy and I am now on a crusade!

I WANT a powershell script that will enumerate the windows updates return what type of update, the KB number and when it was installed!

Right, now this has been a time sink and the question still needs to be answered, so I decided enough messing around, let just Google and get a pre-written script to do this.

I then find this – https://technet.microsoft.com/en-us/library/dd315379.aspx

Function Get-MSHotfix
{
$outputs = Invoke-Expression “wmic qfe list”
$outputs = $outputs[1..($outputs.length)]

foreach ($output in $Outputs) {
if ($output) {
$output = $output -replace ‘y U’,’y-U’
$output = $output -replace ‘NT A’,’NT-A’
$output = $output -replace ‘\s+’,’ ‘
$parts = $output -split ‘ ‘
if ($parts[5] -like “*/*/*”) {
$Dateis = [datetime]::ParseExact($parts[5], ‘%M/%d/yyyy’,[Globalization.cultureinfo]::GetCultureInfo(“en-
US”).DateTimeFormat)
} else {
$Dateis = get-date([DateTime][Convert]::ToInt64(“$parts[5]”, 16))-Format ‘%M/%d/yyyy’
}
New-Object -Type PSObject -Property @{
KBArticle = [string]$parts[0]
Computername = [string]$parts[1]
Description = [string]$parts[2]
FixComments = [string]$parts[6]
HotFixID = [string]$parts[3]
InstalledOn = Get-Date($Dateis)-format “dddd d MMMM yyyy”
InstalledBy = [string]$parts[4]
InstallDate = [string]$parts[7]
Name = [string]$parts[8]
ServicePackInEffect = [string]$parts[9]
Status = [string]$parts[10]
}
}
}
}

 

This is great, it is using the WMIC and looks like it is breaking things down into a custom object that I can address – so let fire this up and see what happens -whatif is for the type of people that don’t take risks!

It runs and works…. it returns the install date, that is the badger of information I been looking for, so as I have wasted so much time trying to achieve this aim, just to get the information I need all I need to do is the following

Get-MSHotfix |Select-Object -Property HotFixId,InstalledOn

Which I can then | export-csv <filepath> and it is all done – not the best or cleanest way of doing things, but it works… Now I wasted quite a few
mins to answer a simple question and I have more important things to do make and drink coffee, but to hell my documentation is going to look good and detailed… hang on, what documentation…grrrr

Hazzy