Capturing created file in powershell

Discussion in 'Scripting' started by juanmanuelsanchez, Sep 25, 2018.

  1. juanmanuelsanchez

    juanmanuelsanchez MDL Novice

    Aug 21, 2009
    42
    1
    0
    Hi everybody. Im using this script to scan a folder for the created files. Sadly this are temp files and gets created and deleted by a program we use.

    Code:
    $folder = 'C:\Users\JuanMa\Desktop\RestBar\RestBar'
    $filter = '*.*'                             # <-- set this according to your requirements
    $destination = 'C:\Users\JuanMa\Desktop\UNB'
    $fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property @{
     IncludeSubdirectories = $true              # <-- set this according to your requirements
     NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
     LockFile = [IO.No
    }
    $onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
     $path = $Event.SourceEventArgs.FullPath
     $name = $Event.SourceEventArgs.Name
     $changeType = $Event.SourceEventArgs.ChangeType
     $timeStamp = $Event.TimeGenerated
     Write-Host "The file '$name' at '$path'was $changeType at $timeStamp"
     Copy-Item $path -Destination $destination -Force -Verbose # Force will overwrite files with same name
    }
    The Script its not being able to copy the file to the destination folder. Im assuming that the files gets deleted before it can be copied. Its there a way to lock the file so it dosent get deleted but after the copy operation?

    Thanks!
     
  2. GodHand

    GodHand MDL Senior Member

    Jul 15, 2016
    378
    410
    10
    You need to either use the Start-Transcript feature, or a much better option of using Moitor-Path so you can monitor and log all events. From there you can query the logs and see exactly what is happening with the deletion of certain files.

    You can "Monitor-Path 'C:\Users\JuanMa\Desktop\RestBar\RestBar'" in which case its output will write a line that it's being monitored for every event: "Monitoring 'C:\Users\JuanMa\Desktop\RestBar\RestBar' and subdirectories. Press Ctrl+C to stop."

    Start-FileSystemWatcher event blocks that are supplied have access to a plethora of variables: $_, $e, $e_ChangeType, $eName, $eFullPath, $eOldName, $eOldFullPath and $EventArgs.

    Your problem may be something very simple like buffering (the events keep buffering during the process). For that you can Unregister-Events and also increase the KeyboardTimeout.

    This is an advanced function I use for this kind of stuff.

    Code:
    Function Start-Scan
    {
       [CmdletBinding()]
       Param
       (
           [Parameter(Mandatory = $true,
                      Position = 0)]
           [string]$Path,
           [scriptblock]$CreatedAction,
           [scriptblock]$DeletedAction,
           [scriptblock]$ChangedAction,
           [scriptblock]$RenamedAction,
           [string]$Filter = "*.*",
           [int]$KeyboardTimeout = -1,
           [string]$LogFile = '',
           [switch]$Recurse
       )
       
       Begin
       {
           Function Invoke-Action
           {
               Param
               (
                   [scriptblock]$Action,
                   [string]$_,
                   [System.Management.Automation.PSEventArgs]$PSEventArgs,
                   $PSEvent
               )
               $Output = Invoke-Command $Action
               If ($Output)
               {
                   Write-Output $Output
                   If ($LogFile -ne '') { Write-Output $Output >> $LogFile }
               }
           }
       }
       Process
       {
           If (!$CreatedAction -and !$DeletedAction -and !$ChangedAction -and !$RenamedAction)
           {
               Write-error "Specify at least one of -CreatedAction, -DeletedAction, -ChangedAction or -RenamedAction"
               Return
           }
           @("FileCreated", "FileDeleted", "FileChanged", "FileRenamed") | ForEach - Process {
               Unregister-Event -SourceIdentifier $_ -ErrorAction SilentlyContinue
               Remove-Event -SourceIdentifier $_ -ErrorAction SilentlyContinue
           }
           $FullPath = (Convert-Path -Path $Path)
           $FSW = New-Object -TypeName System.IO.FileSystemWatcher $FullPath, $Filter -Property @{ IncludeSubdirectories = $Recurse; NotifyFilter = [System.IO.NotifyFilters]'FileName, LastWrite, DirectoryName' }
           If ($CreatedAction) { Register-ObjectEvent $FSW Created -SourceIdentifier "FileCreated" }
           If ($DeletedAction) { Register-ObjectEvent $FSW Deleted -SourceIdentifier "FileDeleted" }
           If ($ChangedAction) { Register-ObjectEvent $FSW Changed -SourceIdentifier "FileChanged" }
           If ($RenamedAction) { Register-ObjectEvent $FSW Renamed -SourceIdentifier "FileRenamed" }
           $RecurseMessage = $null
           If ($Recurse) { $RecurseMessage = " and subdirectories" }
           $PathWithFilter = Join-Path -Path $FullPath $Filter
           If ($KeyboardTimeout -eq -1) { Write-Output "Monitoring '$PathWithFilter'$RecurseMessage. Press Ctrl+C to stop." }
           Else { Write-Output "Monitoring '$PathWithFilter'$RecurseMessage. Press ESC to cancel in at most $KeyboardTimeout seconds, or Ctrl+C to abort." }
           $FSW.EnableRaisingEvents = $true
           $ExitRequested = $false
           Do
           {
               [System.Management.Automation.PSEventArgs]$PSEvent = Wait-Event -Timeout $KeyboardTimeout
               If ($null -eq $PSEvent)
               {
                   While ($Host.UI.RawUI.KeyAvailable)
                   {
                       $Key = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp,IncludeKeyDown")
                       If (($Key.Character -eq 27) -and !$ExitRequested)
                       {
                           Write-Output "ESC pressed. Exiting..."
                           $ExitRequested = $true
                       }
                   }
               }
               Else
               {
                   $Name = $PSEvent.SourceEventArgs.Name
                   [System.IO.WatcherChangeTypes]$changeType = $PSEvent.SourceEventArgs.ChangeType
                   $TimeStamp = $PSEvent.TimeGenerated.ToString("yyyy-MM-dd HH:mm:ss")
                   Write-Verbose "--- START [$($PSEvent.EventIdentifier)] $ChangeType $Name $TimeStamp"
                   Switch ($ChangeType)
                   {
                       Changed { Invoke-Action $ChangedAction $Name $PSEvent $($PSEvent.SourceEventArgs) }
                       Deleted { Invoke-Action $DeletedAction $Name $PSEvent $($PSEvent.SourceEventArgs) }
                       Created { Invoke-Action $CreatedAction $Name $PSEvent $($PSEvent.SourceEventArgs) }
                       Renamed { Invoke-Action $RenamedAction $Name $PSEvent $($PSEvent.SourceEventArgs) }
                   }
                   Remove-Event -EventIdentifier $($PSEvent.EventIdentifier)
                   Write-Verbose "--- END [$($PSEvent.EventIdentifier)] $ChangeType $Name $TimeStamp"
               }
           }
           While (!$ExitRequested)
           If ($CreatedAction) { Unregister-Event FileCreated }
           If ($DeletedAction) { Unregister-Event FileDeleted }
           If ($ChangedAction) { Unregister-Event FileChanged }
           If ($RenamedAction) { Unregister-Event FileRenamed }
           Write-Output "Exited."
       }
    }