[Func] Tester si un fichier est en cours d'utilisation.

Partagez des fonctions et des UDF AutoIt.
Règles du forum
.
Répondre
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11773
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

[Func] Tester si un fichier est en cours d'utilisation.

#1

Message par Tlem »

Voici trois fonctions trouvées sur le forum Anglais.
Ces fonctions permettent de vérifier si un fichier est déjà ouvert/utilisé par une autre application.
La dernière version permet même de retourner les fichiers utilisés par un processus.

Première version par Siao (http://www.autoitscript.com/forum/topic ... _p__410020) :

Code : Tout sélectionner

;===============================================================================
;
; Function Name:    _FileInUse()
; Description:      Checks if file is in use
; Parameter(s):     $sFilename = File name
; Return Value(s):  1 - file in use (@error contains system error code)
;                   0 - file not in use
;
;===============================================================================
Func _FileInUse($sFilename)
    Local $aRet, $hFile
    $aRet = DllCall("Kernel32.dll", "hwnd", "CreateFile", _
                                    "str", $sFilename, _ ;lpFileName
                                    "dword", 0x80000000, _ ;dwDesiredAccess = GENERIC_READ
                                    "dword", 0, _ ;dwShareMode = DO NOT SHARE
                                    "dword", 0, _ ;lpSecurityAttributes = NULL
                                    "dword", 3, _ ;dwCreationDisposition = OPEN_EXISTING
                                    "dword", 128, _ ;dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL
                                    "hwnd", 0) ;hTemplateFile = NULL
    $hFile = $aRet[0]
    If $hFile = -1 Then ;INVALID_HANDLE_VALUE = -1
        $aRet = DllCall("Kernel32.dll", "int", "GetLastError")
        SetError($aRet[0])
        Return 1
    Else
        ;close file handle
        DllCall("Kernel32.dll", "int", "CloseHandle", "hwnd", $hFile)
        Return 0
    EndIf
EndFunc
Deuxième version par Yashied (http://www.autoitscript.com/forum/topic ... _p__853798) :

Code : Tout sélectionner

#Include <WinAPI.au3>

Func _FileIsUses($sFile)

    Local $hFile = _WinAPI_CreateFile($sFile, 2, 2, 0)

    If $hFile Then
        _WinAPI_CloseHandle($hFile)
        Return 0
    EndIf

    Local $Error = _WinAPI_GetLastError()

    Switch $Error
        Case 32 ; ERROR_SHARING_VIOLATION
            Return 1
        Case Else
            Return SetError($Error, 0, 0)
    EndSwitch
EndFunc   ;==>_FileIsUses
Troisième version par ripdad (WMI)(http://www.autoitscript.com/forum/topic ... _p__855503) :

Code : Tout sélectionner

;##############################################################################################
; FileInUseInfo - Modify it for your needs
;
; example $mode = 1; FileInUseInfo("AutoIt3.exe", 1) ;returns file(s) used by process
;
; example $mode = 2; FileInUseInfo("SomeFile.txt", 2) ;returns process(s) using file
;##############################################################################################
Func FileInUseInfo($sInput, $mode = 1, $strComputer = "localhost")
    Local $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
    If @error Then Return SetError(-1)
    Local $output = '', $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", 0x10 + 0x20)
    If Not IsObj($colItems) Then Return SetError(-2)
    For $objItem In $colItems
        If $objItem.CommandLine = '' Or StringLeft($objItem.CommandLine, 1) = '\' Then ContinueLoop
        If $mode = 1 And $objItem.Name = $sInput Then
        ElseIf $mode = 2 And StringInStr($objItem.CommandLine, $sInput) Then
        Else
            ContinueLoop
        EndIf
        $output &= "PID: " & $objItem.ProcessId & @CRLF
        $output &= "CommandLine: " & $objItem.CommandLine & @CRLF & @CRLF
    Next
    Return $output
EndFunc
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
eric
Niveau 5
Niveau 5
Messages : 177
Enregistré le : sam. 21 mars 2009 17:57
Localisation : Bretagne
Status : Hors ligne

Re: [Func] Tester si un fichier est en cours d'utilisation.

#2

Message par eric »

Bonjour Tlem,

Merci pour l'info, cela faisait quelques temps que je cherchais ce genre de fonction.

Pour ma part j'ai simplement testé le premier et cela semble fonctionner correctement.

Merci encore
eric
Niveau 5
Niveau 5
Messages : 177
Enregistré le : sam. 21 mars 2009 17:57
Localisation : Bretagne
Status : Hors ligne

Re: [Func] Tester si un fichier est en cours d'utilisation.

#3

Message par eric »

Par contre lorsque l'on fait une vérification en boucle il arrive que, si le fichier n'est pas ouvert et qu'on l'ouvre avec le logiciel correspondant, un message indique que : le fichier est déjà ouvert - voulez l'ouvrir en lecture seule...

Je pensais que ces fonctions vérifiaient si le fichier était ouvert ou non sans l'ouvrir, mais apparemment ce n'est pas le cas.

Dans ce cas on peut aussi utiliser ce code pour déterminer si le fichier est ouvert ou non :

Code : Tout sélectionner

  $file = "C:\test.docx"

    $rtn = FileOpen($file,1)

    FileClose ($rtn)

if $rtn = -1 then

msgbox ("4096", "fichier ouvert", "le fichier est ouvert")

Else

    msgbox ("4096", "fichier fermé", "le fichier est fermé")
EndIf
Mais le problème est le même si on l'utilise dans un boucle on peut tomber sur le message de lecture seule lorsque l'on essaie de l'ouvrir avec le logiciel.

C'est un peu difficile en plus parce que on peut ouvrir 5 fois ou plus le fichier sans avoir ce message et d'un coup ne pas pouvoir l'ouvrir parce qu’il est déjà ouvert par le script.
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11773
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [Func] Tester si un fichier est en cours d'utilisation.

#4

Message par Tlem »

Les codes proposés précédemment fonctionnent très bien, mais si votre boucle de test est trop rapide, alors il est normal de ce retrouver avec ce problème.
La logique voudrait que ce test soit fait uniquement avant de lancer une ouverture ...

C'est comme lorsque vous testez si le fond de la casserole est chaude avec votre doigt. Si vous le faites trop rapidement, vous vous brulez car votre doigt n'a pas le temps de refroidir ...
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
eric
Niveau 5
Niveau 5
Messages : 177
Enregistré le : sam. 21 mars 2009 17:57
Localisation : Bretagne
Status : Hors ligne

Re: [Func] Tester si un fichier est en cours d'utilisation.

#5

Message par eric »

Effectivement j'avais mal compris le fonctionnement de ces codes.

Je cherchais plutôt une fonction qui contrôle en permanence si un fichier est ouvert ou non. (Donc en boucle rapide).

C’est pourquoi je voulais que cela détecte si le fichier est ouvert sans tenter de l'ouvrir pour ne pas bloquer l'ouverture du fichier par le logiciel.

Pensez-vous que cela est possible ou non ?

Merci
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11773
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [Func] Tester si un fichier est en cours d'utilisation.

#6

Message par Tlem »

Pour les questions d'ordre technique, le mieux est de passer par le forum général.
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
Répondre