2012-09-06 14 views
5

私はネットワーク上のいくつかのファイルを更新するためのVBスクリプトを書いています。始める前に、ファイルがロックされているかどうかを知りたい。私はこれを行うにはの前に私は実際に更新を行います。VBSを使用してファイルがロックされているかどうかを確認するにはどうすればよいですか?

置き換えようとするとファイルがロックされていても処理できますが、ファイルを更新する前にファイルがロックされているかどうかを本当に知りたいと思っています。

VBSを使用してファイルがロックされていることを確認する方法はありますか?

答えて

11

この関数は、「書き込み」モードで目的のファイルにアクセスできるかどうかを決定します。これは、ファイルがプロセスによってロックされているかどうかを判断することとまったく同じではありません。それでも、あなたの状況に適していることがわかります。 (少なくとも何かがうまくいくまで)

この機能は、ファイルが別のプロセスによってロックされているときに「書き込み」アクセスができないことを示します。ただし、その条件を「書き込み」アクセスを禁止する他の条件と区別することはできません。たとえば、ファイルに読み取り専用ビットが設定されている場合や、制限付き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 
+1

ダーリンノートこのモジュールが含まれなければならないこと(他の回答で): 'のConst ForReading = 1、ForWriting = 2、ForAppending = 8' – Smandoli

+0

@Smandoli - 私の注意には、この省略を持っていただき、ありがとうございます。私はそれに応じてコードを更新しました。また、関数の最後に 'oFile'と' oFso'を 'Nothing'に設定する前の私のコメントに注目してください。 – DavidRR

2

例は偉大な動作しますが、あなたは5(不正な手続き)を誤る得る他に以下のものが必要か

Const ForReading = 1, ForWriting = 2, ForAppending = 8 
+1

これはDavidRRが提供する回答に当てはまるようです。私に見える。 – Smandoli

3

以下のスクリプトは、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