使用C#关闭打开的文件

我有一种情况,人们连接到共享上的文件,它阻止我覆盖文件。 我正在尝试编写一个方法来查看我提供的filePath当前是否以这种方式锁定并关闭此资源的网络会话。

我查看了ADSI Winnt提供程序,但是没有实现Resources.Remove成员。 然后我查看了Win32_ServerSession,虽然我能够使用Delete成员,但它会杀死给定用户的所有资源。 我需要弄清楚如何更具体。

我一直在走GetRelationsShips和Properties,但我现在很难过。

要考虑这样做的所有后果是很困难的,因为您无法预测当前锁定文件的应用程序的最终行为。

还有其他方法吗? 例如,您是否必须立即覆盖该文件,或者您是否有一些外部进程每隔几分钟就会不断尝试覆盖该文件,直到成功为止?

我遇到了同样的问题。 到目前为止,我知道,唯一的方法是使用Win32API:

 [DllImport(“Netapi32.dll”,SetLastError = true,CharSet = CharSet.Unicode)]
 public static extern int NetFileClose(string servername,int id);

我做了一个短暂的尝试来实现这一点,我可以直接枚举文件,但在我的代码中 – 我只是看看它 – 关闭文件的代码被设置为注释。 如果你试试这个,我可以发送一个库[NetFileXXX包装]和一个简短的演示,但是,正如我所说:我从未关闭过文件。 但这可能是一个简短的方法。

我不知道,如何在stackoverflow上交换文件:-(?!?

BR – mabra

您可以使用提供完整文件路径的代码,它将返回锁定该文件的任何内容的List

 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 string strAppName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)] public string 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, string[] rgsFilenames, UInt32 nApplications, [In] RM_UNIQUE_PROCESS[] rgApplications, UInt32 nServices, string[] rgsServiceNames); [DllImport("rstrtmgr.dll", CharSet = CharSet.Auto)] static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string 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(string path) { uint handle; string key = Guid.NewGuid().ToString(); 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; string[] resources = new string[] { 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; } } 

然后,迭代进程列表并关闭它们:

  string[] files = Directory.GetFiles(target_dir); List lstProcs = new List(); foreach (string 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); } } } 

并且取决于文件是否在本地计算机上:

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

或网络计算机:

 public static void remoteProcessKill(string computerName, string fullUserName, string pword, string 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(); } } } 

参考文献:
如何找出使用.NET锁定文件的进程?

删除某人打开文件的目录