简体   繁体   English

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

[英]VB.Net 3.5 Check if file is in use

I have an update program that is completely independent of my main application. 我有一个完全独立于我的主应用程序的更新程序。 I run the update.exe to update the app.exe. 我运行update.exe来更新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... 至少那是我的计划......

Main program: app.exe 主程序:app.exe
Update program: update.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. 我需要在update.exe运行时更新app.exe。 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: 要检查app.exe是否仍在使用中,我在try / catch中包含以下内容以查看它是否失败:

IO.File.Move(upddir & "\\app.exe", upddir & "\\app.exe.tst") 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.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. 有趣的是,即使app.exe正在运行,移动也可以将其重命名为app.exe.tst而不会出现任何错误。 I can even continue on in the application without any errors. 我甚至可以继续在应用程序中没有任何错误。

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) Dim readfile As New FileStream(upddir&“\\ app.exe”,FileMode.Open,FileAccess.Read,FileShare.None)
readfile.Dispose() 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 Eroc

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

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.Move MSDN documentation. 看看File.Move MSDN文档。 It details what exceptions are thrown. 它详细说明了抛出的异常。 You are allowed to rename an exe even if it is in Use in Vista. 即使它在Vista中使用,也可以重命名exe。

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. 希望这可以帮助。

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) Private Sub CheckFileIfFileIsInUse(ByVal thefilename As String)
Try 尝试
' on the Vista OS you can rename a file that is in use '在Vista OS上,您可以重命名正在使用的文件
' 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 结束子

Hope this helps the next person. 希望这有助于下一个人。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM