Copy-Item : Cannot bind argument to parameter 'Path' because it is null - powershell

I am not sure what is going on. I am very new to Power Shell.
I have a folder structure containing images in them. I am looking to get all the images that are X days old and copy those images to two other locations. The error I am getting is:
Copy-Item : Cannot bind argument to parameter 'Path' because it is null.
At C:\Documents and Settings\Administrator.VDICORP\Desktop\ProcessOSImages.ps1:37 char:24
+ copy-item -path <<<< $TheImage -destination $TestSite
+ CategoryInfo : InvalidData: (:) [Copy-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand
My code is as follows:
$TodaysDate = get-date
$FileAgeInDays = "-2"
$ImageLocation = "\\vdifiles\Print-Room\FileSrv\Barcode-Order"
$TestSite = "\\10.0.100.3\www2.varietydistributors.com\catalog\newpictures"
$LiveSite = "\\10.0.100.3\Variety Distributors.com\catalog\newpictures"
$WhenFileWritten = $TodaysDate.AddDays($FileAgeInDays)
$IncludeFileTypes = "*.jpeg,*.jpg"
$ExcludeFileTypes = "*.psd,*.tif,*.pdf"
$LogFile = "C:\Temp\FilesCopied.log"
$EmailServer = "mx1.domain.com"
$EmailFrom = "alerts#domain.com"
$AuthUser = "user"
$AuthPass = "pass"
$XHeaderInfo = "X-Header: This email was sent from Laservault."
$EmailTo = "me#domain.com"
$EmailSubject = "Barcode Images Summary."
$EmailBodySent = "TEST Attached to this email is a log file of what images were copied from $ImageLocation to $TestSite and $LiveSite as well as sent to AS2 to send over to Order Stream."
$EmailBodyNotSent = "TEST There were no files in $ImageLocation that matched $WhenFileWritten days old. So, nothing was sent to $TestSite, $LiveSite or AS2."
$TheImages = get-childitem $ImageLocation -include $IncludeFileTypes -exclude $ExcludeFileTypes -recurse -force | where-object {$_.CreationTime -le "$WhenFileWritten" -and $_.PsIsContainer -ne $true}
foreach ($TheImages in $TheImage) {
$FileCount = ($TheImage).count
if (!($FileCount -eq 0)) {
copy-item -path $TheImage -destination $TestSite
copy-item -path $TheImage -destination $LiveSite
write-host $FilesCount "images were copied."
write-output $TheImage >> $LogFile
\\vdifiles\blat$\blat.exe -attach $LogFile -to $EmailTo -s $EmailSubject -i $EmailFrom -body $EmailBodySent -server $EmailServer -u $AuthUser -pw $AuthPass -f $EmailFrom -x $XHeaderInfo
remove-item $LogFile
} else {
\\vdifiles\blat$\blat.exe -to $EmailTo -s $EmailSubject -i $EmailFrom -body $EmailBodyNotSent -server $EmailServer -u $AuthUser -pw $AuthPass -f $EmailFrom -x $XHeaderInfo
}
}
Where am I going wrong?

It's a simple problem. You flipped your variables in your foreach statement. You have:
foreach ($TheImages in $TheImage) {
You should have:
foreach ($TheImage in $TheImages) {
--- Edit
The other issue is with the Get-ChildItem not returning anything. It's a small problem because of the -include and -exclude parameters you are feeding into it. You are defining the variable like this:
$IncludeFileTypes = "*.jpeg,*.jpg"
$ExcludeFileTypes = "*.psd,*.tif,*.pdf"
The problem is that the -include and -exclude parameters are expecting a string array (String[]) what you are giving them is a straight string.
We can prove this, if you create a file with the name "a.jpeg,a.jpg", the get-childitem cmdlt will return the file.
The solution is to change your $IncludeFileTypes and $ExcludeFileTypes variables to a string array, and it should return the results that you are expecting:
$IncludeFileTypes = "*.jpeg","*.jpg"
$ExcludeFileTypes = "*.psd","*.tif","*.pdf"

Related

Powershell- Delete files older then x days and send only email after files are deleted

how to delete files older then x days and send only email notification, if files are deleted by script. Here is my script.. files are deleted by script, but email notification is not working. If I delete the if clauses (if(!$messageBody)) then email notification is working, but I am getting email when no files are deleted, too.
Get-ChildItem temp*.zip -Path "c:\tempfiles" |
Where-Object { -not $_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-0) }|
ForEach-Object {
$_ | Remove-Item -force
-join $([datetime]::Now) + " " + $_.Name| Out-File -FilePath "c:\tempfiles\logs\dellogs.txt" -Append
$OF = "`r`n"
$messageBody = $_.Name + $OF + $messageBody
}
$date = ( get-date )
if(!$messageBody){
$smtpServer = ""
$smtpFrom = ""
$smtpTo = ""
$server = ""
$messageSubject = "Subject $server - $date"
$body= "files"
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($smtpFrom,$smtpTo,$messagesubject,$messagebody)
$messageBody=" "
}
You can do the following to find temp*.zip files, delete them, log the deleted files to a log file, and then email a list of deleted files. This assumes your deletions are successful. You will need to remove the -WhatIf parameter for deletions to occur.
Get-ChildItem -Filter temp*.zip -Path "c:\tempfiles" -File -OutVariable files | Foreach-Object {
$_ | Remove-Item -Force -WhatIf
"{0} {1}" -f (Get-Date),$_.Name |
Out-File -FilePath "c:\tempfiles\logs\dellogs.txt" -Append
}
if ($files) {
$MailParams = #{ 'To' = 'to#domain.com'
'From' = 'from#domain.com'
'Subject' = "Subject server $(Get-Date)"
'Body' = $files.Name | Out-String
'SmtpServer' = 'smtpservername'
}
Send-MailMessage #MailParams
}
If you want error checking and only report when files are deleted, you can make some modifications.
$files = [Collections.Generic.List[String]]#()
Get-ChildItem -Filter temp*.zip -Path "c:\tempfiles" -File | Foreach-Object {
$_ | Remove-Item -Force -WhatIf
if ($?) {
"{0} {1}" -f (Get-Date),$_.Name |
Out-File -FilePath "c:\tempfiles\logs\dellogs.txt" -Append
$files.Add($_.Name)
}
}
if ($files) {
$MailParams = #{ 'To' = 'to#domain.com'
'From' = 'from#domain.com'
'Subject' = "Subject server $(Get-Date)"
'Body' = $files.Name | Out-String
'SmtpServer' = 'smtpservername'
}
Send-MailMessage #MailParams
}
$? returns true if the last command executed successfully. See About_Automatic_Variables.
The syntax #MailParams is called Splatting. It is simply used here for readability.

List all files that were moved in an email Body - Powershell

Trying to accomplish the following:
1)Move files from multiple sources into multiple destinations.
Therefore i listed sources under a SOURCE column, and destinations under a DESTINATION column (WORKING)
2)Send an email with a list of files that were moved and the destination (Not working)
Param (
[string]$SMTPServer = "XXX.XX.xXX",
[string]$From = "from#email.com",
[string]$To = "to#email.com",
[string]$Subject = "New File"
)
Import-Csv -Path "C:\moveallfiles.csv" -ErrorAction Stop | foreach {
if (-not (Test-Path -Path $_.Destination))
{
# Create directory if needed
New-Item -ItemType directory -Path $_.Destination -WhatIf
}
# Copy file
$MoveFileprocess = Move-Item -Path $_.Source -Destination $_.Destination -force -PassThru
}
$SMTPMessage = #{
To = $To
From = $From
Subject = "$Subject"
Smtpserver = $SMTPServer
}
$SMTPBody = "`nThe following files have recently been added `n
$MoveFileprocess `n"
Send-MailMessage #SMTPMessage -Body $SMTPBody
Right now its listing all the files in one single line, hard to read
I was wondering if theres a way to send the body email as
File 1 moved to Destination 1
File 2 moved to Destination 2
and so on...
You were pretty close. Try this:
Param (
[string]$SMTPServer = "XXX.XX.xXX",
[string]$From = "from#email.com",
[string]$To = "to#email.com",
[string]$Subject = "New File"
)
$SMTPBody = "`nThe following files have recently been added `n"
Import-Csv -Path "C:\moveallfiles.csv" -ErrorAction Stop | foreach {
if (-not (Test-Path -Path $_.Destination)){
# Create directory if needed
New-Item -ItemType directory -Path $_.Destination
}
If((Get-Item $_.Source).LastWriteTime -gt (Get-Item $_.Destination).LastWriteTime){
Move-Item -Path $_.Source -Destination $_.Destination -force
$SMTPBody += "$($_.Source) moved to $($_.Destination)`n"
}Else{
Write-Warning "Skipped overwriting newer $($_.Destination)"
}
}
$SMTPMessage = #{
To = $To
From = $From
Subject = "$Subject"
Smtpserver = $SMTPServer
}
Send-MailMessage #SMTPMessage -Body $SMTPBody
Note that Move-Item -PassThru returns the affected object, not a string. I took out the -WhatIf parameter for the New-Item command, indented the foreach{} loop and made indenting and brackets consistent.

Windows powershell file process duplication

My folder structure is "C:\Temp\SalesOrder\20160809\cc.txt" when its looking for all the files that need to be processed as soon as the recursion gets to folder "C:\Temp\SalesOrder" & "C:\Temp\SalesOrder\20160809" its processing cc.txt file. How do I rewrite the gci to not to traverse subfolders and only process files "C:\Temp\SalesOrder\20160809"
$flatFilePath = "C:\Temp\Email.csv"
$flatFile = Import-Csv -Path $flatFilePath -Header Dir,Email
$emailID = #{}
foreach ($record in $flatFile) { $emailID[$record.Dir]=$record.Email }
# organization folder
$orgFolder = Get-ChildItem -Path "C:\Temp\" -Recurse -Exclude *.*
# Send email
foreach ($dir in $orgFolder) {
$processedfiles = $null
$emailTo = $null
Get-ChildItem -Path $dir.FullName -Recurse -Include *.txt,*.xls,*.csv,*.xlsx | ? { $_.FullName } |
Foreach-Object {
[string]$internalOrg = [System.IO.DirectoryInfo]$_.Directory.Name
$processedfiles += [string][System.IO.Path]::GetFileName($_.FullName) + " | ";
}
$emailTo = $emailID.Get_Item($dir.Name) -split ";"
if ($processedfiles) { Send-MailMessage -From $From -to $To -Cc $Cc -Subject $Subject -Body "$Body $processedfiles" -SmtpServer $SMTPServer -port $SMTPPort }
}
Problem area:
Get-ChildItem -Path $dir.FullName -Recurse -Include *.txt,*.xls,*.csv,*.xlsx | ? { $_.FullName } |
Foreach-Object {
[string]$internalOrg = [System.IO.DirectoryInfo]$_.Directory.Name
$processedfiles += [string][System.IO.Path]::GetFileName($_.FullName) + " | ";
}
You can use regex to only select Folders which have the date structure
$orgFolder = Get-ChildItem -Path 'C:\Temp\' -Recurse -Exclude *.*
$orgfolder = $orgfolder -match '(\\(\d{2})(\d{2})(\d{2})(\d{2}))'
As I understand your problem, you have the right code with a small bug.
In your loop...
Foreach-Object {
[string]$internalOrg = [System.IO.DirectoryInfo]$_.Directory.Name
$processedfiles += [string][System.IO.Path]::GetFileName($_.FullName) + " | ";
}
... you concatenate the file names, instead of the $internalOrg variables, where you extracted the folder name.
It should be the following if you want the folders:
Foreach-Object {
[string]$internalOrg = [System.IO.DirectoryInfo]$_.Directory.Name
$processedfiles += [string][System.IO.Path]::GetFileName($internalOrg) + " | ";
}

Images not moving from one UNC to another UNC

