Scripting Games 2010. Advanced Event 6 (Event Sink)

Шестое задание:

Event Scenario

You have a group of files you would like to copy to several portable USB drives for a college course. You do not want to have to drag and drop every time a new drive is inserted into your USB port. You would like instead to automatically copy the files to the drive when the portable drive is inserted into your USB port.

 

Design points

·         Your script should allow you to select a file, a group of files, a folder, or a group of folders to contain the files that will be copied.

·         Your script should offer a “quiet mode” and a “prompt mode” based upon a switch supplied to the script when it is launched. Quiet mode should be the default. In quiet mode, the script copies the target files/folders to the newly inserted drive without user interaction.

·         Your script should run in continuous loop fashion, until it is stopped. Or it should offer to make a specific number of copies based upon a command-line argument. For example, make 5 copies of the data, and then stop.

·         Your script should offer a “force” mode that will overwrite existing files, or a “prompt” mode that will prompt before overwriting existing files. This should also be configurable via the command argument.

·         Extra points for informing the user of the number of files to be copied and their total size; and for checking to ensure that the newly inserted drive has enough free disk space.

Для решения этой задачки пришлось освежить в памяти основы работы с WMI, рекомендую:

Вы всё ещё не используете WMI?(Часть I)

Вы всё ещё не используете WMI?(Часть II)

Узнай секреты WMI: события и провайдеры (Часть I)

Узнай секреты WMI: события и провайдеры (Часть II)

Результат здесь:

<#
Copy-ToRemovableDrive.ps1 PowerShell shs 20100504



.Synopsis
	determine that removable drive was inserted in computer and copy to it files and folders,
	containing in Sources

	Copy-ToRemovableDrive.ps1 [Sources] [-Confirm] [-Force] [NumCopies] [-help]

.Parameter Sources
	One or array of full names of folders to be copied

.Switch Confirm
	Request confirm to copy

.Switch Force
	Rewrite existing files without  request

.Parameter NumCopies
	Number of copies script made before exit

.Examples

	Copy-ToRemovableDrive.ps1 -Sources "c:\_tmp\2","c:\_tmp\3" -Confirm -Force -NumCopies 4

	Copy-ToRemovableDrive.ps1 -Sources "c:\_tmp\2" -NumCopies 10

	Copy-ToRemovableDrive.ps1 -help

