【问题标题】:How to find the window Title of Active(foreground) window using Window Script Host如何使用窗口脚本宿主查找活动(前景)窗口的窗口标题
【发布时间】:2014-12-08 02:55:48
【问题描述】:

我想使用 Window Script Host(WSH) 查找当前处于活动状态(具有焦点)的窗口的标题,因为我希望我的 WSH 脚本仅在所需窗口处于活动状态时才发送键。

注意*我无法使用替代方法,即在调用 sendkeys 之前激活所需的窗口。

感谢任何帮助。

【问题讨论】:

    标签: vbscript wsh


    【解决方案1】:

    简答:你不能。至少要为相关的 Windows API 调用编写 COM 包装器。

    你不能只使用AppActivate 并检查结果吗?

    Set oShell = CreateObject("WScript.Shell")
    If oShell.AppActivate "Untitled - Notepad" Then
      oShell.SendKeys "Hello, world!"
    End If
    


    长答案: 要获取活动窗口标题,您需要调用 Windows API GetWindowText 函数并传递 GetForegroundWindow() 句柄。 VBScript 和 Windows Script Host 不支持 Windows API 调用,因此您需要围绕这些函数编写一个 COM 包装器,然后您可以在脚本中使用它。以下是示例:

    Get current active Window title in C

    How do I get the title of the current active window using c#?

    【讨论】:

    • 这很有用,尽管根据我正在运行的 VBS 版本,提供的 vbscript 在 AppActivateSendKeys 的 func 参数周围缺少 ()。 (没有它们我收到了语法错误)
    【解决方案2】:

    您可以使用 GetForegroundWindow 和 GetWindowText 创建一个 COM 对象。

    将以下行放入 wso.cls 中,然后在您的桌面上存储一个名为 wso 的文件夹。

    Imports System
    Imports System.Runtime.InteropServices
    Imports Microsoft.Win32
    
    Namespace WindowScriptingObject
    
        <Guid("7448E08D-ED0F-4E23-B528-91937BB41756"), _
        InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
       Public Interface _WindowScriptingObject
            <DispId(1)> Function ActiveWindow() As Integer
            <DispId(2)> Function WindowText(ByVal hWnd As Integer) As String
        End Interface
    
        <Guid("B146BF9E-78FC-4DB0-ABFE-9FF026B43E4D"), _
         ClassInterface(ClassInterfaceType.None), _
         ProgId("WindowScriptingObject")> Public Class WindowScriptingObject
            Implements _WindowScriptingObject
    
            Public WindowScriptingObject()
    
            Public Declare Auto Function GetForegroundWindow Lib "user32" Alias "GetForegroundWindow"() As Integer
            Public Declare Auto Function GetWindowText Lib "user32.dll" (ByVal hwnd As Int32, <Out()> ByVal lpString As System.Text.StringBuilder, ByVal cch As Int32) As Int32
            Public Function ActiveWindow() As Integer Implements _WindowScriptingObject.ActiveWindow
        ActiveWindow=GetForegroundWindow()
    
            End Function
    
            Public Function WindowText(hwnd as Integer) As String Implements _WindowScriptingObject.WindowText
        on error resume next
        Dim b As New System.Text.StringBuilder(ChrW(0), 512)
                    Dim ret = GetWindowText(hWnd, b, b.Capacity)
        WindowText = b.tostring
            End Function
    
    
        End Class
    
    End Namespace
    

    然后在名为 wso.bat 的同一文件夹中创建一个 bat 文件。

    "C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc.exe" /target:library /out:"%userprofile%\desktop\wso\wso.dll" "%userprofile%\desktop\wso\wso.cls" /verbose
    
    "C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm" /codebase "%userprofile%\desktop\wso\wso.dll" /tlb:"%userprofile%\desktop\wso\wso.tlb" /v
    
    If /i "%cmdcmdline:~0,6%"=="cmd /c" pause
    

    运行bat文件后在vbs中使用。

    Set wso=CreateObject("WindowScriptingObject")
    x = wso.ActiveWindow
    msgbox x, , "vbs"
    msgbox wso.windowtext(x), , "vbs"
    

    此处使用的 GUID 特定于该项目。不要将它们用于其他目的。

    更多关于我们正在做什么的信息

    http://social.msdn.microsoft.com/Forums/en-US/adcae113-4758-481a-a367-60d5d14d97d6/this-is-how-to-turn-vbs-and-js-files-into-exe-files-from-the-command-line-without-third-party-tools?forum=scripting

    如果您必须按用户安装,请使用 regasm 创建一个 regfile 而不是注册它。然后将所有对HKCR 的引用更改为HKCU\Software\Classes。然后与regedit /s regfile.reg合并。

    要移动文件,您需要在其新位置运行 Regasm。请参阅 bat 文件中的命令。

    为了准确的历史目的,当然会在 MS 网站上摆姿势。

    【讨论】:

    • 运行 vbs 文件时,它给出 wso.vbs(1, 1) Microsoft VBScript 运行时错误:Activ eX 组件无法创建对象:'WindowScriptingObject'
    • @IndrajeetKumarmishra 以上解决方案工作正常!确保使用 SysWOW64 文件夹中的 64 位 wscript.exe 运行脚本。
    【解决方案3】:

    这是一个更新版本供使用。以前的答案是它工作所需的最低限度。

    这也替换了此处的答案 (appactivate between multiple internet explorer instances),因为它不适用于 Windows 7 及更高版本,因为 sendmail 是这些操作系统上的保留名称。

    Imports System
    Imports System.Runtime.InteropServices
    Imports Microsoft.Win32
    
    Namespace WindowScriptingObject
    
        <Guid("7448E08D-ED0F-4E23-B528-91937BB41756"), _
        InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
       Public Interface _WindowScriptingObject
            <DispId(1)> Function ActiveWindow() As UInteger
            <DispId(2)> Function WindowText(ByVal hWnd As UInteger) As String
            <DispId(3)> Function WindowPID(ByVal hWnd As UInteger) As UInteger
        End Interface
    
        <Guid("B146BF9E-78FC-4DB0-ABFE-9FF026B43E4D"), _
         ClassInterface(ClassInterfaceType.None), _
         ProgId("WindowScriptingObject")> Public Class WindowScriptingObject
            Implements _WindowScriptingObject
    
            Public WindowScriptingObject()
    
            Public Declare Auto Function GetForegroundWindow Lib "user32" Alias "GetForegroundWindow"() As UInteger
            Public Declare Auto Function GetWindowText Lib "user32.dll" (ByVal hwnd As Int32, <Out()> ByVal lpString As System.Text.StringBuilder, ByVal cch As Int32) As Int32
            Public Declare Auto Function GetWindowThreadProcessId Lib "user32" Alias "GetWindowThreadProcessId" (ByVal hwnd As UInteger, ByRef lpdwProcessId As UInteger) As UInteger
    
            Public Function ActiveWindow() As UInteger Implements _WindowScriptingObject.ActiveWindow
        ActiveWindow = GetForegroundWindow()
        If err.lastdllerror <> 0 then
            Dim tmp as uinteger = err.lastdllerror and &h80070000
            err.raise(tmp,  "WindowSystemObject.GetForegroundWindow", "Type net helpmsg " & err.lastdllerror & " in a command prompt for help")
            Exit Function
        End If
            End Function
    
            Public Function WindowText(hwnd as UInteger) As String Implements _WindowScriptingObject.WindowText
        Dim b As New System.Text.StringBuilder(ChrW(0), 512)
                    Dim ret as uinteger = GetWindowText(hWnd, b, b.Capacity)
        If err.lastdllerror <> 0 then
            Dim tmp as uinteger = err.lastdllerror and &h80070000
            WindowText = ""
            err.raise(tmp,  "WindowSystemObject.GetWindowText", "Type net helpmsg " & err.lastdllerror & " in a command prompt for help")
            Exit Function
        End If
        WindowText = b.tostring
            End Function
    
            Public Function WindowPID(HWnd as UInteger) As UInteger Implements _WindowScriptingObject.WindowPID 
        Dim X as UInteger
        Dim M as UInteger = 1
        X=GetWindowThreadProcessID(HWnd,M)
        If err.lastdllerror <> 0 then
            Dim tmp as uinteger = err.lastdllerror and &h80070000
            WindowPID = 0
            err.raise(tmp,  "WindowSystemObject.GetWindowThreadProcessID", "Type net helpmsg " & err.lastdllerror & " in a command prompt for help")
            Exit Function
        End If  
        WindowPID = M
            End Function
    
    
        End Class
    
    End Namespace
    

    【讨论】:

      【解决方案4】:

      批处理文件必须无错误地运行。

      第一个命令从 cls 文件生成 dll。它会说编译成功。它希望文件位于您桌面上名为 wso 的文件夹中。

      第二个命令在每台机器上注册它。您必须是管理员才能执行此操作。如果您不是管理员,则必须生成一个 reg 文件,并将所有 HKEY_CURRENT_ROOT 更改为 HKEY_CURRENT_USER\Software\Classes。

      生成一个regfile

      "C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm" /regfile:"%userprofile%\desktop\wso\wso.reg" "%userprofile%\desktop\wso\wso.dll"  /v
      

      编辑 wso.reg 后将其与

      regedit /m "%userprofile%\desktop\wso\wso.reg"
      

      你需要读取命令的结果。

      这是运行的脚本,显示 hwnd、PID 和窗口标题(和错误代码)。请注意,当脚本启动时,大约两秒钟内没有活动窗口(Windows 正在等待您的程序创建一个以使其处于活动状态。它只等待 2 秒钟)。通常在程序启动时,但也有其他时间,短时间内不会有活动窗口。你必须抓住这个。这是一个脚本。

      On error resume next
      Set wso=CreateObject("WindowScriptingObject")
      Do
      x = wso.ActiveWindow
          wscript.echo x
      
          wscript.echo wso.windowtext(x)
      
          wscript.echo (err.number)
          err.clear
          wscript.echo wso.windowpid(x)
      
          wscript.echo (err.number)
          err.clear
          wscript.sleep 1000
      Loop
      

      这就是在命令提示符下使用 CScript 运行时的样子。

      C:\Users\User>cscript "C:\Users\User\Desktop\ActiveWindow.vbs"
      Microsoft (R) Windows Script Host Version 5.7
      Copyright (C) Microsoft Corporation. All rights reserved.
      
      
      -2147024809
      -2147024809
      3344366
      Administrator: Command Prompt - cscript  "C:\Users\User\Desktop\ActiveWin
      dow.vbs"
      0
      972
      0
      3344366
      Administrator: Command Prompt - cscript  "C:\Users\User\Desktop\ActiveWin
      dow.vbs"
      0
      972
      0
      3344366
      1312854
      vbscript - How to find the window Title of Active(foreground) window using Windo
      w Script Host - - Windows Internet Explorer
      0
      4724
      0
      1312854
      vbscript - How to find the window Title of Active(foreground) window using Windo
      w Script Host - - Windows Internet Explorer
      0
      4724
      0
      3344366
      Administrator: Command Prompt - cscript  "C:\Users\User\Desktop\ActiveWin
      dow.vbs"
      0
      972
      0
      ^C
      C:\Users\User>
      

      ----编辑----

      从错误消息中对象名称的有趣间距从网页粘贴时,您似乎遇到了记事本错误。

      如果使用记事本编写,请复制并粘贴到写字板中以检查换行符。记事本完全忽略并隐藏回车,但其他程序不会。记事本只查找换行符。如果处理基于浏览器的文档(例如网页和帮助系统),有时会在记事本中不可见地插入回车。

      【讨论】:

      • 这是我运行bat文件时的输出
      猜你喜欢
      • 1970-01-01
      • 2011-04-25
      • 1970-01-01
      • 2010-10-05
      • 1970-01-01
      • 2018-04-19
      • 1970-01-01
      • 2010-10-25
      • 1970-01-01
      相关资源
      最近更新 更多