IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

Quelle arborescence de processus locke un fichier ou répertoire ?


Sujet :

Delphi

  1. #1
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 551
    Par défaut Quelle arborescence de processus locke un fichier ou répertoire ?
    Bonjour à tous

    J'ai regardé ICI dans la FAQ.

    Je n'arrive pas à le faire fonctionner, mais on peut faire autrement pour savoir si un fichier est locké.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    //Function IsFileLocked(const FileName: string): Boolean;
    Function IsFileLocked(FileName: string): Boolean;
    var
      FS: TFileStream;
     
    begin
      try
        // fmOpenReadWrite pour lecture/écriture, fmShareExclusive pour blocage total
        FS := TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive);
        FreeAndNil(FS);
        Result := False;
      except
        on E: EFOpenError do
          Result := True;  // le fichier est déjà ouvert/exclu
        else
          raise;  // autres erreurs (fichier inexistant, droits, etc.)
      end;
    end;
    Mais comment connaître l'arborescence de processus le bloquant ? Là, je sèche

    Merci pour toute aide

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 92
    Par défaut
    salut peut être en lisant ses propriétés
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    procedure ShowFileInfo(const FilePath: string);
    var
      Size      : Int64;
      Created   : TDateTime;
      Modified  : TDateTime;
      Accessed  : TDateTime;
      Attrs     : TFileAttributes;
    begin
      if not TFile.Exists(FilePath) then
        raise Exception.Create('Fichier introuvable : ' + FilePath);
     
      Size     := TFile.GetSize(FilePath);
      Created  := TFile.GetCreationTime(FilePath);
      Modified := TFile.GetLastWriteTime(FilePath);
      Accessed := TFile.GetLastAccessTime(FilePath);
      Attrs    := TFile.GetAttributes(FilePath);
     
      Writeln('Nom          : ', TPath.GetFileName(FilePath));
      Writeln('Chemin       : ', TPath.GetFullPath(FilePath));
      Writeln('Taille (B)   : ', Size);
      Writeln('Créé le      : ', DateTimeToStr(Created));
      Writeln('Modifié le   : ', DateTimeToStr(Modified));
      Writeln('Accédé le    : ', DateTimeToStr(Accessed));
      Writeln('Attributs    : ', Integer(Attrs).ToString);
    end;

  3. #3
    Membre expérimenté
    Avatar de XeGregory
    Homme Profil pro
    Passionné par la programmation
    Inscrit en
    Janvier 2017
    Messages
    732
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Passionné par la programmation
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2017
    Messages : 732
    Billets dans le blog
    1
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function IsFileLocked(const FileName: string): Boolean;
    var
      FS: TFileStream;
    begin
    Result := False;
      try
        FS := TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive);
        FS.Free;    
      except
        on E: Exception do
          Result := True;  // attrape TOUTES les erreurs de verrouillage
      end;
    end;
    On ne peut pas faire confiance à un code qu'on n'a pas entièrement écrit soi‑même, et encore moins à celui qu'on a écrit entièrement. :aie:

  4. #4
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 551
    Par défaut
    Salut :hello:

    Merci pour vos réponses. Je vais tester ça et donne le retour.

  5. #5
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 551
    Par défaut
    Je dois mal utiliser la fonction. Le fichier désigné est bel et bien ouvert sous ultraEdit.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
     
    function IsFileLocked(const FileName: string): Boolean;
    var
      FS: TFileStream;
     
    begin
     
      Result := False;
        try
          FS := TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive);
          FS.Free;
        except
          on E: Exception do
            Result := True;  // attrape TOUTES les erreurs de verrouillage
            			// NE CAPTE AUCUNE ERREUR DE VERROUILLAGE : fichier ouvert ds UltraEdit, ou fermé
        end;
     
    end;

    Et, de toute façon, ça ne me retourne pas l'arborescence de processus qui locke le truc.

    Et pour un répertoire ? Je peux tenter de le créer (sans ForceDirectories). Mais comment savoir quel est le processus qui l'utilise ?

    C'est ça que je vise. J'aurais peut-être dû le dire plus tôt :/
    Dans une boîte, je trouve très souvent des répertoires de WPS (s*** ce truc !) mais il m'arrive ne ne pas pouvoir les supprimer, même avec Windows Commander.

    Qu'est-ce qui se passe ? Où est-ce que je me gourre ?

    Merci

  6. #6
    Membre expérimenté
    Avatar de XeGregory
    Homme Profil pro
    Passionné par la programmation
    Inscrit en
    Janvier 2017
    Messages
    732
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Passionné par la programmation
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2017
    Messages : 732
    Billets dans le blog
    1
    Par défaut
    Le fichier désigné est bel et bien ouvert sous ultraEdit
    Donc UltraEdit charge les fichiers en mémoire, et c’est précisément pour cela qu’aucune exception n’est levée.
    Mais attention : ouvrir en mémoire ne signifie pas sans handle. UltraEdit garde bien un handle ouvert sur le fichier, mais il ne le verrouille pas en mode exclusif, 90 % des logiciels n’utilisent pas de verrous exclusifs.

    Il n’existe aucune fonction Delphi, ni WinAPI directe, qui te dit : Voici la liste des processus qui ont un handle sur ce fichier/dossier.

    Quel est l’objectif de ton projet ?

    Maintenant, si tu veux supprimer un répertoire ou un fichier déjà utilisé par un autre processus, la méthode consiste à fermer d’abord le processus qui le verrouille, puis à supprimer le fichier ou le dossier.

    Encore faut-il réussir à trouver quel fichu processus refuse de lâcher le morceau.

    Et si on regarde bien, les logiciels de nettoyage ne suppriment aucun fichier lorsqu’un navigateur est encore ouvert. Ils demandent d’abord à l’utilisateur de fermer le navigateur, ou bien ils proposent de le fermer automatiquement afin de pouvoir poursuivre la suppression des fichiers potentiellement utilisés par un processus du navigateur.

    Donc, première étape : fermer le processus qui utilise le fichier ou le répertoire.
    Deuxième étape : procéder à la suppression.
    Mais il faut faire attention, car plusieurs processus, applications ou services Windows peuvent utiliser le même fichier ou le même dossier en même temps.

    Fermer un processus par son nom
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    uses
      TlHelp32, Windows, SysUtils;
     
    function KillProcessByName(const AProcessName: string): Boolean;
    var
      Snapshot: THandle;
      ProcEntry: TProcessEntry32;
      hProcess: THandle;
    begin
      Result := False;
     
      Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
      if Snapshot = INVALID_HANDLE_VALUE then Exit;
     
      ProcEntry.dwSize := SizeOf(TProcessEntry32);
     
      if Process32First(Snapshot, ProcEntry) then
      begin
        repeat
          if SameText(ProcEntry.szExeFile, AProcessName) then
          begin
            hProcess := OpenProcess(PROCESS_TERMINATE, False, ProcEntry.th32ProcessID);
            if hProcess <> 0 then
            begin
              Result := TerminateProcess(hProcess, 0);
              CloseHandle(hProcess);
            end;
          end;
        until not Process32Next(Snapshot, ProcEntry);
      end;
     
      CloseHandle(Snapshot);
    end;
    On ne peut pas faire confiance à un code qu'on n'a pas entièrement écrit soi‑même, et encore moins à celui qu'on a écrit entièrement. :aie:

  7. #7
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 551
    Par défaut
    L'objectif était de savoir justement ce que l'on ne peut pas savoir : quel processus empêche de supprimer certains répertoires.
    Ainsi que tu me l'apprends, c'est impossible.

    Merci aussi pour l'info : UltraEdit ne verrouille pas en mode exclusif.

    Les navigateurs : Chrome et Edge lancent des processus : installer, élévation service, etc. Je vais chercher de ce côté. Avec le gestionnaire de tâches en mode admin, je flingue ces processus, et je verrai bien.

    Bon. C'est résolu, grâce à vous.

    Merci à tous

  8. #8
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    6 013
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 6 013
    Par défaut
    Il est possible de savoir quel processus verrouille un fichier en passant par le Restart Manager.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    unit LockingProcesses;
     
    interface
     
    uses Winapi.Windows, System.SysUtils;
     
    const
      CCH_RM_MAX_APP_NAME = 255;
      CCH_RM_MAX_SVC_NAME = 63;
      CCH_RM_SESSION_KEY  = 32;
     
    type
      TRMAppType = (RmUnknownApp, RmMainWindow, RmOtherWindow, RmService, RmExplorer, RmConsole, RmCritical = 1000);
     
      TRMUniqueProcess = record
        ProcessId: dword;
        ProcessStartTime: TFileTime;
      end;
     
      TRMProcessInfo = record
        Process: TRMUniqueProcess;
        AppName: array[0..CCH_RM_MAX_APP_NAME] of char;
        ServiceShortName: array[0..CCH_RM_MAX_SVC_NAME] of char;
        ApplicationType: TRMAppType;
        AppStatus: ULONG;
        TSSessionId: dword;
        bRestartable: BOOL;
      end;
      PRMProcessInfo = ^TRMProcessInfo;
     
    function GetLockingProcesses(const aFileNames: array of string): TArray<TRMProcessInfo>; overload;
    function GetLockingProcesses(const aFileName: string): TArray<TRMProcessInfo>; overload;
     
    implementation
     
    function RmStartSession(out pSessionHandle: dword; dwSessionFlags: dword; strSessionKey: PChar): dword; stdcall; external 'Rstrtmgr.dll';
    function RmEndSession(dwSessionHandle: dword): dword; stdcall; external 'Rstrtmgr.dll';
    function RmRegisterResources(dwSessionHandle: dword; nFiles: UINT; rgsFilenames: PPWideChar; nApplications: UINT;
               rgApplications: Pointer; nServices: UINT; rgsServiceNames: PPWideChar): dword; stdcall; external 'Rstrtmgr.dll';
    function RmGetList(dwSessionHandle: dword; var nProcInfoNeeded: UINT; var nProcInfo: UINT; rgAffectedApps: PRMProcessInfo;
               var lpdwRebootReasons: dword): dword; stdcall; external 'Rstrtmgr.dll';
     
    function GetLockingProcesses(const aFileNames: array of string): TArray<TRMProcessInfo>;
    begin
      var SessionHandle: THandle;
      var SessionKey: array[0..CCH_RM_SESSION_KEY] of Char;
     
      if RmStartSession(SessionHandle, 0, SessionKey) <> ERROR_SUCCESS then
        RaiseLastOSError;
     
      try
        var PFileNames :array of PChar;
        SetLength(PFileNames, Length(aFileNames));
     
        for var i := 0 to High(aFileNames) do
          PFileNames[i] := PChar(aFileNames[i]);
     
        if RmRegisterResources(SessionHandle, Length(PFileNames), @PFileNames[0], 0, nil, 0, nil) <> ERROR_SUCCESS then
          RaiseLastOSError;
     
        var Needed: cardinal;
        var Count: cardinal := 0;
        var RebootReasons: cardinal := 0;
     
        case RmGetList(SessionHandle, Needed, Count, nil, RebootReasons) of
          ERROR_SUCCESS   : Exit(nil); // Needed = 0 => Pas de verrouillage
          ERROR_MORE_DATA : begin
                              Count := Needed;
                              SetLength(Result, Count);
                              if RmGetList(SessionHandle, Needed, Count, @Result[0], RebootReasons) <> ERROR_SUCCESS then
                                RaiseLastOSError;
                            end;
          else RaiseLastOSError;
        end;
     
      finally
        RmEndSession(SessionHandle);
      end;
    end;
     
    function GetLockingProcesses(const aFileName: string): TArray<TRMProcessInfo>;
    begin
      Result := GetLockingProcesses([aFileName]);
    end;
     
    end.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    begin
      try
        const Processes = GetLockingProcesses('C:\blabla\monfichier.txt');
     
        if Length(Processes) = 0 then
          WriteLn('Le fichier n''est pas verrouillé')
        else
          for var Process in Processes do
            WriteLn(Process.AppName);
     
      except
        on E: Exception do
          Writeln(E.Message);
      end;
     
      ReadLn;
    end.
    EDIT

    Version modifiée pour pouvoir tester tous les fichiers d'un répertoire en une passe par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const Processes = GetLockingProcesses(TDirectory.GetFiles('C:\blabla'));

  9. #9
    Membre expérimenté
    Avatar de XeGregory
    Homme Profil pro
    Passionné par la programmation
    Inscrit en
    Janvier 2017
    Messages
    732
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Passionné par la programmation
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2017
    Messages : 732
    Billets dans le blog
    1
    Par défaut
    Intéressante cette unité de LockingProcesses. Merci Andnotor.
    On ne peut pas faire confiance à un code qu'on n'a pas entièrement écrit soi‑même, et encore moins à celui qu'on a écrit entièrement. :aie:

  10. #10
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 551
    Par défaut
    Merci pour vos réponses !!

    Désolé pour le retard à l'allumage, mais j'étais très pris.

    Je teste ça ce week-end, et vous donne le retour

  11. #11
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 551
    Par défaut
    Salut


    Je dois mal piger le code.
    Blocage à la compilation : [dcc32 Erreur] LockingProcesses.pas(68): E2033 Les types des paramètres VAR originaux et formels doivent être identiques

    Le types ne sont pas les mêmes ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
     
    unit LockingProcesses;
     
    interface
     
    uses Winapi.Windows, System.SysUtils, Messages, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, StdCtrls, TaskDialog;
     
     
    const
      CCH_RM_MAX_APP_NAME = 255;
      CCH_RM_MAX_SVC_NAME = 63;
      CCH_RM_SESSION_KEY  = 32;
     
    type
      TRMAppType = (RmUnknownApp, RmMainWindow, RmOtherWindow, RmService, RmExplorer, RmConsole, RmCritical = 1000);
     
      TRMUniqueProcess = record
        ProcessId: dword;
        ProcessStartTime: TFileTime;
      end;
     
      TRMProcessInfo = record
        Process: TRMUniqueProcess;
        AppName: array[0..CCH_RM_MAX_APP_NAME] of char;
        ServiceShortName: array[0..CCH_RM_MAX_SVC_NAME] of char;
        ApplicationType: TRMAppType;
        AppStatus: ULONG;
        TSSessionId: dword;
        bRestartable: BOOL;
      end;
      PRMProcessInfo = ^TRMProcessInfo;
     
    function GetLockingProcesses(const aFileNames: array of string): TArray<TRMProcessInfo>; overload;
    function GetLockingProcesses(const aFileName: string): TArray<TRMProcessInfo>; overload;
     
     
     
    implementation
     
     
    USES  Unit1;
     
     
    function RmStartSession(out pSessionHandle: dword; dwSessionFlags: dword; strSessionKey: PChar): dword; stdcall; external 'Rstrtmgr.dll';
    function RmEndSession(dwSessionHandle: dword): dword; stdcall; external 'Rstrtmgr.dll';
    function RmRegisterResources(dwSessionHandle: dword; nFiles: UINT; rgsFilenames: PPWideChar; nApplications: UINT;
               rgApplications: Pointer; nServices: UINT; rgsServiceNames: PPWideChar): dword; stdcall; external 'Rstrtmgr.dll';
    function RmGetList(dwSessionHandle: dword; var nProcInfoNeeded: UINT; var nProcInfo: UINT; rgAffectedApps: PRMProcessInfo;
               var lpdwRebootReasons: dword): dword; stdcall; external 'Rstrtmgr.dll';
     
     
    function GetLockingProcesses(const aFileNames: array of string): TArray<TRMProcessInfo>;
    Var
      SessionHandle : THandle;
      SessionKey : array[0..CCH_RM_SESSION_KEY] of Char;
      PFileNames :array of PChar;
      i : integer;
      Needed : cardinal;
      Count : cardinal;
      RebootReasons : cardinal;
     
    begin
     
      Count := 0;
      RebootReasons := 0;
     
    {
    	Blocage à la compilation :
    	Msg d'erreur : [dcc32 Erreur] LockingProcesses.pas(68): E2033 Les types des paramètres VAR originaux et formels doivent être identiques
    	Delphi XE7 : ça viendrait de là ? 
    }	
     
      if RmStartSession(SessionHandle, 0, SessionKey) <> ERROR_SUCCESS then RaiseLastOSError;
     
      try
        SetLength(PFileNames, Length(aFileNames));
     
        for i := 0 to High(aFileNames) do PFileNames[i] := PChar(aFileNames[i]);
     
        if RmRegisterResources(SessionHandle, Length(PFileNames), @PFileNames[0], 0, nil, 0, nil) <> ERROR_SUCCESS then
          RaiseLastOSError;
     
     
        case RmGetList(SessionHandle, Needed, Count, nil, RebootReasons) of
          ERROR_SUCCESS   : Exit(nil); // Needed = 0 => Pas de verrouillage
          ERROR_MORE_DATA : begin
                              Count := Needed;
                              SetLength(Result, Count);
                              if RmGetList(SessionHandle, Needed, Count, @Result[0], RebootReasons) <> ERROR_SUCCESS then
                                RaiseLastOSError;
                            end;
          else RaiseLastOSError;
        end;
     
      finally
        RmEndSession(SessionHandle);
      end;
    end;
     
     
    function GetLockingProcesses(const aFileName: string): TArray<TRMProcessInfo>;
    begin
      Result := GetLockingProcesses([aFileName]);
    end;
     
    End.

  12. #12
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    6 013
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 6 013
    Par défaut
    Déclare SessionHandle en dword.

  13. #13
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 551
    Par défaut
    OK. Ca compile.
    Je vais tester et donne le retour.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo