Jump to content

Detect file access


Recommended Posts

Editing a script to detect when a file inside a path, was accessed, using _WinAPI_ReadDirectoryChanges and $FILE_NOTIFY_CHANGE_LAST_ACCESS

https://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_ReadDirectoryChanges.htm

The script:

#RequireAdmin
#include <APIFilesConstants.au3>
#include <Array.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIDiag.au3>
#include <WinAPIFiles.au3>
#include <WinAPISys.au3>


Global $g_sPath = "C:\Users\Henrique\Downloads"


Local $hDirectory = _WinAPI_CreateFileEx($g_sPath, $OPEN_EXISTING, $FILE_LIST_DIRECTORY, BitOR($FILE_SHARE_READ, $FILE_SHARE_WRITE), $FILE_FLAG_BACKUP_SEMANTICS)

If @error Then
    _WinAPI_ShowLastError('', 1)
EndIf

Local $pBuffer = _WinAPI_CreateBuffer(8388608)

Local $aData
While 1

    $aData = _WinAPI_ReadDirectoryChanges($hDirectory, BitOR($FILE_NOTIFY_CHANGE_LAST_WRITE, $FILE_NOTIFY_CHANGE_SIZE,$FILE_NOTIFY_CHANGE_LAST_ACCESS), $pBuffer, 8388608, 0)
    If Not @error Then
        ConsoleWrite("Writting" & @CRLF)
        MsgBox(0,"",$FILE_NOTIFY_CHANGE_LAST_WRITE)
        MsgBox(0,"",$FILE_NOTIFY_CHANGE_LAST_ACCESS)

    Else
        _WinAPI_ShowLastError('', 1)
    EndIf
    Sleep(200)
WEnd

I can see in the archive properties my recent access is updating correctly (access done with the script running).

image.png.7805267c8eb34c14b3e9f1b0a03e120d.png

MsgBox(0,"",$FILE_NOTIFY_CHANGE_LAST_WRITE)]

MsgBox(0,"",$FILE_NOTIFY_CHANGE_LAST_ACCESS)

The first box value displayed is 16, and second box pop up 32

Quote

; MSDN:
;     ReadDirectoryChangesW          msdn.microsoft.com/en-us/library/aa365465(v=vs.85).aspx
;     FILE_NOTIFY_CHANGE_FILE_NAME   = 1   (0x00000001) : Notify about renaming, creating, or deleting a file.
;     FILE_NOTIFY_CHANGE_DIR_NAME    = 2   (0x00000002) : Notify about creating or deleting a directory.
;     FILE_NOTIFY_CHANGE_ATTRIBUTES  = 4   (0x00000004) : Notify about attribute changes.
;     FILE_NOTIFY_CHANGE_SIZE        = 8   (0x00000008) : Notify about any file-size change.
;     FILE_NOTIFY_CHANGE_LAST_WRITE  = 16  (0x00000010) : Notify about any change to the last write-time of files.
;     FILE_NOTIFY_CHANGE_LAST_ACCESS = 32  (0x00000020) : Notify about any change to the last access time of files.
;     FILE_NOTIFY_CHANGE_CREATION    = 64  (0x00000040) : Notify about any change to the creation time of files.
;     FILE_NOTIFY_CHANGE_SECURITY    = 256 (0x00000100) : Notify about any security-descriptor change.
;     FILE_NOTIFY_INFORMATION        msdn.microsoft.com/en-us/library/aa364391(v=vs.85).aspx
;     FILE_ACTION_ADDED              = 1   (0x00000001) : The file was added to the directory.
;     FILE_ACTION_REMOVED            = 2   (0x00000002) : The file was removed from the directory.
;     FILE_ACTION_MODIFIED           = 3   (0x00000003) : The file was modified.
;     FILE_ACTION_RENAMED            = 4   (0x00000004) : The file was renamed (not defined by Microsoft).
;     FILE_ACTION_RENAMED_OLD_NAME   = 4   (0x00000004) : The file was renamed and this is the old name.
;     FILE_ACTION_RENAMED_NEW_NAME   = 5   (0x00000005) : The file was renamed and this is the new name.
;     GetOverlappedResult            msdn.microsoft.com/en-us/library/ms683209(v=vs.85).aspx
;     CreateFile                     msdn.microsoft.com/en-us/library/aa363858(v=vs.85).aspx
;     FILE_FLAG_BACKUP_SEMANTICS     = 0x02000000
;     FILE_FLAG_OVERLAPPED           = 0x40000000

The script only trigger the boxes when i open any file and edit something like a text. If i only open/close any file it don't detect the access.

Ideas about what's going wrong?

 

Edited by memerim
Link to comment
Share on other sites

