Fermer des fichiers ouverts en utilisant C #

Dans certaines situations, des personnes sont connectées à des fichiers sur un partage, ce qui m’empêche d’écraser le fichier. J’essaie d’écrire une méthode qui vérifiera si un chemin de chemin que je fournis est actuellement verrouillé de cette façon et fermera la session réseau de cette ressource.

J’ai consulté le fournisseur ADSI Winnt, mais le membre Resources.Remove n’est pas implémenté. Ensuite, j’ai regardé Win32_ServerSession et, bien que je puisse utiliser Delete member, il tue toutes les ressources pour un utilisateur donné. J’ai besoin de savoir comment être plus précis.

Je me suis promené dans GetRelationsShips and Properties mais je suis juste perplexe pour le moment.

Il serait difficile d’envisager toutes les ramifications de cette opération car vous ne pouvez pas nécessairement prédire le comportement résultant de l’application pour laquelle le fichier est actuellement verrouillé.

Y a-t-il un autre moyen de faire cela? Par exemple, devez-vous écraser le fichier immédiatement ou pouvez-vous avoir un processus externe qui tente continuellement d’écraser le fichier toutes les quelques minutes jusqu’à ce qu’il réussisse?

J’ai rencontré le même problème. Jusqu’à présent, je sais que le seul moyen de le faire est d’utiliser Win32API:

 [DllImport ("Netapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
 public static extern int NetFileClose (chaîne nom_serveur, id_nt);

J’ai brièvement essayé de comprendre cela et je peux simplement énumérer les fichiers correctement, mais dans mon code – je viens de regarder – le code pour fermer un fichier est défini pour être un commentaire. Si vous voulez essayer ceci, je peux vous envoyer une bibliothèque [wrapper autour de NetFileXXX] et une courte démo, mais, comme je l’ai dit: je n’ai jamais fermé de fichier. Mais c’est peut-être un moyen court pour cela.

Je ne sais pas, comment échanger un fichier sur stackoverflow maintenant :-(?!?

br – mabra

Vous pouvez utiliser le code auquel vous fournissez le chemin d’access complet au fichier et il retournera une List de tout ce qui verrouille ce fichier:

 using System.Runtime.InteropServices; using System.Diagnostics; static public class FileUtil { [StructLayout(LayoutKind.Sequential)] struct RM_UNIQUE_PROCESS { public int dwProcessId; public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime; } const int RmRebootReasonNone = 0; const int CCH_RM_MAX_APP_NAME = 255; const int CCH_RM_MAX_SVC_NAME = 63; enum RM_APP_TYPE { RmUnknownApp = 0, RmMainWindow = 1, RmOtherWindow = 2, RmService = 3, RmExplorer = 4, RmConsole = 5, RmCritical = 1000 } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct RM_PROCESS_INFO { public RM_UNIQUE_PROCESS Process; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)] public ssortingng strAppName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)] public ssortingng strServiceShortName; public RM_APP_TYPE ApplicationType; public uint AppStatus; public uint TSSessionId; [MarshalAs(UnmanagedType.Bool)] public bool bRestartable; } [DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)] static extern int RmRegisterResources(uint pSessionHandle, UInt32 nFiles, ssortingng[] rgsFilenames, UInt32 nApplications, [In] RM_UNIQUE_PROCESS[] rgApplications, UInt32 nServices, ssortingng[] rgsServiceNames); [DllImport("rstrtmgr.dll", CharSet = CharSet.Auto)] static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, ssortingng strSessionKey); [DllImport("rstrtmgr.dll")] static extern int RmEndSession(uint pSessionHandle); [DllImport("rstrtmgr.dll")] static extern int RmGetList(uint dwSessionHandle, out uint pnProcInfoNeeded, ref uint pnProcInfo, [In, Out] RM_PROCESS_INFO[] rgAffectedApps, ref uint lpdwRebootReasons); ///  /// Find out what process(es) have a lock on the specified file. ///  /// Path of the file. /// Processes locking the file /// See also: /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa373661(v=vs.85).aspx /// http://wyupdate.googlecode.com/svn-history/r401/trunk/frmFilesInUse.cs (no copyright in code at time of viewing) /// ///  static public List WhoIsLocking(ssortingng path) { uint handle; ssortingng key = Guid.NewGuid().ToSsortingng(); List processes = new List(); int res = RmStartSession(out handle, 0, key); if (res != 0) throw new Exception("Could not begin restart session. Unable to determine file locker."); try { const int ERROR_MORE_DATA = 234; uint pnProcInfoNeeded = 0, pnProcInfo = 0, lpdwRebootReasons = RmRebootReasonNone; ssortingng[] resources = new ssortingng[] { path }; // Just checking on one resource. res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null); if (res != 0) throw new Exception("Could not register resource."); //Note: there's a race condition here -- the first call to RmGetList() returns // the total number of process. However, when we call RmGetList() again to get // the actual processes this number may have increased. res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons); if (res == ERROR_MORE_DATA) { // Create an array to store the process results RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded]; pnProcInfo = pnProcInfoNeeded; // Get the list res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons); if (res == 0) { processes = new List((int)pnProcInfo); // Enumerate all of the results and add them to the // list to be returned for (int i = 0; i < pnProcInfo; i++) { try { processes.Add(Process.GetProcessById(processInfo[i].Process.dwProcessId)); } // catch the error -- in case the process is no longer running catch (ArgumentException) { } } } else throw new Exception("Could not list processes locking resource."); } else if (res != 0) throw new Exception("Could not list processes locking resource. Failed to get size of result."); } finally { RmEndSession(handle); } return processes; } } 

Ensuite, parcourez la liste des processus et fermez-les:

  ssortingng[] files = Directory.GetFiles(target_dir); List lstProcs = new List(); foreach (ssortingng file in files) { lstProcs = ProcessHandler.WhoIsLocking(file); if (lstProcs.Count > 0) // deal with the file lock { foreach (Process p in lstProcs) { if (p.MachineName == ".") ProcessHandler.localProcessKill(p.ProcessName); else ProcessHandler.remoteProcessKill(p.MachineName, txtUserName.Text, txtPassword.Password, p.ProcessName); } } } 

Et selon que le fichier se trouve sur l'ordinateur local:

 public static void localProcessKill(ssortingng processName) { foreach (Process p in Process.GetProcessesByName(processName)) { p.Kill(); } } 

ou un ordinateur en réseau:

 public static void remoteProcessKill(ssortingng computerName, ssortingng fullUserName, ssortingng pword, ssortingng processName) { var connectoptions = new ConnectionOptions(); connectoptions.Username = fullUserName; // @"YourDomainName\UserName"; connectoptions.Password = pword; ManagementScope scope = new ManagementScope(@"\\" + computerName + @"\root\cimv2", connectoptions); // WMI query var query = new SelectQuery("select * from Win32_process where name = '" + processName + "'"); using (var searcher = new ManagementObjectSearcher(scope, query)) { foreach (ManagementObject process in searcher.Get()) { process.InvokeMethod("Terminate", null); process.Dispose(); } } } 

Références:
Comment savoir quel processus verrouille un fichier à l'aide de .NET?

Supprimer un répertoire où quelqu'un a ouvert un fichier