Доступ к текстовым файлам в VBA: 70 - отказано в разрешении - антивирус? - PullRequest
2 голосов
/ 12 мая 2019

Я обрабатываю 200 текстовых файлов в папке. Когда я их обрабатываю, я записываю прогресс в файл журнала. Когда я собираюсь прочитать его, когда он обработан, и если произойдет какое-либо предопределенное событие.

До сих пор я использовал Open и Close в подпункте WriteToLog. Пока что такой проблемы нет (2 года).

Недавно возникла проблема: после непредсказуемого количества отдельных записей я получил: 70 - Permission denied ошибка при:

Open sFileFullPath For Append As #filenumber.

В качестве фатальной ошибки я прекращаю запуск приложения. - Подозреваю:

a) запрос на новую запись происходит до того, как будет выполнено предыдущее закрытие

b) файл журнала анализа антивируса с большим количеством операций

в) сбойный кластер на жестком диске.

d) некоторая ошибка файловой системы (поскольку chkdsk обнаружил некоторые проблемы, но исправил их).

e) Я подозреваю также, что filenumber = FreeFile техника, которую я недавно изменил, оказывает влияние на Close (не работает должным образом). 2 года с № 1, № 2, № 3 и т. Д. Без такой проблемы.

Это происходит, даже если я проверяю: If f_IsFileOpen(sFileFullPath), прежде чем пытаться открыть его для добавления.

Есть идеи, как точно определить проблему?

Option Explicit

Public bDevMode As Boolean          '-- Development mode - Y/N= where Log file is Opened/Closed
Public sLogPath As String           '-- store log path for easy change
Public sLogFileName As String

Sub ProcessFilesAndLog()
    Dim sLogFileName As String
    Dim sLogFileFullPath As String
    Dim sErrMsg As String
    Dim sInfo As String

    '-- ini variables
    bDevMode = False  '-- i.e. in production mode
    sLogFileName = ActiveSheet.Cells(5, 3) '-- "working.log"
    sLogPath = ActiveSheet.Cells(6, 3)    '-- "c:\temp\"

    '-- STEP INI0.3.5 - try to Write into the Log file in LogFolder given by Options.
    sLogFileFullPath = ActiveSheet.Cells(6, 3)    '-- "c:\temp\"

    sInfo = vbCrLf & Now & "  --- Processing started"
    p_WriteToLogINITEST sLogFileFullPath, sInfo, True, sErrMsg
    sInfo = ""
    'Application.Wait (Now + TimeValue("0:00:02"))
    '--- what to test here ?

    '-- STEP INI0.4 - when in PRODUCTION mode, Open the log file, only once. - 2019-05-09
    If Not bDevMode Then
       Open sLogFileFullPath For Append As #2  '-- HERE occassionally : 70 - Permission denied !
       If sErrMsg <> "" Then Print #2, sErrMsg
    End If  '--- of If not bDevMode
    sErrMsg = ""

    '-- analyze files code ....

    '-- close log file
    If Not bDevMode Then
       Close #2
    End If

    MsgBox "Finished!"
End Sub

и использованные подводные лодки:

'-- check if a file is still open
Function f_IsFileOpen(filename As String) As Boolean
    Dim filenum As Integer
    Dim errnum As Integer

    On Error Resume Next   ' Turn error checking off.
    filenum = FreeFile()   ' Get a free file number.

    '-- Attempt to open the file and lock it.
    Err.Clear
    Open filename For Input Lock Read As #filenum
    errnum = Err.Number    ' Save the error number that occurred.

    Close filenum          ' Close the file.
    On Error GoTo 0        ' Turn error checking back on.

    '-- Check to see which error occurred.
    Select Case errnum
        '-- 0 - No error occurred - File is NOT open by another user.
        Case 0
         f_IsFileOpen = False

        '-- 70 - Error number for "Permission Denied." File is already opened by another user.
        Case 70
            f_IsFileOpen = True

        '-- 53 - doesn't exist
        Case 53
            f_IsFileOpen = False

        '-- Another error occurred.
        Case Else
           f_IsFileOpen = True
           'Error errnum
    End Select
End Function


Sub p_WriteToLogINITEST(ByRef sLogFileFullPath As String, ByVal sMsg As String, ByVal bAppend As Boolean, ByRef sErrMsg As String)
   Dim nCycleCnt As Integer
   nCycleCnt = 1

   On Error GoTo FILE_ERR

   '-- Write ini processing msg to log file
   If sMsg = "" Then sMsg = vbCrLf & Now & "  --- Processing started"

   If bAppend = True Then
      Open sLogFileFullPath For Append As #2
   Else
      Open sLogFileFullPath For Output As #2
   End If
   Print #2, sMsg
   Close #2

   '-- Wait, until it's sure that previous log file writing has finished, incl. Close. Wait max 10 seconds.
   Do While nCycleCnt < 11   '-- 10 trials

      If f_IsFileOpen(sLogFileFullPath) Then
         sErrMsg = sErrMsg & String(nCycleCnt, "#") & "," '-- for DEBUG ! only
         Application.Wait (Now + TimeValue("0:00:01"))

      Else  '-- file IS NOT OPEN, i.e. I can LEAVE this sub !
         Exit Do
      End If

      nCycleCnt = nCycleCnt + 1
   Loop

   Exit Sub

FILE_ERR:
   sErrMsg = "M1.57: Fatal error: Error writing into the log file: " & sLogFile

   '-- better error handling - 2019-05-08
   On Error Resume Next
   Close  '-- MS HELP: If you omit filenumberlist, all active files opened by the Open statement are closed. - 2019-05-08
   On Error GoTo 0  '-- terminate any further error handling here
End Sub

Чаще всего я получал ошибку 70, когда запускался первым после открытия XLSM, когда файл журнала еще не существовал и IDE закрывалась.

...