Use PowerShell to Organize MDT Application and Driver Folders

Use PowerShell to Organize MDT Application and Driver Folders

  • Comments 3
  • Likes

Summary: Learn how to use Windows PowerShell to organize MDT folders for drivers, applications, and operating systems.

Microsoft Scripting Guy, Ed Wilson, is here. MDT Week with Windows PowerShell MVP Sean Kearney continues today.

Yesterday, we learned how to extend one cmdlet in MDT into a useful advanced function that you can use to rebuild Deployment Shares on the fly. Now we will show the raw power of MDT—the ability to easily import applications, operating systems, and drivers into a well-organized image.

Really, all you are doing on the physical side is creating a folder structure under the Deployment Share. MDT presents a nice uniform interface to perform that task and gives you Windows PowerShell cmdlets to easily repeat it.

We are going to presume that you’ve used MDT at least once and that you are familiar with its structure.

Functionally, on the Windows PowerShell side (and even in MDT), when you’re importing an operating system, application, or an out-of-box driver or package, you will have two options: create a folder or import the package into a folder.

The reason you will want to create folders is the same reason you normally would (and should) create folders. Organization. The key to MDT is organization. The more organized (and in some cases granular) your structure is, the better you can select it later when you create Task Sequences and Selection Profiles.

So let us see where Windows PowerShell fits into this equation. When we do something like create a folder to import a single application, we normally get a Window like this:

Image of settings

We will have a Windows PowerShell script provided with it like this one:

Add-PSSnapIn Microsoft.BDD.PSSnapIn
New-PSDrive -Name "DS001" -PSProvider MDTProvider -Root "C:\MyDeploymentShare"
new-item -path "DS001:\Applications" -enable "True" -Name "Base Applications" -Comments "Programs every computer will have" -ItemType "folder" -Verbose

And as we import applications into that folder structure, scripts will be provided at each stage of our journey like this one:

Add-PSSnapIn Microsoft.BDD.PSSnapIn
New-PSDrive -Name "DS001" -PSProvider MDTProvider -Root "C:\MyDeploymentShare"
import-MDTApplication -path "DS001:\Applications\Base Applications" -enable "True" -Name "Adobe Acrobat Reader 9" -ShortName "Acrobat Reader" -Version "9" -Publisher "Adobe" -Language "Klingon" -CommandLine "msiexec.exe /I AcroRead.msi /qb /norestart" -WorkingDirectory ".\Applications\Adobe Acrobat Reader 9" -ApplicationSourcePath "C:\Adobe Reader 9" -DestinationFolder "Adobe Acrobat Reader 9" –Verbose

So if we look at the script and pull it apart, here is a list of details that we need to import the applications into MDT.

ApplicationFolder
DescriptiveName
ShortName of Application
Version
Publisher
Language
CommandLine (to launch the silent install)
WorkingDirectory
SourceFolder
DestinationFolder

This could easily be data that we have in a CSV file—especially if we are doing something like rebuilding a deployment point constantly. Or perhaps we are selling a solution using MDT for clients in a SMB. There are certain applications that you might consistently place within those deployments because there is no issue with licensing (for example, Silverlight, Live Meeting Client, or other Browser add-ons).

Rather than, “Every time I set up MDT for a new client, I have to type type type,” why not let Windows PowerShell do all the work while you collect all the pay?

We could take all of those variables we need and populate them into a CSV file with a format like the following (we will use the parameters we have for Adobe as our example):

"ApplicationFolder","DescriptiveName","ShortName","Version",Publisher","Language","CommandLine","WorkingDirectory","SourceFolder","DestinationFolder"
DS001:\Applications\Base Applications”,"Adobe Acrobat Reader 9","Acrobat Reader","9","Adobe","Klingon","msiexec.exe /I AcroRead.msi /qb /norestart",".\Applications\Adobe Acrobat Reader 9","C:\Adobe Reader 9","Adobe Acrobat Reader 9"

Now we have an easier way to redo this scenario. Rather than rekeying the source paths and details every time, we can have it all within a CSV file. For one application, it’s nice—but imagine if we had Silverlight or LiveMeeting Client…perhaps even some free antivirus or that WebEx client the boss insists must be on every client deployment? You could populate all of that information in your CSV file and then simply do this instead to populate all of it into MDT:

Add-PSSnapIn Microsoft.BDD.PSSnapIn
New-PSDrive -Name "DS001" -PSProvider MDTProvider -Root "C:\MyDeploymentShare"

$List=IMPORT-CSV C:\Powershell\MDTCommonApps.csv

