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

时间:2009-07-03 11:55:37

标签: .net vb.net updating

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

  

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

此程序在网络上使用,无需运行任何服务。因此,用户可以通过网络上的网络运行exe。

我需要在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”)

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

我以为我不在乎,所以我让另一位程序员看看这个并且他验证了我上面所说的内容。

所以,我们尝试将其包裹在try catch中:

  

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

我把文件共享视为无,至少我认为会这样,表明文件中有人。

它仍然没有任何错误。

任何人都知道为什么我可以重命名正在使用的文件? 另外,有没有比我现在做的更好的方法呢?

谢谢! Eroc

5 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:1)

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

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

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

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

答案 2 :(得分:1)

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

此看护人随后会生成目标应用程序,但也会在共享位置创建锁定文件。当应用程序退出时,锁定被释放并删除文件。

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

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

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");
    }
}

更新程序然后查找所有“AppLock_ *”文件,并尝试使用写锁打开它们,如果它无法对其中一个文件执行写锁定,则exe正在使用中。

希望这有帮助。

答案 3 :(得分:0)

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

无论如何,这是:

  

Private Sub CheckFileIfFileIsInUse(ByVal thefilename As String)
        尝试
            '在Vista OS上,您可以重命名正在使用的文件
            原始文件中的“正在使用”遵循新文件名

      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 />
     

结束Sub

希望这有助于下一个人。

答案 4 :(得分:0)

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