FileSystemWatcher to email change. Powershell - powershell

I am attempting to write a powershell script that will look at a file until it gets modified and then email the change that happened. So far I have this code + the code that will send the email using Net.Mail.SmtpClient
$DOCDIR = [Environment]::GetFolderPath("MyDocuments")
$TARGETDIR = "$DOCDIR\MatchedLog"
if(!(Test-Path -Path $TARGETDIR )){
New-Item -ItemType directory -Path $TARGETDIR
}
$FILE = 'matched.txt'
$FSW = New-Object IO.FileSystemWatcher $TARGETDIR, $FILE - Property#{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters]'FirstName, LastWrite'}
Register-ObjectEvent $FSW Changed -SourceIdentifier FileChanged -Action {
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
}
The error I get is:
Register-ObjectEvent : Cannot bind argument to parameter 'InputObject' because it is null.
I am not sure exactly why this is happening

This looks like it might be a typo, but [IO.NotifyFilters] doesn't have the definition FirstName. You probably mean FileName
http://msdn.microsoft.com/en-us/library/system.io.notifyfilters.aspx

This works fine, it prints the change twice in a row for some reason. I saw many people having the same problem online but I am still trying to find the problem. I also need to get the line that has changed from "matched.txt" and print that instead of "Changed: /path/to/file/matched.txt"
$DOCDIR = [Environment]::GetFolderPath("MyDocuments")
$TARGETDIR = "$DOCDIR\MatchedLog"
if(!(Test-Path -Path $TARGETDIR )){
New-Item -ItemType directory -Path $TARGETDIR
}
$FILE = 'matched.txt'
$FSW = New-Object System.IO.FileSystemWatcher
$FSW.Path = $TARGETDIR
$FSW.IncludeSubdirectories = $false
$changed = Register-ObjectEvent $FSW "Changed" -Action{
write-host "Changed: $($eventArgs.FullPath)"
}

Related

Using Filesystemwatcher to rename a monitored file to a directory one level higher than it's own directory

I have a script that will use filesystemwatcher to monitor a folder and it's subdirectories for a new file. Once it detects the new file, it will then rename the file to the directory that the file was placed in.
It works great however the usecase has slightly changed. Instead of a file being copied into the monitored subdirectory, a folder that contains the file is being placed into the monitored directory. the file is detected however, the file is renamed to the folder it was sent in, instead of the directory the folder is placed in.
example:
monitored_directory
monitored_subdirectory#1
new_folder
new_file.txt
new_file.txt becomes new_folder.txt
instead of
monitored_subdirectory#1.txt
Heres what i have so far:
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.IncludeSubdirectories = $true
$watcher.Path = 'C:\monitored_directory'
$watcher.EnableRaisingEvents = $true
$action =
{
$path = $event.SourceEventArgs.FullPath
$changetype = $event.SourceEventArgs.ChangeType
$destination = 'C:\Detected\'
Get-ChildItem C:\monitored_directory -Filter *.txt -Recurse | Copy-Item -Destination { "$($destination)$($_.Directory.Name+'.txt')" }
}
Register-ObjectEvent $watcher 'Created' -Action $action
Placing a folder into the "monitored_directory" folder, will result in the file being named after the wrong folder.
Any help would be appreciated. Thanks!
For anyone else who needs the answer it's simply changing the dot notation from .Directory.Name to .Directory.Parent.Name:
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.IncludeSubdirectories = $true
$watcher.Path = 'C:\monitored_directory'
$watcher.EnableRaisingEvents = $true
$action =
{
$path = $event.SourceEventArgs.FullPath
$changetype = $event.SourceEventArgs.ChangeType
$destination = 'C:\Detected\'
Get-ChildItem C:\monitored_directory -Filter *.txt -Recurse |
Copy-Item -Destination { "$($destination)$($_.Directory.Parent.Name+'.txt')" }
}
Register-ObjectEvent $watcher 'Created' -Action $action