I would add this to my other post, but I can't find it. I have been trying to copy images (JPG and JPEG) from one UNC (source) to two UNCs (destinations) that are three days old. I only need to copy the images, not the folders they are contained in.
I do not get any errors, the email received from the script tells me no images were copied. The destinations do not have any images copied to them and there are images in the source that are newer than three days from todays date. I am completely lost. I have been on Google all day trying to figure this out to no avail so far. Any suggestions would be appreciated.
$ImageLocation = "\\vdifiles\Print-Room\FileSrv\Barcode-Order"
$TestSite = "\\10.0.100.3\www2.varietydistributors.com\catalog\newpictures"
$LiveSite = "\\10.0.100.3\Variety Distributors.com\catalog\newpictures"
$WhenFileWritten = (get-date).AddDays(-3)
$IncludeFileTypes = "*.jpeg,*.jpg"
$LogFile = "C:\Temp\FilesCopied.log"
$EmailServer = "emailserver.me.com"
$EmailFrom = "fromme#me.com"
$AuthUser = "user"
$AuthPass = "pass"
$XHeaderInfo = "X-Header: This email was sent from Laservault."
$EmailTo = "tome#me.com"
$EmailSubject = "Barcode Images Summary."
$EmailBodySent = "Attached to this email is a log file of what images were copied from $ImageLocation to $TestSite and $LiveSite as well as sent to AS2 to send over to Order Stream."
$EmailBodyNotSent = "There were no files in $ImageLocation that matched $WhenFileWritten days old. So, nothing was sent to $TestSite, $LiveSite or AS2."
$TheImages = get-childitem "Microsoft.PowerShell.Core\FileSystem::$ImageLocation" -recurse | where-object {$_.Extension -eq $IncludeFileTypes -and $_.LastWriteTime -gt $WhenFileWritten -and $_.PsIsContainer -eq $false}
foreach ($Images in $TheImages) {
$FileCount = $Images.count
if ($FileCount -gt 0) {
copy-item -path $Images.FullName -destination "Microsoft.PowerShell.Core\FileSystem::$TestSite" -force
copy-item -path $Images.FullName -destination "Microsoft.PowerShell.Core\FileSystem::$LiveSite" -force
write-host "$FileCount files were copied."
write-output $Images >> $LogFile
\\vdifiles\blat$\blat.exe -attach $LogFile -to $EmailTo -s $EmailSubject -i $EmailFrom -body $EmailBodySent -server $EmailServer -u $AuthUser -pw $AuthPass -f $EmailFrom -x $XHeaderInfo
remove-item $LogFile
} else {
\\vdifiles\blat$\blat.exe -to $EmailTo -s $EmailSubject -i $EmailFrom -body $EmailBodyNotSent -server $EmailServer -u $AuthUser -pw $AuthPass -f $EmailFrom -x $XHeaderInfo
}
}
Your original post: Copy-Item : Cannot bind argument to parameter 'Path' because it is null
I copied my answer from there here:
The issue is with the Get-ChildItem not returning anything. It's a small problem because of the -include and -exclude parameters you are feeding into it. You are defining the variable like this:
$IncludeFileTypes = "*.jpeg,*.jpg"
$ExcludeFileTypes = "*.psd,*.tif,*.pdf"
The problem is that the -include and -exclude parameters are expecting a string array (String[]) what you are giving them is a straight string.
We can prove this, if you create a file with the name "a.jpeg,a.jpg", the get-childitem cmdlt will return the file.
The solution is to change your $IncludeFileTypes and $ExcludeFileTypes variables to a string array, and it should return the results that you are expecting:
$IncludeFileTypes = "*.jpeg","*.jpg"
$ExcludeFileTypes = "*.psd","*.tif","*.pdf"
The where-object is not finding any match for any files.
Amend $IncludeFileTypes = "*.jpeg,*.jpg" to $IncludeFileTypes = #("*.jpeg","*.jpg")
Then pass that array of file types into the get-childitem command using the -include Parameter (-filter only takes one filetype, as a string) and remove the $_.Extension check from the where-object command.
e.g.
$TheImages = get-childitem "Microsoft.PowerShell.Core\FileSystem::$ImageLocation" -recurse -include $IncludeFileTypes | where-object {$_.LastWriteTime -gt $WhenFileWritten -and $_.PsIsContainer -eq $false}
You are also checking the count of the wrong variable to get your file count, and it shouldn't be inside the foreach loop.
Get the file count, then if it's greater than zero, iterate through the list if files, copying them.
Try:
$FileCount = $TheImages.count
if ($FileCount -gt 0) {
foreach ($Images in $TheImages) {
And also
write-output $TheImages >> $LogFile
Instead of
write-output $Images >> $LogFile
You are declaring the list wrong, it should be like this:
$IncludeFileTypes = #("*.jpeg","*.jpg")
Try searching with the -Include like this:
$TheImages = get-childitem "Microsoft.PowerShell.Core\FileSystem::$ImageLocation" -recurse -Include $IncludeFileTypes | where-object {$_.LastWriteTime -gt $WhenFileWritten -and $_.PsIsContainer -eq $false}
And check if the variable is empty after that:
if($TheImages -ne $null)
{
#move...
#send email...
#etc
}
Hope this solves your issue.

Powershell - "The process cannot access the file because it is being used by another process"

Below is a script that monitors a directory and its subfolders for deposited files. Every 10 minutes or so, I look for new files and then match them against a database table that tell me where they need to be moved to - then it copies the files to a local archive, moves them to the locations they need to be moved to, and inserts a record into another database table with the file's attributes and where it came and went. If there is no match in the database - or there is an script error - it sends me an email.
However, since files are getting deposited to the directory constantly, it's possible that a file is still being written when the script executes. As a result, I get the error The process cannot access the file because it is being used by another process. emailed to me all the time. In addition, because I'm not dealing with the error up front; it goes through the loop and a false entry is inserted into my log table in the database with incorrect file attributes. When the file finally frees up, it gets inserted again.
I'm looking for a way to identify files that have processes attached to them; and skipping them when the script executes - but several days of web searches and some testing hasn't yielded an answer yet.
## CLEAR ERROR LOG
$error.clear()
Write-Host "***File Transfer Script***"
## PARAMETERS
$source_path = "D:\Files\In\"
$xferfail_path = "D:\Files\XferFailed\"
$archive_path = "D:\Files\XferArchive\"
$email_from = "SQLMail <SQLMail#bar.com>"
$email_recip = [STRING]"foo#bar.com"
$smtp_server = "email.bar.com"
$secpasswd = ConvertTo-SecureString "Pa$$w0rd" -AsPlainText -Force
$smtp_cred = New-Object System.Management.Automation.PSCredential ("BAR\SQLAdmin", $secpasswd)
## SQL LOG FUNCTION
function Run-SQL ([string]$filename, [string]$filepath, [int]$filesize, [int]$rowcount, [string]$xferpath)
{
$date = get-date -format G
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=SQLSERVER;Database=DATABASE;Uid=SQLAdmin;Pwd=Pa$$w0rd;"
$SqlConnection.Open()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "INSERT INTO DATABASE..Table VALUES ('$date','$filename','$filepath',$filesize,$rowcount,'$xferpath',0)"
$SqlCmd.Connection = $SqlConnection
$SqlCmd.ExecuteNonQuery()
$SqlConnection.Close()
}
## DETERMINE IF THERE ARE ANY FILES TO PROCESS
$file_count = Get-ChildItem -path $source_path |? {$_.PSIsContainer} `
| Get-ChildItem -path {$_.FullName} -Recurse | Where {$_.psIsContainer -eq $false} | Where {$_.Fullname -notlike "D:\Files\In\MCI\*"} `
| Measure-Object | Select Count
If ($file_count.Count -gt 0)
{
Write-Host $file_count.Count "File(s) Found - Processing."
Start-Sleep -s 5
## CREATE LIST OF DIRECTORIES
$dirs = Get-ChildItem -path $source_path -Recurse | Where {$_.psIsContainer -eq $true} | Where {$_.Fullname -ne "D:\Files\In\MCI"} `
| Where {$_.Fullname -notlike "D:\Files\In\MCI\*"}
## CREATE LIST OF FILES IN ALL DIRECTORIES
$files = ForEach ($item in $dirs)
{
Get-ChildItem -path $item.FullName | Where {$_.psIsContainer -eq $false} | Sort-Object -Property lastWriteTime -Descending
}
## START LOOPING THROUGH FILE LIST
ForEach ($item in $files)
{
## QUERY DATABASE FOR FILENAME MATCH, AND RETURN TRANSFER DIRECTORY
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=SQLSERVER;Database=DATABASE;Uid=SQLAdmin;Pwd=Pa$$w0rd;"
$SqlConnection.Open()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "SELECT F.DirTransfer FROM DATABASE..Files F WHERE '$item.Name.Trim()' LIKE F.FileName"
$SqlCmd.Connection = $SqlConnection
$DirTransfer = $SqlCmd.ExecuteScalar()
$SqlConnection.Close()
If ($DirTransfer) # if there is a match
{
Write-Host $item.FullName"`t->`t"$DirTransfer
$filename = $item.Name
$filepath = $item.FullName
$filesize = $item.Length
If (!($filesize))
{
$filesize = 0
}
$rowcount = (Get-Content -Path $item.FullName).Length
If (!($rowcount))
{
$rowcount = 0
}
$xferpath = $DirTransfer
Run-SQL -filename "$filename" -filepath "$filepath" -filesize "$filesize" -rowcount "$rowcount" -xferpath "$DirTransfer"
Copy-Item -path $item.FullName -destination $DirTransfer -force -erroraction "silentlycontinue"
Move-Item -path $item.FullName -destination $archive_path -force -erroraction "silentlycontinue"
#Write-Host "$filename $filepath $filesize $rowcount $xferpath"
}
Else # if there is no match
{
Write-Host $item.FullName "does not have a mapping"
Move-Item -path $item.FullName -destination $xferfail_path -force
$filename = $item.FullName
$email_body = "$filename `r`n`r`n does not have a file transfer mapping setup"
Send-MailMessage -To $email_recip `
-From $email_from `
-SmtpServer $smtp_server `
-Subject "File Transfer Error - $item" `
-Body $email_body `
-Priority "High" `
-Credential $smtp_cred
}
}
}
## IF NO FILES, THEN CLOSE
Else
{
Write-Host "No File(s) Found - Aborting."
Start-Sleep -s 5
}
## SEND EMAIL NOTIFICATION IF SCRIPT ERROR
If ($error.count -gt 0)
{
$email_body = "$error"
Send-MailMessage -To $email_recip `
-From $email_from `
-SmtpServer $smtp_server `
-Subject "File Transfer Error - Script" `
-Body $email_body `
-Priority "High" `
-Credential $smtp_cred
}
You can use the SysInternals handles.exe to find the open handles on a file. The exe can be downloaded from http://live.sysinternals.com/.
$targetfile = "C:\Users\me\Downloads\The-DSC-Book.docx"
$result = Invoke-Expression "C:\Users\me\Downloads\handle.exe $targetfile" | Select-String ([System.IO.Path]::GetFileNameWithoutExtension($targetfile))
$result
Outputs:
WINWORD.EXE pid: 3744 type: File 1A0: C:\Users\me\Downloads\The-DSC-Book.docx
Alternatively, you can check for errors either via try/catch or by looking at the $error collection after the Move-Item attempt then handle the condition appropriately.
$error.Clear()
Move-Item -path $item.FullName -destination $xferfail_path -force -ea 0
if($error.Count -eq 0) {
# do something useful
}
else {
# do something that doesn't involve spamming oneself
}
To expand on Arluin's answer. It fails if there's spaces in either the handle.exe or the $targetfile.
This will work for spaces in both and also formats the result to give you the Program Name.exe
$targetfile = "W:\Apps Folder\File.json"
$result = & "W:\Apps (Portable)\handle.exe" "$targetfile" | Select-String ([System.IO.Path]::GetFileNameWithoutExtension($targetfile))
$result = $result -replace '\s+pid\:.+'
$result
# PS> FreeCommander.exe
One way to avoid file locks caused by running the script on a timer is to use an event driven approach using a file system watcher. It has the ability to execute code when an event such as a new file is created in the folder you are monitoring.
To run code when the file is finished copying you would need to listen for the changed event. There is a slight issue with this event in that it fires once when the file begins copying and again when it is finished. I got an idea to work around this chicken/egg problem after checking out the module Mike linked to in the comments. I've updated the code below so that it will only fire off code when file has fully been written.
To try, change $folderToMonitor to the folder you want to monitor and add some code to process the file.
$processFile = {
try {
$filePath = $event.sourceEventArgs.FullPath
[IO.File]::OpenRead($filePath).Close()
#A Way to prevent false positive for really small files.
if (-not ($newFiles -contains $filePath)) {
$newFiles += $filePath
#Process $filePath here...
}
} catch {
#File is still being created, we wait till next event.
}
}
$folderToMonitor = 'C:\Folder_To_Monitor'
$watcher = New-Object System.IO.FileSystemWatcher -Property #{
Path = $folderToMonitor
Filter = $null
IncludeSubdirectories = $true
EnableRaisingEvents = $true
NotifyFilter = [System.IO.NotifyFilters]'FileName,LastWrite'
}
$script:newFiles = #()
Register-ObjectEvent $watcher -EventName Changed -Action $processFile > $null