Click here to Skip to main content
15,897,187 members
Articles / Programming Languages / C#

Automating Windows Applications Using the WCF Equipped Injected Component

Rate me:
Please Sign up or sign in to vote.
4.96/5 (47 votes)
15 Nov 2010CPOL14 min read 102.8K   2K   122  
A .NET WCF equipped component injected into automated process allows both local and remote clients to control the process and get its asynchronous events.
// NotepadPlugin.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"

#import "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.tlb" no_namespace named_guids rename("ReportEvent", "_ReportEvent")

#ifdef _DEBUG
	#import "..\WindowFinder\Debug\WindowFinder.tlb" no_namespace
	#import "..\Debug\NotepadHandlerNET.tlb" no_namespace
#else
	#import "..\WindowFinder\Release\WindowFinder.tlb" no_namespace
	#import "..\Release\NotepadHandlerNET.tlb" no_namespace
#endif

LPCTSTR g_szTargetWndClass = _T("Notepad");

// Notepad menu IDs
const DWORD ID_MENU_FIND = 3;

const UINT WM_CREATE_OBJECT = RegisterWindowMessage(_T("Create Object"));

static DWORD g_pfnOldFrameWndProc;	  // pointer to original frame window procedure
static DWORD g_pfnOldViewWndProc;        // pointer to original view  window procedure

static IHandlerPtr g_spHandlerNET = NULL; // pointer to embedded COM object
static HWND g_hFrameWnd = 0;

static _bstr_t bstCaption;
static _bstr_t bstMachineIPAddress;

//
// New frame window procedure
//
LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT dwMsg, WPARAM wParam, LPARAM lParam) 
{
	HRESULT hr = E_FAIL;

	if (WM_CREATE_OBJECT == dwMsg)
	{
		long t = GetCurrentThreadId(); //TEST 

		// Handler of special message to create embedded COM object
		if (FAILED(CoInitialize(NULL)))
		{
			// If COM initialization failed then restore original window procedure
			SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)g_pfnOldFrameWndProc);
			return 0;
		}	

		if (NULL == g_spHandlerNET)
			// Create embedded COM object. This is a COM-wrapped managed NotepadHandleNET object.
			hr = g_spHandlerNET.CreateInstance(__uuidof(Handler));

		g_hFrameWnd = hWnd;

		if (SUCCEEDED(hr))
		{
			// Get IP address of the machine and show it in the frame window caption.
			_variant_t varIn(_T("MachineIPAddress"));
			_variant_t varOut(_T(""));
			long ret = g_spHandlerNET->Do(varIn, &varOut);
			bstMachineIPAddress = _bstr_t(varOut.bstrVal);

			TCHAR szCaption[MAX_PATH];
			GetWindowText(hWnd, szCaption, MAX_PATH);
			SetWindowText(hWnd, szCaption);
		}

		return hr;
	}

	switch (dwMsg)
	{
	case WM_DESTROY:
		if (NULL != g_spHandlerNET)
		{
			_variant_t varIn(_T("Destroy"));
			_variant_t varOut(0);
			long ret = g_spHandlerNET->Do(varIn, &varOut);
		}

		g_spHandlerNET = NULL;
		MessageBox(hWnd, _T("Bye-Bye..."), _T("Notepad"), MB_TOPMOST);
		break;

	case WM_SETTEXT:
		bstCaption = bstMachineIPAddress + _bstr_t(_T("  [AUTOMATED]  ")) + _bstr_t((LPSTR)lParam);
		lParam = (LPARAM)(LPCTSTR)bstCaption;
		break;
	}

	// Pass message on to the original window procedure
	return CallWindowProc((WNDPROC)g_pfnOldFrameWndProc, hWnd, dwMsg, wParam, lParam);
}


//
// New view window procedure
//
LRESULT CALLBACK ViewWndProc(HWND hWnd, UINT dwMsg, WPARAM wParam, LPARAM lParam) 
{
	switch (dwMsg)
	{
	case WM_CHAR:
		// Key pressed, char inserted to view window
		if (g_spHandlerNET)
		{
			TCHAR szChar[2];
			_stprintf(szChar, _T("%c"), (TCHAR)wParam);

			// Pass inserted character to embedded COM object
			_variant_t varIn(_T("SetText"));
			_variant_t varOut(szChar);
			g_spHandlerNET->Do(varIn, &varOut);	
		}
		break;
	}

	// Pass message on to the original window procedure
	return CallWindowProc((WNDPROC)g_pfnOldViewWndProc, hWnd, dwMsg, wParam, lParam);
}


//
// Injected DLL activities function
//
BOOL PluginProc()
{
	if (FAILED(CoInitialize(NULL)))
		return FALSE;

	IWndFinderHelperPtr spWndFinderHelper(__uuidof(WndFinderHelper));
	if (NULL == spWndFinderHelper)
		return FALSE;

	// Find/wait for window of specified class
	ULONG lWnd = 0;
	spWndFinderHelper->WaitForWndOfClass(g_szTargetWndClass, &lWnd);
	if (0 >= lWnd)
		return FALSE;

	HWND hWnd = (HWND)lWnd;

	// Subclass frame window of target application
	g_pfnOldFrameWndProc = SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)FrameWndProc);

	// Subclass view window
	g_pfnOldViewWndProc = SetWindowLong(GetWindow(hWnd, GW_CHILD), GWL_WNDPROC, (DWORD)ViewWndProc);

	// Post message to new window procedure to create COM object
	PostMessage(hWnd, WM_CREATE_OBJECT, 0, 0);

	return TRUE;
}

	
//
// Dll entry point
//
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD nReason, LPVOID pReserved)
{
	BOOL br = FALSE;
	if (nReason == DLL_PROCESS_ATTACH)
		br = PluginProc();

	return br;
}

long ActivateFindDialog()
{
	LRESULT lr = -1;
	if (0 != g_hFrameWnd)
		lr = SendMessage(g_hFrameWnd, WM_COMMAND, ID_MENU_FIND, 0);

	return lr;
}

long AppendMainMenu(BSTR bsMenuName)
{
	long lr = -1;
	if (0 != g_hFrameWnd)
	{
		long t = GetCurrentThreadId(); //TEST

		_bstr_t bstMenuName(bsMenuName);
		_bstr_t bstAmp(_T("&"));

		HMENU hMenu = GetMenu(g_hFrameWnd); 
		HMENU hMenuLines = CreatePopupMenu(); 
		AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hMenuLines, _T(bstAmp + bstMenuName));
		AppendMenu(hMenuLines, MF_STRING, ID_MENU_FIND, _T("Duplicate &Find...")); 
		DrawMenuBar(g_hFrameWnd);
		lr = 0;
	}

	return lr;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Israel Israel


  • Nov 2010: Code Project Contests - Windows Azure Apps - Winner
  • Feb 2011: Code Project Contests - Windows Azure Apps - Grand Prize Winner



Comments and Discussions