November 4th, 2009

Hey, Scripting Guy! Can I Format a Portable Drive When It Is Inserted Into a Computer?

Bookmark and Share

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I work with portable USB drives all the time. These are used for backup purposes, for temporary storage, for Sneakernet, and as a means to work with extremely large files that I do not want cluttering up the small hard disk drive on my corporate standard desktop. The problem is that I now have more than a dozen portable USB drives, some of which are continually connected, and others that I shuttle in and out of my computer on an hourly basis to transfer files from one computer to another. (Our IT department has disabled file sharing on our computers, and therefore I cannot simply copy one file from one computer to another. In addition, all file attachments get stripped out of e-mail and so I cannot use e-mail to transfer files either. I am therefore left with sneaker net.)

The problem is that, once I have used a portable drive to transfer a file from one computer to another, I do not always delete the file to clean up the drive. As a result some of these drives tend to fill up with useless information. Here is what I currently do: I plug the portable USB drive into my computer, and then navigate to the drive in Windows Explorer to check for files on the drive. If the drive has files, I do a quick format to clean it up. I would love to automate this process. Do you know of a script that will automatically format a portable drive when it is inserted into a computer?

— JM

Hey, Scripting Guy! AnswerHello JM, Microsoft Scripting Guy Ed Wilson here. Well this afternoon, the Scripting Wife made me a nice pot of Earl Grey tea in my little blue tea pot, and even shared one of her Tim Tams with me. I guess she is still excited about her new flat panel monitor for her Windows 7 Ultimate computer. I am listening to “Zapatos de Tacon Alto” (High-Heeled Shoes) by Jose Feliciano on my Zune. I bought the CD-ROM a couple years ago while I was teaching a VBScript class in Monterrey, Mexico. Anyway, I am reviewing the e-mail in the scripter@microsoft.com mail box (we receive several hundred e-mails a week to this alias, and it takes a decent amount of time to go through them all). All in all, it is a terrific afternoon in Charlotte, North Carolina, in the United States—a fine scripting day!

JM, I wrote the MonitorDiskFormatDrive.ps1 script for you. It will detect when a new drive has been added to your system. After the new drive has initialized, the contents of the drive are displayed on your Windows PowerShell console. If there are any files on the portable drive, you will be prompted to format the drive. If no files exist on the drive, it will automatically be formatted. The complete MonitorDiskFormatDrive.ps1 script is seen here.

MonitorDiskFormatDrive.ps1

#Requires -version 2.0

function Test-IsAdministrator
{
    <#
    .Synopsis
        Tests if the user is an administrator
    .Description
        Returns true if a user is an administrator, false if the user is not an administrator       
    .Example
        Test-IsAdministrator
    #>  
    param()
    $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
    (New-Object Security.Principal.WindowsPrincipal $currentUser).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
} #end function Test-IsAdministrator
 
Function Get-IsWindowsXP
 {
   if( (Get-WmiObject -Class win32_operatingsystem).version  -gt “6.1.2600” )
     { $false }
   else { $true }
 } #end function Get-IsWindowsXP

Function Get-DriveEvent
 {
  Register-WmiEvent -Class win32_VolumeChangeEvent -SourceIdentifier volumeChange
  $newEvent = Wait-Event -SourceIdentifier volumeChange
  Get-DriveContents -path $newEvent.SourceEventArgs.NewEvent.DriveName
 } #end function Get-DriveEvent

Function Get-DriveContents ($path)
 {
  If( (Get-ChildItem -Path $path).count -gt 0)
    { 
      Get-ChildItem -Path $path
     $in = Read-Host -Prompt “Drive contains files. Format anyway? y / n”
     if ($in -match “y”) { Set-DriveFormat -path $path }
     if ($in -match “n”) { “Drive will not be formatted. Exiting” ; exit }
    }
   Else { Set-DriveFormat -path $path }

 } #end function Get-DriveContents
 
Function Set-DriveFormat($path)
 {
  “Formatting drive $path this can take some time …”
  $drive = Get-WmiObject -Class win32_volume -Filter “DriveLetter = ‘$path'”
  $drive.Format(“FAT32″,$true,4096,”testFormat”,$false)
 } #end function Set-DriveFormat
 
# *** Entry Point to Script ***
if( -not (Test-IsAdministrator)) { “This script requires admin rights.” ; exit }
if(Get-IsWindowsXP) { “This script requires Windows Server 2003 or newer.” ; exit }
“Watching for new Drive …”
Get-DriveEvent

If you want to format a disk drive, it requires administrator rights. There is no point in running the MonitorDiskFormatDrive.ps1 script if the user does not have administrator rights. To check for these rights, use a function I wrote for the Windows 7 Resource Kit called Test-IsAdministrator. The Test-IsAdministrator function uses the GetCurrent static method from the Security.Principal.WindowsIdentity .NET Framework class to determine the current user. After the current user identity is established, the IsInRole method from the Security.Principal.WindowsPrincipal .NET Framework class is used to determine if the current user is an administrator. The Test-IsAdministrator function is seen here:

