Check for file creation in a loop - powershell

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;

Related

Powershell script not firing Register-ObjectEvent

I have the below script for folder watcher:
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\inetpub\wwwroot\exports\"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = {
start-process C:\inetpub\wwwroot\exports\services\execute.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}
The above script monitors C:\inetpub\wwwroot\exports\ folder and if there is any change to this folder, the $action is called. This script is not working and I see "Not started" error as below:
Any help on how to fix this?
I think its a "feature", the $action script should fire. It only seems to enter Running state after the first event has been fired.
Temporarily insert below before while ($true) {sleep 1} and you should see the state change:
Get-Job
Set-Content -Path "$($watcher.Path)\a_test_file.txt" -Value "hello"
Get-Job
(And for the sake of completeness Get-Job -Id 1 | Stop-Job -PassThru | remove-Job to stop and remove job id #1 - change id as required)

How to detect Folder change (renaming in particular) inside a folder using Powershell file watcher

I am using powershell to detect and record a folder change (created, renamed, deleted etc) inside a folder.
This parent folder receives subfolders from another location in format TEMP_XYZ. Once this folder is copied to this parent folder, the process automatically renames it to XYZ (Removed suffix TEMP_)
This change (rename) had to be detected and recorded in a log file as
\\test\folderwatch\XYZ was Renamed at 7/28/2021 2:03:00 PM
Folder TEMP_XYZ was renamed to XYZ
However, I am not able to achieve this as the code below only works on files. (txt,bmp, zip etc)
Any help is appreciated.
Code:
# specify the path to the folder you want to monitor:
$Monitorpath ="\\test\folderwatch"
$Path = $Monitorpath
# specify which files you want to monitor
$FileFilter = '*'
# specify whether you want to monitor subfolders as well:
$IncludeSubfolders = $true
# specify the file or folder properties you want to monitor:
$AttributeFilter = [IO.NotifyFilters]::FileName, [IO.NotifyFilters]::LastWrite
try
{
$watcher = New-Object -TypeName System.IO.FileSystemWatcher -Property #{
Path = $Path
#Filter = $FileFilter
IncludeSubdirectories = $IncludeSubfolders
NotifyFilter = $AttributeFilter
}
$action = {
# change type information:
$details = $event.SourceEventArgs
$Name = $details.Name
$FullPath = $details.FullPath
$OldFullPath = $details.OldFullPath
$OldName = $details.OldName
$ChangeType = $details.ChangeType
$Timestamp = $event.TimeGenerated
$LogDate = Get-Date -format "dd-MMMM-yy"
# save information to a global variable for testing purposes
# so you can examine it later
# MAKE SURE YOU REMOVE THIS IN PRODUCTION!**************************DO NOT USE FOR PROD**************************
$global:all = $details
$text = "{0} was {1} at {2}" -f $FullPath, $ChangeType, $Timestamp
Write-Host ""
Write-Host $text -ForegroundColor DarkYellow
Add-content "\\test\folder_watch_logs\watchlog_$LogDate.txt" -value $text
switch ($ChangeType)
{
'Changed' { "CHANGE" }
'Created' { "CREATED"}
'Deleted' { "DELETED"
Write-Host "Deletion Handler Start" -ForegroundColor Gray
Start-Sleep -Seconds 4
Write-Host "Deletion Handler End" -ForegroundColor Gray
}
'Renamed' {
# this executes only when a file was renamed
$text = "Folder {0} was renamed to {1}" -f $OldName, $Name
Write-Host $text -ForegroundColor Yellow
Add-content "test\folder_watch_logs\watchlog_$LogDate.txt" -value $text
}
# any unhandled change types surface here:
default { Write-Host $_ -ForegroundColor Red -BackgroundColor White ;
Add-content "test\folder_watch_logs\watchlog_$LogDate.txt" -value $_ }
}
}
$handlers = . {
Register-ObjectEvent -InputObject $watcher -EventName Changed -Action $action
Register-ObjectEvent -InputObject $watcher -EventName Created -Action $action
Register-ObjectEvent -InputObject $watcher -EventName Deleted -Action $action
Register-ObjectEvent -InputObject $watcher -EventName Renamed -Action $action
}
# monitoring starts now:
$watcher.EnableRaisingEvents = $true
$LogDate = Get-Date -format "dd-MMMM-yy"
Write-Host "Watching for changes to $Path"
Add-content "test\folder_watch_logs\watcherstatus.txt" -value "Watching for changes to $Path"
# since the FileSystemWatcher is no longer blocking PowerShell
# we need a way to pause PowerShell while being responsive to
# incoming events. Use an endless loop to keep PowerShell busy:
do
{
Wait-Event -Timeout 1
# write a dot to indicate we are still monitoring:
#Write-Host "." -NoNewline
} while ($true)
}
finally
{
# stop monitoring
$watcher.EnableRaisingEvents = $false
# remove the event handlers
$handlers | ForEach-Object {
Unregister-Event -SourceIdentifier $_.Name
}
$handlers | Remove-Job
# properly dispose the FileSystemWatcher:
$watcher.Dispose()
$LogDate = Get-Date -format "dd-MMMM-yy"
Write-Warning "Event Handler disabled, monitoring ends."
Add-content "test\folder_watch_logs\watcherstatus.txt" -value "Event Handler disabled, monitoring ends."
}
//Jagbir
Adjust your watcher's NotifyFilter so that it is looking at directory names
$AttributeFilter = [IO.NotifyFilters]::FileName, [IO.NotifyFilters]::LastWrite, [IO.NotifyFilters]::DirectoryName
or if you are only interested in changes in directory names only specify
$AttributeFilter = [IO.NotifyFilters]::DirectoryName
If you are only interested in the renaming events do not register the others
$handlers = . {
# Remove Changed, Created, and Deleted if they are of no concern
# Register-ObjectEvent -InputObject $watcher -EventName Changed -Action $action
# Register-ObjectEvent -InputObject $watcher -EventName Created -Action $action
# Register-ObjectEvent -InputObject $watcher -EventName Deleted -Action $action
Register-ObjectEvent -InputObject $watcher -EventName Renamed -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

Powershell: copy-item deletes file

I have a client that removes/writes files every 10 seconds on my laptop. I also have a Powershell script that is supposed to copy files whenever they are changed, to a network location.
Now to the problem: sometimes, quite often, one or two of the files on the remote network location gets deleted. But I have nothing in the script that is supposed to delete any file, only copy.
How come this happens? See the script below:
$block = {
function CreateCopyFile
{
param ($message, $event)
# function to call when event is raised
# do a robocopy or whatever
$path = $Event.SourceEventArgs.FullPath
$targetpath = $targetFolder + "/" + $Event.SourceEventArgs.Name
Copy-Item $path $targetFolder
}
$watchedFolder = "C:\Users\test\Documents\folder"
$targetFolder = "\\TRICASTER-MINI\DataLink Watch Folder"
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $watchedFolder
Register-ObjectEvent -InputObject $watcher -EventName Created -SourceIdentifier File.Created -Action { CreateCopyFile "Created" $event }
Register-ObjectEvent -InputObject $watcher -EventName Changed -SourceIdentifier File.Changed -Action { CreateCopyFile "Changed" $event }
}
$encodedBlock = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($block))
Start-Process PowerShell.exe -verb Runas -argumentlist '-WindowStyle Hidden', '-NoExit', '-EncodedCommand', $encodedBlock

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.