Powershell: copy-item deletes file - powershell

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

Related

Powershell - how to start action after a FEW files have been created

i want to loop a powershell script that monitors if a few xml files were created in a folder. If there are at least 3 it should restart a program.
Here is what i got from the use nixda on here:
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\DVNAV\11842596\nav2016\2019"
$watcher.Filter = "*.xml*"
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $true
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = { Stop-Process -name dvnav -force
Start-Sleep -Seconds 8
Start-Process -FilePath 'C:\Program Files (x86)\DVNAV.exe' -verb RunAs
}
### 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 5}
But i don't know how i can set the monitoring to multiple files not just one.
This should work for you. Don't Forget to unregister Events after using/testing!
#--------------------------------------------------
function Stop-EventWatcher {
#--------------------------------------------------
# To stop the monitoring, run the following commands:
Unregister-Event FileCreated
}
$folderToWatch = 'C:\DVNAV\11842596\nav2016\2019'
$filter = '*.xml'
$script:counter = 0
# In the following line, you can change 'IncludeSubdirectories to $true if required.
$fsw = New-Object IO.FileSystemWatcher
$fsw.Path = $folderToWatch
$fsw.IncludeSubdirectories = $false
$fsw.EnableRaisingEvents = $true
$scriptBlock = {
$message = $event.MessageData # message data is how we pass in an argument to the event script block
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
$script:counter++
if( $script:counter -eq 3 ) {
$script:counter = 0
# do special action here!
}
}
# Here, the event ist registered. You need only subscribe to events that you need:
Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -MessageData 'Hello' -Action $scriptBlock

External powershell scripts only run once when action called

I am trying to call an outside ps script to run every time files are created. The monitoring and logging of files work well, but the Invoke-Expression of running the external script only runs one time even if more files are created. How do I run the external script with every time a new file is created.
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "c:\mypath"
$watcher.Filter = "*.txt*"
$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 "C:\mypath\log.txt" -value $logline
Invoke-Expression (start powershell ("C:\MyOtherScript.ps1")) ###### This only runs one time even if file is changes and logged
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
while ($true) {sleep 5}
EDIT: This got it working incase anyone find themselves here looking to solve the porblem
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "c:\mypath"
$watcher.Filter = "*.txt*"
$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 "C:\mypath\log.txt" -value $logline
Start-Process powershell -argument "C:\MyOtherScript.ps1"
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Created" -Action $action
#while ($true) {sleep 5}
Invoke-Expression is not recommend over using & due to security concerns. In your example, however, I'd suggest Start-Process:
Start-Process -FilePath 'powershell' -ArgumentList #('-File','"C:\MyOtherScript.ps1"')

Wait until copy process is completed and continue in script

I am watching activity in one folder and when there is some activity I want to remove some other files and copy the new files and folders from my watched folder.
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\Users\Acer\Desktop\TestSpace\main"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
$action = { $path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
Add-content "C:\Users\Acer\Desktop\TestSpace\log.txt" -value $logline
Write-Host "Deleting"
Remove-Item C:\Users\Acer\Desktop\TestSpace\ORA\app\ -Exclude web.config -recurse -force -Confirm:$false
Write-Host "Deleting done"
#Write-Host "Copy"
$copy = (Get-Process (Copy-Item -Path C:\Users\Acer\Desktop\TestSpace\main\app -Exclude web.config -Destination C:\Users\Acer\Desktop\TestSpace\ORA\ -Recurse -verbose))
$copy | Wait-Job
wait-process -id $copy.id
Write-Host "Copy Done"
}
### 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 5}
This is fine but there is a problem, the process is running just one time and after that is still waiting.
Write-Host "Copy"
$copy = (Get-Process (Copy-Item -Path C:\Users\Acer\Desktop\TestSpace\main\app -Exclude web.config -Destination C:\Users\Acer\Desktop\TestSpace\ORA\ -Recurse -verbose))
$copy | Wait-Job
wait-process -id $copy.id
Write-Host "Copy Done"

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

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;