Sorting the contents of an MDT 2010 deployment share


Quite some time ago (well over a year ago – time flies) I posted a script at http://blogs.technet.com/mniehaus/archive/2008/06/20/sorting-mdt-s-lists-of-applications-task-sequences-patches-etc.aspx that described how to sort the content in an MDT 2008 distribution share.  Now that MDT 2010 has been released, it’s important to first point out that this script will not work with MDT 2010 for a variety of reasons.


Since MDT 2010 has the same behavior, showing the items in the order that they were added in Workbench, that means you are now in need of a new script.  Fortunately, this isn’t too hard to do using a PowerShell script (and a little bit of knowledge of the underlying workings of the MDT 2010 PowerShell provider).  Here’s the script (also attached in a Zip file for those interested in a simpler download):



# ***************************************************************************
#
# File:      DeploymentShareSorter.ps1
#
# Author:    Michael Niehaus
#
# Purpose:   This PowerShell script will sort the existing files and folders
#            in a deployment share.
#
#            Note that there should be no one actively adding items to the
#            deployment share while running this script, as some of the
#            operations performed could cause these items to be lost.
#
#            This requires PowerShell 2.0 CTP3 or later.
#
# Usage:     Copy this file to an appropriate location.  Edit the file to
#            change the $rootPath variable below, pointing to your
#            deployment share. (This can be a local path or a UNC path.)
#
# ————- DISCLAIMER ————————————————–
# This script code is provided as is with no guarantee or warranty concerning
# the usability or impact on systems and may be used, distributed, and
# modified in any way provided the parties agree and acknowledge the
# Microsoft or Microsoft Partners have neither accountability or
# responsibility for results produced by use of this script.
#
# Microsoft will not provide any support through any means.
# ————- DISCLAIMER ————————————————–
#
# ***************************************************************************


# Constants


$rootPath = “\\mniehaus-t61p-7\DeploymentShare$”


# Conect to the deployment share


Add-PSSnapIn Microsoft.BDD.PSSnapIn -ErrorAction SilentlyContinue
New-PSDrive -Name DeploymentPointSorter -PSProvider MDTProvider -Root “$rootPath”


# Functions


function Sort-MDTFolderItems {


    [CmdletBinding()]
    PARAM
    (
        [Parameter(Position=1, ValueFromPipeline=$true)] $folder
    )
    Process
    {
        Write-Host “Sort-MDTFolderItems: Processing folder $($folder.Name)”
        # Initialize the sorted array
        $sorted = @()
        # Get the list of immediate subfolders, sort by name, and add to the array
        $folderPath = $folder.PSPath.Substring($folder.PSPath.IndexOf(“::”)+2)
        Get-ChildItem $folderPath | ? {-not $_.PSIsContainer} | Sort Name | % { $sorted += $_.Guid }
        # If there were any items found, process them.
        if ($sorted.Count -gt 0)
        {
            # See if the list is already sorted.  If it is, we don’t need to make any updates.
            $compareResults = compare-object $sorted $folder.Item(“Member”) -SyncWindow 0
            if ($compareResults -eq $null)
            {
                Write-Host “Already sorted.”
            }
            else
            {
                Write-Host “Saving sorted list.”
                # First remove all members of the list because the PowerShell provider will “optimize” the change by seeing there
                # were no items added or removed.  Then put all the members back in the sorted order.  (This is actually quite
                # dangerous to do as it could orphan the items, so we need to immediately put them back.)
                $folder.Item(“Member”) = @()
                $folder.Item(“Member”) = $sorted
            }
        }
    }
}


function Sort-MDTFolderSubfolders {


    [CmdletBinding()]
    PARAM
    (
        [Parameter(Position=1, ValueFromPipeline=$true)] $folder
    )
    Process
    {
        Write-Host “Sort-MDTFolderSubfolders: Processing folder $($folder.Name)”
        # Initialize the arrays
        $sorted = @()
        $unsorted = @()
        # Get the list of immediate child folders, sorted and unsorted
        $folderPath = $folder.PSPath.Substring($folder.PSPath.IndexOf(“::”)+2)
        $folderList = Get-ChildItem $folderPath | ? {$_.PSIsContainer}
        $folderList | % { $unsorted += $_.Name }
        $folderList | Sort Name | % { $sorted += $_.Name }
        # If there were any subfolders found, process them.
        if ($sorted.Count -gt 0)
        {
            # See if the list is already sorted.  If it is, we don’t need to make any updates.
            $compareResults = compare-object $sorted $unsorted -SyncWindow 0
            if ($compareResults -eq $null)
            {
                Write-Host “Already sorted.”
            }
            else
            {
                Write-Host “Sorting folders.”
                # Create the temporary folder
                $null = New-Item “$folderPath\__TEMP__” -ItemType Folder
                # Move the folders into the temporary folder
                $sorted | % { Move-Item “$folderPath\$_” “$folderPath\__TEMP__” }
                # Move the folders back
                $sorted | % { Move-Item “$folderPath\__TEMP__\$_” “$folderPath” }


                # Remove the temporary folder
                Remove-Item “$folderPath\__TEMP__”
            }
        }
    }
}


# Enumerate the folders and call the functions above to process each one


Get-ChildItem DeploymentPointSorter: -Recurse | ? {$_.PSIsContainer} | Sort-MDTFolderItems


Get-ChildItem DeploymentPointSorter: -Recurse | ? {$_.PSIsContainer} | Sort-MDTFolderSubfolders


