我正在编写一个 VB 脚本来更新网络上的一些文件。在开始之前,我想知道是否有任何文件被锁定。我想在实际进行任何更新之前执行此操作。
我知道如果在尝试替换文件时文件被锁定,我可以处理该错误,但我真的想知道在开始更新任何文件之前是否有任何文件被锁定。
有什么方法可以查看使用 VBS 锁定文件(除了尝试替换它)?
我正在编写一个 VB 脚本来更新网络上的一些文件。在开始之前,我想知道是否有任何文件被锁定。我想在实际进行任何更新之前执行此操作。
我知道如果在尝试替换文件时文件被锁定,我可以处理该错误,但我真的想知道在开始更新任何文件之前是否有任何文件被锁定。
有什么方法可以查看使用 VBS 锁定文件(除了尝试替换它)?
此函数确定是否可以在“写入”模式下访问感兴趣的文件。这与确定文件是否被进程锁定并不完全相同。不过,您可能会发现它适用于您的情况。(至少在出现更好的东西之前。)
此函数将指示当文件被另一个进程锁定时,无法进行“写”访问。但是,它无法将该条件与其他阻止“写”访问的条件区分开来。例如,如果文件设置了只读位或拥有限制性 NTFS 权限,则也无法进行“写入”访问。当进行“写”访问尝试时,所有这些条件都将导致“权限被拒绝”。
另请注意,如果文件被另一个进程锁定,则此函数返回的答案仅在执行该函数时才是可靠的。因此,并发问题是可能的。
如果找到以下任何条件,则会引发异常:“找不到文件”、“找不到路径”或“非法文件名”(“错误的文件名或编号”)。
Function IsWriteAccessible(sFilePath)
' Strategy: Attempt to open the specified file in 'append' mode.
' Does not appear to change the 'modified' date on the file.
' Works with binary files as well as text files.
' Only 'ForAppending' is needed here. Define these constants
' outside of this function if you need them elsewhere in
' your source file.
Const ForReading = 1, ForWriting = 2, ForAppending = 8
IsWriteAccessible = False
Dim oFso : Set oFso = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Dim nErr : nErr = 0
Dim sDesc : sDesc = ""
Dim oFile : Set oFile = oFso.OpenTextFile(sFilePath, ForAppending)
If Err.Number = 0 Then
oFile.Close
If Err Then
nErr = Err.Number
sDesc = Err.Description
Else
IsWriteAccessible = True
End if
Else
Select Case Err.Number
Case 70
' Permission denied because:
' - file is open by another process
' - read-only bit is set on file, *or*
' - NTFS Access Control List settings (ACLs) on file
' prevents access
Case Else
' 52 - Bad file name or number
' 53 - File not found
' 76 - Path not found
nErr = Err.Number
sDesc = Err.Description
End Select
End If
' The following two statements are superfluous. The VB6 garbage
' collector will free 'oFile' and 'oFso' when this function completes
' and they go out of scope. See Eric Lippert's article for more:
' http://blogs.msdn.com/b/ericlippert/archive/2004/04/28/when-are-you-required-to-set-objects-to-nothing.aspx
'Set oFile = Nothing
'Set oFso = Nothing
On Error GoTo 0
If nErr Then
Err.Raise nErr, , sDesc
End If
End Function
下面的脚本尝试写入文件 30 秒,然后放弃。当我们所有的用户都必须点击一个脚本时,我需要这个。可能有多个用户尝试同时写入。OpenCSV() 尝试以 1 秒的延迟打开文件 30 次。
Const ForAppending = 8
currentDate = Year(Now) & "-" & Month(Now) & "-" & Day(Now) & " " & Hour(Now) & ":" & Minute(Now) & ":" & Second(Now)
filepath = "\\network\path\file.csv"
Set oCSV = OpenCSV( filepath )
oCSV.WriteLine( currentDate )
oCSV.Close
Function OpenCSV( path )
Set oFS = CreateObject( "Scripting.FileSystemObject" )
For i = 0 To 30
On Error Resume Next
Set oFile = oFS.OpenTextFile( path, ForAppending, True )
If Not Err.Number = 70 Then
Set OpenCSV = oFile
Exit For
End If
On Error Goto 0
Wscript.Sleep 1000
Next
Set oFS = Nothing
Set oFile = Nothing
If Err.Number = 70 Then
MsgBox "File " & filepath & " is locked and timeout was exceeded.", vbCritical
WScript.Quit
End If
End Function
或者,更简单地说:
假设您的 VBS 中已经有一个名为FileName的变量,其中包含您要测试的完整文件路径:
Dim oFso, oFile
Set oFso = CreateObject("Scripting.FileSystemObject")
Set oFile = oFso.OpenTextFile(FileName, 8, True)
If Err.Number = 0 Then oFile.Close
第 3 行尝试在启用附加权限的情况下打开要测试的文件。例如,它试图用写锁打开文件。
如果使用写锁打开文件会产生错误,那么您的 VBS 将在第三行出错并且不会继续。那时,您从调用 VBS 的任何位置进行的错误处理都应该启动。如果您无法获得写锁定,则错误消息将是“Permission Denied”。
如果使用锁打开文件不会导致错误,则第 4 行将再次关闭它。您现在可以打开文件或对它做任何您想做的事情,确信它没有写锁。