Vb6 FileSystemObject调用正在执行。。。太快了?

Vb6 FileSystemObject调用正在执行。。。太快了?,vb6,Vb6,我正在开发一个“就地”修改文件的系统。使用引号是因为实际过程如下所示: 使用临时名称将修改写入新文件 移动扩展名为“.bak”的源文件(重命名) 将新文件移动(重命名)到源文件的名称 删除中间文件 此过程涉及使用来修改PDF文件。问题是,当我运行代码时,它有时会在过程中的某个点“跳过”一个步骤,有时会导致与前面某个步骤相关的错误没有发生 当我使用调试器逐步完成代码时,每次都可以正常工作。如果我在每个文件系统调用之间添加以下代码,它也可以工作 Public Sub Wait(seconds As

我正在开发一个“就地”修改文件的系统。使用引号是因为实际过程如下所示:

  • 使用临时名称将修改写入新文件
  • 移动扩展名为“.bak”的源文件(重命名)
  • 将新文件移动(重命名)到源文件的名称
  • 删除中间文件
  • 此过程涉及使用来修改PDF文件。问题是,当我运行代码时,它有时会在过程中的某个点“跳过”一个步骤,有时会导致与前面某个步骤相关的错误没有发生

    当我使用调试器逐步完成代码时,每次都可以正常工作。如果我在每个文件系统调用之间添加以下代码,它也可以工作

    Public Sub Wait(seconds As Integer)
    Dim dTimer As Double
    
        dTimer = Timer
        Do While Timer < dTimer + seconds
            DoEvents
        Loop
    
    End Sub
    

    我怀疑您的问题是shell在启动(或未能启动)进程后立即返回。我建议使用API调用CreateProcess,并至少等待一段时间,让流程返回结果。我用得够多了,我已经为此创建了一个方法。我有时需要等待几个小时才能运行生成的程序,所以我的方法使用无限等待。因为您只希望等待几秒钟,所以我会修改等待时间以适合您自己。等待时间就是它在失败之前等待的时间。否则,它会在生成的进程完成后立即返回

    Private Type STARTUPINFO
       cb As Long
       lpReserved As String
       lpDesktop As String
       lpTitle As String
       dwX As Long
       dwY As Long
       dwXSize As Long
       dwYSize As Long
       dwXCountChars As Long
       dwYCountChars As Long
       dwFillAttribute As Long
       dwFlags As Long
       wShowWindow As Integer
       cbReserved2 As Integer
       lpReserved2 As Long
       hStdInput As Long
       hStdOutput As Long
       hStdError As Long
    End Type
    
    Private Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadID As Long
    End Type
    
    Private Declare Function WaitForSingleObjectEx Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long, ByVal bAlertable As Long) As Long
    Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Private Declare Function CreateProcessA Lib "kernel32" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, ByVal _
        lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
        ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
        ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _
        lpStartupInfo As STARTUPINFO, lpProcessInformation As _
        PROCESS_INFORMATION) As Long
    
    Private Const INFINITE = -1&
    Private Const NORMAL_PRIORITY_CLASS = &H20&
    Private Const SW_SHOW = 5
    Private Const STARTF_USESHOWWINDOW = &H1
    
    Public Function ExecAndWait(ByVal Program As String, Optional ByVal Parms As Variant, _
                                  Optional ByVal hStdOutput As Long) As Long
       Dim proc As PROCESS_INFORMATION
       Dim start As STARTUPINFO
       Dim RET As Long
       Dim strCommandLine As String
       Dim lExitCode As Long
       Dim lWaitTime As Long
    
       On Error GoTo errExecAndWait
    
       ' quote the commandline and parameters if necessary
       If InStr(Program, """") = 0 Then ' if quotes are found assume that any necessary quoting has already been done
          If InStr(Program, " ") > 0 Then
             'do not include any Program parms (" /parm" in the quotes
             If InStr(Program, " /") > 0 Then
                strCommandLine = Chr$(34) & Left$(Program, InStr(Program, " /") - 1) & Chr$(34) & Right$(Program, Len(Program) - InStr(Program, " /") + 1)
             Else
                strCommandLine = Chr$(34) & Program & Chr$(34)
             End If
          Else
             strCommandLine = Program
          End If
       Else
          strCommandLine = Program
       End If
    
       If Not IsMissing(Parms) Then
          If Len(Parms) > 0 Then
             If InStr(Program, """") = 0 Then ' if quotes are found assume that any necessary quoting has already been done
                If InStr(Parms, " ") > 0 Then
                   strCommandLine = strCommandLine & " " & Chr$(34) & Parms & Chr$(34)
                Else
                   strCommandLine = strCommandLine & " " & Parms
                End If
             Else
                strCommandLine = strCommandLine & " " & Parms
             End If
          End If
       End If
    
       start.dwFlags = STARTF_USESHOWWINDOW
       start.wShowWindow = SW_SHOW
    
       lWaitTime = INFINITE    'forever
       ' Initialize the STARTUPINFO structure:
       start.cb = Len(start)
    
       ' Start the shelled application:
       RET& = CreateProcessA(vbNullString, strCommandLine, 0&, 0&, 1&, _
                            NORMAL_PRIORITY_CLASS, 0&, vbNullString, start, proc)
       ' change the return value to 0 if the dll returned other than 0 else return the dll error
       If RET& = 0 Then   'error
          ExecAndWait = 0
          Err.Raise Err.LastDllError, strCommandLine, Translate_DLL_Error(Err.LastDllError)
       Else
          Call Sleep(2000)  ' Wait for the shelled application to get going:
          RET& = WaitForSingleObjectEx(proc.hProcess, lWaitTime, False)
          RET& = GetExitCodeProcess(proc.hProcess, lExitCode)
          ExecAndWait = RET&
          RET& = CloseHandle(proc.hProcess)
          RET& = CloseHandle(proc.hThread)
       End If
    
       Exit Function
    
    errExecAndWait:
        Err.Raise Err.Number, Err.Source & ":ExecAndWait", Err.Description
    
    End Function
    

    我怀疑您的问题是shell在启动(或未能启动)进程后立即返回。我建议使用API调用CreateProcess,并至少等待一段时间,让流程返回结果。我用得够多了,我已经为此创建了一个方法。我有时需要等待几个小时才能运行生成的程序,所以我的方法使用无限等待。因为您只希望等待几秒钟,所以我会修改等待时间以适合您自己。等待时间就是它在失败之前等待的时间。否则,它会在生成的进程完成后立即返回

    Private Type STARTUPINFO
       cb As Long
       lpReserved As String
       lpDesktop As String
       lpTitle As String
       dwX As Long
       dwY As Long
       dwXSize As Long
       dwYSize As Long
       dwXCountChars As Long
       dwYCountChars As Long
       dwFillAttribute As Long
       dwFlags As Long
       wShowWindow As Integer
       cbReserved2 As Integer
       lpReserved2 As Long
       hStdInput As Long
       hStdOutput As Long
       hStdError As Long
    End Type
    
    Private Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadID As Long
    End Type
    
    Private Declare Function WaitForSingleObjectEx Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long, ByVal bAlertable As Long) As Long
    Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Private Declare Function CreateProcessA Lib "kernel32" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, ByVal _
        lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
        ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
        ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _
        lpStartupInfo As STARTUPINFO, lpProcessInformation As _
        PROCESS_INFORMATION) As Long
    
    Private Const INFINITE = -1&
    Private Const NORMAL_PRIORITY_CLASS = &H20&
    Private Const SW_SHOW = 5
    Private Const STARTF_USESHOWWINDOW = &H1
    
    Public Function ExecAndWait(ByVal Program As String, Optional ByVal Parms As Variant, _
                                  Optional ByVal hStdOutput As Long) As Long
       Dim proc As PROCESS_INFORMATION
       Dim start As STARTUPINFO
       Dim RET As Long
       Dim strCommandLine As String
       Dim lExitCode As Long
       Dim lWaitTime As Long
    
       On Error GoTo errExecAndWait
    
       ' quote the commandline and parameters if necessary
       If InStr(Program, """") = 0 Then ' if quotes are found assume that any necessary quoting has already been done
          If InStr(Program, " ") > 0 Then
             'do not include any Program parms (" /parm" in the quotes
             If InStr(Program, " /") > 0 Then
                strCommandLine = Chr$(34) & Left$(Program, InStr(Program, " /") - 1) & Chr$(34) & Right$(Program, Len(Program) - InStr(Program, " /") + 1)
             Else
                strCommandLine = Chr$(34) & Program & Chr$(34)
             End If
          Else
             strCommandLine = Program
          End If
       Else
          strCommandLine = Program
       End If
    
       If Not IsMissing(Parms) Then
          If Len(Parms) > 0 Then
             If InStr(Program, """") = 0 Then ' if quotes are found assume that any necessary quoting has already been done
                If InStr(Parms, " ") > 0 Then
                   strCommandLine = strCommandLine & " " & Chr$(34) & Parms & Chr$(34)
                Else
                   strCommandLine = strCommandLine & " " & Parms
                End If
             Else
                strCommandLine = strCommandLine & " " & Parms
             End If
          End If
       End If
    
       start.dwFlags = STARTF_USESHOWWINDOW
       start.wShowWindow = SW_SHOW
    
       lWaitTime = INFINITE    'forever
       ' Initialize the STARTUPINFO structure:
       start.cb = Len(start)
    
       ' Start the shelled application:
       RET& = CreateProcessA(vbNullString, strCommandLine, 0&, 0&, 1&, _
                            NORMAL_PRIORITY_CLASS, 0&, vbNullString, start, proc)
       ' change the return value to 0 if the dll returned other than 0 else return the dll error
       If RET& = 0 Then   'error
          ExecAndWait = 0
          Err.Raise Err.LastDllError, strCommandLine, Translate_DLL_Error(Err.LastDllError)
       Else
          Call Sleep(2000)  ' Wait for the shelled application to get going:
          RET& = WaitForSingleObjectEx(proc.hProcess, lWaitTime, False)
          RET& = GetExitCodeProcess(proc.hProcess, lExitCode)
          ExecAndWait = RET&
          RET& = CloseHandle(proc.hProcess)
          RET& = CloseHandle(proc.hThread)
       End If
    
       Exit Function
    
    errExecAndWait:
        Err.Raise Err.Number, Err.Source & ":ExecAndWait", Err.Description
    
    End Function
    

    我怀疑您的问题是shell在启动(或未能启动)进程后立即返回。我建议使用API调用CreateProcess,并至少等待一段时间,让流程返回结果。我用得够多了,我已经为此创建了一个方法。我有时需要等待几个小时才能运行生成的程序,所以我的方法使用无限等待。因为您只希望等待几秒钟,所以我会修改等待时间以适合您自己。等待时间就是它在失败之前等待的时间。否则,它会在生成的进程完成后立即返回

    Private Type STARTUPINFO
       cb As Long
       lpReserved As String
       lpDesktop As String
       lpTitle As String
       dwX As Long
       dwY As Long
       dwXSize As Long
       dwYSize As Long
       dwXCountChars As Long
       dwYCountChars As Long
       dwFillAttribute As Long
       dwFlags As Long
       wShowWindow As Integer
       cbReserved2 As Integer
       lpReserved2 As Long
       hStdInput As Long
       hStdOutput As Long
       hStdError As Long
    End Type
    
    Private Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadID As Long
    End Type
    
    Private Declare Function WaitForSingleObjectEx Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long, ByVal bAlertable As Long) As Long
    Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Private Declare Function CreateProcessA Lib "kernel32" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, ByVal _
        lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
        ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
        ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _
        lpStartupInfo As STARTUPINFO, lpProcessInformation As _
        PROCESS_INFORMATION) As Long
    
    Private Const INFINITE = -1&
    Private Const NORMAL_PRIORITY_CLASS = &H20&
    Private Const SW_SHOW = 5
    Private Const STARTF_USESHOWWINDOW = &H1
    
    Public Function ExecAndWait(ByVal Program As String, Optional ByVal Parms As Variant, _
                                  Optional ByVal hStdOutput As Long) As Long
       Dim proc As PROCESS_INFORMATION
       Dim start As STARTUPINFO
       Dim RET As Long
       Dim strCommandLine As String
       Dim lExitCode As Long
       Dim lWaitTime As Long
    
       On Error GoTo errExecAndWait
    
       ' quote the commandline and parameters if necessary
       If InStr(Program, """") = 0 Then ' if quotes are found assume that any necessary quoting has already been done
          If InStr(Program, " ") > 0 Then
             'do not include any Program parms (" /parm" in the quotes
             If InStr(Program, " /") > 0 Then
                strCommandLine = Chr$(34) & Left$(Program, InStr(Program, " /") - 1) & Chr$(34) & Right$(Program, Len(Program) - InStr(Program, " /") + 1)
             Else
                strCommandLine = Chr$(34) & Program & Chr$(34)
             End If
          Else
             strCommandLine = Program
          End If
       Else
          strCommandLine = Program
       End If
    
       If Not IsMissing(Parms) Then
          If Len(Parms) > 0 Then
             If InStr(Program, """") = 0 Then ' if quotes are found assume that any necessary quoting has already been done
                If InStr(Parms, " ") > 0 Then
                   strCommandLine = strCommandLine & " " & Chr$(34) & Parms & Chr$(34)
                Else
                   strCommandLine = strCommandLine & " " & Parms
                End If
             Else
                strCommandLine = strCommandLine & " " & Parms
             End If
          End If
       End If
    
       start.dwFlags = STARTF_USESHOWWINDOW
       start.wShowWindow = SW_SHOW
    
       lWaitTime = INFINITE    'forever
       ' Initialize the STARTUPINFO structure:
       start.cb = Len(start)
    
       ' Start the shelled application:
       RET& = CreateProcessA(vbNullString, strCommandLine, 0&, 0&, 1&, _
                            NORMAL_PRIORITY_CLASS, 0&, vbNullString, start, proc)
       ' change the return value to 0 if the dll returned other than 0 else return the dll error
       If RET& = 0 Then   'error
          ExecAndWait = 0
          Err.Raise Err.LastDllError, strCommandLine, Translate_DLL_Error(Err.LastDllError)
       Else
          Call Sleep(2000)  ' Wait for the shelled application to get going:
          RET& = WaitForSingleObjectEx(proc.hProcess, lWaitTime, False)
          RET& = GetExitCodeProcess(proc.hProcess, lExitCode)
          ExecAndWait = RET&
          RET& = CloseHandle(proc.hProcess)
          RET& = CloseHandle(proc.hThread)
       End If
    
       Exit Function
    
    errExecAndWait:
        Err.Raise Err.Number, Err.Source & ":ExecAndWait", Err.Description
    
    End Function
    

    我怀疑您的问题是shell在启动(或未能启动)进程后立即返回。我建议使用API调用CreateProcess,并至少等待一段时间,让流程返回结果。我用得够多了,我已经为此创建了一个方法。我有时需要等待几个小时才能运行生成的程序,所以我的方法使用无限等待。因为您只希望等待几秒钟,所以我会修改等待时间以适合您自己。等待时间就是它在失败之前等待的时间。否则,它会在生成的进程完成后立即返回

    Private Type STARTUPINFO
       cb As Long
       lpReserved As String
       lpDesktop As String
       lpTitle As String
       dwX As Long
       dwY As Long
       dwXSize As Long
       dwYSize As Long
       dwXCountChars As Long
       dwYCountChars As Long
       dwFillAttribute As Long
       dwFlags As Long
       wShowWindow As Integer
       cbReserved2 As Integer
       lpReserved2 As Long
       hStdInput As Long
       hStdOutput As Long
       hStdError As Long
    End Type
    
    Private Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadID As Long
    End Type
    
    Private Declare Function WaitForSingleObjectEx Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long, ByVal bAlertable As Long) As Long
    Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Private Declare Function CreateProcessA Lib "kernel32" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, ByVal _
        lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
        ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
        ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _
        lpStartupInfo As STARTUPINFO, lpProcessInformation As _
        PROCESS_INFORMATION) As Long
    
    Private Const INFINITE = -1&
    Private Const NORMAL_PRIORITY_CLASS = &H20&
    Private Const SW_SHOW = 5
    Private Const STARTF_USESHOWWINDOW = &H1
    
    Public Function ExecAndWait(ByVal Program As String, Optional ByVal Parms As Variant, _
                                  Optional ByVal hStdOutput As Long) As Long
       Dim proc As PROCESS_INFORMATION
       Dim start As STARTUPINFO
       Dim RET As Long
       Dim strCommandLine As String
       Dim lExitCode As Long
       Dim lWaitTime As Long
    
       On Error GoTo errExecAndWait
    
       ' quote the commandline and parameters if necessary
       If InStr(Program, """") = 0 Then ' if quotes are found assume that any necessary quoting has already been done
          If InStr(Program, " ") > 0 Then
             'do not include any Program parms (" /parm" in the quotes
             If InStr(Program, " /") > 0 Then
                strCommandLine = Chr$(34) & Left$(Program, InStr(Program, " /") - 1) & Chr$(34) & Right$(Program, Len(Program) - InStr(Program, " /") + 1)
             Else
                strCommandLine = Chr$(34) & Program & Chr$(34)
             End If
          Else
             strCommandLine = Program
          End If
       Else
          strCommandLine = Program
       End If
    
       If Not IsMissing(Parms) Then
          If Len(Parms) > 0 Then
             If InStr(Program, """") = 0 Then ' if quotes are found assume that any necessary quoting has already been done
                If InStr(Parms, " ") > 0 Then
                   strCommandLine = strCommandLine & " " & Chr$(34) & Parms & Chr$(34)
                Else
                   strCommandLine = strCommandLine & " " & Parms
                End If
             Else
                strCommandLine = strCommandLine & " " & Parms
             End If
          End If
       End If
    
       start.dwFlags = STARTF_USESHOWWINDOW
       start.wShowWindow = SW_SHOW
    
       lWaitTime = INFINITE    'forever
       ' Initialize the STARTUPINFO structure:
       start.cb = Len(start)
    
       ' Start the shelled application:
       RET& = CreateProcessA(vbNullString, strCommandLine, 0&, 0&, 1&, _
                            NORMAL_PRIORITY_CLASS, 0&, vbNullString, start, proc)
       ' change the return value to 0 if the dll returned other than 0 else return the dll error
       If RET& = 0 Then   'error
          ExecAndWait = 0
          Err.Raise Err.LastDllError, strCommandLine, Translate_DLL_Error(Err.LastDllError)
       Else
          Call Sleep(2000)  ' Wait for the shelled application to get going:
          RET& = WaitForSingleObjectEx(proc.hProcess, lWaitTime, False)
          RET& = GetExitCodeProcess(proc.hProcess, lExitCode)
          ExecAndWait = RET&
          RET& = CloseHandle(proc.hProcess)
          RET& = CloseHandle(proc.hThread)
       End If
    
       Exit Function
    
    errExecAndWait:
        Err.Raise Err.Number, Err.Source & ":ExecAndWait", Err.Description
    
    End Function
    

    好吧,你说的有道理。我将对我正在使用的代码进行这些修改并报告。看起来这是可行的,我有几个不同的情况需要继续测试,但这看起来就是问题所在。谢谢好吧,你说的有道理。我将对我正在使用的代码进行这些修改并报告。看起来这是可行的,我有几个不同的情况需要继续测试,但这看起来就是问题所在。谢谢好吧,你说的有道理。我将对我正在使用的代码进行这些修改并报告。看起来这是可行的,我有几个不同的情况需要继续测试,但这看起来就是问题所在。谢谢好吧,你说的有道理。我将对我正在使用的代码进行这些修改并报告。看起来这是可行的,我有几个不同的情况需要继续测试,但这看起来就是问题所在。谢谢