Trigger script when new folder has been added to a location - powershell

I'm automating a process and already made a powershell script for that. Now I need to make something which will call that script everytime a new folder has been added to a specific location i.e. a new build is dropped.
What should I use for this. Is WCF too much? And if not, got any leads for that? Any useful links.
Or is another powershell script better for that?
Keep in mind I need to check subfolders too.
Thanks.

Personnaly I'ld use System.IO.FileSystemWatcher
$folder = 'c:\myfoldertowatch'
$filter = '*.*'
$fsw = New-Object IO.FileSystemWatcher $folder, $filter
$fsw.IncludeSubdirectories = $true
$fsw.NotifyFilter = [IO.NotifyFilters]'DirectoryName' # just notify directory name events
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action { ... do my stuff here } # and only when is created
Use this to stop watching event
Unregister-Event -SourceIdentifier FileCreated

Try this:
$fsw = New-Object System.IO.FileSystemWatcher -Property #{
Path = "d:\temp"
IncludeSubdirectories = $true #monitor subdirectories within the specified path
}
$event = Register-ObjectEvent -InputObject $fsw –EventName Created -SourceIdentifier fsw -Action {
#test if the created object is a directory
if(Test-Path -Path $EventArgs.FullPath -PathType Container)
{
Write-Host "New directory created: $($EventArgs.FullPath)"
# run your code/script here
}
}

Related

Powershell: Register-ObjectEvent io.filesystemwatcher - Can a single registration watch for created and renamed?

I have something like this snippet:
$Watcher = New-Object IO.FileSystemWatcher $folder_to_watch, $file_name_filter -Property #{
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
Register-ObjectEvent $Watcher -EventName Created -SourceIdentifier $eventname -Action {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$fileextension = [System.IO.Path]::GetExtension($name) # extract extension as string from filename
$changeType = $Event.SourceEventArgs.ChangeType
Right now, this event only fires on file creation.
I want it to fire both on creation and rename.
I tried this:
Register-ObjectEvent $Watcher -EventName 'Created,Renamed'
But this does not work a syntax error is raised:
"Register-ObjectEvent : Cannot register for the specified event. An
event with the name 'Created,Renamed' does not exist. Parameter
name: eventName
Is that possible (and how is it done), or must I declare two events?
(It is not clear from the docs if this is possible, or how to do it in powershell)
SOLUTION
The answer below from HAL9256 is valid. However, before discovering that path, I modified the event type to "changed"
This catches file creation and file rename (and some other things). Since my action code filters to make sure only desired files are actually processed, the event type of "changed" meets my needs at this time.
The short answer is that you can only subscribe to one event at a time.
But you can have multiple subscribed events registered to the same Action. For ex. If you define your action in a Script Block, you can subscribe both Created and Rename to the same Action.
$Watcher = New-Object IO.FileSystemWatcher $folder_to_watch, $file_name_filter -Property #{
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
#Your script block
$Action = {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$fileextension = [System.IO.Path]::GetExtension($name) # extract extension as string from filename
$changeType = $Event.SourceEventArgs.ChangeType
}
Register-ObjectEvent $Watcher -EventName Created -SourceIdentifier $eventname -Action $Action
Register-ObjectEvent $Watcher -EventName Renamed -SourceIdentifier $eventname -Action $Action

how to monitor a folder in windows a run a batch file

I was following this SO answer to monitor a folder , but it is working one time. I mean if create a folder or file the batchfile will run , I created again a folder or edite it , it wont trigger
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Users\uuu\Desktop\new folder\tttt"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = { $path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
Add-content "D:\Copyof\PSlog.txt" -value $logline
cmd.exe /k "D:\Copyof\move.bat"
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
Register-ObjectEvent $watcher "Changed" -Action $action
Register-ObjectEvent $watcher "Deleted" -Action $action
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {sleep 1}
Just so this gets an official answer:
Isn't the problem coming from your "/k" flag on cmd.exe? It means execute the command and remain. – David Brabant
/K Run Command and then return to the CMD prompt. This is useful for testing, to examine variables – Matt
Use a /C instead. – SomethingDark

Unregister a registered filewatcher event does not work

I want to watch a folder with powershell and I am a PS beginner.
That script works ONE time when I start the script.
But when I have to restart the script again because I changed some script code I get this error message:
Cannot subscribe to the specified event. A subscriber with the source identifier 'FileChanged' already exists.
I tried:
this at the top of the script:
Unregister-Event -SourceIdentifier FileChanged
does not work.
How do I correctly unregister the event so I can run my script as often I want and the previously registered event is disposed?
CODE
$folder = "C:\temp"
$Watcher = New-Object IO.FileSystemWatcher $folder -Property #{
IncludeSubdirectories = $true
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
$onChanged = Register-ObjectEvent $Watcher Changed -SourceIdentifier FileChanged -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"
Write-Host $path
#Move-Item $path -Destination $destination -Force -Verbose
}
Ok, looking at what your trying to achieve... to answer your original question, you need to do the following to unregistered the event.
Get-EventSubscriber -SourceIdentifier "filechanged" | Unregister-Event
I have to ask why are you having to make 1000 adjustments to the code. If you are trying to register 1000 different events to be monitored it would make more sense to loop and increment a variable using the ++ modifier.
I have achieved this already if this is what your tying to accomplish and can share some code if you need it.

