/// <summary> /// Determines the file name for a file handle. /// </summary> /// <param name="handle">Handle of the file, which name is to be determined.</param> /// <param name="processId">ID of the owning process.</param> /// <returns>The name of the file, the object handle points to. If the name could not be determined, an empty string is returned.</returns> public static string GetFileNameFromHandle(IntPtr handle, int processId) { Logger.Log(LogLevel.Debug, "Getting filename: PID=" + processId + " handle=" + handle.ToInt32()); string devicePath; if (!LowLevelHandleHelper.GetFileNameFromHandle(handle, processId, out devicePath)) { return(string.Empty); } else { Logger.Log(LogLevel.Debug, " -> device path is " + devicePath); } string dosPath = PathHelper.ConvertDevicePathToDosPath(devicePath); if (dosPath.Length == 0) { return(devicePath); } else { Logger.Log(LogLevel.Debug, " -> dos path is " + dosPath); } return(dosPath); }
/// <summary> /// Default constructor. When this constructor is invoked a snapshot of all running processes and /// their currently open handles is taken. /// </summary> public ProcessHandleSnapshot() { this.snapshot = new Dictionary <int, List <IntPtr> >(); OpenFilesEnumerator openFiles = new OpenFilesEnumerator(); IEnumerator <SystemHandleEntry> enumerator = openFiles.GetEnumerator(); while (enumerator.MoveNext()) { SystemHandleEntry entry = enumerator.Current; int processId = entry.OwnerPid; IntPtr handle = (IntPtr)entry.HandleValue; if (LowLevelHandleHelper.IsFileHandle(handle, processId)) { if (!this.IgnoreSystemHandleEntry(entry)) { if (!this.snapshot.ContainsKey(processId)) { this.snapshot.Add(processId, new List <IntPtr>()); } List <IntPtr> handleList; if (this.snapshot.TryGetValue(processId, out handleList)) { handleList.Add(handle); } } } } Logger.Log(LogLevel.Debug, "Process handle snapshot contains " + this.snapshot.Count + " entries"); }
/// <summary> /// Checks if the object handle is a file handle. /// </summary> /// <param name="handle">Handle of the object.</param> /// <param name="processId">Process that owns this handle.</param> /// <returns>true if and only the handle is a file handle.</returns> public static bool IsFileHandle(IntPtr handle, int processId) { string type = LowLevelHandleHelper.GetHandleTypeToken(handle, processId); Logger.Log(LogLevel.Debug, string.Format("Getting filetype: PID={0}, handle={1}, type={2}", processId, handle.ToInt32(), type)); return(type.Equals("File")); }
/// <summary> /// Tries to delete the file "the hard way". At first this method determines which process(es) has the /// file in use and closes the file handle of the file within the determined process(es). If this has /// been done, the file is deleted using File.Delete(). /// </summary> /// <param name="absoluteFileName">Absolute name of the file to be deleted.</param> /// <returns>true if and only if the file has been deleted.</returns> private bool TryHarderDelete(string absoluteFileName) { // Windows Vista provides a new API which can be used to determine which process // has a file opened. This API is nor available on Windows XP so we have check // all processes on those legacy systems. bool isVistaOrNewer = SystemHelper.IsWindowsVistaOrNewer(); List <int> processIds = isVistaOrNewer ? UsedFileDetector.GetProcesses(absoluteFileName) : SystemHelper.GetProcesses(); foreach (int pid in processIds) { Logger.Log(LogLevel.Debug, "Checking all file handles of process " + pid); foreach (IntPtr handle in this.snapshot.GetHandles(pid)) { Logger.Log(LogLevel.Debug, string.Empty); string fileName = LowLevelHandleHelper.GetFileNameFromHandle(handle, pid); if (absoluteFileName.Equals(fileName, StringComparison.OrdinalIgnoreCase)) { Logger.Log(LogLevel.Verbose, "File " + absoluteFileName + " is in use by process with PID " + pid); this.CloseHandleInRemoteProcess(pid, handle); break; } } } File.Delete(absoluteFileName); return(true); }