As you can see, your last access date equals the creation date.  By default (at least for Win7), the last access notification is disable.  To enable it you need to go to the registry and modify the key :

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem

change NtfsDisableLastAcessUpdate from 1 to 0

Should work after (untested).  Don't forget, you will need to reboot !

Link to comment
Share on other sites

memerim,

what is the final purpose for you to use ReadDirectoryChanges specifically

7 hours ago, memerim said:

If i only open/close any file it don't detect the access.

if you are using  fileopen()  you can test if its accessed with _WinAPI_FileInUse () from another script ..

if you can detail all it needs to do then maybe there are better ways ..

Deye

Link to comment
Share on other sites

1 hour ago, Nine said:

As you can see, your last access date equals the creation date.  By default (at least for Win7), the last access notification is disable.  To enable it you need to go to the registry and modify the key :

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem

change NtfsDisableLastAcessUpdate from 1 to 0

Should work after (untested).  Don't forget, you will need to reboot !

I already had did this key edit. :mellow:

1 hour ago, Deye said:

memerim,

what is the final purpose for you to use ReadDirectoryChanges specifically

if you are using  fileopen()  you can test if its accessed with _WinAPI_FileInUse () from another script ..

if you can detail all it needs to do then maybe there are better ways ..

Deye

Its for my script to detect when wav files are executed, the progam run some wav files in memory, so the only way to i detect it is reading when file was acessed.

Link to comment
Share on other sites

46 minutes ago, memerim said:

Its for my script to detect when wav files are executed, the progam run some wav files in memory, so the only way to i detect it is reading when file was acessed.

The problem is not AutoIt.  It is Windows.  If Windows doesn't update last access date, it is kind of hard to detect it. 

Link to comment
Share on other sites

memerim,

I meant,  in The actual plan process,  for example:

do you need to detect a new instance of a wav file in the downloads folder and run it pended to a previous one playing, waiting for it to end and delete the downloaded file after its been executed  or .etc detail

Thanks

Deye

 

 

 

Link to comment
Share on other sites

Thanks for the help, i will try describe the max what im trying do @Deye

I have multiple instances of an executable 1,2,3,4,5,6.exe etc, in determined actions it plays different wav sounds, the wav is loaded in the process, i could see it using procmon:

Spoiler

Triggers on procmon when process play a sound:

image.thumb.png.c7ac8395e4460e92885821fab795e9ed.png

image.thumb.png.449936b6afe04793efe06f07a403a1b6.png

@Nine

As could be seen in the images the system is updating the last access time correctly, the script should be able to detect it?

The maximum i can do is change the .wav name and path, so i did folders for each process:

Spoiler

image.png.d0b7138acc75004547d2a015036e8702.pngimage.thumb.png.30f29b9f6f92ccc4828bbf9caec4a5ba.png

Trying build a script to detect when a wav is playing, wait it finish, then start next,  like a queu.

Actually it plays like 10 wav sounds together, i cant understand nothing.

If i could detect when a wav is playing from a process, i could write the rest of the script, i could store all process who plaid the file in a .ini, mute the process if one already playing, or i could create empty wav files, and then play originals, following the queu saved in .ini file, there are many ways to do it.

I'm struggled in how to detect when one of those .wav is playing, from determined process.

 

 

Edited by memerim
Link to comment
Share on other sites

do you have any control on those 1,2,3,4,5.exe ?  Are those autoit (i suppose not )?  Do they provide any log ? Can they update sqlite or other database ? What are all the options from their part ? What about procmon ? Can it give a log of all the actions ?

Edited by Nine
Link to comment
Share on other sites

2 hours ago, memerim said:

Actually it plays like 10 wav sounds together, i cant understand nothing.

lets try a little longShoot test that doesn't deal with any other special case scenarios 

 what won't work\look right to you when running it as is, Combined with your script 

the first is for running the test | the second need to be compiled priorly

For $i = 1 to 4
    run(@ScriptDir & "\_SoundPlay.exe")
Next
#AutoIt3Wrapper_Outfile=_SoundPlay.exe

#include <Sound.au3>
#include <Misc.au3>

If Not @Compiled Then Exit MsgBox(262144, '', "remember to compile it first")

Global $Singleton = 9999
_QueuSingleton()

SoundPlay(@WindowsDir & "\media\Windows Notify System Generic.wav", 1)
SoundPlay("")

Func _QueuSingleton()
    If _Singleton($Singleton, 1) = 0 Then
        Do
            $Singleton -= 1
        Until _Singleton($Singleton, 1)
        $Singleton += 1
        While 1
            Sleep(500)
            If _Singleton($Singleton, 1) Then ExitLoop
        WEnd
    EndIf
EndFunc   ;==>_QueuSingleton

 

Edited by Deye
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...