Jump to content

Global System Tray Hook


Recommended Posts

Hey guys....

Looking for some help here on hooking SysTray Balloon notifications of all applications. I already have the DLL, but I'm not that skilled in this part of AutoIt to handle the hooking. First though, some quick background.

This is in regards to the Snarl project extension called "SnarlTray", which is a work-in-progress to wrap Balloon Tips to the Snarl notification engine. First of all, it works - on 32-bit Windows. It is built in VB6 however, thus impossible to work on 64-bit Windows. I have ported the geOTraySpy.dll to an x64 DLL but that is not enough, since the SnarlTray extension itself is a VB6 project and therefore only 32-bit capable.

The point of this exercise is to actually get AutoIt to use this DLL (attached for your convenience) just to show a proof of concept for capturing these messages, something along the lines of intercepting WM_COPYDATA or something like that.

I hope someone can take the time to help out here and write up a script for all of us, because it will not only help the Snarl project but also provide some example code for AutoIt users :blink:

Here's the code I have so far:

ConsoleWrite ( "-----------------------" & @CRLF )
ConsoleWrite ( "[#] Opening " & @ScriptDir & "\geOTraySpy.dll..." & @CRLF )
$libGeotrayspy = DllOpen( @ScriptDir & "\geOTraySpy.dll" )
    If $libGeotrayspy = -1 Then ConsoleWrite ( "    [!] Fail!" & @CRLF )
ConsoleWrite ( "[#] Registering function 'SetTrayHook'..."& @CRLF )
$resGeotrayspyHook = DllCall( $libGeotrayspy, "BOOLEAN", "SetTrayHook", "str", "szServerName" )
    If @error Then ConsoleWrite ( "    [!] Fail!" & @CRLF )
ConsoleWrite ( "[#] Registering function 'UnsetTrayHook'..."& @CRLF )
$resGeotrayspyUnhook = DllCall( $libGeotrayspy, "BOOLEAN", "UnsetTrayHook" )
    If @error Then ConsoleWrite ( "    [!] Fail!" & @CRLF )
ConsoleWrite ( "[#] Registering function 'CopyIcon'..."& @CRLF )
$resCopyIcon = DllCall( "user32.dll", "long", "CopyIcon", "long", "hIcon" )
    If @error Then ConsoleWrite ( "    [!] Fail!" & @CRLF )

...and I have no idea what to do from here. Something to do with GUIRegisterMsg() perhaps?

Looking forward to any help that anyone can provide here! The DLL in question is attached below... I provided both the 32 and 64-bit versions in the ZIP file, make sure you use the x64 if you're on 64-bit (and will also need to run the x64 AutoIt.exe I believe) but the 32-bit DLL should work exactly the same for 32-bit Windows.

Thanks in advance guys =)

EDIT: Original thread on this topic in the official Snarl forum can be found here.

EDIT2: And here is a segment of the original VB6 code from what I already did above, just in case I did it wrong... if anyone needs more data such as the geOTraySpy.dll source just let me know.

Private Declare Function SetTrayHook Lib "geotrayspy.dll" (ByVal szServerName As String) As Boolean
Private Declare Function UnsetTrayHook Lib "geotrayspy.dll" () As Boolean
Private Declare Function CopyIcon Lib "user32" (ByVal hIcon As Long) As Long

geOTraySpy_dll_32and64.zip

Edited by JonusC
Link to comment
Share on other sites

  • Developers

Apparently the scite integrated distribution of AutoIt does not compile to 64bit by default.

Correct as it is just SciTE being distributed and it simply runs autoit3.exe.

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Yeah sorry about that heh I've got my SciTE set up to use the x64 binaries.

So can any of you guys give me a tip of what I should try to do next? Would be extremely grateful :blink:

EDIT: Here is the code I have so far (a little more):

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ButtonConstants.au3>
#include <WinAPI.au3>

ConsoleWrite ( "-----------------------" & @CRLF )
ConsoleWrite ( "[#] Opening " & @ScriptDir & "\geOTraySpy.dll..." & @CRLF )
$libGeotrayspy = DllOpen( @ScriptDir & "\geOTraySpy.dll" )
    If $libGeotrayspy = -1 Then ConsoleWrite ( "    [!] Fail!" & @CRLF )
