【问题标题】:Python or batch file to open multiple vbs files (vbs files open a program+file)Python或批处理文件打开多个vbs文件(vbs文件打开一个程序+文件)
【发布时间】:2016-10-15 07:47:34
【问题描述】:

我有多个 VBS 文件(每个文件打开一个不同的文件,同一个程序),我想打开它们而不需要全部点击。如果我使用我创建的 python 脚本并使用 Notepad++ 中的 NPPExec 执行,我可以让它们毫无问题地打开。我希望文件打开的方式(使用前面所述的方法)是打开程序+文件->敲击一些键盘击键->重复。我遇到的问题是,当我双击python文件时,它只会打开程序+第一个文件->执行键盘敲击,然后对于以下文件,它只会打开程序。我相当肯定这个问题是由于当 VBS 脚本通过击键时没有聚焦正确的窗口引起的,它们没有在正确的窗口上执行。我也有一个批处理文件,我也试过了,我也遇到了同样的问题。

打开程序+文件的VBS文件-->击键 我尝试过使用 App.Activate 没有运气

Dim objShell
Set objShell = WScript.CreateObject( "WScript.Shell" )
objShell.Run """C:\Program Files (x86)\Program\Program.exe""" & """C:\temp_folder\file.ext"""
objShell.AppActivate """C:\Program Files (x86)\Program\Program.exe"""
WScript.Sleep 3000
objShell.SendKeys "{TAB}"
objShell.SendKeys "{TAB}"
objShell.SendKeys "{UP}"
objShell.SendKeys "{TAB}"
objShell.SendKeys "{DOWN}"
objShell.SendKeys "{ENTER}"

打开多个 VBS 文件的 Python 代码 以我想要的方式工作,但前提是从 Notepad++ 和 NPPExec 运行 双击 python 脚本无法正常工作

import os
import time
import subprocess
alfs = []
for file in os.listdir(os.getcwd()):
    if file.endswith(".ext"):
        alfs.append(file)

for f, item in enumerate(alfs):
    subprocess.call('cmd /c %s'%alfs[f])    
    time.sleep(2)

批处理文件打开多个 VBS 文件 我正在通过双击运行批处理文件,结果类似于Python双击方法。

for /r "." %%a in (*.vbs) do %%~fa

我主要是拼凑我发现的代码,让它按我想要的方式工作。我对 Python 非常了解,但我对 VBS 和 Batch 完全陌生。

