VB.Net 3.5 检查文件是否正在使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1079036/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 12:57:37  来源:igfitidea点击:

VB.Net 3.5 Check if file is in use

.netvb.netupdating

提问by ErocM

I have an update program that is completely independent of my main application. I run the update.exe to update the app.exe. To check to see if the file is in use, I move it to another file and catch an error if it is in use. If no problems occurr I rename it back. At least that was my plan...

我有一个完全独立于我的主应用程序的更新程序。我运行 update.exe 来更新 app.exe。为了检查文件是否在使用中,我将它移到另一个文件中并在它正在使用时捕获错误。如果没有出现问题,我将其重命名。至少这是我的计划......

Main program: app.exe
Update program: update.exe

主程序:app.exe
更新程序:update.exe

This program is used over the network without any services running. So, the users is quite literally running the exe over the network on thier machine.

该程序通过网络使用,无需运行任何服务。因此,用户实际上是在他们的机器上通过网络运行 exe。

I need to update the app.exe when the update.exe has run. To check to see if the app.exe was still in use I was wrapping the following in a try/catch to see if it failed:

当 update.exe 运行时,我需要更新 app.exe。要检查 app.exe 是否仍在使用中,我将以下内容包装在 try/catch 中以查看它是否失败:

IO.File.Move(upddir & "\app.exe", upddir & "\app.exe.tst")
IO.File.Move(upddir & "\app.exe.tst", upddir & "\app.exe")

IO.File.Move(upddir & "\app.exe", upddir & "\app.exe.tst")
IO.File.Move(upddir & "\app.exe.tst", upddir & "\app.exe" ”)

The funny thing is, even if the app.exe is running, the move can rename it to the app.exe.tst without any error. I can even continue on in the application without any errors.

有趣的是,即使 app.exe 正在运行,移动也可以将其重命名为 app.exe.tst,而不会出现任何错误。我什至可以继续在应用程序中没有任何错误。

I thought I was out of my mind, so I had another programmer look at this and he verified what I said above.

我以为我疯了,所以我让另一个程序员看了这个,他验证了我上面说的。

So, we tried this wrapped in a try catch:

因此,我们尝试将其包裹在 try catch 中:

Dim readfile As New FileStream(upddir & "\app.exe", FileMode.Open, FileAccess.Read, FileShare.None)
readfile.Dispose()

Dim readfile As New FileStream(upddir & "\app.exe", FileMode.Open, FileAccess.Read, FileShare.None)
readfile.Dispose()

I put the fileshare as none that, at least I thought it would, show that there was someone in the file.

我将文件共享设置为无,至少我认为它会表明文件中有人。

It still continued without any error.

它仍然继续没有任何错误。

Anyone know why I can rename a file in use? Also, is there a better way to do this than what I am doing now?

有人知道为什么我可以重命名正在使用的文件吗?另外,有没有比我现在正在做的更好的方法来做到这一点?

Thanks! Eroc

谢谢!爱罗克

采纳答案by James

You could do the following to check if the application has other instances running:

您可以执行以下操作来检查应用程序是否正在运行其他实例:

Process.GetProcessesByName("app.exe", "Machine1").Length > 0

Which is a more appropriate way of checking if the app is running.

这是检查应用程序是否正在运行的更合适的方法。

Have a look at File.MoveMSDN documentation. It details what exceptions are thrown. You are allowed to rename an exe even if it is in Use in Vista.

查看File.MoveMSDN 文档。它详细说明了抛出什么异常。即使在 Vista 中使用,您也可以重命名 exe。

回答by Manuel Alves

The same code using "using" :)

使用“使用”的相同代码:)