Monitor folder on remote PC for changed files

I have a measuring device on a PC in our network. The PC is not joined to the domain, however has a shared folder for which I have a username and password.
I am attempting to build a Powershell script to monitor this folder from a remote server, for new CSV files, the script will then copy the file to a specified folder location. I am struggling to pass through the parameters to the FileSystemWatcher cmdlet.
Any ideas?
$folder = '\\remoteip\folder\subfolder'# <--'<full path to the folder to watch>'
$filter = '*.csv'
$destination = '\\mynetworkstorage\folder\' # <--' Where is the file going?
$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubdirectories = $true # <-- set this according to your requirements
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
$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' was $changeType at $timeStamp"
Copy-Item $path -Destination $destination -Force -Verbose
}
EDIT -
The script will be run from a server joined to our domain, so there is a need to pass through credentials to the folder in order that I can access it. I have these credentials.
I refactored the code a little (mainly so I could more easily understand it):
$folder = '\\localhost\c$\tmp'
$filter = '*.*'
$destination = '\\localhost\c$\tmp_destination\'
$fsw = New-Object IO.FileSystemWatcher
$fsw.Path = $folder
$fsw.Filter = $filter
$fsw.IncludeSubdirectories = $true
$fsw.EnableRaisingEvents = $true
$fsw.NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
$action = {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host "The file '$name' was $changeType at $timeStamp"
Copy-Item $path -Destination $destination -Force -Verbose
}
$created = Register-ObjectEvent $fsw Created -Action $action
while ($true) {sleep 1}
I ran this code locally and managed to get files created in $folder automatically copied to $destination.
FileSystemWatcher run in the context of the current user. In the case of accessing remote systems that require login, impersonation is required.
If the remote system only got local users, no domain user that the source system can log on as, then impersonation does not seem to be possible.
See this and this link for more details on impersonation.

Copy-Item does not work with FileSystemWatcher