#>
param($Sources="c:\_tmp\2", [switch]$Confirm, [switch]$Force,[int]$NumCopies=0, [switch]$help)
#
#
#########################################################################################################
#
# Function Show-Help. Write  first blok comment of this script to the host
#
Function Show-Help ($ScriptFullName){
   if ($ScriptFullName) {
       $IsHelpLine=$false
       switch -file $ScriptFullName {
           {$_ -match "<#"}     {Write-Host $_;$IsHelpLine=$true;continue}
           {$_ -match "#>"}     {Write-Host $_;$IsHelpLine=$false;break}
           {$IsHelpLine}        {Write-Host $_;}
       }
   }
}
#########################################################################################################
#
#    Function Clean-Event
#    Remove event with EventSourceID from event queue and
#    unregister all event subscriberes for event with this EventSourceID
#
#.Parameter $EventSourceID
#    Event Source Identifier
#
Function Clean-Event ($EventSourceID) {
  #Clean event queue from events with $EventSourceID
  Get-Event -SourceIdentifier $EventSourceID -ErrorAction SilentlyContinue| Remove-Event
  #Unregister event with $MyQuery
  get-eventsubscriber -force| ?{ $_.SourceIdentifier -eq $EventSourceID}| unregister-event -force
}
#########################################################################################################
#
#    Function MeasureSources
#    Return hash-table with total files and size of files in $Sources
#
Function MeasureSources ($Sources) {
  $Measure = dir $Sources -Recurse -Force| Measure-Object Length -Sum
  @{Size=$Measure.sum;TotalFiles=$Measure.count}
}
#########################################################################################################
#
#    Function AdvCopy
#    copy files from Sources to destination drive
#.Parameter Sources (FullName of sourse)
#    One Source or Array of Sources to copy
#
#.Parameter Destination (path to the root of destination drive)
#    Destination to the files
#
#.Parameter Confirm ($true|$false)
#    Confirm copy form sources to destination drive
#
#.Parameter Force ($true|$false)
#    Force to copy form sources to destination drive
#
Function AdvCopy ($Sources, $Destination, $Confirm, $Force) {
  if ($Force) {
      $CopyOptions+=" -Force"
  }
  if ($Confirm) {
      $CopyOptions+=" -Confirm"
  }
  foreach ($Source in $Sources) {
      #try to copy from source to destination with the given parameters
      try {
          $CopyExpression='copy'+$CopyOptions+' -Recurse $Source $Destination -ErrorAction Stop'
          Write-Verbose "Copy Expression=$CopyExpression"
          Invoke-Expression $CopyExpression
      }
      #if error occured...
      catch {
          #...and if copy was made without -Force switch ...
          if (!$Force) {
              # ...then ask the user
              if ((Read-Host "Error copying. To try to force copy?[Y] Yes -Y [N] No -N (Default value - 'N')")[0] -match "[Yy]") {
                  #try to repeat copy with -Force switch
                  copy -Recurse -Force -Path $Source  -Destination $Destination -ErrorAction SilentlyContinue
              }
          }
      }
  }
}
#==================================== Script entry point ================================================
if (!$Help) {
	#Name for event identifier
	$EventSourceID="Drive added"
	#Number of loops during which no offer to stop the script
	$DoNotOffertoStopNum=1
	#To clear session from events with ID =$EventSourceID  and subscribers for these enevts
	Clean-Event $EventSourceID
	#Query for removable drive
	$MyQuery = "SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_LogicalDisk' AND TargetInstance.DriveType = 2"
	#Register Event for $MyQuery
	Register-WmiEvent -Query $MyQuery -SourceIdentifier $EventSourceID
	#
	#Initialize loop variables
	$Stop="No"
	$i=0
	While ((($i -le $NumCopies) -or ($NumCopies -eq 0)) -and !($Stop[0] -match "[Yy]")) {
	#Increment loop counter
	$i+=1
	Write-Verbose "Loop counter = $i"
	#Get Sources properties (files count, size of files)
	$SourcesProperties=MeasureSources $Sources
	#Waiting for the events in the events queue
	$NewEvent = Wait-Event -SourceIdentifier $EventSourceID
	#Get target instance properties (properties of inserted removable drive)
	$RemDrive=$NewEvent.SourceEventArgs.NewEvent.TargetInstance
	#write report
	Write-Host "`nRemovable Drive`t-`t$($RemDrive.DeviceID)"
	Write-Host "Free spase on drive $($RemDrive.DeviceID)`t-`t$([math]::Round($RemDrive.FreeSpace/1mb,2)) Mb"
	Write-Host "Total size of files to copy`t-`t$([math]::Round($SourcesProperties.Size/1mb,2)) Mb"
	Write-Host "Total count of files to copy`t-`t$($SourcesProperties.TotalFiles)"
	#if removable drive have enough disk space...
	if ($RemDrive.FreeSpace -gt $SourcesProperties.Size) {
			Write-Host "Copying started..."
			AdvCopy -Sources $Sources -Destination "$($RemDrive.DeviceID)\" -Confirm $Confirm -Force $Force
		Write-Host "...copying completed"
	}
	else {
			Write-Host "Not enough disk space"
	}
	#
	if ($i -gt $DoNotOffertoStopNum) {
		$Stop=Read-Host "Do you want to stop copying files to removable drives? [Y] Yes -Y [N] N -N (Default value - 'N')"
	}
	Remove-Event -SourceIdentifier $EventSourceID
	}
	#To clear session from events with ID =$EventSourceID  and subscribers for these enevts
	Clean-Event $EventSourceID
}
else {
	#Write top block comment as help
	Show-Help $MyInvocation.MyCommand.Path
}

One Comment

  1. Pingback: Scripting Games 2010. Advanced Event 9 (Logging Out Users Forcibly Based on a Program’s Launch) « ShS's Blog

Leave a Reply

Your email address will not be published. Required fields are marked *

Notify me of followup comments via e-mail. You can also subscribe without commenting.