【问题讨论】:

    标签: python batch-file vbscript multiple-instances nppexec


    【解决方案1】:

    AppActivate Method参考:

    激活应用程序窗口。

    • 语法:object.AppActivate title
    • 参数:
      • 对象WshShell 对象。
      • title:指定要激活的应用程序。这可以是一个字符串,其中包含应用程序的标题(它出现在 标题栏)或应用程序的进程 ID

    确保提供给objShell.AppActivate 的字符串是Program.exe所需实例 的标题,或者是进程ID

    除了参考SendKeys Method,请阅读Sending Keystrokes to a Program。本文解释了 your any 脚本的根本不足 - 时间问题:

    您应该知道,向应用程序发送击键不是 自动化程序的最佳方法。如果你有一个 您的企业中需要自动化的应用程序,它没有 基于 COM 的对象模型,您可能会考虑这种技术。然而, 您应该首先检查是否存在其他方法进行自动化 那个特定的应用程序。

    虽然SendKeys可以有效地使用,但有几个潜力 这种方法的问题:

    • 脚本可能难以确定将击键发送到哪个窗口。
    • 由于应用程序在 GUI 模式下运行,用户可能会提前关闭应用程序。不幸的是,这不会终止 脚本,并且脚本最终可能会将击键发送到错误的 应用程序
    • 脚本可能难以与应用程序同步

    这个计时问题特别麻烦,只是因为脚本 运行速度往往比 GUI 应用程序快得多。

    使用AppActivate

    在向应用程序发送击键之前,您必须首先确保 应用程序正在运行并且焦点位于 应用程序(即应用程序运行在活动 窗户)。
    ...
    您可以定期将脚本置于循环中 调用 AppActivate 直到返回值为 True。那时, 应用程序已加载并准备接受击键。

    什么时候 该脚本正在确定要激活哪个应用程序,给定的 标题与屏幕上可见的每个窗口的标题进行比较。 如果 不存在完全匹配,AppActivate 方法将焦点设置为 标题以给定文本开头的第一个窗口。如果一个窗口 仍然找不到,标题字符串以结尾的第一个窗口 文本被赋予焦点。与前导和部分匹配 标题栏的尾随文本确保 AppActivate 与 显示当前名称的应用程序,例如记事本 标题栏上打开的文档。 (例如,当您第一次开始 Notepad,窗口标题是Untitled - Notepad,而不是Notepad。)

    (以上引用仅是我重点的摘要:太长,无法在此处引用整篇文章。)

    编辑

    让我们正视SendKeys 方法将击键发送到活动窗口sight unseen,因为实际上我们从来没有知道当前焦点所在的窗口。利用Run Method (Windows Script Host) 完整语法objShell.Run sCmdLine, 1, False 其中窗口样式1 的含义是

    • 1 激活并显示一个窗口。如果窗口被最小化或最大化,系统会将其恢复为原始大小并 位置。应用程序应该在显示时指定此标志 第一次打开窗户。

    使用下一个示例脚本进行测试(为更好理解而添加注释):

    option explicit
    On Error GoTo 0
    
    Dim objShell, sProgram, sTxtFile, sTxtPath, sCmdLine, sTxtExists
    Set objShell = WScript.CreateObject( "WScript.Shell" )
    
    sProgram = "C:\Windows\System32\notepad.exe" 
    sTxtFile = Replace( Wscript.ScriptName, ".vbs", ".txt", 1, -1, vbTextCompare)
    sTxtPath = CreateObject("Scripting.FileSystemObject").BuildPath( _
                 objShell.ExpandEnvironmentStrings("%temp%"), sTxtFile)
    sTxtExists = CreateObject("Scripting.FileSystemObject").FileExists(sTxtPath)
    
        ' delete file merely for testing and debugging to ensure that 
        '             `NOTEPAD` will ask whether create nonexistent file
    If sTxtExists Then CreateObject("Scripting.FileSystemObject").DeleteFile( sTxtPath)
    WScript.Sleep 500                       ' wait for deleting
    
    sCmdLine = """" & sProgram & """ """ & sTxtPath & """"
    objShell.Run sCmdLine, 1, False
                  '  this `1` activates currently launched notepad
                  '           and its possible initial dialogue takes focus
    WScript.Sleep 1000      ' hence, `AppActivate` is not necessary
    
                                      ' alternative to `DeleteFile( sTxtPath)`
    ' If NOT sTxtExists Then          ' answer initial dialogue only if necessary  
        objShell.SendKeys "{TAB}"
        WScript.Sleep 100
        objShell.SendKeys "{TAB}"
        WScript.Sleep 100
        objShell.SendKeys "{TAB}"
        WScript.Sleep 100
        objShell.SendKeys "{ENTER}"
        WScript.Sleep 100
    ' End If
    objShell.SendKeys Cstr(Now)
    WScript.Sleep 100
    

    但是,您的启动器中还有另一个 timingfocus 问题。 Python time.sleep(2) 就足够了吗?当然不是:每个 vbs 脚本在第一个 SendKeys 之前等待 3 秒,但下一个脚本每 2 秒启动一次!

    等效的批处理脚本:Timeout command 将命令处理器暂停指定的秒数。
    尾随1>NUL hides output倒计时Waiting for X seconds, press CTRL+C to quit ...

    for /r "." %%a in (*.vbs) do (
        C:\Windows\System32\wscript.exe "%%~fa"
        timeout /T 5 /NOBREAK 1>NUL
    )
    

    5 秒就够了吗?

    【讨论】:

    • 我了解使用 SendKeys 的缺陷,但对于我打开的程序/文件,这是我能想到的唯一选择。我为 App.Activate 使用了正确的名称,但是在打开文件时会弹出一个对话框(在其中进行了击键),但是该对话框并未与程序分开调用。我试图弄清楚如何使用进程 ID,但在使用 Run 命令时找不到获取 ID # 的好方法,因为 Exec 命令不适用于我的情况(我认为)
    【解决方案2】:

    从 DOS BATCH 的角度来看,这应该对您有所帮助:

    FOR %%G IN (file1.txt file2.txt file3.txt) DO start notepad.exe %%G
    

    您可以进行必要的修改来处理 VBS 文件。

    【讨论】:

    • 我试过了,但我认为它不能解决我想要解决的问题。
    • 不是DOS,是windows批处理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    相关资源
    最近更新 更多