Foreach ($App in $list) {

import-MDTApplication –path $App.ApplicationFolder -enable "True" –Name $App.DescriptiveName –ShortName $App.Shortname –Version $App.Version –Publisher $App.Publisher –Language $App.Language –CommandLine $App.CommandLine –WorkingDirectory $App.WorkingDirectory –ApplicationSourcePath $App.SourceFolder –DestinationFolder $App.DestinationFolder –Verbose

}

The beautiful part about MDT is importing additional patches, drivers, applications (and even operating systems) by following the same format. Identify what information you could drop into a CSV file, get the appropriate sample scripts, and edit them as needed.

For example, let’s say are importing drivers. Here are the sample scripts that I received for creating a folder called Network and importing all of my network drivers into it after creating a subfolder for each computer model:

Add-PSSnapIn Microsoft.BDD.PSSnapIn
New-PSDrive -Name "DS001" -PSProvider MDTProvider -Root "C:\testing"
new-item -path "DS001:\Out-of-Box Drivers" -enable "True" -Name "Network" -Comments "" -ItemType "folder" –Verbose

Add-PSSnapIn Microsoft.BDD.PSSnapIn
New-PSDrive -Name "DS001" -PSProvider MDTProvider -Root "C:\testing"
new-item -path "DS001:\Out-of-Box Drivers\Network" -enable "True" -Name "DellLatitude6410" -Comments "All Network Drivers for the Latitude 6410" -ItemType "folder" –Verbose

Add-PSSnapIn Microsoft.BDD.PSSnapIn
New-PSDrive -Name "DS001" -PSProvider MDTProvider -Root "C:\testing"
import-mdtdriver -path "DS001:\Out-of-Box Drivers\Network\DellLatitude6410" -SourcePath "C:\dell\drivers\Nic\6410" –Verbose

I simplify it by removing the repetitive lines because all the first two lines do is add the snap-in so we can use the cmdlets in MDT. Then I create a temporary mount point into the MDT deployment structure.

Add-PSSnapIn Microsoft.BDD.PSSnapIn
New-PSDrive -Name "DS001" -PSProvider MDTProvider -Root "C:\testing"

new-item -path "DS001:\Out-of-Box Drivers" -enable "True" -Name "Network" -Comments "" -ItemType "folder" –Verbose

new-item -path "DS001:\Out-of-Box Drivers\Network" -enable "True" -Name "DellLatitude6410" -Comments "All Network Drivers for the Latitude 6410" -ItemType "folder" –Verbose

import-mdtdriver -path "DS001:\Out-of-Box Drivers\Network\DellLatitude6410" -SourcePath "C:\dell\drivers\Nic\6410" –Verbose

Now we can consistently import drivers and keep them organized by Model and Driver type. We need only a small set of information for a CSV file (by stepping through each cmdlet one line at time). But really, we are performing two tasks. First, we are creating a folder structure for the drivers; and secondly, we are importing the drivers. We can get really complex or just stick to the KISS principle (Keep It Simple, Sir).

(No, I don’t mean singing, “I was made for lovin’ you baby baby.”)

The first file will simply be the folders that we want to create, probably with a simply header like this:

FolderName

Which means that our sample CSV file might look like this:

“FolderName”,”Comments”
”Network”,”All of Our Network Drivers”
”Video”,”Ummmm Video drivers too”
”Storage”,”I guess we need storage drivers”

The second file will be the locations of the sources and destinations of the data that we need to bring into MDT. Here is the data we will need:

DriverType
Comments
Destination Path
Model
DriverSource

Our sample CSV file could look like this:

“FolderPath”,“DriverType,”Comments”,”Destination Path”,”Model”,”DriverSource”
“DS001:\Out-of-Box Drivers”,“Network”,”All Network Drivers for the Latitude 6410”,”DS001:\Out-of-Box Drivers”,”Dell”,”C:\Dell\Drivers\Nic\6410”

Then to import these drivers, we would simply need to run a script similar to the last one. Import the data from a CSV file, execute the cmdlet based on the imported data, and then run home for lunch. We will have to do this twice for the drivers—once for the folder creation and once to import the actual data.

Add-PSSnapIn Microsoft.BDD.PSSnapIn
New-PSDrive -Name "DS001" -PSProvider MDTProvider -Root "C:\MyDeploymentShare"

$Folders=IMPORT-CSV C:\Powershell\DriverFolders.csv