function Test-IsAdministrator
{
    <#
    .Synopsis
        Tests if the user is an administrator
    .Description
        Returns true if a user is an administrator, false if the user is not an administrator       
    .Example
        Test-IsAdministrator
    #>  
    param()
    $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
    (New-Object Security.Principal.WindowsPrincipal $currentUser).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
} #end function Test-IsAdministrator

Because the MonitorDiskFormatDrive.ps1 script relies on the Win32_Volume WMI class, the first thing the script does is to determine the version of the operating system (OS) the script is running on. This is because the Win32_Volume WMI class does not exist on Windows XP. The OS check is performed in the Get-IsWindowsXP function. The Win32_OperatingSystem WMI class is used to determine the version of the OS. If the version of the OS is higher than 6.1.2600 (which was the OS version of Windows XP), the script returns false to the calling code. If the version of the OS is not greater than 6.1.2600, the function returns true to the calling code. The complete Get-IsWindowsXP function is seen here:

Function Get-IsWindowsXP
 {
   if( (Get-WmiObject -Class win32_operatingsystem).version  -gt “6.1.2600” )
     { $false }
   else { $true }
 } #end function Get-IsWindowsXP

The Get-DriveEvent function is used to create the WMI event that will monitor for a volume change. To do this, the Win32_VolumeChangeEvent WMI class is used. This WMI class is designed to detect when a volume change event occurs. The event could be a new drive or a drive that was removed from the system. Because of the way the MonitorDiskFormatDrive.ps1 script will be used, it is safe to assume the volume change event that will occur will be a drive-added event. The Register-WmiEvent Windows PowerShell cmdlet is used to create the WMI event. The Wait-Event Windows PowerShell cmdlet will pause the Windows PowerShell console until an event occurs. This is great for halting the execution of your script when you know that something is about to occur, such as if you are getting ready to insert a USB drive into your computer. When the event occurs, the script will continue and will retrieve the DriveName property from the instance of the Win32_VolumeChangeEvent WMI class. This is important because when a removable drive is added to my system, a drive letter is assigned to it. The letter is not always the next available drive letter, nor is it always the same drive letter. This is seen here:

Image of the next drive letter assigned


The complete Get-DriveEvent function is seen here:

Function Get-DriveEvent

 {

  Register-WmiEvent -Class win32_VolumeChangeEvent -SourceIdentifier volumeChange

  $newEvent = Wait-Event -SourceIdentifier volumeChange

  Get-DriveContents -path $newEvent.SourceEventArgs.NewEvent.DriveName

 } #end function Get-DriveEvent

The Get-DriveContents cmdlet uses the Get-ChildItem Windows PowerShell cmdlet to retrieve the contents of the newly added drive. If the drive has files (in other words, if the count is greater than zero), the Read-Host cmdlet is used to prompt the user for permission to format the drive. If the user types “y”, the Set-DriveFormat function is called. If the user types “n”, the script exits without making any changes. If the drive contains no files, the Set-DriveFormat function is called and the drive is formatted. The Get-DriveContents function is seen here:

Function Get-DriveContents ($path)

 {

  If( (Get-ChildItem -Path $path).count -gt 0)

    { 

      Get-ChildItem -Path $path

     $in = Read-Host -Prompt “Drive contains files. Format anyway? y / n”

     if ($in -match “y”) { Set-DriveFormat -path $path }

     if ($in -match “n”) { “Drive will not be formatted. Exiting” ; exit }

    }

   Else { Set-DriveFormat -path $path }

 

 } #end function Get-DriveContents

The Set-DriveFormat function uses the Win32_Volume WMI class, which is documented on MSDN. When the script is run, it must be run with administrator rights to format the drive. If it is not run with administrator rights, the script will display a message that indicates administrator rights are required. This is shown here:

Image showing administrator rights are required


The complete Set-DriveFormat function is seen here:

Function Set-DriveFormat($path)

 {

  “Formatting drive $path this can take some time …”

  $drive = Get-WmiObject -Class win32_volume -Filter “DriveLetter = ‘$path'”

  $drive.Format(“FAT32″,$true,4096,”testFormat”,$false)

 } #end function Set-DriveFormat

When the MonitorDiskFormatDrive.ps1 script is run, the script first uses the WMI event to monitor for a new drive event. When the drive event is detected, the drive letter is captured, and the contents of the drive are displayed. If contents are present on the drive, a prompt is used to ask if you wish to format the drive. If you type “y” for yes, the drive will be formatted. If you type “n” for no, the script will exit. If the drive is to be formatted, a message that states the drive is being formatted is displayed. The return code from the format method of the Win32_Volume WMI class is displayed when the format job is complete. This is shown here:

Image of the return code shown when format job is complete

 

JM, that is all there is to using a WMI event class to monitor for the insertion of a new drive on your computer. WMI Event Week will continue tomorrow when we will talk about…

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
 

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

Author

0 comments

Discussion are closed.