Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

wsh

vbscript

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 window is active.

Note* I am not in a condition to use the alternative i.e activating the desired window before invoking sendkeys.

Any help is appreciated.

like image 498
Indrajeet Kumar mishra Avatar asked Oct 13 '14 13:10

Indrajeet Kumar mishra


3 Answers

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#?

like image 136
Helen Avatar answered Nov 04 '22 11:11

Helen


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.

like image 4
triggerthefeline Avatar answered Nov 04 '22 10:11

triggerthefeline


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
like image 2
triggeradeadcat Avatar answered Nov 04 '22 09:11

triggeradeadcat