ConsoleWrite ( "[#] Registering function 'SetTrayHook'..."& @CRLF )
$resGeotrayspyHook = DllCall( $libGeotrayspy, "BOOLEAN", "SetTrayHook", "str", "szServerName" )
    If @error Then ConsoleWrite ( "    [!] Fail!" & @CRLF )
ConsoleWrite ( "[#] Registering function 'UnsetTrayHook'..."& @CRLF )
$resGeotrayspyUnhook = DllCall( $libGeotrayspy, "BOOLEAN", "UnsetTrayHook" )
    If @error Then ConsoleWrite ( "    [!] Fail!" & @CRLF )
ConsoleWrite ( "[#] Registering function 'CopyIcon'..."& @CRLF )
$resCopyIcon = DllCall( "user32.dll", "long", "CopyIcon", "long", "hIcon" )
    If @error Then ConsoleWrite ( "    [!] Fail!" & @CRLF )
ConsoleWrite ( "[#] Registering window message 'GSSPY_DOWNLOAD'..." & @CRLF )
$WM_GSSPY_DOWNLOAD = _WinAPI_RegisterWindowMessage("GSSPY_DOWNLOAD")
    If @error Then ConsoleWrite ( "    [!] Fail!" & @CRLF )
GUIRegisterMsg ( $WM_GSSPY_DOWNLOAD, "Testing" )

While 1
    Sleep(100)
WEnd

Func Testing($hWnd, $Msg, $wParam, $lParam)
    ConsoleWrite ( $hWnd & " " & $Msg & " " & $wParam & " " & $lParam & @CRLF )
EndFunc

...but it doesn't do anything.

Also, here is the source for the DLL I'm using - http://www.koders.com/cpp/fid1D274FC1958528D058A74AF3161C18E7459C211B.aspx

What am I missing? I think it's something to do with szServerName, or maybe (looking at the DLL code) to do with the SendMessage ( g_hTargetWin [...] ) function...

Edited by JonusC
Link to comment
Share on other sites

There's actually an example port of the snarl API to AutoIt and an example of using the AutoIt based API already:

#588064

As to what the SnarlTray extension does itself: Is VB code SnarlTray for it available? If so it would be a simple matter of converting. Otherwise yea, we'd have to take a look at what SnarlTray does exactly and use the Snarl API to mimic it.

Link to comment
Share on other sites

There's actually an example port of the snarl API to AutoIt and an example of using the AutoIt based API already:

#588064

As to what the SnarlTray extension does itself: Is VB code SnarlTray for it available? If so it would be a simple matter of converting. Otherwise yea, we'd have to take a look at what SnarlTray does exactly and use the Snarl API to mimic it.

Sorry, I don't really have any problem with the Snral Tray API - at least, I have not gotten that far yet. The geOTraySpy DLL has nothing to do with Snarl really, I'm just trying to see if this x64 DLL will work at intercepting the WM_COPYDATA messages of the Balloon Tips. Only, I'm stuck with how to do it.

My last post has a link to the source code of the DLL (C++). The AutoIt script loads the hook code already, I think. But I don't know how to actually get the DLL hook to "talk back" to my AutoIt script.

Ignore anything "Snarl" right now... that's not the main concern. Sorry to have confused, I really do appreciate the help :blink:

EDIT: Here is the source for the SnarlTray extension itself. Most of the code can be ignored, because all I really want to do right now in the AutoIt script is get a Messagebox/ConsoleWrite the result of a BalloonTip from the hook. So it might be easier seeing it in the VB6 example. http://cid-e9fb2bf7954e2e2e.office.live.com/browse.aspx/Public/SnarlTray

EDIT2: Looking at the code, my guess is that I need to create a window with a specific classname so the hook knows where to forward data to. But I don't know how to do that. The GSSPY_DOWNLOAD registration is actually not needed, I didn't realize that the code was commented-out in the SnarlTray VB6 app.

Edited by JonusC
Link to comment
Share on other sites

Any windows you make in AutoIt will have a hard-coded class name of "AutoIt v3 GUI". If you need to make a custom window with a custom class name, you'd need to use the RegisterClassEx windows API function. If it's possible, having the DLL match a window based on Title would be much easier for AutoIt interaction. Otherwise, you could send in a feature request to have the class name be customizable, there was talk about that at one time: http://www.autoitscript.com/forum/index.php?showtopic=20876

