The Deployment Bunny

OS Deployment, Virtualization, Microsoft based Infrastructure…

  • about.me

    about.me/mikaelnystrom

  • Archives

  • Meta

OSD – BIOS upgrade during OS Deployment in MDT/ConfigMgr (v3)

Posted by Mikael Nystrom on July 20, 2016

This is the third version of the script solution; it is very simple. You detect make/model in any way you would like to, create a rule based on BIOS version, if the rule match, nothing happens, otherwise it runs any command you want. That said, you could use this for other task as well. Most common question is “does it work with any Make/Model”`No, there are some vendors that does not provide the ability to run a BIOS upgrade silently without reboot without control, that is, the darn thing reboots immediately and that usually breaks the Task Sequence. I have one thing for those vendors to say “Shame on you!”

here are older posts on the subject

https://deploymentbunny.com/2011/05/20/step-by-step-upgrading-bios-during-litetouch-deployment-for-dell-hewlett-packard-and-lenovo/

https://deploymentbunny.com/2013/12/16/step-by-step-upgrading-bios-during-litetouchzerotouch-deployment-for-dell-hewlett-packard-and-lenovo-v2/

Detect the Model

The detection in the script is actually whatever you want, it is just a “If-then”  here are two sample lines detection that you will find in the script

if($((Get-WmiObject Win32_ComputerSystem).model) -eq 'HP EliteBook 8560w'){}
if($ModelAlias -eq 'HP EliteBook 8460p'){}

Use the detection method for each model you like, very simple

Detect the BIOS version

This is also not that hard, here are 2 sample lines from the script

if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68SCF Ver. F.63'){}
if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '786G1 v01.27'){}

Store the upgrade files

The upgrade files are stored with the model name, like this:

image

The Silent Command

You also need to figure out the command, not really hard, download the bios upgrade, read how to run it from a command line, update the script and you are done, here is a sample of one of those sections.

$Exe = 'hpqflash.exe'
$Location = "$SCRIPTDIR\Source\HP EliteBook 8460p"
$Executable = $Location + "\" + $exe
Set-Location -Path $Location
Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68SCE.CAB" –Verbose

Run the script

in MDT you can import the folder with the script as a application and set this as the command line:

PowerShell.exe -ExecutionPolicy Bypass -File Install-BIOSUpgrade.ps1

In ConfigMgr you can import this as a Package and then run the command line the same way

It is also possible to run this outside of a task sequence if you like, it works as a stand alone script, however, you cannot use the integration with MDT of course.

If you want it is possible to add a custom property in customsettings.ini, something like “NeedReboot”, then you can add the following to happen if the BIOS has been upgraded

$tsenv.Value(“NeedReboot”) = “YES”

If you then in the step after this, set a condition on a reboot step, well then it will reboot when needed, otherwise not, you can read about that in one of my old postings here

https://deploymentbunny.com/2013/12/16/step-by-step-upgrading-bios-during-litetouchzerotouch-deployment-for-dell-hewlett-packard-and-lenovo-v2/

The result

BiosUpgradeResult
It was needed.

BiosUpgradeResultNotNeeded
It was not needed.

The Script


Function Import-SMSTSENV{
    try
    {
        $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
        Write-Output "$ScriptName - tsenv is $tsenv "
        $MDTIntegration = "YES"
        
        #$tsenv.GetVariables() | % { Write-Output "$ScriptName - $_ = $($tsenv.Value($_))" }
    }
    catch
    {
        Write-Output "$ScriptName - Unable to load Microsoft.SMS.TSEnvironment"
        Write-Output "$ScriptName - Running in standalonemode"
        $MDTIntegration = "NO"
    }
    Finally
    {
    if ($MDTIntegration -eq "YES"){
        $Logpath = $tsenv.Value("LogPath")
        $LogFile = $Logpath + "\" + "$ScriptName.log"

    }
    Else{
        $Logpath = $env:TEMP
        $LogFile = $Logpath + "\" + "$ScriptName.log"
    }
    }
}
Function Start-Logging{
    start-transcript -path $LogFile -Force
}
Function Stop-Logging{
    Stop-Transcript
}
Function Invoke-Exe{
    [CmdletBinding(SupportsShouldProcess=$true)]
 
    param(
        [parameter(mandatory=$true,position=0)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Executable,
 
        [parameter(mandatory=$false,position=1)]
        [string]
        $Arguments
    )
 
    if($Arguments -eq "")
    {
        Write-Verbose "Running $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru"
        $ReturnFromEXE = Start-Process -FilePath $Executable -NoNewWindow -Wait -Passthru
    }else{
        Write-Verbose "Running $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru"
        $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru
    }
    Write-Verbose "Returncode is $($ReturnFromEXE.ExitCode)"
    Return $ReturnFromEXE.ExitCode
}

# Set vars
$SCRIPTDIR = split-path -parent $MyInvocation.MyCommand.Path
$SCRIPTNAME = split-path -leaf $MyInvocation.MyCommand.Path
$SOURCEROOT = "$SCRIPTDIR\Source"
$SettingsFile = $SCRIPTDIR + "\" + $SettingsName
$LANG = (Get-Culture).Name
$OSV = $Null
$ARCHITECTURE = $env:PROCESSOR_ARCHITECTURE

#Try to Import SMSTSEnv
. Import-SMSTSENV

# Set more vars
$Make = $tsenv.Value("Make")
$Model = $tsenv.Value("Model")
$ModelAlias = $tsenv.Value("ModelAlias")
$MakeAlias = $tsenv.Value("MakeAlias")

#Start Transcript Logging
. Start-Logging

#Output base info
Write-Output ""
Write-Output "$ScriptName - ScriptDir: $ScriptDir"
Write-Output "$ScriptName - SourceRoot: $SOURCEROOT"
Write-Output "$ScriptName - ScriptName: $ScriptName"
Write-Output "$ScriptName - Current Culture: $LANG"
Write-Output "$ScriptName - Integration with MDT(LTI/ZTI): $MDTIntegration"
Write-Output "$ScriptName - Log: $LogFile"
Write-Output "$ScriptName - Model (win32_computersystem): $((Get-WmiObject Win32_ComputerSystem).model)"
Write-Output "$ScriptName - Name (Win32_ComputerSystemProduct): $((Get-WmiObject Win32_ComputerSystemProduct).Name)"
Write-Output "$ScriptName - Version (Win32_ComputerSystemProduct): $((Get-WmiObject Win32_ComputerSystemProduct).Version)"
Write-Output "$ScriptName - Model (from TSENV): $Model"
Write-Output "$ScriptName - ModelAlias (from TSENV): $ModelAlias"

#Check Model
if($((Get-WmiObject Win32_ComputerSystem).model) -eq 'HP EliteBook 8560w'){
    Write-Output "Model is $((Get-WmiObject Win32_ComputerSystem).model)"
    Write-Output "Checking BIOS Version"
    Write-Output "Version is $((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion)"
    if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68SVD Ver. F.50'){
        Write-Output "Needs upgrade"
        $Exe = 'hpqflash.exe'
        $Location = "$SCRIPTDIR\Source\HP EliteBook 8560w"
        $Executable = $Location + "\" + $exe
        Set-Location -Path $Location
        Invoke-Exe -Executable "$Executable" -Arguments "/s /p LCadmin1.bin" -Verbose
    }
    else
    {
        Write-Output "No Need to upgrade"
    }
}
if($((Get-WmiObject Win32_ComputerSystem).model) -eq 'HP ProBook 6570b'){
    Write-Output "Model is $((Get-WmiObject Win32_ComputerSystem).model)"
    Write-Output "Checking BIOS Version"
    Write-Output "Version is $((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion)"
    if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -Like '*ICE*'){
        if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68ICE Ver. F.62'){
            Write-Output "Needs upgrade"
            $Exe = 'hpqflash.exe'
            $Location = "$SCRIPTDIR\Source\HP ProBook 6570b"
            $Executable = $Location + "\" + $exe
            Set-Location -Path $Location
            Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68ICE.cab" -Verbose
        }
        else
        {
            Write-Output "No Need to upgrade"
        }
    }
    if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -Like '*ICF*'){
        if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68ICF Ver. F.62'){
            Write-Output "Needs upgrade"
            $Exe = 'hpqflash.exe'
            $Location = "$SCRIPTDIR\Source\HP ProBook 6570b"
            $Executable = $Location + "\" + $exe
            Set-Location -Path $Location
            Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68ICF.cab" -Verbose
        }
        else
        {
            Write-Output "No Need to upgrade"
        }
    }
}
if($ModelAlias -eq 'HP EliteBook 8460p'){
    Write-Output "Model is $((Get-WmiObject Win32_ComputerSystem).model)"
    Write-Output "Checking BIOS Version"
    Write-Output "Version is $((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion)"
    if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -Like '*SCF*'){
        if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68SCF Ver. F.63'){
            Write-Output "Needs upgrade"
            $Exe = 'hpqflash.exe'
            $Location = "$SCRIPTDIR\Source\HP EliteBook 8460p"
            $Executable = $Location + "\" + $exe
            Set-Location -Path $Location
            Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68SCF.CAB" -Verbose
            }
        else
            {
            Write-Output "No Need to upgrade"
        }
    }
    if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -Like '*SCE*'){
        if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '68SCE Ver. F.63'){
            Write-Output "Needs upgrade"
            $Exe = 'hpqflash.exe'
            $Location = "$SCRIPTDIR\Source\HP EliteBook 8460p"
            $Executable = $Location + "\" + $exe
            Set-Location -Path $Location
            Invoke-Exe -Executable "$Executable" -Arguments "/s /f 68SCE.CAB" -Verbose
            }
        else
            {
            Write-Output "No Need to upgrade"
        }
    }
}
if($((Get-WmiObject Win32_ComputerSystem).model) -eq 'HP Compaq dc7900 Small Form Factor'){
    Write-Output "Model is $((Get-WmiObject Win32_ComputerSystem).model)"
    Write-Output "Checking BIOS Version"
    Write-Output "Version is $((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion)"
    if($((Get-WmiObject Win32_Bios).SMBIOSBIOSVersion) -ne '786G1 v01.27'){
        Write-Output "Needs upgrade"
        $Exe = 'hpqflash.exe'
        $Location = "$SCRIPTDIR\Source\HP Compaq dc7900 Small Form Factor\HPQFlash"
        $Executable = $Location + "\" + $exe
        $SourceFile = $Location + "\" + "Password01.bin"
        $Destination = $env:TEMP
        $DestinationFile = $Destination + "\" + "Password01.bin"
        Copy-Item -Path $SourceFile -Destination $DestinationFile -Force -Verbose 
        Set-Location -Path $Location
        Invoke-Exe -Executable $Executable -Arguments "/s /p $DestinationFile"
    }
    else
    {
        Write-Output "No Need to upgrade"
    }
}

#Stop Logging
. Stop-Logging


/mike

Posted in BIOS, ConfigMgr, MDT, OS Deployment, OSD, PowerShell | Tagged: , , , , , | 2 Comments »

Just for fun–Converting a Laptop to a Tablet

Posted by Mikael Nystrom on July 12, 2016

very long time ago I did a teaser for a event, it was a joke on how to convert a Laptop computer into a Tablet PC. It turns out that for some reason a lot of people are searching for that video on my blog (I have no idea why), but here it is.

Understand that this “might” render the functionality of the computer… In other words, don’t do this…

/mike

Posted in Fun | Tagged: | Leave a Comment »

OSD–Customizing Images and deployment, think about that for a second

Posted by Mikael Nystrom on July 12, 2016

This is one of those blogposts that tries to answer lost of question and and the same time create new questions, but I get a lot of questions regarding the topic of “Image Customization”, and mainly about how-to, but

Why?

Before you even consider doing this, you need to understand why. The reason “we have always done that” is not really a great answer. There are basically to kinds of devices. The device is either going to be used as a “normal” computer by a user or it is a “thing” or in other words a task-oriented computer, like a teller machine, a kiosk machine. The later type needs heavy modifications to be adjusted, but spending the same effort a a regular computer is just waste of time.

But my users are idiots?

No, they are not. There will always be a few percent that don’t want to learn or actually have a hard time figuring out how to perform certain operations. But modifying every car on the planet so that every person can drive them is not really a smart thing, if a few percent of the org cannot select to add an application from ConfigMgr, why would you make it impossible for others do to so. Help them few percent that cannot do it and ask yourself the following?

– Do you reimage the phone for them?

– Do you reimage the TV set for them?

– Do you reimage the car stereo for them?

Windows 10 is different in more ways you can imagine

First, the operating system is “serviced”, that means that you will receive a new version approximately 2 times every year and that will be a upgrade, meaning it will fall back to the same apps you spent so many hours to remove, so that was just a waste of time.

Windows 10 will stick around for a while and it will not change much over the next 9 years (I’ll guess), so it is better that users learn it, they will have it at home and having a look and feel that is similar make sense for most users, but by trying to make Windows 10 look like Windows 7 does not really help people, it just prolong the learning that they need.

If you need to redo the work every time there is a new version, you will spend the rest of the Windows 10 era to find new ways to do these modifications, since the solution that worked in one version most likely will be broken in the next, we can see that happen over and over again.

My users should not be able to run “that”

Ok, so you want to remove the Xbox application, because? What is the danger? What could possible happen. Users are usually afraid of everything, so they don’t click at all when they have no idea what it is, and even if they do, running the Xbox app does not really do any harm. There are Security Baseline Policy’s that include the possibility to turn of many of those settings (not all) but this one will fix a lot of those “consumer” things.

“Enabled "Turn off Microsoft consumer experiences," – https://blogs.technet.microsoft.com/secguide/2016/01/22/security-baseline-for-windows-10-v1511-threshold-2-final/

Maybe there are other tasks that are more important then to make sure that it “looks” like Windows 7?

There are a lot of new security features that are very important, maybe it is better to think of a way to shift from BIOS to UEFI. That makes it possible to take advantage of many things, like Secure Boot and one of the most important features in Windows 10, Credential Guard.

Supported?

If you really want to do image-hacking, maybe you should consider if it is supported. Just because you can make it work today, it might render the possibility to deploy upgrades and updates when the next version comes around?

Yes, I do lost of modifications!

But I also have a long conversation with the customer before we go ahead and do it, i always check with friends inside Microsoft to see if it is kind of “ok”, before we do that.

What could be ok?

That is kind of easy, everything you can modify using GPO, GPP’s is usually perfectly fine to do, in most cases using PowerShell is also fine.

What I’m really try to say is

Think for a while, is that really, REALLY needed? or is it just “something we have always done”

Where can i find Information about this stuff?

https://blogs.technet.microsoft.com/secguide/2016/01/22/security-baseline-for-windows-10-v1511-threshold-2-final/

https://blogs.technet.microsoft.com/mniehaus/2015/12/31/updated-remove-apps-script-and-a-workaround/

http://ccmexec.com/

https://blogs.technet.microsoft.com/deploymentguys/

http://garytown.com/

/mike

Posted in OSD | Tagged: | 7 Comments »

PowerShell is King – Getting a massive amount of hotfixes from the Windows Update Site

Posted by Mikael Nystrom on June 30, 2016

Working for a customer in Norway, I received a list of “hotfixes” that needs to be downloaded and imported into WSUS for distribution, number of patches was 90. I have not found any great way to automate download from the Update Catalog into WSUS (there must be). So the here is the ugly version:

The ugly PowerShell script that starts Internet Explorer and add every patch to a separate tab

$Urls = Get-Content -Path C:\Temp\hotfixes.txt

$TabSettings = 0x1000;
$ie = New-Object -ComObject InternetExplorer.Application
$ie.Navigate2("http://www.microsoft.com");
foreach($Url in $Urls){
    $ie.Navigate2("$Url", $TabSettings);
}
$ie.Visible = $true;

The content of hotfixes.txt

http://catalog.update.microsoft.com/v7/site/Search.aspx?q=2965733
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=2981330
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3000123
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3014795
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3020813
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3020773
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3022333
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3027115
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3027110
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3025080
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3027108
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3023894
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3020717
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=2970653
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3033917
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3036614
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3042121
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3046481
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3042127
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3044457
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3046826
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3031598
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3036173
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3047296
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3018489
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3049448
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3047280
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3052122
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3049443
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3061460
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3060678
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3063283
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3068445
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3072380
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3068444
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3072381
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3077354
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3075610
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3076950
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3076946
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3075161
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3078411
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3080728
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3078584
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3076953
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3012714
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3073062
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3087856
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3078420
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3025091
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3078631
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3094197
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3053667
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3093571
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3090322
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3093272
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3094199
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3094209
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3095711
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3082343
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3093899
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3093550
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3095319
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3091403
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3084093
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3095308
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3091057
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3090973
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3092005
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3095663
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3091402
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3063109
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3102354
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3105881
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3100527
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3101694
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3087288
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3092604
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3100477
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3080141
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3084463
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3102770
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3109099
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3102997
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3114133
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3109973
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3123538
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3127673
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3123593
http://catalog.update.microsoft.com/v7/site/Search.aspx?q=3107677

Posted in PowerShell | Tagged: | Leave a Comment »

PowerShell is King – Simple function to test a VMSwitch is present

Posted by Mikael Nystrom on May 27, 2016

When building VM’s, they are usually connected to a Hyper-V switch, so when working for a customer I suddenly needed to verify that the switch actually exists before building the VM. One way to solve this is of course to use Get-VMSwitch –Name, but if it cant find it, it blows up and turns red and angry, the other way is to use “Count”, that way I can return whatever I need, in this case I Return True or False.

Usage:

Create a .psm1 file, copy the content, paste into the file, save the file and use the Import-Module function. After that you can test it by running commands similar to this.

image
Using the function to test a VMswitch is present on the local machine.

The Function:

Function Test-FAVMSwitchexistence
{
    Param(
        [string]$VMSwitchname
    )
        $Item = (Get-VMSwitch | Where-Object -Property Name -EQ -Value $VMSwitchname).count
        If($Item -eq '1'){Return $true}else{Return $false}
}

Mike

Posted in Hyper-V, PowerShell | Tagged: , | Leave a Comment »

OSD – The future of MDT is going to be PowerShell!

Posted by Mikael Nystrom on May 18, 2016

At MMSmoa today, Michael Niehaus presented a new approach for MDT, the shift from VBscript to PowerShell. They idea is to get the code up on GitHub. The basic engine and framework will be done, but it will allow for contributors to test and verify and even provide suggestions.

You can check it out here: https://github.com/mtniehaus/PSD

The New Task Sequence:

image

image

The Install App Step:

image

/mike

Posted in MDT | Tagged: | 6 Comments »

OSD – Export drivers using a task sequence in Lite Touch and some PowerShell

Posted by Mikael Nystrom on May 18, 2016

Yesterday i did a demo of a Task Sequence I use to extract drivers from a computer that already have all drivers correctly installed, could be a system that I need to reinstall, or a new machine with fairly new drivers installed. The Task Sequence basically grabs information from the computer, such as Operating System, Architecture and Model or Modelalias, grabs the drivers and copy them to the deployment share. I can then import the drivers to a ConfigMgr package or use them in LiteTouch for deployment.

The script is fairly simple and easy to change to fit in your environment.

The Task Sequence

It contains 3 steps, a gather step to get the inventory of the machine correctly, a set finish action to avoid reboot if your are using finish action in customsettings.ini and the application that grabs the drivers. Since it is a application this task sequence works only when Windows is running, not in WinPE.

image
The Task Sequence.

The Application

The Script runs as an application, so you need to download the script to a folder and then import it as an application with following settings:

PowerShell.exe -ExecutionPolicy Bypass -File ExportDrivers.ps1

image
The Extract Drivers Application in Deployment Workbench.

The Script

The PowerShell script is a generic script I use a s “wrapper”, so it does have functions that is not really needed in this scenario, so it is possible to make it shorter if you for any reason want that. The script detects if it has been invoked from a task sequence or not, if it has, it will create a path based on deployment root, Operating System, Architecture and ModelAlias (If you don’t use ModelAlias UserExit, start to do that or change to Model in the script), otherwise it will export the drivers to C:\ExportedDrivers

The active part of the script looks like this:

image
The active part of the script.

Note that it will delete all drivers that begins with PRN. That is printer drivers and I usually do not want them.

ExportDrivers.ps1

<#
 Install Wrapper 1.0
 Author: Mikael Nystrom
 http://www.deploymentbunny.com 
#>
 
Function Invoke-Exe{
    [CmdletBinding(SupportsShouldProcess=$true)]
 
    param(
        [parameter(mandatory=$true,position=0)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Executable,
 
        [parameter(mandatory=$false,position=1)]
        [string]
        $Arguments
    )
 
    if($Arguments -eq "")
    {
        Write-Verbose "Running $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru"
        $ReturnFromEXE = Start-Process -FilePath $Executable -NoNewWindow -Wait -Passthru
    }else{
        Write-Verbose "Running $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru"
        $ReturnFromEXE = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Wait -Passthru
    }
    Write-Verbose "Returncode is $($ReturnFromEXE.ExitCode)"
    Return $ReturnFromEXE.ExitCode
}
Function Get-OSVersion([ref]$OSv){
    $OS = Get-WmiObject -class Win32_OperatingSystem
    Switch -Regex ($OS.Version)
    {
    "6.1"
        {If($OS.ProductType -eq 1)
            {$OSv.value = "Windows 7 SP1"}
                Else
            {$OSv.value = "Windows Server 2008 R2"}
        }
    "6.2"
        {If($OS.ProductType -eq 1)
            {$OSv.value = "Windows 8"}
                Else
            {$OSv.value = "Windows Server 2012"}
        }
    "6.3"
        {If($OS.ProductType -eq 1)
            {$OSv.value = "Windows 8.1"}
                Else
            {$OSv.value = "Windows Server 2012 R2"}
        }
    "10."
        {If($OS.ProductType -eq 1)
            {$OSv.value = "Windows 10"}
                Else
            {$OSv.value = "Windows Server 2016"}
        }
    DEFAULT { "Version not listed" }
    } 
}
Function Import-SMSTSENV{
    try
    {
        $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
        Write-Output "$ScriptName - tsenv is $tsenv "
        $MDTIntegration = "YES"
         
        #$tsenv.GetVariables() | % { Write-Output "$ScriptName - $_ = $($tsenv.Value($_))" }
    }
    catch
    {
        Write-Output "$ScriptName - Unable to load Microsoft.SMS.TSEnvironment"
        Write-Output "$ScriptName - Running in standalonemode"
        $MDTIntegration = "NO"
    }
    Finally
    {
    if ($MDTIntegration -eq "YES"){
        $Logpath = $tsenv.Value("LogPath")
        $LogFile = $Logpath + "\" + "$ScriptName.log"
 
    }
    Else{
        $Logpath = $env:TEMP
        $LogFile = $Logpath + "\" + "$ScriptName.txt"
    }
    }
}
Function Start-Logging{
    start-transcript -path $LogFile -Force
}
Function Stop-Logging{
    Stop-Transcript
}
 
# Set Vars
$SCRIPTDIR = split-path -parent $MyInvocation.MyCommand.Path
$SCRIPTNAME = split-path -leaf $MyInvocation.MyCommand.Path
$SOURCEROOT = "$SCRIPTDIR\Source"
$LANG = (Get-Culture).Name
$OSV = $Null
$ARCHITECTURE = $env:PROCESSOR_ARCHITECTURE
 
#Try to Import SMSTSEnv
. Import-SMSTSENV
 
#Start Transcript Logging
. Start-Logging
 
#Detect current OS Version
. Get-OSVersion -osv ([ref]$osv) 
 
#Output base info
Write-Output ""
Write-Output "$ScriptName - ScriptDir: $ScriptDir"
Write-Output "$ScriptName - SourceRoot: $SOURCEROOT"
Write-Output "$ScriptName - ScriptName: $ScriptName"
Write-Output "$ScriptName - OS Name: $OSV"
Write-Output "$ScriptName - OS Architecture: $ARCHITECTURE"
Write-Output "$ScriptName - Current Culture: $LANG"
Write-Output "$ScriptName - Integration with MDT(LTI/ZTI): $MDTIntegration"
Write-Output "$ScriptName - Log: $LogFile"
 
if($MDTIntegration -eq "YES"){
    $RootFolder = $tsenv.Value("Deployroot")
    $Arch = $tsenv.Value("Architecture")
    $Model = $tsenv.Value("ModelAlias")
    $Path = $RootFolder + "\Drivers\" + $OSV + "\" + $Arch + "\" + $Model
}
else{
    $Path = "C:\ExportedDrivers"
}

Write-Output "$ScriptName - Driver export path: $Path"

#Export Drivers
Export-WindowsDriver -Destination $Path -Online -Verbose

#Get Printer Drivers
Get-ChildItem -Path $Path -Filter PRN* -Directory | Remove-Item -Force -Recurse

. Stop-Logging

/mike

Posted in Lite Touch, MDT, OS Deployment, OSD | Tagged: , , , | 6 Comments »

OSD – In MDT 2013 Update 2–Sometimes “WimSplit” works and sometimes not

Posted by Mikael Nystrom on May 11, 2016

and i do not like “sometimes”. The need for WimSplit is big, the most common reason is to install Windows on a UEFI based machine. In that case the boot media must be FAT32 and a single file cannot be larger then 4095 MB, but a plain vanilla Windows Server 2016 is bigger, so…

The fix

Make sure that the operating system name ends with .WIM

image

Make sure that the Settings.XML file in the Deployment share\Control folder has the following setting:

image

And, look it is working…

image

/mike

Posted in MDT, OS Deployment, OSD | Tagged: , , | 7 Comments »

OSD – Prevent Windows to “randomly” run Windows Update during the creation of a reference image

Posted by Mikael Nystrom on May 10, 2016

You should absolutely have patches installed in your reference image, no question about the. The default setting in Microsoft Deployment Toolkit is to run Windows Update “when needed” and the default behavior is the same, so basically Windows will run Windows Update when it “feels” for it. When the machine is managed it is controlled, but a reference image is created when the operating system is unmanaged. This could result in all kinds of issues, it could result in a pending reboot “sometimes” or failure to install software “sometimes”. I don’t like “sometimes” or random…

Turn of random Windows Updates during reference image creation

It is actually very easy, you need to change “Protect Your PC” from 1 to 3

image
All settings for ProtectYourPC.

If you open the unattend.xml file in Windows System Image Manager it looks like this:

image
ProtectYourPC is now set to 3.

This way Windows Update will performed manually or since you are using MDT and LiteTouch as your tool to create the reference image, the two Windows Update steps will do the updates and no more “random” updates.

image
The two Windows Update steps in the LTI task sequence.

/mike

Posted in OS Deployment, OSD | Tagged: , | 15 Comments »

Windows Server 2016 Technical Preview 5 is available for download

Posted by Mikael Nystrom on April 28, 2016

Compared to TP4, yes there are improvement’s, that is for sure.

Your can read most of it here https://technet.microsoft.com/en-us/library/dn765472(v=ws.12).aspx 

image

However, there is also a “release notes” that you must read, it mention one very important piece!

“Install Cumulative Update for Windows Server 2016 Technical Preview 5 (KB3157663) before installing any server roles, features, or other products. If you install roles before installing the update, a variety of issues can occur. If this happens, reinstall the preview release and then immediately install the update.”

You can read more about that update here https://support.microsoft.com/en-us/kb/3157663 and download it from Microsoft Catalog:

image

/mike

Posted in Windows Server 2016 | Tagged: | 2 Comments »

 
Follow

Get every new post delivered to your Inbox.

Join 7,423 other followers