2012-09-06 21 views
5

Piszę skrypt VB, aby zaktualizować niektóre pliki w sieci. Przed rozpoczęciem chciałbym się dowiedzieć, czy któryś z plików jest zablokowany. Chciałbym to zrobić przed I rzeczywiście zrobić żadnych aktualizacji.Jak ustalić, czy plik jest zablokowany za pomocą VBS?

Jestem świadomy, że mogę obsłużyć błąd, jeśli plik jest zablokowany, gdy próbuję go zastąpić, ale naprawdę chcę wiedzieć, czy jakiekolwiek pliki są zablokowane, zanim zacznę aktualizować jakiekolwiek pliki.

Czy istnieje sposób sprawdzenia, czy plik jest zablokowany przy użyciu VBS (oprócz próby zastąpienia go)?

Odpowiedz

11

Ta funkcja określa, czy dostęp do pliku będącego przedmiotem zainteresowania można uzyskać w trybie "zapisu". Nie jest to dokładnie to samo, co ustalenie, czy plik jest zablokowany przez proces. Mimo to może się okazać, że działa to w twojej sytuacji. (Przynajmniej dopóki nie pojawi się coś lepszego.)

Ta funkcja pokaże, że dostęp "zapis" nie jest możliwy, gdy plik jest zablokowany przez inny proces. Nie może jednak odróżnić tego warunku od innych warunków, które uniemożliwiają dostęp do zapisu. Na przykład dostęp "zapisu" nie jest również możliwy, jeśli plik ma ustawiony bit tylko do odczytu lub ma restrykcyjne uprawnienia NTFS. Wszystkie te warunki spowodują "odmowę zgody", gdy zostanie podjęta próba "zapisu".

Należy również zauważyć, że jeśli plik jest zablokowany przez inny proces, odpowiedź zwrócona przez tę funkcję jest niezawodna tylko w momencie, gdy funkcja jest wykonywana. Tak więc problemy z współbieżnością są możliwe.

Wyjątek jest zgłaszany, jeśli zostanie znaleziony dowolny z następujących warunków: "plik nie znaleziony", "ścieżka nie znaleziona" lub "nielegalna nazwa pliku" ("zła nazwa lub numer pliku").

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

Darin zauważa (w innej odpowiedzi), że moduł ten powinien zawierać: 'Const ForReading = 1, ForWriting = 2, ForAppending = 8' – Smandoli

+0

@Smandoli - Dziękuję za zwrócenie mojej uwagi na pominięcie. Zaktualizowałem kod odpowiednio. Zwróć także uwagę na mój komentarz poprzedzający ustawienie "oFile" i "oFso" na "Nic" na końcu funkcji. – DavidRR

2

przykład działa świetnie, ale potrzebne są następujące albo masz naruszył procedurę 5 (nielegalnym)

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

Wygląda na to, że dotyczy odpowiedzi udzielonej przez DavidRR. Wygląda mi dobrze. – Smandoli

3

Skrypt poniżej próbuje zapisać do pliku przez 30 sekund i daje się potem. Potrzebowałem tego, kiedy wszyscy nasi użytkownicy musieli kliknąć skrypt. Możliwe, że wielu użytkowników próbuje pisać w tym samym czasie. OpenCSV() próbuje otworzyć plik 30 razy z opóźnieniem 1 sekundy pomiędzy.

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 
Powiązane problemy