【问题标题】:VBScript - How to make program wait until process has finished?VBScript - 如何让程序等到进程完成?
【发布时间】:2012-04-23 11:09:57
【问题描述】:

我在与 VBA/Excel 宏和 HTA 一起使用的 VBScript 中遇到问题。问题只是 VBScript,我还有其他两个组件,即 VBA 宏和 HTA 前端工作正常。但在我解释问题之前,我想为了你帮助我,我必须帮助你理解VBScript的上下文。

因此,基本上所有组件(VBScript、VBA 宏和 HTA)都是我正在构建的工具的一部分,用于自动化一些手动杂务。它几乎是这样的:

A - HTA

~~~~~~~~~~~~

  1. 用户从 HTA/GUI 中选择一些文件。
  2. 在 HTA 的 HTML 中,“SCRIPT”标签中有一些 VBScript,它将用户 4 个输入文件作为参数传递给 VBScript(由 WScript.exe 执行 - 为了清楚起见,您可以参考注释 #1)
  3. 脚本,我们从现在开始将其称为 myScript.vbs,然后处理 4 个参数,其中 3 个是特定文件,第 4 个是包含多个文件的路径/文件夹位置 - (为清楚起见,另请参见注释 #2)

B - myScript.vbs

~~~~~~~~~~~~

  1. myScript.vbs 打开前 3 个参数,它们是 Excel 文件。其中之一是包含我的 VBA 宏的 *.xlsm 文件。
  2. myScript.vbs 然后使用第 4 个参数,它是包含多个文件的文件夹的 PATH,并将其分配给一个变量,以便在调用 GetFolder 时传递给 FileSystemObject 对象,即

    ... 'Other code here, irrelevant for this post
    Dim FSO, FLD, strFolder
    ... 'Other code here, irrelevant for this post
    arg4 = args.Item(3)
    strFolder = arg4
    Set FSO = CreateObject("Scripting.FileSystemObject"
    'Get a reference to the folder you want to search
    Set FLD = FSO.GetFolder(strFolder)
    ...
    
  3. 从这里我创建一个循环,以便我可以按顺序打开文件夹中的文件 然后运行我的宏,即

    ...
    Dim strWB4, strMyMacro
    strMyMacro = "Sheet1.my_macro_name"
    
    'loop through the folder and get the file names
    For Each Fil In FLD.Files
    
        Set x4WB = x1.Workbooks.Open(Fil)
    x4WB.Application.Visible = True
    
    x1.Run strMyMacro
    
    x4WB.close
    Next 
    ...
    

请注意,当前 3 个 Excel 文件打开时(由循环之前的代码控制,这里没有显示,因为我对那部分没有问题)我必须保持它们打开。

文件夹中的文件(作为第四个参数传递)必须按顺序打开和关闭。但是在打开和关闭之间,我需要 VBA/宏(在之前打开的 3 个 Excel 文件之一中编写)每次运行循环迭代并从文件夹中打开一个新文件(我希望你关注 - 如果没有,请告诉我 :) )。

我遇到的问题是文件夹中的文件打开和关闭,打开和关闭,n 次(n = 文件夹中的文件数,自然)而不等待宏运行。这不是我想要的。我在“x1.Run strMyMacro”语句后延迟了 10 秒尝试了 WScript.sleep 语句,但无济于事。

有什么想法吗?

谢谢, 资历。

注意事项:

1 - 为简单起见,如下所示:

    strCMD = cmd /c C:\windows\system32\wscript.exe myScript.vbs <arg1> <arg2> <arg3> <arg4>
    'FYI - This is run by creating a WShell object, wsObj, and using the .run method, i.e. WShell.run(strCMD)

2 HTA 使用一段 JavaScript 去除用户的第 4 个输入文件(HTML:INPUT TYPE="file")并将其传递给 HTA 中的 VBScript。这让我解决了无法在 HTML 中专门选择文件夹的问题。

【问题讨论】:

  • 能否将x4WB.close 添加到 VBA 宏的末尾而不是 VBScript 中?
  • @oraclecertifiedprofessional:稍后我将与其他参考资料一起试一试。谢谢。

标签: vba vbscript excel excel-2010


【解决方案1】:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process")
objWMIService.Create "notepad.exe", null, null, intProcessID
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colMonitoredProcesses = objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceDeletionEvent Within 1 Where TargetInstance ISA 'Win32_Process'")
Do Until i = 1
    Set objLatestProcess = colMonitoredProcesses.NextEvent
    If objLatestProcess.TargetInstance.ProcessID = intProcessID Then
        i = 1
    End If
Loop
Wscript.Echo "Notepad has been terminated."

【讨论】:

    【解决方案2】:

    您需要告诉运行等待该过程完成。比如:

    const DontWaitUntilFinished = false, ShowWindow = 1, DontShowWindow = 0, WaitUntilFinished = true
    set oShell = WScript.CreateObject("WScript.Shell")
    command = "cmd /c C:\windows\system32\wscript.exe <path>\myScript.vbs " & args
    oShell.Run command, DontShowWindow, WaitUntilFinished
    

    在脚本本身中,像这样启动 Excel。调试开始时可见:

    File = "c:\test\myfile.xls"
    oShell.run """C:\Program Files\Microsoft Office\Office14\EXCEL.EXE"" " & File, 1, true
    

    【讨论】:

    • 也许我误解了这个问题,但文件循环在 vbs 内,因此上述方法不能用于使脚本在 x4WB.Close 之后等待 :) 但是就像我说的那样,我可以误会了……
    • @peter:嗨,彼得,我想你可能误解了。你有你的“命令”变量,然后你将它传递给你的 WScript 对象,我已经在我的 HTA 中完成了。然后我的 myScript.vbs 接管,我在这个脚本中进行所有 Excel 处理。不过,我已经在 myScript.vbs 中尝试了您的想法,方法是:Dim WshShell Set WshShell = CreateObject("WScript.Shell") WshShell.run "C:\Program Files\Microsoft Office\Office14\EXCEL.exe" &amp; " " &amp; Fil, 0, true 但这会返回一个 VBScript 错误,指出无法找到该文件...?
    • 除了我在空间不足时的评论之外,我还测试了我传递给 Excel 的字符串,以通过在 MsgBox 中打印它来测试它是否是错误字符串。但是,MsgBox 显示我正在将文件的字符串正确地传递给 Excel。我不明白还有什么问题。
    • 对此感到抱歉,但请始终在命令中提供完整路径,否则您不知道脚本试图从哪里获取它,那么您的 Fil 变量是完整路径吗?在控制台中尝试完整的命令行
    • @peter:是的,我已经从 cmd 提示符处完成了,它可以很好地打开文件。我会再试一次...敬请期待...
    【解决方案3】:

    大概是这样的吧? (未测试

    Sub Sample()
        Dim strWB4, strMyMacro
        strMyMacro = "Sheet1.my_macro_name"
    
        '
        '~~> Rest of Code
        '
    
        'loop through the folder and get the file names
        For Each Fil In FLD.Files
            Set x4WB = x1.Workbooks.Open(Fil)
            x4WB.Application.Visible = True
    
            x1.Run strMyMacro
    
            x4WB.Close
    
            Do Until IsWorkBookOpen(Fil) = False
                DoEvents
            Loop
        Next
    
        '
        '~~> Rest of Code
        '
    End Sub
    
    '~~> Function to check if the file is open
    Function IsWorkBookOpen(FileName As String)
        Dim ff As Long, ErrNo As Long
    
        On Error Resume Next
        ff = FreeFile()
        Open FileName For Input Lock Read As #ff
        Close ff
        ErrNo = Err
        On Error GoTo 0
    
        Select Case ErrNo
        Case 0:    IsWorkBookOpen = False
        Case 70:   IsWorkBookOpen = True
        Case Else: Error ErrNo
        End Select
    End Function
    

    【讨论】:

      【解决方案4】:

      这可能无法具体回答您的长 3 部分问题,但该线程很旧,我在今天搜索时发现了这个。这是一种更短的方法:“等到进程完成。”如果你知道进程的名称如“EXCEL.EXE”

      strProcess = "EXCEL.EXE"    
      Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
      Set colProcesses = objWMIService.ExecQuery ("Select * from Win32_Process Where Name = '"& strProcess &"'")
      Do While colProcesses.Count > 0
          Set colProcesses = objWMIService.ExecQuery ("Select * from Win32_Process Where Name = '"& strProcess &"'")
          Wscript.Sleep(1000) 'Sleep 1 second
         'msgbox colProcesses.count 'optional to show the loop works
      Loop
      

      归功于:http://crimsonshift.com/scripting-check-if-process-or-program-is-running-and-start-it/

      【讨论】:

      • 这是真的,但完全错过了这个问题。你可以使用 sleep 1 秒,但是如果这个过程需要超过 1 秒呢?你不知道要花多少钱,所以没用……
      • 这不是没用的。再看一下代码。睡眠只是为了减少查询次数,即每秒 1 次,并避免“忙循环”。程序会一直卡在循环中,直到进程结束。
      • 好的,知道了。谢谢:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-17
      • 1970-01-01
      • 1970-01-01
      • 2019-10-17
      • 2017-01-04
      • 1970-01-01
      • 2017-07-09
      相关资源
      最近更新 更多