Check for file creation in a loop

Can I run this script one time automate when the .exe show up on folder?
Get-ChildItem -Filter *.exe | ForEach {
&$_.Fullname /s
I want a script to check if .exe file shows up on folder, then run that commands, else check again for .exe file.
You can use the FileSystemWatcher to listen for these events.
Get-EventSubscriber -SourceIdentifier ExeCreated -ErrorAction SilentlyContinue | Unregister-Event;
$Watcher = New-Object -TypeName System.IO.FileSystemWatcher;
$Watcher.Filter = '*.exe';
$Watcher.Path = 'c:\test';
$Action = { Write-Host -Object ('New file created: {0}' -f $event.SourceArgs[1].Name); };
Register-ObjectEvent -InputObject $Watcher -EventName Created -Action $Action -SourceIdentifier ExeCreated;

FileSystemWatcher works in the PowerShell ISE but not when run

I want to monitor a folder and move files that match certain criteria, so I'm trying to use the FileSystemWatcher.
I have a function that will be called with each new file:
function ProcessFile()
{
param ([string]$filename)
Write-Host "Processing file '$filename' to $destination"
}
And then I set up a FSW:
Write-Host "Watching $source for new files..."
$fsw = New-Object IO.FileSystemWatcher $source, $filter -Property #{IncludeSubdirectories = $false; NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'}
Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action
{
ProcessFile $Event.SourceEventArgs.FullPath
}
That works fine when I run it from the ISE, and any files I drop into the watched folder are correctly tracked, but if I start a PowerShell window and run the script with .\FileWatch.ps1 then nothing happens.
I see the "watching ..." message, but never see a "processing..." message
Here's the full script that works in the ISE but not in a shell...
$source = 'D:\Dev\PowerShell\FileWatch\Test\Source'
$filter = '*.*'
$destination = 'D:\Dev\PowerShell\FileWatch\Test\Found\'
function ProcessFile()
{
param ([string]$filename)
Write-Host "Processing file '$filename' to $destination"
}
Write-Host "Watching $source for new files..."
$fsw = New-Object IO.FileSystemWatcher $source, $filter -Property #{IncludeSubdirectories = $false; NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'}
Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
ProcessFile $Event.SourceEventArgs.FullPath
}
The problem is that your function ProcessFile isn't loaded in powershell session.
Try loading you script in this way:
. .\myscript.ps1
In this way your code in my system works!
Read about Dot Sourcing a script in powershell.