我如何以编程方式确定哪个应用程序正在锁定文件? [重复]

时间:2021-02-22 18:21:15

Possible Duplicate:
How do I find out which process is locking a file using .NET?

可能重复:如何找出使用.NET锁定文件的进程?

I want to copy a file but it is locked by another application, so a FileInUseException is thrown. I would like to tell the user which application is locking the file I'm trying to copy. Is there a way in the .NET Framework to do this? Without this knowledge, I'm resorting to telling the users to use the Unlocker application.

我想复制一个文件,但它被另一个应用程序锁定,因此抛出了FileInUseException。我想告诉用户哪个应用程序正在锁定我正在尝试复制的文件。 .NET Framework中有没有办法做到这一点?如果没有这方面的知识,我会告诉用户使用Unlocker应用程序。

2 个解决方案

#1


4  

You could try the code provided in this question over here, or look at other suggestions here.

你可以在这里尝试这个问题中提供的代码,或者在这里查看其他建议。

The general approach is to enumerate the handles of all processes, get the file paths of those handles, and compare against the file you're interested in.

一般方法是枚举所有进程的句柄,获取这些句柄的文件路径,并与您感兴趣的文件进行比较。

But a problem with this approach is that even if you can determine that the file is locked and which application has the file lock then you will still have to cope with race conditions, for example...

但是这种方法的一个问题是,即使您可以确定文件已被锁定以及哪个应用程序具有文件锁定,您仍然需要应对竞争条件,例如......

one millisecond later

一毫秒之后

  • the file is not locked
  • 文件未锁定
  • the application that did hold the lock is now not
  • 现在没有锁定的应用程序

then two milliseconds later

然后两毫秒后

  • the file is locked (again)
  • 文件被锁定(再次)
  • a different application has the lock
  • 一个不同的应用程序有锁

then three milliseconds later

然后三毫秒之后

  • the file is still locked
  • 该文件仍然被锁定
  • yet another app has the lock
  • 另一个应用程序有锁

...etc

...等等

One suggestion is to attempt to get the file handle in your app, and catch the exception when you can't.

一个建议是尝试在您的应用程序中获取文件句柄,并在您不能时捕获异常。

 try
 {
    using (Stream stream = new FileStream("MyFilename.txt"))
   {
   }
 } catch {
   //check here why it failed and ask user to retry if the file is in use.
}

Of course this won't help identify the culprit(s) but at least you have a safer way of attempting to access the file.

当然,这无助于识别罪魁祸首,但至少您有一种更安全的方式来尝试访问该文件。

#2


3  

Keeping in mind the caveats Ed pointed out, on Vista an later, you can use the Restart Manager APIs to accomplish this (even if your app isn't an installer).

请记住Ed指出的警告,稍后在Vista上,您可以使用Restart Manager API来完成此操作(即使您的应用程序不是安装程序)。

You create a new session, register the file of interest, then call RmGetList to get the list of applications or services that have a handle on the file. You should be able to even initiate a restart of those applications if they're Restart Manager-aware without involving the user.

您创建一个新会话,注册感兴趣的文件,然后调用RmGetList以获取具有该文件句柄的应用程序或服务的列表。如果这些应用程序在不涉及用户的情况下具有重新启动管理器感知功能,您甚至应该能够重新启动这些应用程序。

Clearly, the Restart Manager is a Win32 API, but you should be able to P/Invoke into it. This article: http://msdn.microsoft.com/en-us/magazine/cc163450.aspx has the needed P/Invoke signatures as well as examples of use in this manner.

显然,Restart Manager是一个Win32 API,但您应该能够进行P / Invoke。本文:http://msdn.microsoft.com/en-us/magazine/cc163450.aspx具有所需的P / Invoke签名以及以这种方式使用的示例。

#1


4  

You could try the code provided in this question over here, or look at other suggestions here.

你可以在这里尝试这个问题中提供的代码,或者在这里查看其他建议。

The general approach is to enumerate the handles of all processes, get the file paths of those handles, and compare against the file you're interested in.

一般方法是枚举所有进程的句柄,获取这些句柄的文件路径,并与您感兴趣的文件进行比较。

But a problem with this approach is that even if you can determine that the file is locked and which application has the file lock then you will still have to cope with race conditions, for example...

但是这种方法的一个问题是,即使您可以确定文件已被锁定以及哪个应用程序具有文件锁定,您仍然需要应对竞争条件,例如......

one millisecond later

一毫秒之后

  • the file is not locked
  • 文件未锁定
  • the application that did hold the lock is now not
  • 现在没有锁定的应用程序

then two milliseconds later

然后两毫秒后

  • the file is locked (again)
  • 文件被锁定(再次)
  • a different application has the lock
  • 一个不同的应用程序有锁

then three milliseconds later

然后三毫秒之后

  • the file is still locked
  • 该文件仍然被锁定
  • yet another app has the lock
  • 另一个应用程序有锁

...etc

...等等

One suggestion is to attempt to get the file handle in your app, and catch the exception when you can't.

一个建议是尝试在您的应用程序中获取文件句柄,并在您不能时捕获异常。

 try
 {
    using (Stream stream = new FileStream("MyFilename.txt"))
   {
   }
 } catch {
   //check here why it failed and ask user to retry if the file is in use.
}

Of course this won't help identify the culprit(s) but at least you have a safer way of attempting to access the file.

当然,这无助于识别罪魁祸首,但至少您有一种更安全的方式来尝试访问该文件。

#2


3  

Keeping in mind the caveats Ed pointed out, on Vista an later, you can use the Restart Manager APIs to accomplish this (even if your app isn't an installer).

请记住Ed指出的警告,稍后在Vista上,您可以使用Restart Manager API来完成此操作(即使您的应用程序不是安装程序)。

You create a new session, register the file of interest, then call RmGetList to get the list of applications or services that have a handle on the file. You should be able to even initiate a restart of those applications if they're Restart Manager-aware without involving the user.

您创建一个新会话,注册感兴趣的文件,然后调用RmGetList以获取具有该文件句柄的应用程序或服务的列表。如果这些应用程序在不涉及用户的情况下具有重新启动管理器感知功能,您甚至应该能够重新启动这些应用程序。

Clearly, the Restart Manager is a Win32 API, but you should be able to P/Invoke into it. This article: http://msdn.microsoft.com/en-us/magazine/cc163450.aspx has the needed P/Invoke signatures as well as examples of use in this manner.

显然,Restart Manager是一个Win32 API,但您应该能够进行P / Invoke。本文:http://msdn.microsoft.com/en-us/magazine/cc163450.aspx具有所需的P / Invoke签名以及以这种方式使用的示例。