Otherwise like I said, you'd be doing it manually. In which case you might find these resources helpful:

http://www.winprog.org/tutorial/simple_window.html

http://www.autoitscript.com/forum/index.php?showtopic=66889

http://msdn.microsoft.com/en-us/library/ms633577(v=VS.85).aspx

Putting the Vb code into a zip file would be most helpful, the layout and UI interactions on the office live site seem be designed to not let me download the folder as a whole...

Link to comment
Share on other sites

Thanks evilertoaster, I'll check them out and see if I can figure any more out. Here's the SnarlTray extension in a ZIP archive:

http://cid-e9fb2bf7954e2e2e.office.live.com/self.aspx/Public/SnarlTray.zip

Note that it won't compile or anything, though, as it's just a fragment of the entire Snarl repository and thus has some missing includes. However, code that's specific to this DLL is all in there.

Link to comment
Share on other sites

*Bump*

I've tried everything I can think of, it's just beyond my ability. The source for the DLL and the old VB6 code is there, but all I am trying to do is get AutoIt to make the hook, and make a MsgBox when it gets a notification from it. But I just can't get them "talking", as soon as I can though I will easily figure the rest out on my own...

Really hope someone can find the time to lend a hand with this so I can kiss their feet :blink:

Link to comment
Share on other sites

Ok...

Well I spent a good deal of time on this as a matter of interest... Here's some things:

1. That source code for the DLL is not really compilable... I puts around with it myself for a while trying to get it to compile so I could debug it... Here's what I came up with:

#ifndef __MINGW__
#pragma once
#endif /* __MINGW__ */

extern "C" __declspec(dllexport) bool WINAPI SetTrayHook( char* szServerName );
bool WINAPI UnsetTrayHook();
bool WINAPI IsNt();

#define GSSPY_DOWNLOAD  "GSSPY_DOWNLOAD"

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// geOTraySpy.cpp
//
// Main implementation file for geOTraySpy.dll
//
// This is based on Mike Lin's traysaver code.
//
// It builds a dll which contains code to establish a hook into
// the Shell_TrayWnd class, receiving all wndProc messages after they
// have been processed by Shell_TrayWnd itself.
//
// It then forwards any copydata messages to the geOShell TrayService.
//
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

#include <windows.h>
//#include "../geOLib/AggressiveOptimize.h"
#include <stdio.h>
//#include "tsdebug.h"
#include "geOTraySpy.h"

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Globals
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

#define PAD_SIZE    65

struct stTrayItem
{
    COPYDATASTRUCT  CopyData;

    struct stNicHolder
    {
        BYTE            bPad[8];
        NOTIFYICONDATA  IconData;
        CHAR            szPad[PAD_SIZE];    // The Tip can be up to 128 chars long
    }               NicHolder;
};

#define MAX_SAVEDTRAYDATA   25

#pragma data_seg( "shared" )

CHAR                g_cServerClass [100]    = "";
HWND                g_hTargetWin            = 0;
HWND                g_hTrayWin              = 0;
HHOOK               g_hHook                 = 0;
UINT                g_iNextFreePos          = 0;
struct stTrayItem   g_SavedTrayData[MAX_SAVEDTRAYDATA];

#pragma data_seg()

#pragma comment( linker, "/SECTION:shared,rws" )

const UINT WM_GSSPY_DOWNLOAD    = ::RegisterWindowMessage(GSSPY_DOWNLOAD);
const char CLASS_TrayProc[]     = "Shell_TrayWnd";

#ifndef NIF_INFO
#define NIF_INFO         0x00000010
#endif

typedef struct _MYNOTIFYICONDATA { 
    DWORD   cbSize; 
    HWND    hWnd; 
    UINT    uID; 
    UINT    uFlags; 
    UINT    uCallbackMessage; 
    HICON   hIcon; 
    TCHAR   szTip[128];
    DWORD   dwState;
    DWORD   dwStateMask;
    TCHAR   szInfo[256];
    union
    {
        UINT  uTimeout;
        UINT  uVersion;
    } MYDUMMYUNIONNAME;
    TCHAR   szInfoTitle[64];
    DWORD   dwInfoFlags;
} MYNOTIFYICONDATA, *PMYNOTIFYICONDATA;

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Functions
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// IsNT
//
// Returns true if we are running under Windows NT.
//////////////////////////////////////////////////////////////////////

