Saturday, January 30, 2016

Deploy Windows 8.1 to Windows 8 via SCCM

We have some Windows 8 devices that needs to be upgraded to 8.1.  There is no installer for IE 11 and support has ended on Jan 12, 2016.  I did some research regarding upgrades for enterprise deployment tools but came across only a few articles that said the same thing.  It would have to be refreshed through OSD or downloaded through the Microsoft App Store.

I came across a Technet article of all things that didn't even come up as a top results for this and had a short mention for enterprise customers using SCCM 2012 to deploy the upgrade using the Windows 8.1 install media.  They must have added that upgrade switch later on because of the limited choices enterprise customers to upgrade and it wasn't easily found on any other tech sites.

Here's the article for reference:

https://technet.microsoft.com/en-us/library/dn744271.aspx

The only applicable part for my scenario.


For organizations running Windows 8 Enterprise RTM, the Windows 8.1 update process is simply running the Windows 8.1 setup.exe with a few command-line switches. The switches used in this update scenario are commonly the following:
  • /auto:upgrade. Required switch that runs the update process with no user interaction.
  • /noautoexit. Optional switch. If something goes wrong during setup, wait for user input.
This means that if you have only a few machines to upgrade, or if you want to test upgrading a few machines, you can simply download Windows 8.1 Enterprise ISO and run the setup.exe /auto:upgrade command. For larger numbers, you probably want to automate the setup using System Center 2012 R2 Configuration Manager.
We're still on CM 2007 so I figured why not give this a try and if it works, we just saved a lot of time and resources, if not then it would have to refreshed or upgraded through some other means.
I have tested it successfully on an HP Elitebook 8440p and it upgraded w/o a hitch, I thought something went wrong when I couldn't connect to it 2 hours later but the next morning I tried again and it worked.  So even if they don't officially list CM 2007, I can verify that it works.  I'll have to re-run the upgrade to see what goes on and how long it takes.  The tablets are powered by Atom processors and have SSD so I'm not sure how long they will take.  The only issue with them besides their sites having low bandwidth is their drive is only 32GB and near full.  Deploying a 3GB install might not work if it requires a lot of space during the upgrade.
Looking at the execmgr.log it appears that the SCCM client was still working as it periodically re-ran the advertisements and provided a 0 status every few hours and stopped at 2AM with occassionally lines of system restarted in between.  I'm thinking CM 2007 could not accurately track the install from the command line.

An interesting "side effect" of the upgrade was that it generated 15 more resourceID entries in the DB.  It's all obsolete but didn't expect to see that.



Thursday, January 21, 2016

SCCM Reporting: All Succeeded or Reboot Pending Status from advertisements using a specific package

We are progressing well with the IE 11 upgrade globally and all kinks are fixed for the most part.

Here's a query I use have used often when looking at the overall deployments success status for a large deployment project such as this.   We have over 12000+ machines to deploy to and for this project it was done with care from all the incompatibility and other environmental things that's not set for IE 11 until after IE 11 is installed on the system.   So this came in handy again for advertisements from testing, pilot, and production deployments and there are still more to be created!

This is a sub-query that pulls the advertisements status of 'Succeeded' and 'Reboot Pending' from the advertisements IDs tied to the package you're using.  In this instance it's both IE 11 packages.


Code below:

SELECT     v_R_System.Name0, vSMS_ClientAdvertisementStatus.LastStateName, vSMS_ClientAdvertisementStatus.LastStatusTime,
                      vSMS_ClientAdvertisementStatus.AdvertisementID, v_Advertisement.AdvertisementName, v_Advertisement.CollectionID, v_Collection.Name,
                      vSMS_ClientAdvertisementStatus.LastStatusMessageID
FROM         vSMS_ClientAdvertisementStatus INNER JOIN
                      v_R_System ON vSMS_ClientAdvertisementStatus.ResourceID = v_R_System.ResourceID AND
                      ((vSMS_ClientAdvertisementStatus.LastStateName = 'Succeeded' OR
                      vSMS_ClientAdvertisementStatus.LastStateName = 'Reboot Pending') and vSMS_ClientAdvertisementStatus.LastStatusMessageID != '10040') INNER JOIN
                      v_Advertisement ON vSMS_ClientAdvertisementStatus.AdvertisementID = v_Advertisement.AdvertisementID INNER JOIN
                      v_Collection ON v_Advertisement.CollectionID = v_Collection.CollectionID
WHERE     (vSMS_ClientAdvertisementStatus.AdvertisementID IN
                          (SELECT     adv.AdvertisementID
                            FROM          v_Advertisement AS adv INNER JOIN
                                                   v_Package AS pkg ON adv.PackageID = pkg.PackageID INNER JOIN
                                                   v_Collection AS v_Collection_1 ON adv.CollectionID = v_Collection_1.CollectionID
                            WHERE      (pkg.PackageID = 'XXX00853') OR
                                                   (pkg.PackageID = 'XXX00854')))

Wednesday, January 6, 2016

Create Collections from CSV file in SCCM 2007

Here's a script I use often for when we do targeted global deployments, I've combined a create collection script with one that reads from a CSV from the MSDN sample here: https://msdn.microsoft.com/en-us/library/ms974559.aspx .

