Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

check multiple files (Moved the Post from VBScriptto here) 1

Status
Not open for further replies.

sugram

Technical User
Feb 5, 2021
26
DE
Hello

i have postet here an question and there mikrom posted a powershell solution to me.
So I'm moving this to here.

I would like to check several files, ideally from several PCs, for changes and then receive a notification.
after some googling I have this script

Code:
Add-Type -AssemblyName PresentationFramework
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "c:\tmp\tk"
$watcher.Filter = "*.cfg"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
$null = Register-ObjectEvent $watcher "Changed" -Action {Send-MailMessage –To "Email.Adress@domain.com" –Subject "CFG DATEI GEÄNDERT!" –Body "CFG Datei wurde geändert!" –SmtpServer "smtp.com" –From "noreplay@domain.com" -encoding ([System.Text.Encoding]::UTF8)}
while ($true) {sleep 10}

it works, only I always get two email's.
But i don't understand why

Can you tell me why?
And how can I query multiple paths ?!
Because I would like to be able to query several PCs

And when i edit the script to open a Picture, i get multiple E-Mails
Code:
Add-Type -AssemblyName PresentationFramework
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "c:\tmp\tk"
$watcher.Filter = "*.cfg"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
$null = Register-ObjectEvent $watcher "Changed" -Action {Send-MailMessage –To "Email.Adress@domain.com" –Subject "CFG DATEI GEÄNDERT!" –Body "CFG Datei wurde geändert!" –SmtpServer "smtp.com" –From "noreplay@domain.com" -encoding ([System.Text.Encoding]::UTF8)}
$null = Register-ObjectEvent $watcher "Changed" -Action {Invoke-Item "C:\Users\username\Documents\test.jpg"}
while ($true) {sleep 10}

I hope that someone here can explain or help me, why I get several emails here, although only one file changes.
And of course how I could check several PCs

Many Thanks
 
sugram said:
it works, only I always get two email's.
But i don't understand why

Can you tell me why?

It's probably because you experimented with the script and so you started your script twice. If you run the script once again, you will get 3 emails.
If you think, that you finished the script with Ctrl-C then it's not true - it's still running.
Look how many powershell processes are running and kill those which are unnecessary.
 
I found out, that after activating System.IO.FileSystemWatcher with Register-ObjectEvent, the files are being monitored until deactivating it with Unregister-Event - even if I end the script with Ctrl-C
 
>deactivating it with Unregister-Event

Hence the commented out line in my original illustrative idea in the original thread :)
 
I found very nice example here:
I adapted it a little bit (using several other sources). Now it works great for me.
Here it is - you can try it too:

