Last modified: May 27, 2001

Perl Win32 AdvNotify module version 1.31

Author: Amine Moulay Ramdane

Email: aminer@generation.net .......... Phone: (514) 485-6659

Website: http://www.generation.net/~aminer/Perl

Copyright © 1999 Amine Moulay Ramdane.All rights reserved

 

Description

With this object oriented Perl module you will be able to monitor the changes on your directories, this allows your Perl application to respond to changes in the file system, such as new file and/or directory creation, renaming, size,attribute, time, security-descriptor changes etc. Also, with AdvNotify you can run multiple threads from inside your Perl application to monitor the file system changes and you will be notified of wich file has been changed. The AdvNotify's interface has been carefully designed to be very easy to use.

Note: AdvNotify does use asynchronous completion to receive notification from the WinNT OS (no wasting CPU time "polling"), hence AdvNotify is very efficient. This module needs the API module, please download and install the API module before installing AdvNotify.

 

The AdvNotify interface

new
StartThread
Wait
Read
SendSignal
EnableWatch
DisableWatch
Terminate
KeyPressed
TextColor
ClrScr

 

The AdvNotify methods

Index

$obj = new Win32::AdvNotify

The new() class method creates a new AdvNotify object and returns a reference to it or undef if the creation failed.

Example:

use Win32::AdvNotify;

my $obj=new Win32::AdvNotify || die "Can't create an AdvNotify object\n";


Index

$thread = $obj->StartThread(Directory => $directory, Filter => $filer, WatchSubtree => bool)

StartThread() Starts a (monitoring) thread.

If the call to StartThread() is successful, a thread object (reference) is returned, undef otherwise.

Note: The started thread will enter immediatly in a wait state. Call EnableWatch to enable monitoring.

Directory: Specifies a directory to watch. If the specified directory does not exist, or cannot be opened (for example if other process uses it exclusively) then EnableWatch() will fail (will returns undef)..

Filter: specifies what events your application will respond to. One or more of the following constants are allowed:

FILE_NAME Any filename change in the watched directory or subtree causes a change notification wait operation to return. Changes include renaming, creating, or deleting a file.

DIR_NAME Any directory-name change in the watched directory or subtree causes a change notification wait operation to return. Changes include creating or deleting a directory.

ATTRIBUTES Any attribute change in the watched directory or subtree causes a change notification wait
operation to return.

SIZE Any file-size change in the watched directory or subtree causes a change notification wait operation to return. The operating system detects a change in file size only when the file is written to the disk. For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed.

LAST_WRITE Any change to the last write-time of files in the watched directory or subtree causes a change notification wait operation to return. The operating system detects a change to the last write-time only when the file is written to the disk. For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed.

LAST_ACCESS Any change to the last access time of files in the watched directory or subtree causes a change notification wait operation to return.

CREATION Any change to the creation time of files in the watched directory or subtree causes a change notification wait operation to return.

SECURITY Any security-descriptor change in the watched Directory or subtree causes a change notification wait operation to return.

Note: if you want to specify all of them, you have to import and use the "All" constant or simply don't provide the "Filter" property.

WatchSubtree specifies whether the thread will monitor the directory or the directory tree. If it's Yes or 1, the thread will monitor the directory tree. If it's No or 0, the thread will monitor only the directory specified.

Example:

#!perl -w

use Win32::AdvNotify qw(Yes No All FILE_NAME SIZE SECURITY);

my $obj = new Win32::AdvNotify || die "Can't create object\n";

# Now we will start two threads
# Note: You can start more threads if you want..

my $thread1 = $obj->StartThread(Directory => "c:\\Win32\\",

Filter => FILE_NAME|SIZE|SECURITY, WatchSubtree => Yes ) || die "Can't start thread1..\n";

my $thread2 = $obj->StartThread(Directory => "c:\\Unix\\",

Filter => FILE_NAME|SIZE|SECURITY, WatchSubtree => Yes ) || die "Can't start thread2..\n";

$thread1->EnableWatch() || die "Problem starting EnableWatch()\n";

$thread2->EnableWatch() || die "Problem starting EnableWatch()\n";

See also: EnableWatch and DisableWatch

Note: Please see Read for a more complete example.


Index

$ret = $obj->Wait($msTimeout)

Wait() Checks if an event has occured, the calling thread enters an efficient wait state. The thread consumes very little processor time while waiting for the event to occur.

Wait() will returns when one of the following occurs:

- The event specified in the Filter property has occured

- The time-out interval elapses.

- If one of the following signals occurs, Wait() will return with undef (this will allow to exit from the loop), and the $obj->{Event} property will indicates the type of signal received. This value is one of the following:

