How to find the window Title of Active(foreground) window using WindowScript Host

后端 未结 4 598
温柔的废话
温柔的废话 2020-11-30 11:56

I want to find the title of the window which is currently active(having focus) using Window Script Host(WSH) because I want my WSH script to Sendkeys only If the desired win

相关标签:
4条回答
  • 2020-11-30 12:22

    You can make a COM object with GetForegroundWindow and GetWindowText.

    Put following lines into wso.cls and store is a folder called wso on your desktop.

    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
    

    Then create a bat file in same folder called wso.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
    

    To use in vbs after running bat file.

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

    The GUIDs used here are specific to this project. Do not use them for other purposes.

    More info on what we are doing

    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

    If you must do a per user install, use regasm to make a regfile instead of registering it. Then change all references to HKCR to HKCU\Software\Classes. Then merge with regedit /s regfile.reg.

    To move the file you need to run Regasm on it in it's new location. See command in bat file.

    Will be posed at MS site of course for accurate historical purposes.

    0 讨论(0)
  • 2020-11-30 12:25

    The batch file has to run without errors.

    The first command makes the dll from the cls file. It will say Compilation Sucessfull. It expects the files to be in a folder called wso on your desktop.

    The second command registers it per machine. You must be an admin to do this. If you are not an admin then you must generate a reg file, and change all HKEY_CURRENT_ROOT to HKEY_CURRENT_USER\Software\Classes.

    To generate a regfile

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

    After editing wso.reg merge it with

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

    And you need to read the results of the commands.

    Here is the script running showing hwnd, PID, and window title (and error code). Note how when script starts there is no active window for about two seconds (windows is waiting for your program to create one for it to make active. It only waits 2 seconds). Usually at program starts, but also other times, for short periods there will be no active window. You must trap this. Here's a script that does.

    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
    

    And this is what it looks like when run with CScript in a command prompt.

    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>
    

    ----EDIT----

    It's looks like you've been hit by a notepad bug when pasting from web pages from the funny spacing of the object name in the error message.

    If using notepad to write it copy and paste into wordpad to check line breaks. Notepad totally ignores and hides carriage returns but other programs don't. Notepad only looks for line feeds. If coping from browser based documentation such as web pages and help systems sometimes stray carriage returns get invisibly inserted in notepad.

    0 讨论(0)
  • 2020-11-30 12:39

    This is an updated version for use. Previous answer is minimun needed for it to work.

    This also replaces the answer here (appactivate between multiple internet explorer instances), as it didn't work for Windows 7 and later due to sendmail being a reserved name on those OSs.

    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
    
    0 讨论(0)
  • 2020-11-30 12:41

    Short answer: You can't. At least not without writing a COM wrapper for the relevant Windows API calls.

    Can't you just use AppActivate and check the result?

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


    Long answer: To get the active window title, you need to call the Windows API GetWindowText function and pass the GetForegroundWindow() handle. VBScript and Windows Script Host don't support Windows API calls, so you'll need to write a COM wrapper around these functions, that you can then use in your script. Here're examples:

    Get current active Window title in C

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

    0 讨论(0)
提交回复
热议问题