The Deployment Bunny

OS Deployment, Virtualization, Microsoft based Infrastructure…

  • Archives

  • Meta

Archive for the ‘OSD’ Category

OSD – Adding Description to the WIM file during Build and Capture

Posted by Mikael Nystrom on October 10, 2017

The default capture function in MDT does not add any description. It is not needed, but can be added by modifying ZTIBackup.wsf. In this case I added the Task Sequence Name, but you can add other things as will, like Task Sequence Description or Task Sequence version. I did this at a demo at Microsoft Ignite last week but I did not post it at that time, so here it is.

The Session from Ignite is here if you would like to see it: https://www.youtube.com/watch?v=H9HGSVEaqQk

The how:

Modifying the Script

Take a copy of ZTIBackup.wsf, open it in your favorite VBscript editor and look for this section:

image

At line 436 you will see this:

sCmd = " /Capture-Image /CaptureDir:" & oDrive.Path & "  /ImageFile:""" & sBackupPath & """  /Name:""" & sPrefix & Left(oDrive.Path, 1) & "Drive"" /Compress:MAX /ConfigFile:""" & sWimScriptPath & """ /ScratchDir:""" & oUtility.LocalRootPath & "\Scratch"""

Change that to:

sCmd = " /Capture-Image /Description:""" & oEnvironment.Item("TaskSequenceName") & """ /CaptureDir:" & oDrive.Path & "  /ImageFile:""" & sBackupPath & """  /Name:""" & sPrefix & Left(oDrive.Path, 1) & "Drive"" /Compress:MAX /ConfigFile:""" & sWimScriptPath & """ /ScratchDir:""" & oUtility.LocalRootPath & "\Scratch"""

(The yellow text shows the modification)

The result:

Using Get-WindowsImage will show you that the description is now set to the Task Sequence name:

image

If you import the WIM file into ConfigMgr you will also see the description set as well as the Comment:

image

/Mike

Posted in ConfigMgr, Ignite, MDT, OS Deployment, OSD | Tagged: , , , , | Leave a Comment »

OSD – App-V tools are missing in ADK 1703 when being installed on Windows Server 2016 (sometimes)

Posted by Mikael Nystrom on April 6, 2017

In ADK 1607 the App-V tools was included in the ADK, for some reason they don’t show up when installing on Windows Server 2016 (sometimes). If you install on Windows Server 2012 R2 it works as expected

Install ADK 1703 on windows server 2016 - 1

The App-V task Sequencer is missing.

The solution:

It is however possible to manually install the App-V Sequencer if you downloaded the entire kit.

Find the file “Appman Sequencer on amd64-x64_en-us.msi” and run the installer, and “woops”, there it is:

image

 

/mike

Posted in ADK, OS Deployment, OSD | Tagged: , , | 6 Comments »

OS Deployment – Installing ADK 1703 on Windows Server 2016 could fail

Posted by Mikael Nystrom on April 6, 2017

Update:It does not happens on all WS2016 machines, it happens only on computer where Secure Boot is enabled. This also means that this will happen on every machine that is using Secure Boot, regardless of OS version. It is a confirmed bug.

Yesterday Microsoft released Windows 10 1703 and also ADK 1703. But it fails to install correctly, the ADK actually installs, but it is the WIM mount driver that fails, du to this absurd message.

Install ADK 1703 on windows server 2016 - 2

A digitally signed driver is required

The message indicates that the driver Windows Overlay Filter is not signed.

The Solution:

According to this https://social.msdn.microsoft.com/Forums/en-US/1fa43cc7-a82d-4dd3-8d28-f76fe2d7593e/hardware-development-kits-for-windows-10-version-1703-april-2017?forum=wdk , the solution is to disable Secure Boot, really???

image

/mike

Posted in ADK, OS Deployment, OSD | Tagged: , , | 2 Comments »

OSD – Conditional disk layout (based on model)

Posted by Mikael Nystrom on February 10, 2017

A while back I did an online training for Penton Tech https://education.pentontechnology.com/courses/deploying-windows-10-os-using-microsoft-deployment-toolkit on Windows 10 OS Deployment. One of the attendees had a question (you know who you are).

– Is it possible to format and partition differently, based on what model I’m deploying?

Yes, you can have different disk layout/partitioning/volumes, based on anything, and that includes the model of the computer. I use this when deploying servers and client to have different partition schemas on virtual machines, I do not need to have the recovery partition in the end of the virtual disk, I don’t really “repair” a Virtual Machine the same way as i recover a physical machine, and you should not.

So, how do you do this?

Open your task sequence and modify the New Computer step like this.

image
The modified Task Sequence.

In this Task Sequence there are three different group’s, one for virtual machines, one for HP ZBook Studio G3 and the last one for everything else.

The modification starts under Validate, the first step after that sets DiskDone=NO, next step is the Group named Virtual Machine with the following conditions set:

image
Conditions on the group Virtual Machine.

The the group is executed if the Model is ‘Virtual Machine’ and DiskDone is NOT set to YES, so basically if it is a Virtual Machine it will partition/format according to the steps in the group. In the end of the group it will set DiskDone to YES, that way we know the disks are done and we can use that to prevent the following partitioning steps from running. Let us check the next step:

image 
Conditions on the group HP ZBook Studio G3.

This step is the same as the step for Virtual Machine with one difference, in this case it only runs when the Model is a HP ZBook Studio G3. Let us check the last step:

image
Conditions on the group All others.

The last groups executes on any device, as long as DiskDone is NOT set to YES.

The Result.

Here is the result when running this in a Virtual Machine:

image

Here is the result when running this on a HP:

image

Here is a plain vanilla install:

image

Have fun!

/mike

Posted in Lite Touch, MDT, OS Deployment, OSD | Tagged: , , , | Leave a Comment »

OSD – Deploying Windows Server 2016 NANO using Microsoft Deployment Toolkit

Posted by Mikael Nystrom on January 31, 2017

The “Gandalf” of Windows Operating System has done it once again, I’m talking about Michael Niehaus of course. He has created a package for MDT Build 8443 that enables you to deploy NANO Server using MDT, including Domain Join.

image

Here is the link to the post. https://blogs.technet.microsoft.com/mniehaus/2017/01/11/deploying-nano-server-using-mdt/

Happy Deployment

/mike

Posted in NANO, OS Deployment, OSD, Windows Server 2016 | Tagged: , , , | Leave a Comment »

OSD – Add information to the Computer during OSD using a Custom Tattoo Step

Posted by Mikael Nystrom on December 2, 2016

When using an MDT (integrated in ConfigMgr or standalone) there is a step called Tattoo, this step will write information to the registry as well as to the WMI repository.

Let us see what it looks by default:

Get-WMIObject –Class Microsoft_BDD_Info

image
Result.

Get-Item -Path ‘HKLM:\SOFTWARE\Microsoft\Deployment 4’

image

Cool, but I need my own stuff?

We have done this for various  reasons and many customers, it could be used for making sure the computer ends up in certain ConfigMgr Collections, or that applications behave in a certain way, or that the asset management tools does the job differently, or that the correct support team can know what the computer was configured for, or what task sequence that was used, or…. As you see the are some valid reasons for this, no doubt.

The question is of course, should you modify the existing ZTITatto.wsf and corresponding .MOF file?, No, you should not do that, instead you should create new files and use them instead.

So, here is the download : https://github.com/DeploymentBunny/Files/tree/master/Tools/Custom-ZTITatoo

To make the work in a task sequence you need to add the files to you Scripts folder, update the CustomSettings.ini if you are using Custom Properties and add a step in the Task Sequence.

Here is a sample of CustomSettings.ini

image

I have added 4 new properties, added them to a MacAddress, so first step is to verify that the ZTIGather process reads this correct, let us verify this by running:

cscript \\redepl01\mdtproduction$\Scripts\ZTIGather.wsf /inifile:c:\Temp\CustomSettings.ini

image
Result after running the following command to perform the inventory.

Now, lets run the custom tattoo script:

cscript \\redepl01\mdtproduction$\Scripts\ViaMonstraTatoo.wsf

image
That looks great!

Now, let us verify that we get the correct data from WMI and Registry:

First, get the WMI repository:

Get-WmiObject -Class ViaMonstra_Info

image
The WMI repository was updated.

Let us check the Registry:

Get-Item -Path ‘HKLM:\SOFTWARE\ViaMonstra\OSD’

image
The Registry was updated.

At LabCenter

The Customer LabCenter deploys computer for hands-on labs and they wanted each computer to be tattooed with information regarding the LAB and one thing they use it for is to be able to display the information directly in the screen using BGinfo, but they also use it for other purposes. BGInfo reads the Registry values, or WMI

image

How to change my own stuff then?

Download the files from:https://github.com/DeploymentBunny/Files/tree/master/Tools/Custom-ZTITatoo and edit the scripts, (.wsf and .mof) by replacing the values that are in use, like

  • ViaMonstra
  • ViaRole
  • ViaClass
  • ViaOwner
  • ViaTag

Save, and verify

/mike

Posted in ConfigMgr, Lite Touch, MDT, OSD, Zero Touch | Tagged: , , , , | 5 Comments »

OSD – Microsoft Deployment Toolkit Build 8443 is out

Posted by Mikael Nystrom on November 14, 2016

Today a new version of MDT was released, the main reason is Quality Updates and full support for Windows Server 2016 as well as Windows 10 1607. It does require ADK 1607. If you are using MDT in your OS deployment solution, go ahead, download, read, update and enjoy live.

image

/mike

Posted in MDT, OSD | Tagged: , | 2 Comments »

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: , , , , , | 5 Comments »

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 »

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 »