bool WINAPI IsNT()
{
    static bool         bNT = false;
    static bool         bFound = false;
    OSVERSIONINFO       ovi;
    
    if( !bFound )
    {
        ovi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );

        GetVersionEx( &ovi );

        bNT = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT;

        bFound = true;
    }

    return bNT;
}

//////////////////////////////////////////////////////////////////////
// TrayWndProc
//
// New window proc for the system tray window
//////////////////////////////////////////////////////////////////////

LRESULT CALLBACK TrayWndProc( int nCode, WPARAM wParam, LPARAM lParam )
{
    CWPRETSTRUCT *pInfo = reinterpret_cast< CWPRETSTRUCT * >( lParam );
    
    if( nCode >= 0 )
    {
        // Interested in copydata messages
        if ( pInfo->message == WM_COPYDATA )
        {
            
            // Make sure we have a valid handle on the Tray window
            if( !g_hTrayWin || !IsWindow( g_hTrayWin ) )
                g_hTrayWin = FindWindow( CLASS_TrayProc, NULL );

            // Make sure this message is from the Tray window
            if (IsWindow( g_hTrayWin) && pInfo->hwnd == g_hTrayWin )
            {
                //MessageBox(NULL, "WM_COPYDATA from tray...", "", MB_OK);
                COPYDATASTRUCT* pcds = reinterpret_cast< COPYDATASTRUCT* >( pInfo->lParam );

                if( pcds->dwData == 1 ) // if this data refers to a tray icon...
                {
                    //MessageBox(NULL, "is tray icon...", "", MB_OK);
                    // Maintain our own copy of the tray icons
                    NOTIFYICONDATA  *nicData = (NOTIFYICONDATA *)(((BYTE *)pcds->lpData) + 8);
                    INT             iTrayCmd = *(INT *)(((BYTE *)pcds->lpData) + 4);

                    if ((int)nicData->uID == -1)
                    {
                        MessageBox(NULL, "early return, calling next hook.", "", MB_OK);
                        return CallNextHookEx( g_hHook, nCode, wParam, lParam );
                    }

                    if (iTrayCmd == NIM_ADD || iTrayCmd == NIM_MODIFY)
                    {
                        //MessageBox(NULL, "itraycmd is add or mod", "", MB_OK);
                        bool    bFound = false;
                        UINT    i = 0;

                        for (i = 0; i < g_iNextFreePos && i < MAX_SAVEDTRAYDATA; i++)
                        {
                            if (g_SavedTrayData[i].NicHolder.IconData.uID == nicData->uID && 
                                g_SavedTrayData[i].NicHolder.IconData.hWnd == nicData->hWnd)
                            {


                                memcpy (&g_SavedTrayData[i].CopyData, pcds, sizeof (COPYDATASTRUCT));

                                if (iTrayCmd == NIM_ADD)
                                {
                                    memcpy (&g_SavedTrayData[i].NicHolder.IconData,
                                            nicData,
                                            (int) nicData->cbSize <= (sizeof (NOTIFYICONDATA) + PAD_SIZE) ? (int) nicData->cbSize : (sizeof (NOTIFYICONDATA) + PAD_SIZE));
                                }
                                else
                                {
                                    if ((nicData->uFlags | NIF_ICON && nicData->hIcon) || 
                                        (g_SavedTrayData[i].NicHolder.IconData.hIcon == NULL && nicData->hIcon))
                                    {
//                                      MessageBox(NULL, "Icon", "", MB_OK);
                                        g_SavedTrayData[i].NicHolder.IconData.hIcon = nicData->hIcon;
                                    }

                                    if ((nicData->uFlags | NIF_MESSAGE) ||
                                        (!g_SavedTrayData[i].NicHolder.IconData.uCallbackMessage && nicData->uCallbackMessage))
                                    {
//                                      MessageBox(NULL, "Msg", "", MB_OK);
                                        g_SavedTrayData[i].NicHolder.IconData.uCallbackMessage = nicData->uCallbackMessage;
                                    }

                                    if ((nicData->uFlags | NIF_TIP) ||
                                        (g_SavedTrayData[i].NicHolder.IconData.szTip[0] == '\0' && nicData->szTip[0] != '\0'))
                                    {
                                        memcpy (g_SavedTrayData[i].NicHolder.IconData.szTip, nicData->szTip, sizeof (nicData->szTip) + (int) nicData->cbSize - sizeof(NOTIFYICONDATA));
                                    }   

                                    g_SavedTrayData[i].NicHolder.IconData.uFlags = nicData->uFlags;
                                }

                                bFound = true;
                                break;
                            }
                        }

                        if (!bFound && (i < MAX_SAVEDTRAYDATA))
                        {
                            memcpy (&g_SavedTrayData[i].CopyData, pcds, sizeof (COPYDATASTRUCT));
                            memcpy (&g_SavedTrayData[i].NicHolder.IconData,
                                    nicData,
                                    (int) nicData->cbSize <= (sizeof (NOTIFYICONDATA) + PAD_SIZE) ? (int) nicData->cbSize : (sizeof (NOTIFYICONDATA) + PAD_SIZE));
                            g_iNextFreePos++;
                        }
                    }
                    else if (iTrayCmd == NIM_DELETE)
                    {
                        //MessageBox(NULL, "itraycmd is delete", "", MB_OK);
                        for (UINT i = 0; i < g_iNextFreePos && i < MAX_SAVEDTRAYDATA; i++)
                        {
                            if (g_SavedTrayData[i].NicHolder.IconData.uID == nicData->uID && 
                                g_SavedTrayData[i].NicHolder.IconData.hWnd == nicData->hWnd)
                            {
                                memmove(&g_SavedTrayData[i], &g_SavedTrayData[i + 1], sizeof(struct stTrayItem) * (g_iNextFreePos - (i + 1)));
                                g_iNextFreePos--;
                                break;
                            }
                        }
                    }

                    // Make sure we have a valid handle on the target window
                    if( !g_hTargetWin || !IsWindow( g_hTargetWin ) )
                        g_hTargetWin = FindWindow( g_cServerClass, NULL );
                    //MessageBox(NULL, "finding target window...", "", MB_OK);
                    // OK?
                    if (IsWindow( g_hTargetWin ))
                    {
                        //MessageBox(NULL, "sending WM_COPY", "", MB_OK);
                        // Forward the message
                        SendMessage( g_hTargetWin, 
                                     WM_COPYDATA, 
                                     reinterpret_cast< WPARAM >( g_hTrayWin ), 
                                     pInfo->lParam );
                        DWORD dw = GetLastError();
                        if (dw>0){
                        char szMyString[14] ={0};
                        sprintf(szMyString, "0x%08x",dw);
                        MessageBox(NULL, szMyString, TEXT("Message Sent, LastError:"), MB_OK) ;
                        }
                    }
                }
            }
        }
        else if ( pInfo->message == WM_GSSPY_DOWNLOAD )
        {
            if( !g_hTargetWin || !IsWindow( g_hTargetWin ) )
                g_hTargetWin = FindWindow( g_cServerClass, NULL );

            for (UINT i = 0; i < g_iNextFreePos && i < MAX_SAVEDTRAYDATA; i++)
            {
                g_SavedTrayData[i].CopyData.lpData = &g_SavedTrayData[i].NicHolder;

                SendMessage( g_hTargetWin, 
                             WM_COPYDATA, 
                             reinterpret_cast< WPARAM >( g_hTrayWin ), 
                             (long) &g_SavedTrayData[i] );
                
            }
        }
    }

    return CallNextHookEx( g_hHook, nCode, wParam, lParam );
}

BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{
    return TRUE;
}

//////////////////////////////////////////////////////////////////////
// SetTrayHook
//
// Sets our hook
//////////////////////////////////////////////////////////////////////


__declspec(dllexport) bool WINAPI SetTrayHook (char* szServerName)
{
    DWORD dwThreadID = 0;
    //MessageBox(NULL, "Called Set", "", MB_OK);
    if( g_hHook )
        return false;
    //MessageBox(NULL, "n ghook", "", MB_OK);
    if (strlen(szServerName) > 99 || strlen(szServerName) == 0)
        return false;
    //MessageBox(NULL, "length ok", "", MB_OK);
    strcpy (g_cServerClass, szServerName);
    //MessageBox(NULL, "copied ok", "", MB_OK);
    if( IsNT() )
    {
        HWND hwndTray = FindWindow( CLASS_TrayProc, NULL );
        //MessageBox(NULL, "is nt", "", MB_OK);
        if( !hwndTray )
            return false;
        //MessageBox(NULL, "found class", "", MB_OK);
        if( hwndTray )
            dwThreadID = GetWindowThreadProcessId( hwndTray, NULL );
    }

    memset (g_SavedTrayData, '\0', MAX_SAVEDTRAYDATA * sizeof (COPYDATASTRUCT));
    g_hHook = SetWindowsHookEx( WH_CALLWNDPROCRET, TrayWndProc, GetModuleHandle( "geOTraySpy.dll" ), dwThreadID );
    if (g_hHook == 0)
    {
        DWORD dw = GetLastError(); 

        char szMyString[14] ={0};
        sprintf(szMyString, "0x%08x",dw);
        //MessageBox(NULL, szMyString, TEXT("Last Error"), MB_OK) ;
    }

    
    //MessageBox(NULL, "sethook called", "", MB_OK);
    return g_hHook != 0;
}