SIG_INT: A CTRL-C signal from the keyboard.

SIG_TSTP: A CTRL-BREAK signal from the keyboard or from a signal generated by SendSignal.

SIG_KILL: A signal that the system sends when the user closes the console (by choosing the Close command from the console window's System menu..).

SIG_LOGOFF: A signal that the system sends when a user is logging off. This signal does not indicate which user is logging off, so no assumptions can be made.

SIG_SHUTDOWN: A signal that the system sends when the system is shutting down.

Note: To get the text name of the signal you have to import the %EventName hash and use it like this: $EventName{$obj->{Event}}.

$msTimeout Specifies the time-out interval, in milliseconds. The function returns if the interval elapses, even if the event didn't occur. If $msTimeout is INFINITE or -1, the function's time-out interval never elapses.

Example1:

#!perl -w

use Win32::AdvNotify qw(FILE_NAME SIZE INFINITE Yes No All %ActionName %ActionColor %EventName);

my $obj = new Win32::AdvNotify || die "Can not create an AdvNotify object\n";

print "\nTo exit from the loop press [CTRL-C] or [CTRL-BREAK]..\n\n";

while($obj->Wait(INFINITE))

{;}

print "\nThe signal is: ".$EventName{$obj->{Event}}."\n";

# don't forget to call the destructor

$obj->Free;


Example2:

use Win32::AdvNotify qw(INFINITE Yes No All %ActionName %ActionColor %EventName);

my $obj = new Win32::AdvNotify || die "Can not create an AdvNotify object\n";

# Now we will start two threads
# Note: You can start more threads if you want..

my $thread1 = $obj->StartThread(Directory => "c:\\Win32\\",

Filter => All , WatchSubtree => Yes ) || die "Can't start thread1..\n";

my $thread2 = $obj->StartThread(Directory => "c:\\Unix\\",

Filter => All , WatchSubtree => Yes ) || die "Can't start thread2..\n";

$thread1->EnableWatch() || die "Problem starting EnableWatch()\n";
$thread2->EnableWatch() || die "Problem starting EnableWatch()\n";

print "\n";

while($obj->Wait(INFINITE))
{
while($obj->Read(\@data))
{for($i=0;$i<=$#data;$i++)
{$obj->TextColor($ActionColor{$data[$i]->{Action}});
print $data[$i]->{Directory}.$data[$i]->{FileName}." ".
$ActionName{$data[$i]->{Action}}." on ".$data[$i]->{DateTime}."\n";}}}

print "\nThe signal is: ".$EventName{$obj->{Event}}."\n";

# don't forget to terminate your threads.

$thread1->Terminate(); # terminate thread1
$thread2->Terminate(); # terminate thread2

# don't forget to call the destructor

$obj->Free;

 


Index

$ret = $obj->Read(\@data)

Read() Reads all the data from the synchronized shared list, if there is no data to read, $ret will be undef and this will automaticaly exit the reader (thread) from the loop.

Note: If the data is successfuly read, the synchronized shared list is cleared..

If the function is successful then @data (an array of hash references) is populated with the following:

$data[$i]->{Directory}: Directory

$data[$i]->{FileName}: File name

$data[$i]->{Action}: Action/Event that occured

$data[$i]->{DateTime}: Date and Time when the Action/Event occured

Note: To get the text name of the action you have to import the %ActionName hash and use it like this: $ActionName{$data[$i]->{Action}}

The $ActionName{$data[$i]->{Action}} specifies wich of the following action occured:

FILE_ACTION_ADDED: The file was added to the directory.

FILE_ACTION_REMOVED: The file was removed from the directory.

FILE_ACTION_MODIFIED: The file was modified. This can be a change in the time stamp, size or attributes.

FILE_ACTION_RENAMED_OLD_NAME: The file was renamed and this is the old name.

FILE_ACTION_RENAMED_NEW_NAME: The file was renamed and this is the new name.


.Example:

#!perl -w

use Win32::AdvNotify qw(INFINITE Yes No All %ActionName %ActionColor %EventName);

my $obj = new Win32::AdvNotify || die "Can not create an AdvNotify object\n";

# Now we will start two threads
# Note: You can start more threads if you want..

my $thread1 = $obj->StartThread(Directory => "c:\\Win32\\",

Filter => All , WatchSubtree => Yes ) || die "Can't start thread1..\n";

my $thread2 = $obj->StartThread(Directory => "c:\\Unix\\",

Filter => All , WatchSubtree => Yes ) || die "Can't start thread2..\n";

$thread1->EnableWatch() || die "Problem starting EnableWatch()\n";
$thread2->EnableWatch() || die "Problem starting EnableWatch()\n";

print "\n";

while($obj->Wait(INFINITE))
{
while($obj->Read(\@data))
{for($i=0;$i<=$#data;$i++)
{$obj->TextColor($ActionColor{$data[$i]->{Action}});
print $data[$i]->{Directory}.$data[$i]->{FileName}." ".
$ActionName{$data[$i]->{Action}}." on ".$data[$i]->{DateTime}."\n";}}}

print "\nThe signal is: ".$EventName{$obj->{Event}}."\n";

# don't forget to terminate your threads.

$thread1->Terminate(); # terminate thread1
$thread2->Terminate(); # terminate thread2

# don't forget to call the destructor

$obj->Free;


Index

$ret = $obj->SendSignal(Signal,$ProcessId)

SendSignal() Sends a signal to a console process group that shares the console associated with the calling process.

Signal: Specifies the type of signal to send.

$ProcessId: A process identifier.

Note: Only SIG_TSTP is supported by SendSignal().

If SendSignal()fails, the returned value is undef.To get extended error information, call LastError().

Example1: (The parent process..)

#!perl -w

use Win32::AdvNotify qw (SIG_TSTP);

use Win32::IProcess

qw( INHERITED CREATE_NEW_CONSOLE CREATE_NEW_PROCESS_GROUP NULL);

my($Title)="Welcome to the world of Perl !!";

print "\n Please hit <Enter> to start the demo...: ";

<STDIN>;

my $iproc=new Win32::IProcess || die "Can't create an IProcess object\n";

my $obj = new Win32::AdvNotify || die "Can't create an AdvNotify object\n";

$iproc->Create(NULL,"perl child.pl",INHERITED,CREATE_NEW_PROCESS_GROUP,

".", $Title) || die $iproc->LastError();

print "\n[Parent process]: Hit <Enter> to send a SIG_TSTP to the child process: ";

<STDIN>;

$obj->SendSignal(SIG_TSTP,$iproc->{ProcessId});

select(undef,undef,undef,0.2);

#$obj->LastError;

print "\nPlease hit <Enter> to finish the demo: ";

<STDIN>;

# don't forget to call the destructor

$obj->Free;

Example2: (The child process that shares the parent process console)

#!perl -w

use Win32::AdvNotify qw(FILE_NAME SIZE INFINITE Yes No All

%ActionName %ActionColor %EventName);

my $obj = new Win32::AdvNotify || die "Can't create object\n";

my $thread1 = $obj->StartThread(Directory => "c:\\Win32\\",

Filter => All , WatchSubtree => Yes ) || die "Can't start thread1..\n";

my $thread2 = $obj->StartThread(Directory => "c:\\Unix\\",

Filter => All , WatchSubtree => Yes ) || die "Can't start thread2..\n";

$thread1->EnableWatch() || die "Problem starting EnableWatch()\n";

$thread2->EnableWatch() || die "Problem starting EnableWatch()\n";

while($obj->Wait(INFINITE))

{while($obj->Read(\@data))

{for($i=0;$i<=$#data;$i++)

{$obj->TextColor($ActionColor{$data[$i]->{Action}});

print $data[$i]->{Directory}.$data[$i]->{FileName}." ".

$ActionName{$data[$i]->{Action}}." on ".$data[$i]->{DateTime}."\n";}}}

print "\n[Child process]: The signal received is ".$EventName{$obj->{Event}}."\n";

# don't forget to terminate your threads.

$thread1->Terminate(); # terminate thread1

$thread2->Terminate(); # terminate thread2

# don't forget to call the destructor

$obj->Free;


Index

$ret = $thread->EnableWatch()

EnableWatch() Enable/Start monitoring .

Example:

See Read


Index

$ret = $thread->DisableWatch()

DisableWatch() Disable/Stop monitoring.

Example:

See Read


Index

$ret = $thread->Terminate()

Terminate() Terminates the calling (monitoring) thread..

Example:

See Read


Index

$ret = $obj->KeyPressed()

KeyPressed Returns 1 if a key has been pressed on the keyboard, undef otherwise.

Example:

use Win32::AdvNotify;

my $obj=new Win32::AdvNotify || die "Can't create an AdvNotify object\n";

do {print "Press a key to exit from this loop\n"; select(undef,undef,undef,0.2);} until($obj->KeyPressed);

$obj->Free;


Index

$ret = $obj->TextColor()

TextColor() Selects the forground character color.

Example:

See Read


$ret = $obj->ClrScr()

ClrScr() Clears the active window and places the cursor in the upper left-hand corner.