Code:
[COLOR=#008080]$filewatcher[/color] = [COLOR=#804040][b]New-Object[/b][/color] System.IO.FileSystemWatcher
[COLOR=#0000ff]# folder and file types to monitor[/color]
[COLOR=#008080]$path[/color] = [COLOR=#ff00ff]"c:\tmp\"[/color]
[COLOR=#008080]$filter[/color] = [COLOR=#ff00ff]"*.txt"[/color]
[COLOR=#008080]$filewatcher[/color].Path = [COLOR=#008080]$path[/color]
[COLOR=#008080]$filewatcher[/color].[COLOR=#804040][b]Filter[/b][/color] = [COLOR=#008080]$filter[/color]
[COLOR=#0000ff]# include subdirectories $true/$false[/color]
[COLOR=#008080]$filewatcher[/color].IncludeSubdirectories = [COLOR=#008080]$true[/color]
[COLOR=#008080]$filewatcher[/color].EnableRaisingEvents = [COLOR=#008080]$true[/color]  
 
[COLOR=#0000ff]# define actions after an event is detected[/color]
[COLOR=#008080]$writeaction[/color] = {
  [COLOR=#008080]$path[/color] = [COLOR=#008080]$Event[/color].SourceEventArgs.FullPath
  [COLOR=#008080]$changeType[/color] = [COLOR=#008080]$Event[/color].SourceEventArgs.ChangeType
  [COLOR=#008080]$logline[/color] = [COLOR=#ff00ff]"$(Get-Date), $changeType, $path"[/color]
  [COLOR=#0000ff]# write to logfile[/color]
  [COLOR=#804040][b]Add-content[/b][/color] [COLOR=#ff00ff]"C:\tmp\FileWatcher_log.log"[/color] -value [COLOR=#008080]$logline[/color]
  [COLOR=#0000ff]# write to console[/color]
  [COLOR=#804040][b]Write-Host[/b][/color] [COLOR=#008080]$logline[/color]
  [COLOR=#0000ff]# send email[/color]
  [COLOR=#804040][b]Send-MailMessage[/b][/color] –To [COLOR=#ff00ff]"email.adress@domain.com"[/color] `
                   –Subject [COLOR=#ff00ff]"Event on file: $path"[/color] `
                   –Body [COLOR=#008080]$logline[/color] `
                   –SmtpServer [COLOR=#ff00ff]"smtp.com"[/color] `
                   –From [COLOR=#ff00ff]"noreplay@domain.com"[/color] `
                   -encoding ([COLOR=#2e8b57][b][System.Text.Encoding][/b][/color]::UTF8)
}    
[COLOR=#0000ff]# subscribe to events which should be watched[/color]
[COLOR=#804040][b]Register-ObjectEvent[/b][/color] [COLOR=#008080]$filewatcher[/color] [COLOR=#ff00ff]"Created"[/color] -Action [COLOR=#008080]$writeaction[/color]
[COLOR=#804040][b]Register-ObjectEvent[/b][/color] [COLOR=#008080]$filewatcher[/color] [COLOR=#ff00ff]"Changed"[/color] -Action [COLOR=#008080]$writeaction[/color]
[COLOR=#804040][b]Register-ObjectEvent[/b][/color] [COLOR=#008080]$filewatcher[/color] [COLOR=#ff00ff]"Deleted"[/color] -Action [COLOR=#008080]$writeaction[/color]
[COLOR=#804040][b]Register-ObjectEvent[/b][/color] [COLOR=#008080]$filewatcher[/color] [COLOR=#ff00ff]"Renamed"[/color] -Action [COLOR=#008080]$writeaction[/color]

[COLOR=#0000ff]# write info[/color]
[COLOR=#804040][b]Write-Host[/b][/color]
[COLOR=#804040][b]Write-Host[/b][/color] [COLOR=#ff00ff]"Start monitoring files: $path$filter"[/color]
[COLOR=#804040][b]Write-Host[/b][/color] [COLOR=#ff00ff]"(press Ctrl-C to stop)"[/color]
[COLOR=#804040][b]Write-Host[/b][/color]

[COLOR=#0000ff]# Ctrl+C is treated as ordinary input[/color]
[COLOR=#2e8b57][b][console][/b][/color]::TreatControlCAsInput = [COLOR=#008080]$true[/color]

[COLOR=#008080]$stepCounter[/color] = [COLOR=#ff00ff]0[/color]
[COLOR=#804040][b]while[/b][/color] ([COLOR=#008080]$true[/color]) {
  sleep [COLOR=#ff00ff]1[/color]
  [COLOR=#0000ff]# if Ctrl-C is pressed[/color]
  [COLOR=#804040][b]if[/b][/color] ([COLOR=#008080]$Host[/color].UI.RawUI.KeyAvailable -[COLOR=#804040][b]and[/b][/color] `
     ([COLOR=#ff00ff]3[/color] -[COLOR=#804040][b]eq[/b][/color] [COLOR=#2e8b57][b][int][/b][/color][COLOR=#008080]$Host[/color].UI.RawUI.ReadKey([COLOR=#ff00ff]"AllowCtrlC,IncludeKeyUp,NoEcho"[/color]).Character)) {
    [COLOR=#0000ff]# cancel all event subscriptions in the session[/color]
    [COLOR=#804040][b]Get-EventSubscriber[/b][/color] -Force | [COLOR=#804040][b]Unregister-Event[/b][/color] -Force
    [COLOR=#0000ff]# write info[/color]
    [COLOR=#804040][b]Write-Host[/b][/color] [COLOR=#ff00ff]"`n"[/color]
    [COLOR=#804040][b]Write-Host[/b][/color] [COLOR=#ff00ff]"End of monitoring."[/color] -Background DarkRed
    [COLOR=#0000ff]# exit loop[/color]
    [COLOR=#804040][b]break[/b][/color];
  }
}
 
Hello Strongm,
Thank you very much for showing me the right way with the PowerShell !
 
@mikrom
Many Thanks!!

I test it in the Powershell ISE Console, but i get a error Message:

Code:
Start monitoring files: c:\tmp\*.cfg
(press Ctrl-C to stop)

Ausnahme beim Festlegen von "TreatControlCAsInput": "Das Handle ist ungültig.
"
In Zeile:42 Zeichen:1
+ [console]::TreatControlCAsInput = $true
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
    + FullyQualifiedErrorId : ExceptionWhenSetti
I ignore the Message and change one file and Save it.
I also get 2 e-mails here, although I have only one Powershell open.

Code:
Start monitoring files: c:\tmp\*.cfg
(press Ctrl-C to stop)

Ausnahme beim Festlegen von "TreatControlCAsInput": "Das Handle ist ungültig.
"
In Zeile:41 Zeichen:1
+ [console]::TreatControlCAsInput = $true
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
    + FullyQualifiedErrorId : ExceptionWhenSetting
 
02/18/2021 07:32:00, Changed, c:\tmp\TK\205.cfg
02/18/2021 07:32:00, Changed, c:\tmp\TK\205.cfg

PS C:\Windows\System32\WindowsPowerShell\v1.0>
 
Hi sugram,
I wrote it in ISE, but tested it directly on powershell command line. When I run it now on command line it runs nice. But when I try it in ISE, I get the same error as you. I don't know now, where the error in ISE come from, try it on powershell command line.

sugram_powershell_gucxsg.png
 
hi mikrom,

ok, in the Powershell console i get no error message ;-)
But i get always 2 Messages when i change one file.
(i open it, change something and save the file)
power_zdogjm.png
 
Here I found why the ISE error like above comes out:
It's because, when powershell starts then conhost.ese will be started automatically, but ISE does not start it.

conhost_exe_oagric.png



So now a I have this workaround:
Before starting the script in ISE, I execute on the powershell console in ISE a command which starts conhost.exe. It is for example ping as described in the link above.
After executing ping on powershell console in ISE, the script runs without error - here is my output:
Code:
PS U:\> ping

Usage: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS]
            [-r count] [-s count] [[-j host-list] | [-k host-list]]
            [-w timeout] [-R] [-S srcaddr] [-c compartment] [-p]
            [-4] [-6] target_name

Options:
    -t             Ping the specified host until stopped.
                   To see statistics and continue - type Control-Break;
                   To stop - type Control-C.
    -a             Resolve addresses to hostnames.
    -n count       Number of echo requests to send.
    -l size        Send buffer size.
    -f             Set Don't Fragment flag in packet (IPv4-only).
    -i TTL         Time To Live.
    -v TOS         Type Of Service (IPv4-only. This setting has been deprecated
                   and has no effect on the type of service field in the IP
                   Header).
    -r count       Record route for count hops (IPv4-only).
    -s count       Timestamp for count hops (IPv4-only).
    -j host-list   Loose source route along host-list (IPv4-only).
    -k host-list   Strict source route along host-list (IPv4-only).
    -w timeout     Timeout in milliseconds to wait for each reply.
    -R             Use routing header to test reverse route also (IPv6-only).
                   Per RFC 5095 the use of this routing header has been
                   deprecated. Some systems may drop echo requests if
                   this header is used.
    -S srcaddr     Source address to use.
    -c compartment Routing compartment identifier.
    -p             Ping a Hyper-V Network Virtualization provider address.
    -4             Force using IPv4.
    -6             Force using IPv6.


PS U:\> C:\00_mikrom\Work\sugram.ps1

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                 
--     ----            -------------   -----         -----------     --------             -------                 
1      4d13aac3-b15...                 NotStarted    False                                ...                     
2      b54d0be9-1d3...                 NotStarted    False                                ...                     
3      9ea162b9-fe0...                 NotStarted    False                                ...                     
4      4e497f6d-120...                 NotStarted    False                                ...                     

Start monitoring files: c:\tmp2\*.txt
(press Ctrl-C to stop)

02/18/2021 09:51:44, Created, c:\tmp2\sugram_05.txt
02/18/2021 09:51:50, Deleted, c:\tmp2\sugram_05.txt

PS U:\>
 
sugram said:
But i get always 2 Messages when i change one file.
Maybe you have opened the ISE, where you tried the script before, so still 2 instances are running.
Close everything, i.e: ISE, powershell command window, maybe restart your computer.

Then when you open powershell command window again and run the script once, then you should get only one message for every change. Then when you stop the script with Ctrl-C and run again, then again only one message. If I work hygienic at this way with the Powershell beast then it works fine for me.
 
Hi Mikrom


i think my Computer hates me.
I reboot my pc and open one Powershell window, and run the script.
And i get 2 messages :(


 
I don't know, try this: On the powershell console where your script runs, stop it and look at the subscribed events with the command
Code:
Get-EventSubscriber -Force
and then end all subscriptions with:
Code:
Get-EventSubscriber -Force | Unregister-Event -Force

 
Hi mikrom,

Many thanks for your help!

i don't know what do my PC.
The results you can see here.

power_ciodc8.png
 
I don't understand what's going wrong.
Are you using the exact same script as I posted above (only with changed email and smtp)?

You need to find out where the 2 messages come from:
Stop the script.
Then change the file to see if you get the email, that would mean that the other instance of the script is elsewhere running ..
Or modify the message in the script, then run it and change the file again, to see if exact the same two messages comes out, or if the old and new message come out ...
 
You only try to change the file. Maybe it's something wrong how you change the file, for example when i press quickly two times Ctrl-S in notepad, the file changes two times and I get two messages.
Try what happens if you create a file and if you delete a file: if you then get 2 create and 2 delete messages too, or only 1 ?
 
Ok,

i have only changed the Part of Email in the script for testing.
So i get only a picture and no emails ;-)

Code:
# define actions after an event is detected
$writeaction = {
  $path = $Event.SourceEventArgs.FullPath
  $changeType = $Event.SourceEventArgs.ChangeType
  $logline = "$(Get-Date), $changeType, $path"
  # write to logfile
  Add-content "C:\tmp\FileWatcher_log.log" -value $logline
  # write to console
  Write-Host $logline
  # send email
  #Send-MailMessage –To "Email@domain.com" `
  #                 –Subject "Event on file: $path" `
  #                 –Body $logline `
  #                 –SmtpServer "smtp.com" `
  #                 –From "noreplay@domain.com" `
  #                 -encoding ([System.Text.Encoding]::UTF8)
  Invoke-Item "C:\Users\username\Documents\test.jpg"
}

i open the Powershell console and run the script.
I change one File and save it -> i get 2 messages.
After this i Stop the script and change the same File again and no Picture or new entry in the Logfile.

You postet an NEW Message and THIS was the solution!!

I changed the Files with Notepad++ and press Ctrl-S or the Save Button -> i get 2 Messages.
When i use the Notepad.exe and after i change the file and i go to File Save -> i get only 1 Message!

Then just one more question.
Would it be possible to check several different paths
 
Oh then it wasn't Powershell's fault but Notepad++'s ! :)
 
sugram said:
Would it be possible to check several different paths

Yes, it must be possible.

Maybe modify path and filter to be script command line arguments:
Code:
$filewatcher.Path = $args[0]
$filewatcher.Filter = $args[1]
and then run the script more times:
Code:
.\monitoring_script.ps1 c:\tmp_01\ *.cfg
...
.\monitoring_script.ps1 c:\tmp_02\ *.txt
...

Other possibility would be to use more instances of System.IO.FileSystemWatcher in one script:
Code:
$filewatcher_01 = New-Object System.IO.FileSystemWatcher
$filewatcher_01.Path = "c:\tmp_01\"
$filewatcher_01.Filter = "*.cfg"
...
$filewatcher_02 = New-Object System.IO.FileSystemWatcher
$filewatcher_02.Path = "c:\tmp_02\"
$filewatcher_02.Filter = "*.txt"
...
Register-ObjectEvent $filewatcher_01 "Created" -Action $writeaction
Register-ObjectEvent $filewatcher_01 "Changed" -Action $writeaction
Register-ObjectEvent $filewatcher_01 "Deleted" -Action $writeaction
Register-ObjectEvent $filewatcher_01 "Renamed" -Action $writeaction
...
Register-ObjectEvent $filewatcher_02 "Created" -Action $writeaction
Register-ObjectEvent $filewatcher_02 "Changed" -Action $writeaction
Register-ObjectEvent $filewatcher_02 "Deleted" -Action $writeaction
Register-ObjectEvent $filewatcher_02 "Renamed" -Action $writeaction
...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top