//////////////////////////////////////////////////////////////////////
// UnsetTrayHook
//
// Unsets the hook
//////////////////////////////////////////////////////////////////////

bool WINAPI UnsetTrayHook ()
{
    if( UnhookWindowsHookEx( g_hHook ) )
    {
        g_hHook = NULL;
        g_hTargetWin = NULL;
        return true;
    }

    return false;
}

Step 2 I tried calling this in AutoIt... It didn't seem to like it very much, here's how I think it *should* work:

ConsoleWrite ( "-----------------------" & @CRLF )
ConsoleWrite ( "[#] Opening " & @ScriptDir & "\geOTraySpy.dll..." & @CRLF )
$libGeotrayspy = DllOpen( @ScriptDir & "\geOTraySpy.dll" )
    If $libGeotrayspy = -1 Then ConsoleWrite ( "    [!] Fail!" & @CRLF )
ConsoleWrite ( "[#] Registering function 'SetTrayHook'..."& @CRLF )

$win = GUICreate("Test")

$resGeotrayspyHook = DllCall( $libGeotrayspy, "BOOLEAN", "SetTrayHook", "str", "AutoIt v3 GUI" )
    If @error Then ConsoleWrite ( "    [!] Fail!" & @CRLF )
ConsoleWrite ( "[#] 'SetTrayHook' Result: '..."& $resGeotrayspyHook[0] & @CRLF )

GUIRegisterMsg(0x4A,"SomeFunction")
GUISetState()

while 1
    Sleep(100)
WEnd

func SomeFunction($hWndGUI, $MsgID, $WParam, $LParam)
    MsgBox(0,"WM_COPY sent","")
EndFunc

You may want to ask personally some of more experienced Win API scripting dudes, there is a post of note:

http://www.autoitscript.com/forum/index.php?showtopic=110231 which notes that what we're trying to do may not work in AutoIt at the moment... wraithdu and kafu seem to have messed around with it a bit, you could try them...

However I can verify the DLL works, as I've tested in in C# via the following code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace HookTest
{
    public partial class Form1 : Form
    {
        [DllImport("geOTraySpy.dll")]
        private static extern bool SetTrayHook(string szServerName);

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        internal static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string className = GetCurrentClassName();
            bool res = SetTrayHook(className);
            MessageBox.Show(res.ToString());
        }
        protected override void WndProc(ref Message m)
        {
            Debug.WriteLine(m.ToString());
            base.WndProc(ref m);
        }
        protected string GetCurrentClassName()
        {
            StringBuilder className = new StringBuilder(255);
            GetClassName(this.Handle, className, 255);
            return className.ToString();
        }
    }

}

I see the WM_COPYDATA messages being sent though.

Hopefully that answers your question to some degree...

Link to comment
Share on other sites

evilertoaster,

Thanks for the help - I really appreciate it. Well, In fact I don't mind that it may/probably not work in AutoIt, I think it a good platform for rapid development. The C# sample code you've provided is actually much more useful, since this makes it easier to write up a Snarl-specific extension without the reliance on a separate process running all the time.

I myself am only a novice at C#, but you have indeed provided a solution I can use. Thanks a lot =)

P.S. For those interested, another chap has started working on a Snarl Balloon-Notification-Capture program and detailed it in the Snarl group - working on x64 - it is python-based and doesn't use DLL hooking, however it is incomplete. I will continue to work on this method in particular with C# though out of personal interest.

Thanks again evilertoaster, much appreciated :blink:

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...