2012-09-06 29 views
5

Sto scrivendo uno script VB per aggiornare alcuni file sulla rete. Prima di iniziare, voglio sapere se uno qualsiasi dei file è bloccato. Mi piacerebbe fare questo prima del Realmente faccio tutti gli aggiornamenti.Come posso determinare se un file è bloccato usando VBS?

Sono consapevole del fatto che posso gestire l'errore se il file è bloccato quando provo a sostituirlo, ma voglio davvero sapere se alcuni file sono bloccati prima di iniziare ad aggiornare i file.

C'è un modo per vedere che un file è bloccato usando VBS (a parte cercare di sostituirlo)?

risposta

11

Questa funzione determina se è possibile accedere a un file di interesse in modalità 'scrittura'. Questo non è esattamente lo stesso di determinare se un file è bloccato da un processo. Tuttavia, potresti scoprire che funziona per la tua situazione. (Almeno finché arriva qualcosa di meglio.)

Questa funzione indica che l'accesso in "scrittura" non è possibile quando un file è bloccato da un altro processo. Tuttavia, non è in grado di distinguere quella condizione da altre condizioni che impediscono l'accesso in "scrittura". Ad esempio, l'accesso in scrittura non è possibile anche se un file ha il set di bit di sola lettura o possiede autorizzazioni NTFS restrittive. Tutte queste condizioni comporteranno il "permesso negato" quando viene effettuato un tentativo di accesso in "scrittura".

Si noti inoltre che se un file è bloccato da un altro processo, la risposta restituita da questa funzione è affidabile solo al momento dell'esecuzione della funzione. Quindi, i problemi di concorrenza sono possibili.

Viene generata un'eccezione se viene trovata una di queste condizioni: "file non trovato", "percorso non trovato" o "nome file non valido" ("nome file o numero errato").

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 note (in altra risposta) che questo modulo dovrebbe includere: 'Const ForReading = 1, ForWriting = 2, ForAppending = 8' – Smandoli

+0

@Smandoli - Grazie per aver portato questa omissione alla mia attenzione. Ho aggiornato il codice di conseguenza. Nota anche il mio commento precedente all'impostazione di 'oFile' e' oFso' a 'Nothing' alla fine della funzione. – DavidRR

2

esempio funziona grande, ma sono necessari i seguenti, altrimenti si ottiene sbagliare 5 (procedura illegale)

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

Appare applicabile alla risposta offerta da DavidRR. Sembra giusto per me – Smandoli

3

Lo script di seguito tenta di scrivere in un file per 30 secondi e si arrende dopo. Avevo bisogno di questo quando tutti i nostri utenti dovevano cliccare su uno script. Le probabilità sono che più utenti provano a scrivere allo stesso tempo. OpenCSV() prova ad aprire il file 30 volte con un ritardo di 1 secondo.

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 
Problemi correlati