{"id":8882,"date":"2025-05-16T04:47:55","date_gmt":"2025-05-16T04:47:55","guid":{"rendered":"https:\/\/pariswells.com\/blog\/?p=8882"},"modified":"2025-05-19T06:38:33","modified_gmt":"2025-05-19T06:38:33","slug":"shrink-and-defrag-avd-fslogix-profiles","status":"publish","type":"post","link":"https:\/\/pariswells.com\/blog\/research\/shrink-and-defrag-avd-fslogix-profiles","title":{"rendered":"Shrink and Defrag AVD Fslogix Profiles"},"content":{"rendered":"\n<p><a href=\"https:\/\/github.com\/FSLogix\/Invoke-FslShrinkDisk\">https:\/\/github.com\/FSLogix\/Invoke-FslShrinkDisk<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\"># Define the folder path containing the virtual disks\n$folderPath = \"\\\\xxxxxx\\fslogix-o365\"\n\n# Function to get an available drive letter, excluding floppy and CD-ROM drives\nfunction Get-AvailableDriveLetter {\n    # Get used drive letters\n    $usedLetters = Get-Partition | Where-Object { $_.DriveLetter } | Select-Object -ExpandProperty DriveLetter\n    # Get drive letters assigned to CD-ROM drives\n    $cdromLetters = Get-CimInstance -ClassName Win32_CDROMDrive | Select-Object -ExpandProperty Drive | ForEach-Object { $_[0] }\n    # Define reserved letters for floppy disks\n    $reservedLetters = @('A', 'B')\n    # Combine used, CD-ROM, and reserved letters\n    $excludedLetters = $usedLetters + $cdromLetters + $reservedLetters | Sort-Object | Get-Unique\n    # Get available letters from C to Z, excluding the ones above\n    $availableLetters = [char[]](67..90) | Where-Object { $_ -notin $excludedLetters }\n    if ($availableLetters) {\n        return $availableLetters[0]\n    }\n    throw \"No available drive letters found\"\n}\n\n# Function to get the disk number of a newly mounted VHD\nfunction Get-MountedVHDDiskNumber {\n    param (\n        [string]$VHDPath\n    )\n    # Get disk information after mounting\n    $disks = Get-Disk\n    # Look for the disk with the VHD path in its location or signature\n    $mountedDisk = $disks | Where-Object { $_.Location -eq $VHDPath -or $_.Path -eq $VHDPath }\n    if ($mountedDisk) {\n        return $mountedDisk.Number\n    }\n    throw \"Could not determine disk number for VHD: $VHDPath\"\n}\n\n# Get all VHD and VHDX files in the folder\n$vdiskFiles = Get-ChildItem -Recurse -Path $folderPath -Filter *.vhdx -File\n\n# Loop through each virtual disk file and compact it\nforeach ($vdisk in $vdiskFiles) {\n    Write-Host \"Compacting $($vdisk.FullName)...\"\n\n    try {\n        # Mount the VHD\n        Mount-VHD $vdisk.FullName -ErrorAction Stop\n\n        # Get the disk number of the mounted VHD\n        $diskNumber = Get-MountedVHDDiskNumber -VHDPath $vdisk.FullName\n        Write-Host \"Mounted VHD is on Disk $diskNumber\"\n\n        # Find an available drive letter\n        $driveLetter = Get-AvailableDriveLetter\n        Write-Host \"Using drive letter $driveLetter\"\n\n        # Assign the drive letter to the partition (assuming first partition, typically 1 for VHDs)\n        Get-Partition -DiskNumber $diskNumber -PartitionNumber 1 | Set-Partition -NewDriveLetter $driveLetter\n\n        # Run disk maintenance commands\n        chkdsk \"$($driveLetter):\" \/f \/x \/forceofflinefix \/scan\n        chkdsk \"$($driveLetter):\" \/sdcleanup \/x\n        defrag \"$($driveLetter):\" \/x\n        defrag \"$($driveLetter):\" \/k \/l\n        defrag \"$($driveLetter):\" \/x\n        defrag \"$($driveLetter):\" \/k\n\n        # Dismount the VHD\n        Dismount-VHD $vdisk.FullName\n\n        # Optimize the VHD\n        Optimize-VHD -Path $vdisk.FullName -Mode Full\n\n        Write-Host \"Compaction of $($vdisk.FullName) completed.\"\n    }\n    catch {\n        Write-Host \"Error processing $($vdisk.FullName): $_\"\n        # Ensure VHD is dismounted in case of error\n        try { Dismount-VHD $vdisk.FullName -ErrorAction SilentlyContinue } catch {}\n    }\n}\n\nWrite-Host \"All virtual disks in the folder have been compacted.\"<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>https:\/\/github.com\/FSLogix\/Invoke-FslShrinkDisk<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-8882","post","type-post","status-publish","format-standard","hentry","category-research"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts\/8882","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/comments?post=8882"}],"version-history":[{"count":2,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts\/8882\/revisions"}],"predecessor-version":[{"id":8891,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/posts\/8882\/revisions\/8891"}],"wp:attachment":[{"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/media?parent=8882"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/categories?post=8882"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pariswells.com\/blog\/wp-json\/wp\/v2\/tags?post=8882"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}