I'm trying to create a watch folder on a network share that simply copies files (300mb-20gb) in size to a destination folder. The FileSystemWatcher and subscription works great with small files (i.e. 1-3kb). However, larger files do not copy. I do see a copy is triggered in the verbose stream, but no file is copied to the destination folder.
$Folder = "\\10.11.233.91\vol_tx01\delivered_media"
$Filter = "*.mxf"
$destination = "C:\Users\Leeds TX 11\Desktop\support\Testy"
$Watcher = New-Object IO.FileSystemWatcher $Folder, $Filter -Property #{
NotifyFilter = [IO.NotifyFilters]'Filename, LastAccess'
}
$onCreated = Register-ObjectEvent $Watcher Created -SourceIdentifier `
FileCreated -Action {
$path = $event.SourceEventArgs.FullPath
$name = $event.SourceEventArgs.Name
$ChangeType = $event.SourceEventargs.ChangeType
$Timestamp = $event.TimeGenerated
Write-Host "The file '$name' was $ChangeType at $Timestamp"
Copy-Item $path -Destination $destination -Force -Recurse -Verbose
}
Combination of issue were at hand. Firstly thank you JohnLBevan for pointing out LastWrite should be the notifyfilter to use. Also found that in this case copy-item does not wait for the file transfer in the source directory to close. I fixed this by putting in a while loop waiting for the file to be locked:
##################### DANGER BOX ####################################
$Folder = "C:\Users\Leeds TX 12\Desktop\Source" #Source dir
$Filter = "*.mxf" # MXF Filter
$destination = "C:\Users\Leeds TX 12\Desktop\Destination" # Destination dir
################### Watch for file system events###########################
$Watcher = New-Object IO.FilesystemWatcher $Folder, $Filter -Property #{
NotifyFilter = [IO.NotifyFilters]'LastWrite, Filename'
}
################### Register filesystemwatcher & subscribe to notifyfilters #################
$onCreated = Register-ObjectEvent $Watcher Created -SourceIdentifier filecreated -Action {
$path = $event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$ChangeType = $Event.SourceEventargs.ChangeType
$Timestamp = $event.TimeGenerated
write-host "The file '$name' was $ChangeType at $Timestamp" # Debug
################# Wait for file lock collapse #########################################
while($True)
{
Try {
[IO.File]::OpenWrite($path).Close()
Break
}
Catch { Start-Sleep -Seconds 1}
}
#################### Copy item #############################
Copy-item $path -Destination $Destination -force -Recurse -Verbose}

Copy-Item does not copy item when actioned by filesystemwatcher

I'm trying to create a watch folder on a network share that simply copies files (300mb-20gb) in size to a destination folder. The filesystemwatcher and subscription works great with small files (i.e. 1-3kb). However, larger files do not copy. I do see a copy is triggered in the verbose stream, but no file is copied to the destination folder.
$Folder = "\\10.11.233.91\vol_tx01\delivered_media"
$Filter = "*.mxf"
$destination = "C:\Users\Leeds TX 11\Desktop\support\Testy"
$Watcher = New-Object IO.FileSystemWatcher $Folder, $Filter -Property #{
NotifyFilter = [IO.NotifyFilters]'Filename, LastAccess'
}
$onCreated = Register-ObjectEvent $Watcher Created -SourceIdentifier FileCreated -Action {
$path = $event.SourceEventArgs.FullPath
$name = $event.SourceEventArgs.Name
$ChangeType = $event.SourceEventargs.ChangeType
$Timestamp = $event.TimeGenerated
Write-Host "The file '$name' was $ChangeType at $Timestamp"
Copy-Item $path -Destination $destination -Force -Recurse -Verbose
}

powershell, how to mointor a directory and move files over to another folder

I am using powershell 3. need to monitor a folder, if there are any image files, move them over to antoher folder.
here's my code, i test it, its not working, couldn't figure out what need to be fixed.
#<BEGIN_SCRIPT>#
#<Set Path to be monitored>#
$searchPath = "F:\download\temp"
$torrentFolderPath = "Z:\"
#<Set Watch routine>#
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $searchPath
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $true
$created = Register-ObjectEvent $watcher "Created" -Action {
Copy-Item -Path $searchPath -Filter *.jpg -Destination $torrentFolderPath –Recurse
}
#<END_SCRIPT>#
UPDATE:
I got it partially working. still have one issue left. lets start with an empty folder. I download an image (1.jpg) to the folder, nothing moved to Z: drive. then I download another image (2.jpg) to the folder. 1.jpg will be moved to Z: drive. seems like the newly created one never get moved over.
$folder = "F:\\download\\temp"
$dest = "Z:\\"
$filter = "*.jpg"
$fsw = new-object System.IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubDirectories=$false
NotifyFilter = [System.IO.NotifyFilters]'FileName, LastWrite'
}
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
Move-Item -Path F:\download\temp\*.jpg Z:\
}
You have not registered the NotifyFilter. That is why your code is not working.
here is a sample which registers the NotifyFilter and prints the file details which was created
$folder = "c:\\temp"
$filter = "*.txt"
$fsw = new-object System.IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubDirectories=$false
NotifyFilter = [System.IO.NotifyFilters]'FileName, LastWrite'
}
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceVentArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host $path
Write-Host $name
Write-Host $changeType
Write-Host $timeStamp
}
Event action scripts run in a separate scope that only has access to global variables, so depending on your implementation you have have issues trying to use those variables in the action script. One way around without resorting to declaring global variables (bad mojo!) is to use an expandable string to create a script block with the variables expanded before you register the event:
$ActionScript =
[Scriptblock]::Create("Copy-Item -Path $searchPath -Filter *.jpg -Destination $torrentFolderPath –Recurse")
$created = Register-ObjectEvent $watcher "Created" -Action $ActionScript