Saves a lot of time from not using the console.  It reads from a CSV file with Headers defined as "Name" and "CollectionID" saved to c:\csv folder with the file named collections.csv which you can change to your liking.

The collectionID is the parent collection that will be created under.  Why 2 columns?  I like to separate EU, APAC, North America into their own given.  You may need to have parent collection created a head of time to retrieve the CollectionID.

Chances are you are running this on a x64 machine, if so, execute using cscript from c:\windows\syswow64\ instead of c:\windows\system32 or you might get an ADODB error.  You should not need any MDAC components, I'm running this on a Windows 2003 server.

Script contents:

'On Error Resume Next
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = &H0001

Set objConnection = CreateObject("ADODB.Connection")
Set objRecordSet = CreateObject("ADODB.Recordset")

Set objLoc =  CreateObject("WbemScripting.SWbemLocator")
Set objSMS= objLoc.ConnectServer(strSMSServer, "root\sms")
Set Results = objSMS.ExecQuery     ("SELECT * From SMS_ProviderLocation WHERE ProviderForLocalSite = true")
For each Loc in Results
    If Loc.ProviderForLocalSite = True Then
        Set objSMS = objLoc.ConnectServer(Loc.Machine, "root\sms\site_" & Loc.SiteCode)
    end if
Next
 

strPathtoTextFile = "C:\csv\"

objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
          "Data Source=" & strPathtoTextFile & ";" & _
          "Extended Properties=""text;HDR=YES;FMT=Delimited"""

objRecordset.Open "SELECT * FROM collections.csv", _
          objConnection, adOpenStatic, adLockOptimistic, adCmdText

Do Until objRecordset.EOF
    strColName=objRecordset.Fields.Item("Name")
    strParentID=objRecordset.Fields.Item("CollectionID")
    wscript.echo strColName & " " & strParentID
    CreateSCCMCollection
    objRecordset.MoveNext
Loop

Sub CreateSCCMCollection
Set newCollection = objSMS.Get("SMS_Collection").SpawnInstance_()

newCollection.Name = strColName
newCollection.OwnedByThisSite = True
path=newCollection.Put_

'the following two lines are used to obtain the CollectionID
'of the collection we just created
Set Collection=objSMS.Get(path)
strCollID= Collection.CollectionID
'now we create a relationship betwen the new collection
'and it's parent.

Set newCollectionRelation = objSMS.Get ( "SMS_CollectToSubCollect" ).SpawnInstance_()
newCollectionRelation.parentCollectionID = strParentID
newCollectionRelation.subCollectionID = strCollID
newCollectionRelation.Put_
End Sub

Tuesday, January 5, 2016

SCCM 2007 DCM using VBscript

I assume anyone reading this would already know about but may not have looked at other ways to set up a compliance item.

I have tried using Powershell which is much even easier to write and shorter but you will need to ensure your environment has the proper PS policies in place.   Since they will not budge on the PS policies I used VBScript.

In the script below, it is looking for the Encase agent service name and querying for 2 names depending on what OS it was installed on.  I also use a modified version to check on the service state for running or stopped.  I use this for all security applications for our retail environment to reduce any non-PCI compliant systems.

Script contents:

strComputer = "."

   Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
   Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Service where Name = 'enstart' or Name = 'enstart64' ")

   For Each objItem In colItems
      encasename=objItem.Name
      'encasestate=objItem.State
        Next

Select Case encasename
Case "enstart"
wscript.echo "Compliant"
Case "enstart64"
wscript.echo "Compliant"
Case Else
wscript.echo "Non-Compliant"
End Select

Monday, January 4, 2016

Remove packages from DP from SCCM 2007 using Powershell

Here's a script to remove all packages from a DP in 2007 scheduled to be decommissioned.  I'm aware of the cmd-lets that are available for this but unfortunately Windows 2003 R2 can only have PS v2 and internal firewall rules prevents me from running this from a remote 2008 R2 servers, this is what I have come up with a variation of what I found of adding a package to a DP but instead to delete.

$ErrorActionPreference = "SilentlyContinue"
$SCCMServer = ''YourSCCMSERVER"
$SMSSitecode = "YourSiteCode"
$DP = "YourDP"

$pkgs = Get-WMIObject -ComputerName $SCCMServer -Namespace "root\sms\site_$SMSSitecode"  -Query "Select * From SMS_DistributionPoint WHERE ServerNalPath like '%$DP%' and SourceSite = '$smssidecode'"
foreach ($pkg in $pkgs){write-host $pkg.PackageID;$ID.Delete()}

If you want to find out the ServerNalPath of the servers replace the code with the below.  If you have PXE shares, you may end up accidentally deleting something you don't want but those shares shouldn't be holding software packages.  Enter a packageID to limit the results or it will pull the ServerNALPath from all packageIDs.

$pkgs = Get-WMIObject -ComputerName $SCCMServer -Namespace "root\sms\site_$SMSSitecode"  -Query "Select * From SMS_DistributionPOint WHERE PackageID = '$packageid' and SourceSite = 'XXX'"

foreach ($pkg in $pkgs){write-host $pkg.ServerNalPath}

Replace XXX with your site code above.

Good resources for scripting in general and SCCM related.

https://technet.microsoft.com/en-us/scriptcenter/bb410849.aspx

https://msdn.microsoft.com/en-us/library/cc145334.aspx