Save this as “DeploymentShareSorter.ps1” and you are all set.  A few notes on this script:



  • This script requires PowerShell 2.0 – that’s all I use any more.

  • As provided, this will only sort one deployment share at a time, but it would be fairly simple to do multiple: just duplicate the final two lines, passing each path (e.g. DS001:) that you want to sort.

  • There is one operation in this script that is somewhat dangerous:
  •                  $folder.Item(“Member”) = @()
                    $folder.Item(“Member”) = $sorted

    I would suggest avoiding adding other items (drivers, applications, etc.) to the deployment share while this script is running, because those two lines could possibly cause those new items to be lost.  They first remove all items from the current folder and then add them back again (working around an optimization in the PowerShell provider code that tries to be smart about modified items – if you took out the first line the second line would have absolutely no effect).
  • This could take a while the first time through, but it should get faster after that first time because most of the content will already be sorted.

  • Don’t use a folder name of “__TEMP__” because that’s used by the script for sorting purposes.

  • Remember to edit the value assigned to the $rootPath variable.

  • If you want to schedule this script to run using the Windows Task Scheduler, just specify an action command line of “powershell.exe -File C:\Scripts\DeploymentShareSorter.ps1” (assuming the script was saved in C:\Scripts).

DeploymentShareSorter.zip


Comments (9)
  1. Hmm, haven’t seen that error before.  Does it happen every time you try?

  2. Anonymous says:

    Running the script for the first time and I had this error:

    Get-ChildItem : This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.

    At C:Documents and SettingsadmjfmartelDesktopDeploymentShareSorter.ps1:143 char:14

    + Get-ChildItem <<<<  DeploymentPointSorter: -Recurse | ? {$_.PSIsContainer} | Sort-MDTFolderSubfolders

       + CategoryInfo          : InvalidOperation: (:) [Get-ChildItem], RowNotInTableException

       + FullyQualifiedErrorId : ExceptionCaught,Microsoft.PowerShell.Commands.GetChildItemCommand

    Looks like everything is fine tough.

  3. j_seet says:

    Hi Mike,

    Nevermind.  I’ve managed to fix it by repairing the MDT2010 installation.  

  4. Hollanders Rens says:

    A functionality that should be in MDT by default, nevertheless this blog made my day! Many thanks!

  5. j_seet says:

    Hi Mike,

    I’m attempting to run your script but I receive the following errors:

    New-PSDrive : Cannot find a provider with name ‘MDTProvider’.

    At line:41 char:12

    + New-PSDrive <<<<  -Name DeploymentPointSorter -PSProvider MDTProvider -Root "$rootPath"

       + CategoryInfo          : ObjectNotFound: (MDTProvider:String) [New-PSDrive], ProviderNotFoundException

       + FullyQualifiedErrorId : ProviderNotFound,Microsoft.PowerShell.Commands.NewPSDriveCommand

    Get-ChildItem : Cannot find drive. A drive with name ‘DeploymentPointSorter’ does not exist.

    At line:143 char:14

    + Get-ChildItem <<<<  DeploymentPointSorter: -Recurse | ? {$_.PSIsContainer} | Sort-MDTFolderItems

       + CategoryInfo          : ObjectNotFound: (DeploymentPointSorter:String) [Get-ChildItem], DriveNotFoundException

       + FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

    Get-ChildItem : Cannot find drive. A drive with name ‘DeploymentPointSorter’ does not exist.

    At line:145 char:14

    + Get-ChildItem <<<<  DeploymentPointSorter: -Recurse | ? {$_.PSIsContainer} | Sort-MDTFolderSubfolders

       + CategoryInfo          : ObjectNotFound: (DeploymentPointSorter:String) [Get-ChildItem], DriveNotFoundException

       + FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

    I’ve only just uninstalled PowerShell v1 and installed v2 for the sole purpose of running this script as we have a LOT of applications that was seemingly randomly added.  

    Any Ideas to help get this going would be greatly appreciated!!

    Regards,

    Jon

  6. jasonj86tx says:

    Got the same error as jfmartel, most everything was sorted, but it dies at the same spot each time. Ran a second time and got the same thing

  7. JustinEdw says:

    I know this might be asking a lot. But is there anyway to make this work with MDT 2012 Beta 1? I have tried and it doesn't sort anything, I am guessing they changed the xml files around so they are slightly different…

  8. I always get this says:

    Get-ChildItem : This row has been removed from a table and does not have any data. BeginEdit() will allow creation of new data in this row. At C:Users__apjtDesktopDeploymentShareSorter.ps1:144 char:1 + Get-ChildItem DeploymentPointSorter: -Recurse
    | ? {$_.PSIsContainer} | Sort-MDTF … + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [Get-ChildItem], RowNotInTableException + FullyQualifiedErrorId : ExceptionCaught,Microsoft.PowerShell.Commands.GetChildItemCommand

  9. aw says:

    hai, I just want to tell you that I am just very new to blogs and seriously loved this website. More than likely I’m planning to bookmark your blog post .
    You amazingly come with really good posts. Thanks a lot for sharing your blog Microsoft.

    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Aceh
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Bali
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Balikpapan
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Bandung
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Banjarmasin
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Banten
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Batam
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Bekasi
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Bengkulu
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Bogor
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Bontang
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Cianjur
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Cikarang
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Cilegon
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Cirebon
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Denpasar
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Jakarta
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Jambi
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Jember
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Karawang
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Kendal
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Kudus
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Kupang
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Lampung
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Madiun
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Makasar
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Malang
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Maluku
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Manado
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Medan
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20NTT
    http://www.lokerjobindo.com/search/label/Loker%20Daerah%20Padang

Comments are closed.

Skip to main content