31 October 2012

SCCM/MDT BIOS Settings

If you have ever wondered how to automate setting the BIOS settings before an image is laid down on a machine using MDT or SCCM, here is the solution. This VBScript will inject the Dell CCTK into the WIM boot files that SCCM/MDT generate for booting a machine into the image setup. This allows the BIOS settings to be set before the SCCM/MDT image setup screen appears. There are certain BIOS settings, such as the Serial ATA controller setting that must be set before the image is laid down. This is where this script comes into play.

This will do the following to the MDT/SCCM generated boot WIM files: inject the Dell CCTK, inject the HAPI drivers, and modify the unattend.xml file so that the BIOS settings are updated before the Windows Deployment Wizard appears.

You can download this script from here.


 '*******************************************************************************   
 '      Program: Install.vbs   
 '       Author: Mick Pletcher   
 '         Date:   
 '     Modified:   
 '   
 '  Description: This will do the following to the MDT/SCCM generated WIM files:   
 '               inject the Dell CCTK, inject the HAPI drivers, and modify the   
 '               unattend.xml file.   
 ' Requirements: Microsoft WAIK, location for the locally stored WinPE files   
 '               (WinPEDIR Global Variable), MDT Server (I have 2 servers   
 '               MDT01 and MDT02), designation of architecture, and Dell CCTK.   
 '               NOTE: This script has been created to automate the update process   
 '               on a Windows 7 64-bit PC, therefor the directory locations of   
 '               the CCTK files will differ for an x86 machine.   
 '*******************************************************************************   
 Option Explicit   

 REM Define Constants   
 CONST TempFolder    = "c:\temp\"   
 CONST LogFolderName = "CCTK"   
 CONST MDT01         = "MDT01"   
 CONST MDT02         = "MDT02"   
 CONST WinPEDIR      = "c:\winpe\"   
 CONST x64           = "x64"   
 CONST x86           = "x86"   

 REM Define Global Variables   
 DIM LogFolder    : LogFolder        = TempFolder & LogFolderName & "\"   
 DIM RelativePath : Set RelativePath = Nothing   

 DefineRelativePath()   
 REM Refresh Local WIM Files from MDT Servers   
   DeleteLocalWIMFiles()   
   CopyWIMFiles( MDT01 )   
   RenameWIMFiles( MDT01 )   
   CopyWIMFiles( MDT02 )   
   RenameWIMFiles( MDT02 )   
 REM Process Local x86 file for MDT01   
   MountWIM MDT01,x86   
   AddWMI(x86)   
   CopyHAPIFiles( x86 )   
   CopyCCTKFiles( x86 )   
   EditUnattend( x86 )   
   DismountWIM()   
 REM Process Local x64 File for MDT01   
   MountWIM MDT01,x64   
   AddWMI(x64)   
   CopyHAPIFiles( x64 )   
   CopyCCTKFiles( x64 )   
   EditUnattend( x64 )   
   DismountWIM()   
 REM Process Local x86 File for MDT02   
   MountWIM MDT02,x86   
   AddWMI(x86)   
   CopyHAPIFiles( x86 )   
   CopyCCTKFiles( x86 )   
   EditUnattend( x86 )   
   DismountWIM()   
 REM Process Local x64 File for MDT02   
   MountWIM MDT02,x64   
   AddWMI(x64)   
   CopyHAPIFiles( x64 )   
   CopyCCTKFiles( x64 )   
   EditUnattend( x64 )   
   DismountWIM()   
 Complete()   
 GlobalVariableCleanup()   

 '*******************************************************************************   
 '*******************************************************************************   

 Sub DefineRelativePath()   

   REM Get File Name with full relative path   
   RelativePath = WScript.ScriptFullName   
   REM Remove file name, leaving relative path only   
   RelativePath = Left(RelativePath, InStrRev(RelativePath, "\"))   

 End Sub   

 '*******************************************************************************   

 Sub DeleteLocalWIMFiles()   

   REM Define Local Objects   
   DIM FSO    : Set FSO    = CreateObject("Scripting.FileSystemObject")   
   DIM oShell : SET oShell = CreateObject("Wscript.Shell")   

   REM Define Local Variables   
   DIM Parameters : Parameters = "/F /Q"   
   DIM sCMD_1     : sCMD_1   = "%COMSPEC% /c del " & RelativePath & "*MDT01.wim"   
   DIM sCMD_2     : sCMD_2   = "%COMSPEC% /c del " & RelativePath & "*MDT02.wim"   
   DIM sCMD_3     : sCMD_3   = "%COMSPEC% /c del " & RelativePath & "generic*.wim"   

   oShell.Run sCMD_1 & Parameters, 1, True   
   oShell.Run sCMD_2 & Parameters, 1, True   
   oShell.Run sCMD_3 & Parameters, 1, True   

   REM Cleanup Local Variables   
   Set sCMD_1     = Nothing   
   Set sCMD_2     = Nothing   
   Set sCMD_3     = Nothing   
   Set FSO        = Nothing   
   Set oShell     = Nothing   
   Set Parameters = Nothing   

 End Sub   

 '*******************************************************************************   

 Function CopyWIMFiles(Server)   

   REM Define Local Objects   
   DIM oShell : SET oShell = CreateObject("Wscript.Shell")   

   REM Define Local Variables   
   DIM Source      : Source      = "\\" & Server & "\DeploymentShare\Boot"   
   DIM Destination : Destination = "c:\winpe"   
   DIM Parameters  : Parameters  = "*.wim /eta /r:1 /w:0"   
   DIM Command01   : Command01   = "robocopy" & Chr(32) & Source & Chr(32) & Destination & Chr(32) & Parameters   

   oShell.Run Command01, 1, True   

   REM Cleanup Local Variables   
   Set Command01   = Nothing   
   Set Destination = Nothing   
   Set oShell      = Nothing   
   Set Parameters  = Nothing   
   Set Source      = Nothing   

 End Function   

 '*******************************************************************************   

 Function RenameWIMFiles(Server)   

   REM Define Local Objects   
   DIM FSO  : Set FSO  = CreateObject("Scripting.FileSystemObject")   

   REM Define Local Variables   
   DIM Source_x86 : Source_x86 = RelativePath & "LiteTouchPE_x86.wim"   
   DIM Source_x64 : Source_x64 = RelativePath & "LiteTouchPE_x64.wim"   
   DIM Dest_x86   : Dest_x86   = RelativePath & "LiteTouchPE_x86_" & Server & ".wim"   
   DIM Dest_x64   : Dest_x64   = RelativePath & "LiteTouchPE_x64_" & Server & ".wim"   

   If FSO.FileExists(Source_x86) then   
     If NOT FSO.FileExists(Dest_x86) then   
       FSO.MoveFile Source_x86, Dest_x86   
     End If   
   End If   
   If FSO.FileExists(Source_x64) then   
     If NOT FSO.FileExists(Dest_x64) then   
       FSO.MoveFile Source_x64, Dest_x64   
     End If   
   End If   

   REM Cleanup Local Variables   
   Set Dest_x86   = Nothing   
   Set Dest_x64   = Nothing   
   Set FSO        = Nothing   
   Set Source_x86 = Nothing   
   Set Source_x64 = Nothing   

 End Function   

 '*******************************************************************************   

 Function MountWIM(Server,Architecture)   

   REM Define Local Objects   
   DIM oShell : SET oShell = CreateObject("Wscript.Shell")   

   REM Define Local Variables   
   DIM MountDIR  : MountDIR  = RelativePath & "Mount"   
   DIM WIMFile   : WIMFile   = RelativePath & "LiteTouchPE_" & Architecture & "_" & Server & ".wim"   
   DIM Command01 : Command01 = "DISM /Mount-Wim /WIMFile:" & WIMFile & Chr(32) & "/Index:1 /MountDIR:" & MountDIR   

   oShell.Run Command01, 1, True   

   REM Cleanup Local Variables   
   Set Command01 = Nothing   
   Set MountDIR  = Nothing   
   Set oShell    = Nothing   
   Set WIMFile   = Nothing   

 End Function   

 '*******************************************************************************   

 Sub AddWMI(Architecture)   

   REM Define Local Objects   
   DIM oShell : SET oShell = CreateObject("Wscript.Shell")   

   REM Define Local Variables   
   DIM Image           : Image           = "/Image:" & RelativePath & "Mount"   
   DIM AddPackage      : AddPackage      = "/Add-Package"   
   DIM PackagePath     : Set PackagePath = Nothing   
   DIM PackagePath_x86 : PackagePath_x86 = "/PackagePath:" & Chr(34) &_   
                         "C:\Program Files\Windows AIK\Tools\PETools\x86\WinPE_FPs\winpe-wmi.cab" & Chr(34)   
   DIM PackagePath_x64 : PackagePath_x64 = "/PackagePath:" & Chr(34) &_   
                         "C:\Program Files\Windows AIK\Tools\PETools\amd64\WinPE_FPs\winpe-wmi.cab" & Chr(34)   
   DIM Command01       : Set Command01  = Nothing   

   If Architecture = "x86" Then   
     PackagePath = PackagePath_x86   
   Else   
     PackagePath = PackagePath_x64   
   End If   
   Command01 = "DISM" & Chr(32) & Image & Chr(32) & AddPackage & Chr(32) & PackagePath   
   oShell.Run Command01, 1, True   

   REM Cleanup Local Variables   
   Set AddPackage      = Nothing   
   Set Command01       = Nothing   
   Set Image           = Nothing   
   Set oShell          = Nothing   
   Set PackagePath     = Nothing   
   Set PackagePath_x86 = Nothing   
   Set PackagePath_x64 = Nothing   

 End Sub   

 '*******************************************************************************   

 Sub CreateFolderStructure(Architecture)   

   REM Define Local Objects   
   DIM FSO    : Set FSO    = CreateObject("Scripting.FileSystemObject")   
   DIM oShell : SET oShell = CreateObject("Wscript.Shell")   

   REM Define Local Variables   
   DIM Command01     : Set Command01 = Nothing   
   DIM Directory     : Set Directory = Nothing   
   DIM Directory_x86 : Directory_x86 = RelativePath & "Mount\CCTK\x86\HAPI"   
   DIM Directory_x64 : Directory_x64 = RelativePath & "Mount\CCTK\x86_64\HAPI"  
 
   If Architecture = "x86" Then   
     Directory = Directory_x86   
   Else   
     Directory = Directory_x64   
   End If   
   If NOT FSO.FolderExists(Directory) then   
     FSO.CreateFolder(Directory)   
   End If   

   REM Cleanup Local Variables   
   Set Command01     = Nothing   
   Set Directory     = Nothing   
   Set Directory_x86 = Nothing   
   Set Directory_x64 = Nothing   
   Set FSO           = Nothing   
   Set oShell        = Nothing   

 End Sub   

 '*******************************************************************************   

 Sub CopyHAPIFiles(Architecture)   

   REM Define Local Objects   
   DIM FSO    : Set FSO    = CreateObject("Scripting.FileSystemObject")   
   DIM oShell : SET oShell = CreateObject("Wscript.Shell")   

   REM Define Local Variables   
   DIM sCMD_1     : Set sCMD_1 = Nothing   
   DIM sCMD_2     : Set sCMD_2 = Nothing   
   DIM Source     : Set Source = Nothing   
   DIM Source_x86 : Source_x86 = "C:\Program Files (x86)\Dell\CCTK\X86\HAPI\*.*"   
   DIM Source_x64 : Source_x64 = "C:\Program Files (x86)\Dell\CCTK\X86_64\HAPI\*.*"   
   DIM Dest       : Set Dest   = Nothing   
   DIM Dest_x86   : Dest_x86   = RelativePath & "mount\CCTK\x86\HAPI"   
   DIM Dest_x64   : Dest_x64   = RelativePath & "mount\CCTK\x86_64\HAPI"   

   If Architecture = "x86" Then   
     Source = Source_x86   
     Dest  = Dest_x86   
   Else   
     Source = Source_x64   
     Dest  = Dest_x64   
   End If   
   sCMD_1 = "%COMSPEC% /c mkdir " & Dest   
   If NOT FSO.FolderExists(Dest) then   
     oShell.Run sCMD_1, 1, True   
   End If   
   sCMD_2 = "%COMSPEC% /c copy " & Chr(34) & Source & Chr(34) & Chr(32) & Dest & Chr(32) & "/V /Y"   
 '  If FSO.FolderExists(Source) then   
     oShell.Run sCMD_2, 1, True   
 '  End If   

   REM Cleanup Local Variables   
   Set Dest       = Nothing   
   Set Dest_x86   = Nothing   
   Set Dest_x64   = Nothing   
   Set FSO        = Nothing   
   Set oShell     = Nothing   
   Set sCMD_1     = Nothing   
   Set sCMD_2     = Nothing   
   Set Source     = Nothing   
   Set Source_x86 = Nothing   
   Set Source_x64 = Nothing   

 End Sub   

 '*******************************************************************************   

 Sub CopyCCTKFiles(Architecture)   

   REM Define Local Objects   
   DIM FSO : Set FSO = CreateObject("Scripting.FileSystemObject")   

   REM Define Local Variables   
   DIM CCTKFile   : CCTKFile   = "cctk.exe"   
   DIM MXMLFile   : MXMLFile   = "mxml1.dll"   
   DIM INIFile    : INIFile    = "multiplatform.ini"   
   DIM PCIFile    : PCIFile    = "pci.ids"   
   DIM NetSource  : NetSource  = "\\global.gsp\data\clients\na_clients\Dell\BIOS\"   
   DIM Source     : Set Source = Nothing   
   DIM Source_x86 : Source_x86 = "C:\Program Files (x86)\Dell\CCTK\X86\"   
   DIM Source_x64 : Source_x64 = "C:\Program Files (x86)\Dell\CCTK\X86_64\"   
   DIM Dest       : Set Dest   = Nothing   
   DIM Dest_x86   : Dest_x86   = RelativePath & "mount\CCTK\x86\"   
   DIM Dest_x64   : Dest_x64   = RelativePath & "mount\CCTK\x86_64\"   

   If Architecture = "x86" Then   
     Source = Source_x86   
     Dest  = Dest_x86   
   Else   
     Source = Source_x64   
     Dest  = Dest_x64   
   End If   
   If NOT FSO.FolderExists(Dest) then   
     FSO.CreateFolder(Dest)   
   End If   
   If FSO.FolderExists(Source) then   
     FSO.CopyFile Source & CCTKFile, Dest, 1   
   End If   
   If FSO.FolderExists(Source) then   
     FSO.CopyFile NetSource & INIFile, Dest, 1   
   End If   
   If FSO.FolderExists(Source) then   
     FSO.CopyFile Source & PCIFile, Dest, 1   
   End If   
   If FSO.FolderExists(Source) then   
     FSO.CopyFile Source & MXMLFile, Dest, 1   
   End If   

   REM Cleanup Local Variables   
   Set CCTKFile   = Nothing   
   Set INIFile    = Nothing   
   Set MXMLFile   = Nothing   
   Set PCIFile    = Nothing   
   Set Dest       = Nothing   
   Set Dest_x86   = Nothing   
   Set Dest_x64   = Nothing   
   Set FSO        = Nothing   
   Set Source     = Nothing   
   Set Source_x86 = Nothing   
   Set Source_x64 = Nothing   

 End Sub   

 '*******************************************************************************   

 Sub EditUnattend(Architecture)   

       REM Define Local Constants   
   CONST ForReading = 1   
   CONST ForWriting = 2   

   REM Define Local Objects   
   DIM File     : File       = "C:\winpe\mount\unattend.xml"   
   DIM strOld1    : strOld1      = "<Order>1</Order>"   
   DIM strNew1    : strNew1      = "<Order>4</Order>"   
   DIM strOld2    : strOld2      = "<RunSynchronous>"   
   DIM strNew2    : strNew2      = "<RunSynchronous>" & Chr(10) &_   
                     "<RunSynchronousCommand wcm:action=" & Chr(34) & "add" & Chr(34) & ">" & Chr(10) &_   
                     "<Description>Map BIOS Drive</Description>" & Chr(10) &_   
                     "<Order>1</Order>" & Chr(10) &_   
                     "<Path>net use \\global.gsp\data\clients\na_clients\dell\bios /user:{username/password}</Path>" & Chr(10) &_   
                     "</RunSynchronousCommand>" & Chr(10) &_   
                     "<RunSynchronousCommand wcm:action=" & Chr(34) & "add" & Chr(34) & ">" & Chr(10) &_   
                     "<Description>Initiate HAPI</Description>" & Chr(10) &_   
                     "<Order>2</Order>" & Chr(10) &_   
                     "<Path>X:\CCTK\x86_64\HAPI\hapint -i -k C-C-T-K -p X:\CCTK\x86_64\HAPI\</Path>" & Chr(10) &_   
                     "</RunSynchronousCommand>" & Chr(10) &_   
                     "<RunSynchronousCommand wcm:action=" & Chr(34) & "add" & Chr(34) & ">" & Chr(10) &_   
                     "<Description>Set BIOS Settings</Description>" & Chr(10) &_   
                     "<Order>3</Order>" & Chr(10) &_   
                     "<Path>x:\CCTK\x86_64\cctk.exe -i \\global.gsp\data\clients\na_clients\Dell\BIOS\multiplatform.ini</Path>" & Chr(10) &_   
                     "</RunSynchronousCommand>"   
   DIM objFSO        : Set objFSO        = CreateObject("Scripting.FileSystemObject")   
   DIM objFile       : Set objFile       = objFSO.getFile(File)   
   DIM objTextStream : Set objTextStream = objFile.OpenAsTextStream(ForReading)   
   DIM strInclude    : strInclude        = objTextStream.ReadAll   

   objTextStream.Close   
   Set objTextStream = Nothing   
   If InStr(strInclude,strOld1) > 0 Then   
      strInclude = Replace(strInclude,strOld1,strNew1)   
      Set objTextStream = objFile.OpenAsTextStream(ForWriting)   
      objTextStream.Write strInclude   
      objTextSTream.Close   
      Set objTextStream = Nothing   
   End If   
   If InStr(strInclude,strOld2) > 0 Then   
      strInclude = Replace(strInclude,strOld2,strNew2)   
      Set objTextStream = objFile.OpenAsTextStream(ForWriting)   
      objTextStream.Write strInclude   
      objTextSTream.Close   
      Set objTextStream = Nothing   
   End If   

   REM Cleanup Local Variables   
   Set File          = Nothing   
   Set objFile       = Nothing   
   Set objFSO        = Nothing   
   Set objTextStream = Nothing   
   Set strInclude    = Nothing   
   Set strNew1       = Nothing   
   Set strNew2       = Nothing   
   Set strOld1       = Nothing   
   Set strOld2       = Nothing   

 End Sub   

 '*******************************************************************************   

 Sub DismountWIM()   

   REM Define Local Objects   
   DIM oShell : SET oShell = CreateObject("Wscript.Shell")   

   REM Define Local Variables   
   DIM MountDIR  : MountDIR  = RelativePath & "Mount"   
   DIM Command01 : Command01 = "DISM /Unmount-WIM /MountDir:" & MountDIR & Chr(32) & "/commit"   

   oShell.Run Command01, 1, True   

   REM Cleanup Local Variables   
   Set Command01 = Nothing   
   Set MountDIR  = Nothing   
   Set oShell    = Nothing   

 End Sub   

 '*******************************************************************************   

 Sub Complete()   

   MsgBox "Process Complete"   

 End Sub   

 '*******************************************************************************   

 Sub GlobalVariableCleanup()   

   Set LogFolder    = Nothing   
   Set RelativePath = Nothing   

 End Sub  

30 October 2012

SCCM Automation Checklist

I have a checklist of automation procedures I want to include in SCCM during the upgrade process from SMS 2003.


  1. Create a script that will test the WMI on all machines. If an error occurs, SCCM will create a ticket in SCSM to be followed up on.
  2. Create a script that will find machines with low HDD space and create a ticket in SCSM.

SCCM Advanced Client Cache Size Reporting

This script will run a WMI query to gather the size of the advanced client cache and the amount of cache memory in use. It then makes a copy of the MIF file to be modified with the cache size and memory in use. It is then moved to the NOIDMIFS directory. A hardware inventory is then triggered which will force the server to retrieve the MIF file.

To properly execute this script, the MIF file included below needs to reside in the same directory as this script. It is a MIF template the VB script modifies to include the cache size and amount of cache being used.

NOTE: If you are needing a little remediation of MIF files, you can take a look at my other blog about the basics of MIF files.

You can download the script and MIF from the following links:



 '*******************************************************************************  
 '      Author: Mick Pletcher  
 '        Date: 29 October 2012  
 '    Modified:  
 '  
 '     Program: SMSCache  
 '     Version:  
 ' Description: This will retrieve the SMS/SCCM cache size and amount of memory  
 '                 in use to return to SMS via a MIF this script modifies.  
 '*******************************************************************************  
 Option Explicit  
 
 REM Define Constants  
 CONST TempFolder    = "c:\temp\"  
 CONST LogFolderName = "SMSCache"  

 REM Define Global Variables  
 DIM CACHESIZE    : Set CACHESIZE    = Nothing  
 DIM INUSE        : Set INUSE        = Nothing  
 DIM LogFolder    : LogFolder        = TempFolder & LogFolderName & "\"  
 DIM RelativePath : Set RelativePath = Nothing  

 REM Define the relative installation path  
 DefineRelativePath()  
 REM Create the Log Folder  
 CreateLogFolder()  
 REM Get Cache Info  
 GetCacheInfo()  
 REM Create MIF File to be copied to NOIDMIF directory  
 CreateMIF()  
 REM Generate MIF File  
 GenerateMIF()  
 REM Copy MIF to NOIDMIF directory  
 CopyMIF()  
 REM Initiate Hardware Inventory  
 InitiateHardwareInventory()  
 REM Cleanup Global Variables  
 GlobalVariableCleanup()  

 '*******************************************************************************  
 '*******************************************************************************  

 Sub DefineRelativePath()  

      REM Get File Name with full relative path  
      RelativePath = WScript.ScriptFullName  
      REM Remove file name, leaving relative path only  
      RelativePath = Left(RelativePath, InStrRev(RelativePath, "\"))  

 End Sub  

 '*******************************************************************************  

 Sub CreateLogFolder()  

      REM Define Local Objects  
      DIM FSO : Set FSO = CreateObject("Scripting.FileSystemObject")  

      If NOT FSO.FolderExists(TempFolder) then  
           FSO.CreateFolder(TempFolder)  
      End If  
      If NOT FSO.FolderExists(LogFolder) then  
           FSO.CreateFolder(LogFolder)  
      End If  

      REM Cleanup Local Variables  
      Set FSO = Nothing  

 End Sub  

 '*******************************************************************************  

 Sub GetCacheInfo()  

      DIM objWMIService : Set objWMIService = GetObject("winmgmts:\\.\root\ccm\softmgmtagent")  
      DIM colCacheInfo  : Set colCacheInfo  = objWMIService.ExecQuery("SELECT * FROM CacheConfig")  
      DIM objCacheInfo  : Set objCacheInfo  = Nothing  

      For Each objCacheInfo In colCacheInfo  
           INUSE     = objCacheInfo.INUSE  
           CACHESIZE = objCacheInfo.Size  
      Next  

      REM Cleanup Local Memory  
      Set colCacheInfo  = Nothing  
      Set objCacheInfo  = Nothing  
      Set objWMIService = Nothing  

 End Sub  

 '*******************************************************************************  

 Sub CreateMIF()  

      REM Define Local Objects  
      DIM FSO : Set FSO = CreateObject("Scripting.FileSystemObject")  

      If FSO.FileExists(RelativePath & "CacheInfo.mif") Then  
           If FSO.FileExists(RelativePath & "SMSCache.mif") Then  
                FSO.DeleteFile(RelativePath & "SMSCache.mif")  
           End If  
           FSO.CopyFile RelativePath & "CacheInfo.mif", RelativePath & "SMSCache.mif", True  
      End If  

      REM Cleanup Local Memory  
      Set FSO = Nothing  

 End Sub  

 '*******************************************************************************  

 Sub GenerateMIF()  

      REM Define Local Constants  
      CONST ForReading = 1  
      CONST ForWriting = 2  

      REM Define Local Objects  
      DIM objFSO        : Set objFSO        = CreateObject("Scripting.FileSystemObject")  
      DIM objFile       : Set objFile       = objFSO.getFile(File)  
      DIM objTextStream : Set objTextStream = objFile.OpenAsTextStream(ForReading)  
      DIM strInclude    : strInclude        = objTextStream.ReadAll  

      REM Define Local Variables
      DIM File     : File     = RelativePath & "SMSCache.mif"  
      DIM strOld01 : strOld01 = "        Value = " & Chr(34) & "INUSE" & Chr(34)  
      DIM strNew01 : strNew01 = "        Value = " & Chr(34) & INUSE & Chr(34)  
      DIM strOld02 : strOld02 = "        Value = " & Chr(34) & "CACHESIZE" & Chr(34)  
      DIM strNew02 : strNew02 = "        Value = " & Chr(34) & CACHESIZE & Chr(34)  


      objTextStream.Close  
      Set objTextStream = Nothing  
      If InStr(strInclude,strOld01) > 0 Then  
           strInclude = Replace(strInclude,strOld01,strNew01)  
           Set objTextStream = objFile.OpenAsTextStream(ForWriting)  
           objTextStream.Write strInclude  
           objTextSTream.Close  
           Set objTextStream = Nothing  
      End If  
      If InStr(strInclude,strOld02) > 0 Then  
           strInclude = Replace(strInclude,strOld02,strNew02)  
           Set objTextStream = objFile.OpenAsTextStream(ForWriting)  
           objTextStream.Write strInclude  
           objTextSTream.Close  
           Set objTextStream = Nothing  
      End If  

      REM Cleanup Local Memory  
      Set File          = Nothing  
      Set objFile       = Nothing  
      Set objFSO        = Nothing  
      Set objTextStream = Nothing  
      Set strInclude    = Nothing  
      Set strNew01      = Nothing  
      Set strNew02      = Nothing  
      Set strOld01      = Nothing  
      Set strOld02      = Nothing  

 End Sub  

 '*******************************************************************************  

 Sub CopyMIF()  

      REM Define Local Objects  
      DIM FSO      : Set FSO      = CreateObject("Scripting.FileSystemObject")  
      DIM NOIDMIFS : Set NOIDMIFS = Nothing  

      If FSO.FolderExists("C:\Program Files (x86)\") Then  
           NOIDMIFS = "C:\Windows\SysWOW64\CCM\Inventory\noidmifs\"  
      Else  
           NOIDMIFS = "C:\Windows\System32\CCM\Inventory\noidmifs\"  
      End If  
      IF FSO.FileExists(NOIDMIFS & "SMSCache.mif") Then  
           FSO.DeleteFile NOIDMIFS & "SMSCache.mif", True  
      End IF  
      FSO.CopyFile RelativePath & "SMSCache.mif", NOIDMIFS, True  
      If FSO.FileExists(RelativePath & "SMSCache.mif") Then  
           FSO.DeleteFile(RelativePath & "SMSCache.mif")  
      End If  

      REM Cleanup Local Memory  
      Set FSO      = Nothing  
      Set NOIDMIFS = Nothing  

 End Sub  

 '*******************************************************************************  

 Sub InitiateHardwareInventory()  

      On Error Resume Next  

      REM Define Local Objects
      DIM oCPAppletMgr   : Set oCPAppletMgr   = CreateObject("CPApplet.CPAppletMgr")  
      DIM oClientAction  : Set oClientAction  = Nothing  
      DIM oClientActions : Set oClientActions = oCPAppletMgr.GetClientActions()  

      For Each oClientAction In oClientActions  
           If oClientAction.Name = "Hardware Inventory Collection Cycle" Then  
                oClientAction.PerformAction  
           End If  
      Next  

      REM Cleanup local memory
      Set oCPAppletMgr   = Nothing
      Set oClientAction  = Nothing
      Set oClientActions = Nothing

 End Sub  

 '*******************************************************************************  

 Sub GlobalVariableCleanup()  

      Set CACHESIZE    = Nothing  
      Set INUSE        = Nothing  
      Set LogFolder    = Nothing  
      Set RelativePath = Nothing  

 End Sub  


MIF File

 Start Component   
    Name = "SMS Client Info"  
    Start group  
      Name = "SMS Cache"  
      ID = 1  
      Class = "SMSCache"   
      Start Attribute   
         Name = "In Use"  
         ID = 1  
         Type = String(10)  
         Value = "INUSE"  
      End Attribute   
      Start Attribute   
         Name = "Size"  
         ID = 2  
         Type = String(10)  
         Value = "CACHESIZE"  
      End Attribute   
    End group   
  End Component   

26 October 2012

OpenLM Agent Silent Install

Installing OpenLM Agent is a relatively straight-forward process. There are no settings required for the msi installer. In order to make it a silent install, you first need to install it on your own machine. Once installed, the  first time it runs, there will be a configuration window appear. Input the server name and any other pertinent data and then click apply. Now, go to the %ProgramFiles%\OpenLM\OpenLM Agent\ and copy the OpenLM_Agent.exe.config file to your installation directory. In your installation script, copy this file to the %ProgramFiles%\OpenLM\OpenLM Agent\ directory once the app is installed. That is all that needs to be done to automate the silent install.

You can download the script from here

Here is the tasks in file I named install.cmd:
 msiexec.exe /i %~dp0\openlm_utilizer_agent_win_1713.msi /qb- /norestart  
 timeout 2  
 taskkill.exe /IM OpenLM_Agent.exe /t /f  
 timeout 2  
 copy %~dp0\OpenLM_Agent.exe.config "C:\Program Files (x86)\OpenLM\OpenLM Agent\OpenLM_Agent.exe.config" /v /y /z  
 "C:\Program Files (x86)\OpenLM\OpenLM Agent\OpenLM_Agent.exe"  

17 October 2012

Font Installation Script

This script will install all fonts residing in the same folder as this script resides. I reads all of the font file names in the directory into an array. It then binds the script to the fonts folder and copies the fonts over to it, thereby initiating an automatic install upon copying. As an error checking mechanism, it first checks to make sure the font does not already exists in the c:\windows\Fonts folder. If it does, it skips over the installation of that font.

NOTE: On line 81, I have it compare the name in the array to the hardcoded filename. If they are the same, then it skips and goes to the next one. This is so the script does not read the VB Script. I left off the extension because I encapsulate the VB Script within an IPF file so that SCCM only has to execute the EXE. By leaving off the extension, it doesn't read the install.ipf, install.vbs, install.exe, or the install.wsm files.

Here is the download.

 '*******************************************************************************  
 '   Author: Mick Pletcher  
 '    Date: 17 October 2012  
 '  Modified:  
 '  
 ' Description: This will install all fonts residing in the same folder as this  
 '                 script.  
 '                 1) Define the relative installation path  
 '                 2) Create the Log Folder  
 '                 3) Read list of Fonts into Array  
 '                 4) Install Fonts  
 '                 5) Cleanup Global Memory  
 '*******************************************************************************  
 Option Explicit  

 REM Define Constants  
 CONST TempFolder    = "c:\temp\"  
 CONST LogFolderName = "Fonts"  

 REM Define Global Variables  
 DIM Count        : Count = 1  
 DIM LogFolder    : LogFolder = TempFolder & LogFolderName & "\"  
 DIM RelativePath : Set RelativePath = Nothing  
 ReDIM arrFiles(1)  

 REM Define the relative installation path  
 DefineRelativePath()  
 REM Create the Log Folder  
 CreateLogFolder()  
 REM Read list of Fonts into Array  
 ReadFonts()  
 REM Install Fonts  
 InstallFonts()  
 REM Cleanup Global Memory  
 GlobalMemoryCleanup()  

 '*******************************************************************************  
 '*******************************************************************************  

 Sub DefineRelativePath()  

      REM Get File Name with full relative path  
      RelativePath = WScript.ScriptFullName  
      REM Remove file name, leaving relative path only  
      RelativePath = Left(RelativePath, InStrRev(RelativePath, "\"))  

 End Sub  

 '*******************************************************************************  

 Sub CreateLogFolder()  

      REM Define Local Objects  
      DIM FSO : Set FSO = CreateObject("Scripting.FileSystemObject")  

      If NOT FSO.FolderExists(TempFolder) then  
           FSO.CreateFolder(TempFolder)  
      End If  
      If NOT FSO.FolderExists(LogFolder) then  
           FSO.CreateFolder(LogFolder)  
      End If  

      REM Cleanup Local Variables  
      Set FSO = Nothing  

 End Sub  

 '*******************************************************************************  

 Sub ReadFonts()  

      REM Define Local Objects  
      DIM FSO : Set FSO = CreateObject("Scripting.FileSystemObject")  

      REM Define Local Variables  
      DIM Folder : Set Folder = FSO.GetFolder(RelativePath)  
      DIM Files  : Set files  = Folder.Files  
      DIM File   : Set File   = Nothing  

      For each File in Files  
           If NOT Left(File.Name,Len(File.Name)-4) = "Install" then  
                arrFiles(Count) = File.Name  
                Count = Count + 1  
                ReDim Preserve arrFiles(Count)  
           End If  
      Next  
      Count = Count - 1  

      REM Cleanup Local Memory  
      Set File   = Nothing  
      Set Files  = Nothing  
      Set Folder = Nothing  
      Set FSO    = Nothing  

 End Sub  

 '*******************************************************************************  

 Sub InstallFonts()  

      REM Define Local Constants  
      Const FONTS = &H14&  

      REM Define Local Objects  
      DIM FSO      : Set FSO = CreateObject("Scripting.FileSystemObject")  
      DIM i        : Set i = Nothing  
      DIM oShell   : SET oShell = CreateObject("Shell.Application")  
      DIM oFolder  : Set oFolder = oShell.Namespace(FONTS)  
      DIM WshShell : Set WshShell = WScript.CreateObject("Wscript.Shell")  

      For i = 1 to Count  
           If NOT FSO.FileExists("c:\windows\Fonts\" & arrFiles(i)) then  
                oFolder.CopyHere RelativePath & arrFiles(i), 16  
           End If  
      Next  

      REM Cleanup Local Variables  
      Set FSO = Nothing  
      Set i = Nothing  
      Set oFolder = Nothing  
      Set oShell = Nothing  
      Set WshShell = Nothing  

 End Sub  

 '*******************************************************************************  

 Sub GlobalMemoryCleanup()  

      Set Count = Nothing  
      Set LogFolder = Nothing  
      Set RelativePath = Nothing  
      Erase arrFiles  

 End Sub  

10 October 2012

Adobe CS6 Error 1603

You are trying to install the Adobe CS6 distribution package you created using Adobe Application Manager, and it fails due to an error 1603. There are several different issues I encountered that can cause this.

  • The most common cause I saw was due to creating the distribution package using the 32-bit setting and trying to install it on a 64-bit OS. You are probably thinking about Microsoft Office 2010 where you can do that, but with CS6, you have to create independent packages for each architecture.
  • Another cause I encountered was the installation of Adobe Air while trying to install CS6 Design Stadfandard. When I uninstall Air, Design Standard successfully installed.
  • I also found that the prerequisites do not always install correctly with the distribution package the Application  Manager creates. For that, I downloaded the packages and prereq packages and installed them before the Design Standard installation. The packages are Visual C++ 2005 x86, Visual C++ 2010, and Visual C++ 2008.
  • Two machines I installed CS6 on were caused by the users having adobe CS5.5 applications open. CS6 was being installed in conjunction with the CS5.5 apps. Their profiles were still logged in with the apps open. If you manually run the installation, you will see the message appear below. Reboot the machine and it should fix this.

  • Another cause was due to the need to specify the installation directory in the configuration window of the Adobe Application Manager. You can specify an environmental variable like I did and it will translate it during installation.


07 October 2012

12v 4-pin Power Cable Shorts the Computer Out

If your computer is shorting out when you turn on the power button and you have narrowed the issue down to the short out occurring only when the 4-pin 12 volt power cable is connected, then most likely the issue is being caused by the CPU cooling device not being secured to the CPU. If this occurs, the motherboard will short out. To fix this, reseat the cooling device over the CPU. This may require you to also apply a new film of thermal paste for good contact.

In my case, my CPU is liquid cooled and the cooling channel had come loose. When I re-tightened the screws, the system powered right up with no issues. 

03 October 2012

Display All Logged On Users in a Domain

If you are like me, sometimes you need to find a few machines where no users are logged in. I have written this script that will scan a list of machines and tell whether a user is logged on or not. It reads a list of machine  names from a text file and then scans the list. It displays a status window while running of how far along it is in the scans. This can take sometime because it queries the WMI on each machine. If a machine is offline, then it will take a while to continue trying to connect to that machine until it goes to the next machine name in the list. The reason I have it read from a list is because I can easily export the list of computer names out of SMS/SCCM and into a simple delimited text file. The output file will display the list of machines with either a username to the right, signifying that there is a user logged on, or with no username beside the machine name.

You can download the file from here


 REM ***************************************************************************  
 REM ***     Program: UserLoggedOn.vbs  
 REM ***      Author: Mick Pletcher  
 REM ***     Created: 10 January 2010  
 REM ***      Edited: 02 October 2012  
 REM ***  
 REM *** Description: This script will read from a list of computer names and  
 REM ***              check to see if a user is logged on. It will write the   
 REM ***              status to the output text file for each system read from  
 REM ***              the input file. This was written like this so that admins  
 REM ***              can export lists of workstations from SMS/SCCM to find  
 REM ***              machines with no user logged on for troubleshooting  
 REM ***              deployments and/or find free machines to test other  
 REM ***              issues. It will display an error if there is no input  
 REM ***              file.  
 REM ***  
 REM ***************************************************************************  
 Option Explicit  

 REM Define Global Constants  
 CONST InputFileName  = "Workstations.txt"  
 CONST OutputFileName = "LoggedOn.txt"  

 REM Define Global Variables  
 DIM arrComputers    : Set arrComputers    = Nothing  
 DIM InputFile       : Set InputFile       = Nothing  
 DIM InputFileExists : Set InputFileExists = Nothing  
 DIM objIE           : Set objIE           = CreateObject("InternetExplorer.Application")  
 DIM OutputFile      : Set OutputFile      = Nothing  
 DIM RelativePath    : Set RelativePath    = Nothing  

 REM Define Relative Path  
 DefineRelativePath()  
 REM Define Input and Output Files  
 DefineIOFiles()  
 REM Create Display Window  
 CreateDisplayWindow()  
 If InputFileExists then  
      REM Read Input File  
      ReadInputFile()  
      REM Parse Computer Status  
      ParseComputerStatus()  
 Else  
      Wscript.Echo " File containing workstation list does not exist."  
 End If  
 REM Cleanup Global Memory  
 CleanupGlobalMemory()  

 '*******************************************************************************  
 '*******************************************************************************  

 Sub DefineRelativePath()  

      REM Get File Name with full relative path  
      RelativePath = WScript.ScriptFullName  
      REM Remove file name, leaving relative path only  
      RelativePath = Left(RelativePath, InStrRev(RelativePath, "\"))  

 End Sub  

 '*******************************************************************************  

 Sub DefineIOFiles()  

      REM Define Local Objects  
      DIM FSO : Set FSO = CreateObject("Scripting.FileSystemObject")  

      InputFile  = RelativePath & InputFileName  
      OutputFile = RelativePath & OutputFileName  
      If FSO.FileExists(InputFile) then  
           InputFileExists = True  
      Else  
           InputFileExists = False  
      End If  
      If FSO.FileExists(OutputFile) then  
           FSO.DeleteFile OutputFile, True  
      End If  

      REM Cleanup Memory  
      Set FSO = Nothing  

 End Sub  

 '*******************************************************************************  

 Sub CreateDisplayWindow()  

      REM Define Local Constants  
      CONST strComputer = "."  

      REM Define Local Objects  
      DIM objWMIService : Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")  
      DIM colItems      : Set colItems      = objWMIService.ExecQuery ("Select PelsWidth,PelsHeight From Win32_DisplayConfiguration")  
      DIM objItem       : Set objItem       = Nothing  

      REM Define Local Variables  
      DIM intWidth        : intWidth            = 500  
      DIM intHeight       : intHeight           = 300  
      DIM intScreenWidth  : Set intScreenWidth  = Nothing  
      DIM intScreenHeight : Set intScreenHeight = Nothing  

      For Each objItem in colItems  
           intScreenWidth  = objItem.PelsWidth  
           intScreenHeight = objItem.PelsHeight  
      Next  
      objIE.Navigate "about:blank"  
      objIE.Document.Title = "Users Logged On"  
      objIE.Toolbar  = 0  
      objIE.StatusBar = 0  
      objIE.AddressBar = 0  
      objIE.MenuBar  = 0  
      objIE.Resizable = 0  
      objIE.Width   = 500  
      objIE.Height   = 300  
      While objIE.ReadyState <> 4  
           WScript.Sleep 100  
      Wend  
      objIE.Left = (intScreenWidth / 2) - (intWidth / 2)  
      objIE.Top = (intScreenHeight / 2) - (intHeight / 2)  
      objIE.Visible = True  

      REM Cleanup Local Variables  
      Set colItems        = Nothing  
      Set intScreenWidth  = Nothing  
      Set intScreenHeight = Nothing  
      Set intWidth        = Nothing  
      Set intHeight       = Nothing  
      Set objItem         = Nothing  
      Set objWMIService   = Nothing  

 End Sub  

 '******************************************************************************  

 Sub ReadInputFile()  

      REM Define Local Constant  
      CONST ForReading = 1  

      REM Define Local Variables  
      DIM FSO         : Set FSO         = CreateObject("Scripting.FileSystemObject")  
      DIM objTextFile : Set objTextFile = FSO.OpenTextFile(InputFile, ForReading)  
      DIM strText     : strText         = objTextFile.ReadAll  

      objTextFile.Close  
      arrComputers = Split(strText, VbCrLf)  

      REM Cleanup Local Variables  
      Set FSO         = Nothing  
      Set objTextFile = Nothing  
      Set strText     = Nothing  

 End Sub  

 '*******************************************************************************  

 Sub ParseComputerStatus()  

      On Error Resume Next  

      REM Define Local Objects
      DIM FSO           : Set FSO           = CreateObject("Scripting.FileSystemObject")  
      DIM objFile       : Set objFile       = FSO.CreateTextFile(OutputFile, True)  
      DIM objWMIService : Set objWMIService = Nothing  

      REM Define Local Variables  
      DIM colItems    : Set colItems    = Nothing  
      DIM Count       : Count           = 0  
      DIM objItem     : Set objItem     = Nothing  
      DIM strComputer : Set strComputer = Nothing  
      DIM Total       : Set Total       = Nothing  

      objIE.Document.Body.InnerHTML = "<font color=black>"  
      objIE.Document.Body.InnerHTML = ""  
      objIE.Document.Body.InnerHTML = "Scanning Systems..." & "<BR>"  
      Count = Count + 1  
      Total = UBound(arrComputers)  
      For Each strComputer In arrComputers  
           Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")  
           Set colItems = objWMIService.ExecQuery("Select * from Win32_ComputerSystem",,48)  
           For Each objItem in colItems  
                If IsNull(objItem.UserName) then  
                     objFile.WriteLine( strComputer & ": ")  
                else  
                     objFile.WriteLine( strComputer & ": " & objItem.UserName )  
                End IF  
                If Round((Count/Total)*100, 0) <= 100 Then  
                     objIE.Document.Body.InnerHTML = "<font color=black>"  
                     objIE.Document.Body.InnerHTML = "Scanning Systems..." & "<BR>" & "<BR>" & Round((Count/Total)*100, 0) & "% complete"   
                     Count = Count + 1  
                End If  
           Next  
      Next  
      objIE.Document.Body.InnerHTML = "100% complete" & "<BR>" & "<BR>"&_  
                                              Total & Chr(32) & "systems scanned."  

      REM Cleanup Local Memory  
      Set colItems      = Nothing  
      Set Count         = Nothing  
      Set FSO           = Nothing  
      Set Total         = Nothing  
      Set objItem       = Nothing  
      Set objFile       = Nothing  
      Set objWMIService = Nothing  
      Set strComputer   = Nothing  

 End Sub  

 '*******************************************************************************  

 Sub CleanupGlobalMemory()  

      Set arrComputers    = Nothing  
      Set InputFile       = Nothing  
      Set InputFileExists = Nothing  
      Set OutputFile      = Nothing  
      Set RelativePath    = Nothing  

 End Sub