Thursday, April 28, 2016

Lenovo BIOS Updates in the Task Sequence

The question popped up in a forum the other day about how people handle the upgrade of Lenovo BIOS in a Task Sequence.  There are several ways of course which can be handled, of variable sophistication.  Mikael Nystrom developed a solution for me several years back which I used for several years and enhanced on my own, in MDT Task Sequences.  However when my organization was shifting to SCCM Task Sequencing I was asked to develop something a bit lighter. The old solution kept all the BIOS update files in one very large (500MB+) package.  Clearly not the right solution in SCCM where every package used has to be downloaded from the DP during imaging. 

I moved to a much lighter solution for SCCM. 

Each BIOS revision is kept in its own container package (that's what I call them anyway, a package with no assigned program, just used to hold content for use by something else).  Its basically the same idea as an SCCM Toolkit package, or Settings package.

Creating the BIOS packages:

  1. Go out to Lenovo and download the BIOS for each model for which you want to perform an upgrade during imaging.
  2. Extract the BIOS packages into a structure on your Package content share similar to:
    \\servername\imagecontent$\BIOSpackages\Lenovo\T450-V1.45
    \\servername\imagecontent$\BIOSpackages\Lenovo\T440-V2.08
    \\servername\imagecontent$\BIOSpackages\Lenovo\T430-V2.65
  3. Use the Administrator Console to create one Legacy type package from each of these folders
    (using the example above you'll end up with 3 packages)
  4.  Distribute these packages


Task Sequence Changes:

  1. Someplace after the machine has booted into Windows for the first time place the steps to perform the BIOS upgrades.  Be sure that the you place them after the Use Toolkit and Gather steps. 
  2. Create a new TS Group for the BIOS Updates to nest under, it makes turning the BIOS updates off if needed easier and keeps the TS cleaner
  3. Under the BIOS Updates group create a Run Command Line step for Model to be upgraded
    • The command line in each case will be "Winuptp.exe /S" this is the BIOS update installer for all Lenovo Laptop models and is contained in every BIOS update.  The "/S" tells it to run quietly and automated with new GUI. It will also suppress rebooting. 
    • Add a condition on the step using a WMI query so this step will only run for the proper model
      select * from win32_computersystemproduct where version = "ThinkPad T430"
    • Add a reference to the proper BIOS Package for the model being updated buy this step.
      • I've found it easiest to create the step once the copy it for each model, updating the package reference and the name of the step to reflect the proper model
    • It s a good idea to place a reboot computer step soon after the BIOS updates complete.  Be sure to put Use Toolkit package and Gather steps immediately after the reboot.
    I have exported the BIOS Steps from my Production TS, you should be able to import this open the stub TS, then copy and paste the steps into your own TS.  The Package References will be broken, because I didn't export the content.  My packages have naming and paths in them that I'd prefer not to expose.  You will only need to create the proper packages and update the references if you start with my stub.

    BiosStub


    Tuesday, April 19, 2016

    ZTIOSDNotify.ps1

    Sometime ago I started using Mikael Nystrom's ZTISendmail.ps1.  It was a great script however what I wanted and needed to do in my environment grew over time and I have expanded the script.  I therefore present ZTIOSDNotify.ps1 with much thanks and Credit to Mikael for providing the jumping off point.  

    While nothing was wrong with Mikael's script there was a need to do some additional things.  I was asked to post my results of OSD deployments to Sharepoint, the original script didn't handle SCCM deployments and the generated log files in in a way I liked (didn't give me everything), and I was asked to also post the logs to a network share (this part is actually in the TS and not the script,  but they work together so I'm including all of it)

    I am including links to the Script itself and to an exported SCCM TS with component parts that need to be added to a TS to use the script one Section however requires the SCCM NAA account so I will point out where to add that and how to set it up, since I can't save and export that step without valid details.

    ZTIOSDNotify.ps1

    NotifyTS Parts


    I keep the script in my toolkit package, however it could be a package of its own as well so long as the toolkit package is also loaded since it depends on functionality from the Toolkit package.

    Using the script requires a number of TS Variables (either in CS.ini or the TaskSequence, I actually do some in both places) and some specific setup in the Task Sequence to use all of the functionality.  I will document everything below.

    Task Sequence Variables (Where and how to set):
    Set or create the following TS variables in the Customsettings.ini (or Task Sequence Initialization)


    [Settings]
    Priority=Sendmail, Default
    Properties=OSDSendMailFrom, OSDSendMailToPri, OSDSendMailToSec,  OSDSendMailSMTPServer, OSDSendMailIncludeBDDLog

    [SendMail]
    OSDSendMailFrom=ImagingTeam@domain.com
    OSDSendMailToPri=ImagingTeam@domain.com
    OSDSendMailToSec=OtherPartys@domain.com
    OSDSendMailSMTPServer=smtp1.domain.com


    or
    (if your organization has more than one SMTP Server and you want to route traffic regionally for example)

    [Settings]
    Priority=SetSMTP, Sendmail, Default
    Properties=OSDSendMailFrom, OSDSendMailToPri, OSDSendMailToSec,  OSDSendMailSMTPServer, OSDSendMailIncludeBDDLog

    [SendMail]
    [SendMail]
    OSDSendMailFrom=ImagingTeam@domain.com
    OSDSendMailToPri=ImagingTeam@domain.com
    ;this could be removed from CS.ini and populated in the gather phase to be generated some other way into a list of people to be notified, say the Local IT technicians for the office the machine is being imaged in.
    OSDSendMailToSec=OtherPartys@domain.com
    ;OSDSendMailSMTPServer=smtp1.domain.com

    [SetRegion]
    UserExit=RegionExit.vbs
    OSDRegion=#GetRegion()#


    [SetSMTP]
    ;You will need some sort of Userexit or other code which returns the OSDRegion similar to the reference to RegionExit.vbs above
    Subsection=SMTP-%OSDRegion%

    [SMTP-AMR]
    OSDSendMailSMTPServer=smtp1.domain.com
    [SMTP-EUR]
    OSDSendMailSMTPServer=smtp2.domain.com
    [SMTP-ASP]
    OSDSendMailSMTPServer=smtp3.domain.com

    Set or Create the Following Task Sequence Variables in the Task Sequence Initialization:

    TSVersion  - This is a custom variable I use in my environment which stamps a version of the TS in the log files so the script can reflect which TS and version of it.  My environment has a couple TS in deployment so its good to know which one generated the Logs, Email, SharePoint Post, etc  Its typically set to a Major and a Minor version xx.yy (ex 12.34, 14.22)

    OSDSendMailIncludeBDDLog - Custom Variable a YES/NO Value should the script Capture and send the OSD logs, for SCCM the will cause the SMSTSLOG folder to be zipped up and captured, since the BDD.log doesn't contain everything like MDT.  This Variable instead be set in the Success or Failure sections later to get more control over if the logs should be included or not depending on success or failure

    Logcapture - Custom Variable to indicate under what conditions the results should be emailed, copied to network, posted to sharepoint - Success/Failure/Both

    OSDPostToSharePoint - Custom Variable a YES/NO Value should the script attempt to post the OSD results to a sharepoint site defined in the script. This Variable could instead be set in the Success or Failure sections later to get more control over if the logs should be included or not depending on success or failure

    TestSettings - This has some extended use in my environment, but for the purpose of the script it indicates in the email and postings if the TS was in testing which is a quick reference to those seeing the results if the results should be followed up or not.  Is a YES/NO Value

    LaunchSUI - I use this to trigger the launching of the Service UI Command line for debugging purposes of an image

    Using the Script and Integrating with the TS:

    Two sections are added to the TS to handle success and failure notifications in the TS, they are substantially the same, but need to be located in different places, particularly the Failure sections so it will properly process the Task Sequence Error code.

    For a failed TS:
    By Default a Standard TS includes a section to handle errors, this section should be enhanced adding a number of steps between "Copy Logs" and "Error in the Task Sequence"



    Define the RunFailure Variable Set to YES in this section so the script will know it is handling a TS failure



    For a Successful TS:

    For a successful TS a very similar set of steps needs to be added someplace before your TS successfully exits, keeping in mind that the Toolkit package and Gather step must exist shortly before the Steps run to have all the required information available.  A good place to do this is just before the "Report Done" step, Add a toolkit package reference and Gather step then add the Success section.

    Define the RunFailure Variable set to NO so the Script and TS will know to handle the reporting of status as a Successful TS Run.



    Both Success and Failure require a connection to a network location by the SCCM NAA if the log file copying to a network share functionality will be used, this step is "Connect to Network SCCM Log Folder" it couldn't be exported without including valid account details for a NAA so, I will instead detail how to set it up:

    1. A "Connect to Network Folder" step to the Task Sequence and Name it "Connect to Network SCCM Log Folder"
    2. Create a share on a server in your environment which will receive the files, under that share create a "Failure" and "Success" subfolder
      ex:
      \\logsserver\logsdir$
      \\logsserver\logsdir$\Success
      \\logsserver\logsdir$\Failure
    3. The SCCM NAA Account should have at least "Modify" NTFS Permissions and Read/Write on the Share
    4. In the TS Step Input the path to logsdir$ on the server
    5. make it the "L:" drive
    6. In the Account property add the SCCM NAA and the valid password when prompted
    SharePoint Integration:

    If the TS Variable OSDPostToSharePoint is set to YES, then the functionality to post to SharePoint will be triggered.

    A SharePoint List must be setup to receive the posting information through WEBDAV.  The account the TS is running as needs to have modify permissions to the SharePoint list.

    I have included a screenshot of the Sharepoint list settings.  I'll enhance this section of documentation as needed and as I find time. 


    Basically a SharePoint list needs to be created with the above field names.  The SCCM NAA or MDT Deployment Account needs to have permissions to the list. 

    The URL to the list needs to be added to the ZTIOSDNotify.ps1 script at line 31:
    Replacing the information in the "<>"
    $TeamSiteURL = "http://<site>.<Replace Domain>.com/sites/<Sharepoint Sub Site>"

    Update the List name at line 33:

    $List = "OSD Results"


    Other Notes:

    In the ZTIOSDNotify.ps1 Script there are lines of code which picks up the MODEL TS Variable,  If you are using the ModelAliasExit script in your environment to get more sane and friendly Model Names especially for Lenovo models.  I advise replacing the lines of code in the script with a reference to the MODELALIAS TS variable created by that script to get a sane model name. 

    Line 67:
    Write-Progress -Activity "Sending email" -Status "Got Machine Model $TSEnv:Model" -PercentComplete 55 -Id 1
    Becomes:
    Write-Progress -Activity "Sending email" -Status "Got Machine Model $TSEnv:ModelAlias" -PercentComplete 55 -Id 1

    Line 104:
    Model: $TSEnv:Model<br/>
    Becomes:
    Model: $TSEnv:ModelAlias<br/>

    Line 124:
    Model: $TSEnv:Model<br/>
    Becomes:
    Model: $TSEnv:ModelAlias<br/>


    Monday, April 4, 2016

    ModelAlias Exit and Lenovo Machines

    Long time users of MDT will most likely be aware of the ModelAliasExit.vbs script. 

    The Deployment Bunny has several articles on the script and download links to the script:

    Deployment Bunny

    There have been several updates to the script in it's lifetime.  However it seems that the definitive version of the script has been frozen at 1.0.4 for a few years now.  However this version has a serious issue in IMHO when it comes to Lenovo Models.  Between the 1.0.3 and 1.0.4 versions of the script line 143 was commented out.  This has the effect of not pulling the friendly model name for Lenovo machines.  It more or less forces the user MDT Admin using it to have to create an aliasing table for Lenovo models by hand.  

    I am not one to generally second guess the creators of such scripts.  However I truly do not understand the logic of what was done.  However every time someone mentions the script I feel the need to make mention of the problem with Lenovo models. 

    So let this post serve two purposes:

    1. Give me someplace where I've already documented the problem to point people to when I see such mentions of the script.

    2. Provide a location they can get what I consider to be a corrected version of the script.
    ModelAliasExit 1.0.5


    Thursday, March 3, 2016

    Quick and Easy MDT DB Clean UP

    For a while now I've been searching for a way to cleanup the 30,000 or so records that I just didn't need in my MDT database. I finally realized that Michael Niehaus MDT PowerShell Module held the answer with a little use of some Piping:

    Import-Module M:\MDTDB\MDTDB.psm1...
    Get-MDTComputer | Select-Object -Property ID,OSInstall | Where OSInstall -eq NO | Remove-MDTComputer


    In our environment we control if a machine can be imaged or not by setting and looking for the OSInstall Value in the DB. We have a Web front end to enter machines into the DB, and if the machine is valid for imaging (we check against a few data sources to detiremine this, sepecial cases require my team to manualy flip the vlaue to YES after we do further validation)Therefore I know if a Machine is set to OSInstall = NO that it has already been imaged. Therefore I was able to find all the DB records for machines that are currently NO and delete them with the above commandline in Powershell after importing the module.

    The second selected property to detiremine what machines to select out and the pipe to Remove-MDTComputer can be any value contained in the record for that computer in the database.

    Tuesday, February 9, 2016

    Move the MDT Progress Bar out of the way

    Sometime ago I had a problem with a dialog I was creating in my Task Sequences being covered up  by the Task Sequence Progress bar.  Back then I was able to find a simple AutoIT script which would automatically move the Progress bar out of the way.

    Alas as with many things on the internet it has disappeared from the Net, plenty of pointers to the script. However the location of the actual script no longer exists.  So having a copy I thought I'd do the world a favor and give it a new home.

    Progressmove.au3:

    #NoTrayIcon
    #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_Compile_Both=y
    #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
    ;zCFG-MoveTaskWindow
    ;Version 2.0 March 2008
    ;Reruns itself and returns - only works when compiled
    If $CmdLine[0] = 0 Then
        ; Rerun ourself and let this copy return to the task sequencer
        Run('"' & @AutoItExe & '" rerun')
        Exit
    EndIf
    Sleep(5000)        ; Time for the first script to return
    If WinExists("Installation Progress") Then
        $size = WinGetPos("Installation Progress")
        Mousemove($size[0]+50, $size[1]+50)
        MouseClick("left")
        WinMove("Installation Progress", "", 0, 0)
        Exit
    Else
        Exit
    EndIf

    I claim no rights or authorship to the script, just trying to help out since the original location seems to have disappeared.