题
我在寻找一种方式来删除的文件,该文件是锁定的另一个进程使用。我怀疑的方法必须能够找到其过程是锁定的文件(或许是通过跟踪处理,虽然我不知道该如何做到这一点在C#)然后关闭这一进程才能够完成该文件的删除使用 File.Delete()
.
解决方案
杀害其他进程,不是一个健康的事情要做。如果你的方案涉及到的东西喜欢卸载,可以使用 MoveFileEx
API功能 标记的文件对于删除在下次重新启动。
如果你真的需要删除的文件在使用由另一个进程,我建议你重新考虑实际问题之前考虑任何解决方案。
其他提示
典型的方法如下。你说你想要做到这一点,在C#所以这里去...
- 如果你不知道这过程中具有的文件锁,只需要检查每一个过程的处理列表,并可查询每一处理,以确定如果它确定该上锁的文件。这样做在C#可能需要P/援引或中介C++/CLI呼吁本机Api你会需要。
- 一旦你已经想通了其中的过程(es)有的文件锁,你就需要安全注射的小型机DLL入过程(也可以注入一个管理的问题,但这是梅西尔,因为然后必须开始或附加的。净运行时)。
- 这引导DLL然后关闭该处理使用CloseHandle,等等。
基本上:的方式来解锁"锁定"文件是以注射DLL文件,进入有问题的进程的地址空间和接近自己。你可以做到这一使用地或托管的代码。不管是什么,你会需要少量的机代码或至少P/援引入相同。
有用的链接:
祝你好运!
如果你想要做的,它通过程序.我不确定...我真的建议反对它。如果你们只是排除东西在你自己的机器, 微软处理资源管理器 可以帮助你
它运行,使用的发现处理的命令(我认为这是在发现或处理菜单),并搜索名称的文件。一旦处理(s)被发现,你可以强行关闭它们。
然后你可以删除的文件,等等。
当心, ,这样做可能造成程序,它拥有处理的行为奇怪的是,正如你刚才拉的众所周知的地毯从下它,但是它的工作原理以及调试时你自己的错误代码,或者当visual studio/windows资源管理器是被废话,而不是释放文件处理即使你告诉他们关闭该文件很久以前...叹息:-)
你可以使用这一程序, 手柄, ,找到这一进程已锁在你的文件。这是一个命令行工具,所以我猜你用的输出那个...我不知道找到它编程。
如果删除该文件可以等等,你可以指定为删除的时候你的计算机接下来开始:
开始
REGEDT32 (W2K)
或REGEDIT (WXP)
和导航:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager
W2K和WXP
W2K:
编辑
增加价值...
数据类型:REG_MULTI_SZ
值名称:PendingFileRenameOperations
"确定"WXP:
编辑
新的
多String Value
输入
PendingFileRenameOperations
在区域的数据,输入
"\??\" + filename
被删除。LFNs可能 可以进入不被埋在报价。删除C:\Long Directory Name\Long File Name.exe
, 输入的数据如下:\??\C:\Long Directory Name\Long File Name.exe
然后按下 "确定".
"目的地的文件名称"是一个null(zero)string.它进入 如下:
W2K:
编辑
二进制
选择数据格式:Hex
点击在结束hex string
该0000(四零)
"确定"WXP:
右击的价值
选择"修改的二进制数据"
点击在结束hex string
该0000(四零)
"确定"
靠近
REGEDT32/REGEDIT
和重启删除的文件。
(无耻地窃 一些随机论坛, 为子孙后代的缘故。)
使用"猎户座"爱德华兹建议,我下微软 处理资源管理器 这又允许我发现的文件,我是有困难删除是事实上正在举行不通过 Excel.Applications
对象我想象的,而事实上,我的C#代码发送邮件代码创造了一个附件目的留下把柄,这一文件开放。
一旦我看到这个,我很简单的呼吁处置方法的附件的目的,以及处理被释放。
该资源管理器微软允许我发现这个结合使用Visual Studio2005年调试器。
我强烈推荐这个工具!
哦,一个大的黑客我雇用年前,是Windows不会让你 删除 的文件,但它不会让你 移动 它们。
伪排序的代码:
mv %WINDIR%\System32\mfc42.dll %WINDIR\System32\mfc42.dll.old
Install new mfc42.dll
Tell user to save work and restart applications
当的应用程序重新启动(注意,我们不需要重新启动机),它们载入新的 mfc42.dll
, 和所有物。那,再加 PendingFileOperations
删除旧的下一次全系统重新启动,工作相当好。
这看起来很有希望。一的方式杀人的文件处理。...
http://www.timstall.com/2009/02/killing-file-handles-but-not-process.html
你可以使用代码,你提供的全部文件的路径,它将会返回 List<Processes>
什么锁,文件:
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);
/// <summary>
/// Find out what process(es) have a lock on the specified file.
/// </summary>
/// <param name="path">Path of the file.</param>
/// <returns>Processes locking the file</returns>
/// <remarks>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)
///
/// </remarks>
static public List<Process> WhoIsLocking(string path)
{
uint handle;
string key = Guid.NewGuid().ToString();
List<Process> processes = new List<Process>();
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<Process>((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<Process> lstProcs = new List<Process>();
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);
}
File.Delete(file);
}
else
File.Delete(file);
}
并且取决于如果文件是在当地计算机:
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();
}
}
}
参考文献:
我怎么找出这个过程是锁定一个文件使用。净?