Show-Fat32Converter.ps1

function Show-Fat32Converter
{
  <#
    .SYNOPSIS
    Provides a GUI to format removable disks using a command line utility. The command line utility requires the Windows operating system.
 
    .DESCRIPTION
    The actual formatting is performed by an open-source command line utility (requiring Windows).
    This function provides a simple GUI interface that lets you select a removable drive, and set its label.
    Your input is then automatically submitted to the command line utility.
 
    .EXAMPLE
    Show-Fat32Converter
    Opens the GUI
 
    .LINK
    https://done.land/tools/powershell
  #>


  Add-Type -AssemblyName PresentationFramework
  $xaml = @'
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width ="400"
SizeToContent="Height"
ResizeMode="NoResize"
WindowStartupLocation = "CenterScreen"
Title="FAT32 Disk Formatting - done.land"
Topmost="True">
<Grid Margin="10,40,10,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Name="txtHeader" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Margin="5">Please select the disk drive to format:</TextBlock>
 
<TextBlock Grid.Column="0" Grid.Row="1" Margin="5">Drive</TextBlock>
<TextBlock Grid.Column="0" Grid.Row="2" Margin="5">Volume Label</TextBlock>
<ComboBox Name="comboDrive" Grid.Column="1" Grid.Row="1" Margin="5"/>
<TextBox Name="txtLabel" Grid.Column="1" Grid.Row="2" Margin="5" CharacterCasing="Upper" MaxLength="11"/>
 
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,10,0,0" Grid.Row="3" Grid.ColumnSpan="2">
<Button Name="ButOk" MinWidth="80" Height="22" Margin="5">Format</Button>
<Button Name="ButCancel" MinWidth="80" Height="22" Margin="5">Cancel</Button>
</StackPanel>
</Grid>
</Window>
'@

  #endregion
  
  #region find formatting tool
  $exepath = Join-Path -Path $PSScriptRoot -ChildPath "binaries/fat32format.exe"
  $exists = Test-Path -Path $exepath -PathType Leaf
  if (!$exists)
  {
    [System.Windows.MessageBox]::Show("fat32format.exe not found. This file must be located in binaries/$PSScriptRoot", "FAT32 Disk Formatting - done.land", 'Ok', 'warning')
    return
  }
  
  try { Unblock-File -Path $exepath } catch {}
  #endregion find formatting tool
  
  #region get removable disks
  [Array]$list = Get-CimInstance -ClassName Win32_Volume -Filter 'DriveType=2' | 
  Select-Object -Property DriveLetter, FileSystem, Label, @{N='FriendlyName';E={
      $label = if ([string]::IsNullOrEmpty($_.Label)) { '(no drive label set)' } else { $_.Label }
    '{0} [{1:n1} GB {3}] - {2}' -f $_.DriveLetter, ($_.Capacity/1GB),$label, $_.FileSystem}
  } | 
  Sort-Object -Property DriveLetter
    
  if ($list.Count -eq 0)
  {
    [System.Windows.MessageBox]::Show("No removable disks found. Insert disk and try again.", "FAT32 Disk Formatting - done.land", 'Ok', 'warning')
    return
  }
    
    
  $firstNonFat32 = 0
  foreach($_ in $list)
  {
    if ($_.FileSystem -ne 'FAT32') { break }
    $firstNonFat32++
  }
    
  $count = ($list | Where-Object FileSystem -ne 'FAT32').Count
  if ($count -eq 0)
  {
    if ([System.Windows.MessageBox]::Show("All removable disks are already FAT32.`r`n`r`nContinue anyway?", "FAT32 Disk Formatting - done.land", 'yesNo', 'warning', 'no') -eq 'no')
    {
      return
    }
    $firstNonFat32 = 0
  }
    
  #endregion get removable disks
  
  #region Code Behind
  function Convert-XAMLtoWindow
  {
    param
    (
      [Parameter(Mandatory=$true)]
      [string]
      $XAML
    )
      
    Add-Type -AssemblyName PresentationFramework
      
    $reader = [XML.XMLReader]::Create([IO.StringReader]$XAML)
    $result = [Windows.Markup.XAMLReader]::Load($reader)
    $reader.Close()
    $reader = [XML.XMLReader]::Create([IO.StringReader]$XAML)
    while ($reader.Read())
    {
      $name=$reader.GetAttribute('Name')
      if (!$name) { $name=$reader.GetAttribute('x:Name') }
      if($name)
      {$result | Add-Member NoteProperty -Name $name -Value $result.FindName($name) -Force}
    }
    $reader.Close()
    $result
  }
    
  function Show-WPFWindow
  {
    param
    (
      [Parameter(Mandatory=$true)]
      [Windows.Window]
      $Window
    )
      
    $result = $null
    $null = $window.Dispatcher.InvokeAsync{
      $result = $window.ShowDialog()
      Set-Variable -Name result -Value $result -Scope 1
    }.Wait()
    $result
  }
  #endregion Code Behind
  
  #region Convert XAML to Window
  $window = Convert-XAMLtoWindow -XAML $xaml 
  #endregion
  
  #region Define Event Handlers
  $window.ButCancel.add_Click(
    {
      $window.DialogResult = $false
    }
  )
    
  $window.ButOk.add_Click(
    {
      $window.ButCancel.IsEnabled = $false
      $window.ButOk.IsEnabled = $false
      $window.txtLabel.isEnabled = $false
      $window.comboDrive.IsEnabled = $false
      $drive = $window.comboDrive.SelectedItem.DriveLetter
      $label = $window.txtLabel.Text.Trim()
      $containsData = (Get-ChildItem -Path "$drive\").Count -gt 0
      $message = 
      if ($containsData)
      {
        "The drive contains data that will be lost.`r`n`r`nAll data on drive $drive will be erased. Are you sure?"
      }
      else
      {
        "All data on drive $drive will be erased. Are you sure?"
      }
      if ([System.Windows.MessageBox]::Show($window, $message, "FAT32 Disk Formatting - done.land", 'yesNo', 'warning', 'no') -eq 'yes')
      {
        try
        {
          $window.txtHeader.Text = 'Formatting...'
          $window.Dispatcher.Invoke([System.Action]{}, 'Background')
          
          $arguments = "-l""$label""", '-y', $drive
          Start-Process -FilePath $exepath -ArgumentList $arguments -Wait -WindowStyle Hidden
          
          $window.txtHeader.Text = 'Formatting completed.'
          $window.Dispatcher.Invoke([System.Action]{}, 'Background')
          
          [System.Windows.MessageBox]::Show($window, "Formatting completed.", "FAT32 Disk Formatting - done.land", 'Ok', 'information')
        }
        catch
        {
          [System.Windows.MessageBox]::Show($window, "Unable to format: $($_.Exception.Message)`r`n`r`nThis tool requires the Windows operating system.", "FAT32 Disk Formatting - done.land", 'Ok', 'information')
        }
        $window.DialogResult = $true
        try
        {
          explorer.exe shell:MyComputerFolder
        }
        catch {}
      }
      else
      {
        $window.DialogResult = $false
      }
    }
  )
  $window.comboDrive.add_SelectionChanged{
    $window.txtLabel.Text = $_.source.SelectedItem.Label
  }
    
  #endregion Event Handlers
  
  #region Manipulate Window Content
  
    
  $window.comboDrive.ItemsSource = $list
  $window.comboDrive.SelectedIndex = $firstNonFat32
  $window.comboDrive.DisplayMemberPath = 'FriendlyName'
    
  $window.txtLabel.SelectionLength = $window.txtLabel.Text.Length
  $null = $window.txtLabel.Focus()
  #endregion
  
  # Show Window
  $result = Show-WPFWindow -Window $window
}