Public Function FileInUse(ByVal sFile As String) As Boolean
 Dim thisFileInUse As Boolean = False
 If System.IO.File.Exists(sFile) Then
     Try
       Using f As New IO.FileStream(sFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
                ' thisFileInUse = False
       End Using
     Catch
       thisFileInUse = True
     End Try
 End If
 Return thisFileInUse
End Function

回答by Binary Worrier

What you could do is replace the target application with a caretaker exe.

您可以做的是用看守 exe 替换目标应用程序。

This caretaker then spawns the target application, but also creates a locked file in a shared location. The lock is released and the file is deleted when the app exits.

然后,这个管理员会生成目标应用程序,但也会在共享位置创建一个锁定文件。当应用退出时,锁被释放,文件被删除。

Then, before you update the app.exe, you check are there any locked files in the shared location, if there are locked files then the app.exe is in use.

然后,在更新 app.exe 之前,检查共享位置中是否有任何锁定的文件,如果有锁定的文件,则 app.exe 正在使用中。

The caretaker program could be a window-less application, the following console app does pretty much what it needs to do

看守程序可能是一个无窗口的应用程序,下面的控制台应用程序几乎可以完成它需要做的事情

class Program
{
    static string lockFileName;
    static System.IO.StreamWriter lockFileWrtier;
    static void Main(string[] args)
    {
        lockFileName = "AppLock_" + System.IO.Path.GetRandomFileName();

        lockFileWrtier = new System.IO.StreamWriter(lockFileName);

        System.Diagnostics.Process p = new Process();
        p.StartInfo.FileName = "cmd.exe";
        p.EnableRaisingEvents = true;
        p.Exited += new EventHandler(p_Exited);

        p.Start();

        Console.WriteLine("Press any key to stop");
        Console.ReadKey();
    }

    static void p_Exited(object sender, EventArgs e)
    {
        lockFileWrtier.Dispose();
        System.IO.File.Delete(lockFileName);

        Console.WriteLine("Process has exited");
    }
}

The updater then looks for all "AppLock_*" files, and attempts to open them with a write lock, if it can't get a write lock on one of them, the exe is in use.

然后更新程序查找所有“AppLock_*”文件,并尝试使用写锁打开它们,如果无法获得其中之一的写锁,则说明该exe正在使用中。

Hope this helps.

希望这可以帮助。

回答by ErocM

This is what I ended up doing. The network scan did not work on a peer-to-peer network. It didn't resolve the other computers at all.

这就是我最终要做的。网络扫描在对等网络上不起作用。它根本没有解决其他计算机。

Anyhow, here it is:

无论如何,这里是:

Private Sub CheckFileIfFileIsInUse(ByVal thefilename As String)
Try
' on the Vista OS you can rename a file that is in use
' the 'in use' of the original file follows the new file name

      Dim testfile As String = thefilename & ".tst"<br />

      If IO.File.Exists(testfile) Then<br />
          IO.File.Delete(testfile)<br />
      End If<br />

      ' so we have to rename it to something else<br />
      IO.File.Move(thefilename, testfile)<br />

      ' copy it back to the original file name in case something <br />breaks 
      ' this just keeps them in working order if it does<br />
      IO.File.Copy(testfile, thefilename)<br />

      ' then we try to delete the original file that could be in use <br />
      ' which will return an 'in use' error at this point<br />
      If IO.File.Exists(testfile) Then<br />
          IO.File.Delete(testfile)<br />
      End If<br />

  Catch ex As Exception<br />
      'throw it to the originating method<br />
      Throw<br />
  End Try<br />

End Sub

Private Sub CheckFileIfFileIsInUse(ByVal thefilename As String)
Try
' 在 Vista 操作系统上,您可以重命名正在使用
的文件 ' 原始文件的 '使用中' 跟随新文件名

      Dim testfile As String = thefilename & ".tst"<br />

      If IO.File.Exists(testfile) Then<br />
          IO.File.Delete(testfile)<br />
      End If<br />

      ' so we have to rename it to something else<br />
      IO.File.Move(thefilename, testfile)<br />

      ' copy it back to the original file name in case something <br />breaks 
      ' this just keeps them in working order if it does<br />
      IO.File.Copy(testfile, thefilename)<br />

      ' then we try to delete the original file that could be in use <br />
      ' which will return an 'in use' error at this point<br />
      If IO.File.Exists(testfile) Then<br />
          IO.File.Delete(testfile)<br />
      End If<br />

  Catch ex As Exception<br />
      'throw it to the originating method<br />
      Throw<br />
  End Try<br />

结束子

Hope this helps the next person.

希望这对下一个人有所帮助。

回答by Destek

Public Function FileInUse(ByVal sFile As String) As Boolean
    If System.IO.File.Exists(sFile) Then
        Try
            Dim F As Short = FreeFile()
            FileOpen(F, sFile, OpenMode.Binary, OpenAccess.ReadWrite, OpenShare.LockReadWrite)
            FileClose(F)
        Catch
            Return True
        End Try
    End If
End Function