Foreach ($Folder in $Folders) {

new-item -path "DS001:\Out-of-Box Drivers" -enable "True" –Name $Folder.Foldername –Comments $Folder.Comments -ItemType "folder" –Verbose

$List=IMPORT-CSV C:\Powershell\MDTDrivers.csv

Foreach ($Driver in $list) {

new-item -path "DS001:\Out-of-Box Drivers\Network" -enable "True" -Name "DellLatitude6410" -Comments "All Network Drivers for the Latitude 6410" -ItemType "folder" –Verbose

import-mdtdriver -path "DS001:\Out-of-Box Drivers\Network\DellLatitude6410" -SourcePath "C:\dell\drivers\Nic\6410" –Verbose

}

}

If we had to rebuild this system for disaster recovery purposes, or if we needed to easily redeploy it for clients as a solution, we simply need the drivers that we are going to deploy in addition to a little organization. By the way, if you are providing solutions for a small business, this is a great time to keep the “S” word in mind. Standardization. Trying to keep your workstation models as common as you possibly can across a client base allows you to use a more minimal driver set. You can, of course, use whatever drivers you want with MDT, but it is nice to keep a deployed image that works the same across all platforms.

If you had to repeat these techniques for importing patches or applications, the pattern is repetitive. Simply identify what data you need to repeat in the cmdlet, place that into a CSV file, and import away!

In all cases, you should be documenting your server build for MDT, but having that server build as an easily repeatable process pays for itself in the long term.

Next time, we will look at how to really get funky and down with MDT by fully automating the installation and creation of an MDT deployment share.

~Sean

Awesome, Sean. I am looking forward to Part 4 tomorrow.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Sean,

    as I already mentioned, I can't follow you on the MDT part of the articles, because I don't have it here.

    But again, your code is obviously not correct!

    Have a look at the inner loop of your script:

    ...

    $List=IMPORT-CSV C:\Powershell\MDTDrivers.csv

    Foreach ($Driver in $list) {

      new-item -path "DS001:\Out-of-Box Drivers\Network" -enable "True" -Name "DellLatitude6410" -Comments "All Network Drivers for the Latitude 6410" -ItemType "folder" –Verbose

      import-mdtdriver -path "DS001:\Out-of-Box Drivers\Network\DellLatitude6410" -SourcePath "C:\dell\drivers\Nic\6410" –Verbose

    }

    The least thing I'm missing is the use of $Driver inside the loop!

    Instead i'm finding constants here like "DellLatitude6410"

    This is not, what I expected!

    Maybe this is closer to what you wanted to do?

    Foreach ($Driver in $list) {

      new-item -path "$Driver.FolderPath\$Driver.DriverType" -enable "True" -Name "DellLatitude6410" -Comments "$Driver.Comments" -ItemType "folder" –Verbose

      import-mdtdriver -path "$Driver.FolderPath\$Driver.DriverType\DellLatitude6410" -SourcePath "$Driver.DriverSource" –Verbose

    }

    But i suspect that you even wanted something more, but we can't get it, using the given structure of the CSV files!

    The "model" in MdtDrivers.csv should be "DellLatitude6410" not "Dell" to be able to use $Driver.Model in the inner loop, that I couldn't now.

    I would exclude $Driver.FolderPath from MdtDrivers.csv and add it to DriverFolders.csv

    Additionally I would exclude the name of the MDT root from the path variables in the CSV files to make it "relativ".

    So we might end up with something like this:

    Add-PSSnapIn Microsoft.BDD.PSSnapIn

    $MdtRoot="$MdtRoot"

    New-PSDrive -Name $MdtRoot -PSProvider MDTProvider -Root "C:\MyDeploymentShare"

    $Folders=IMPORT-CSV C:\Powershell\DriverFolders.csv

    Foreach ($Folder in $Folders) {

    new-item -path "$MdtRoot:\$Folder.FolderPath" -enable "True" –Name $Folder.Foldername –Comments $Folder.Comments -ItemType "folder" –Verbose

    $List=IMPORT-CSV C:\Powershell\MDTDrivers.csv

    Foreach ($Driver in $list) {

    new-item -path "$MdtRoot:\$Driver.FolderPath\$Driver.DriverType" -enable "True" -Name $Driver.Model -Comments $Driver.Comments -ItemType "folder" –Verbose

    import-mdtdriver -path "$MdtRoot:\$Driver.Destination_Path" -SourcePath $Driver.DriverSource –Verbose

    }

    }

    Klaus.

  • I forgot to mention, that

    $List=IMPORT-CSV C:\Powershell\MDTDrivers.csv

    should be move before the loop as it is behaves like a constant, or better a loop invariant

    Klaus,

  • Hi Sean,

    hoe do i import many source files in single command