Jump to content

Event-based scripting with the windows shell COM object


Recommended Posts

I want to listen for certain windows events like window open/closed. After reading the help I think I need to use ObjCreate('shell.application') and ObjEvent with that object to create/register a listener. The problem is I don't know what interface or events (i.e. the specific event names) are available for the listener. I tried searching MSDN but it is a labyrinth and I'm not that familiar with the programming frameworks/models used by Windows, and all the examples seem to refer to compiled code using .NET or some other api.

Can any1 point me in the right direction? Also is using COM objects considered the 'modern' way to do this, or should I be using some other framework/resources?

Link to comment
Share on other sites

@spudw2k I want to listen to events of an external app. So in the meantime I found winapi's shellhookex(), with shellproc but I can't seem to trigger it when I create new windows after running the script.

 

#include <MsgBoxConstants.au3>
#include <StructureConstants.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>

Global $g_hHook

Example()

Func Example()
    OnAutoItExitRegister("Cleanup")   

    $pcallback = DllCallbackGetPtr(DllCallbackRegister("MyCallback", "long", "int;wparam;lparam"));$WM_SHELL types
    $g_hHook = _WinAPI_SetWindowsHookEx($WH_SHELL, $pcallback, _WinAPI_GetModuleHandle(0))

    MsgBox($MB_SYSTEMMODAL, "", "Click OK, then in notepad type..." & _
            @CRLF & @CRLF & "Jon" & @CRLF & "AutoIt" & @CRLF & @CRLF & "Press Esc to exit script")

    Run("notepad.exe")
    WinWait("[CLASS:Notepad]")
    WinActivate("[CLASS:Notepad]")

    While 1
        Sleep(10)
    WEnd
EndFunc   ;==>Example

Func EvaluateKey()
    
EndFunc   ;==>

; ===========================================================
; callback function
; ===========================================================
Func MyCallback($nCode, $wParam, $lParam)    ; never called
    msgbox(0,"Test","Test")
    If $nCode < 0 Then
        Return _WinAPI_CallNextHookEx($g_hHook, $nCode, $wParam, $lParam)
    EndIf
    If $nCode <> 1 Then
        msgbox(0,"Test","Test")
    EndIf

    Return _WinAPI_CallNextHookEx($g_hHook, $nCode, $wParam, $lParam)
EndFunc   ;==>_KeyProc

Func Cleanup()
    _WinAPI_UnhookWindowsHookEx($g_hHook)
    ;DllCallbackFree($g_hStub_KeyProc)
EndFunc   ;==>Cleanup

 

Edited by jiggunjer
added example script
Link to comment
Share on other sites

Hello. try something like this.

#include <WinAPIProc.au3>
#include <WinAPI.au3>
#include <WinAPISys.au3>
#include <Array.au3>
#include <GUIConstants.au3>
#include <APISysConstants.au3>


Global $hGUI = GUICreate("GUI")

GUISetState(@SW_SHOW, $hGUI)

GUIRegisterMsg(_WinAPI_RegisterWindowMessage('SHELLHOOK'), 'WM_SHELLHOOK')
_WinAPI_RegisterShellHookWindow($hGUI)



Run("notepad.exe")

Local $nMsg=0
While 1
    $nMsg = GUIGetMsg()
    Select
        Case $nMsg = $GUI_EVENT_CLOSE
            ExitLoop
    EndSelect

WEnd

_WinAPI_DeregisterShellHookWindow($hGUI)
Exit

Func WM_SHELLHOOK($hWnd, $iMsg, $wParam, $lParam)
    #forceref $iMsg
    Switch $wParam
        Case $HSHELL_WINDOWDESTROYED
            ConsoleWrite('Destroyed: ' & @CRLF & _
                    @TAB & 'PID: ' & WinGetProcess($lParam) & @CRLF & _ ; This will be -1.
                    @TAB & 'ClassName: ' & _WinAPI_GetClassName($lParam) & @CRLF & _ ; This will be empty.
                    @TAB & 'hWnd: ' & $lParam & @CRLF) ; This will be the handle of the window closed.
        Case $HSHELL_WINDOWCREATED
            ConsoleWrite('Created: ' & @CRLF & _
                    @TAB & 'PID: ' & WinGetProcess($lParam) & @CRLF & _
                    @TAB & 'ClassName: ' & _WinAPI_GetClassName($lParam) & @CRLF & _
                    @TAB & 'hWnd: ' & $lParam & @CRLF) ; This will be the handle of the window closed.
    EndSwitch
EndFunc   ;==>WM_SHELLHOOK

 

Saludos

Link to comment
Share on other sites

@Danyfirex Thanks but that raises at least 3 questions for me:

- Do I always need to use an AutoIt GUI to get the shell hook stuff?

- How do you know the parameters WM_SHELLHOOK takes, I can't find it on MSDN :(

- Don't you need to call the next hook in the chain after your callback?

Link to comment
Share on other sites

Yes You need a handle to a window. But you can create a dummy GUI. Keep it hidden.

Parameters are here https://msdn.microsoft.com/en-us/library/windows/desktop/ms644989(v=vs.85).aspx

No need Next Hook Call.

 

Saludos

Edited by Danyfirex
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...