1

This is with reference to this question:

How to read output and give input to a program from c program?

I found the answer to the above question very useful. In the same way, can I do it for windows applications? Like can I give input into a Windows form (like .net, C# applications) application's text box programmatically? Can I do the action of button click from a program?

If so, can I do it from a C program (with Tiny C compiler or any other on windows platform)? If not, how and in which language can I do it? Please don't take it as a silly question. Any example codes will be very much appreciated.

Edit: Can I do the same with web applications and web pages?

Community
  • 1
  • 1
Enjoy coding
  • 4,268
  • 12
  • 40
  • 50
  • Exactly what are you trying to accomplish? Is this for testing, or do you simply need to invoke the functionality of the windows forms application from another program? If the latter, then you could host a WCF service in the Windows Forms application and call it from other programs. Same with a web application. – John Saunders Jun 04 '09 at 13:48

4 Answers4

4

If your application mainly just needs to manipulate other windows, by sending keystrokes etc. i would use AutoIt. It's mainly function is exactly this job and it does it very well.

So maybe you should give it a try, cause not every problem is a nail and can be solved with a hammer (C#) ;-))

Oliver
  • 43,366
  • 8
  • 94
  • 151
  • 1
    Autoit is an adhoc programming language which seemed to me like a magical language at first. Then I fell in love with it and started doing crazy things with it. Thanks for the answer on achieving the popular question badge. – Enjoy coding May 13 '11 at 11:09
  • @Enjoy coding: Yes i wished just the half of them had upvote my answer. ;-)) – Oliver May 13 '11 at 11:11
2

You can enumerate all the windows of the system.
You can send windows messages to any window.

E.g. to set the text of a textbox you have to send a WM_SETTEXT message.

FYI: Winspector is a very interesting tool which makes heavy use of this as well (also to debug or otherwise first inspect the windows you're trying to programmatically access).

You might also be interested in this:

AutoIt v3 is a freeware BASIC-like scripting language designed for automating the Windows GUI and general scripting. It uses a combination of simulated keystrokes, mouse movement and window/control manipulation in order to automate tasks in a way not possible or reliable with other languages (e.g. VBScript and SendKeys). AutoIt is also very small, self-contained and will run on all versions of Windows out-of-the-box with no annoying "runtimes" required!

fretje
  • 8,322
  • 2
  • 49
  • 61
  • Isn't it mad that applications can be interfered with like that? Is there any sort of process-level protection in Windows, or can every process see every process? – dreamlax Jun 04 '09 at 12:51
  • Not that I know of no... That's e.g. how Revelation (http://www.snadboy.com/) works to reveal passwords in password fields... Although there are other measures in place to prevent that now... – fretje Jun 04 '09 at 12:54
  • It's not mad at all to allow windows to be controlled remotely. Without an API to allow this you couldn't have things like debuggers, task managers, automated testing tools, and innumerably useful other applications. Heck, without the ability to send windows messages to any window you couldn't even shut down unresponsive apps. – Ron Warholic Jun 04 '09 at 14:04
  • @BlodBath, you obviously do not know what I mean. If the application was unresponsive, why would it respond to a message that you sent it? Killing a process is done entirely independently from messaging. Also, debugging is done by spawning a sub-process, or by attaching to a process, not by messaging windows. Not all processes have window procedures yet these can still be debugged and killed. – dreamlax Jun 05 '09 at 13:08
2

As fretje pointed out, you can certainly do it.

It's much more challenging for windows apps. Because individual controls also count as windows, the total window count will be much higher than you might expect; and finding the specific control you want to send input to can take a lot of work.

But you can programmatically move, resize, check, fill, maximize or otherwise affect an app's windows, once you know which one is your target.

I wrote code to do the discovery process a few years ago. It found all the windows of a target app, then using their size & location data, produced a translucent overlay of each child window, along with the handle number. So I could visually tell which control went with which handle.

EDIT: Added some code. This is some basic C# interop code that will let you make easy calls into user32.dll, which holds the fns to which fretje referred. This just gives you the basic calls for discovery and manipulation; you'll still have to do the hard work of enumerating and examining what you find. If you can find a 3rd-party package that does the job for you, save yourself the trouble; I only did it as a learning experience, and it was pretty laborious.

using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;

namespace WinAPI
{
    [Flags] public enum WindowStyleFlags : uint
    {
        WS_OVERLAPPED      = 0x00000000,
        WS_POPUP           = 0x80000000,
        // more...
    }

    [Flags] public enum ExtendedWindowStyleFlags: int
    {
        WS_EX_DLGMODALFRAME    = 0x00000001,
        WS_EX_NOPARENTNOTIFY   = 0x00000004,
        // more...
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct POINT
    {
        public int Left;
        public int Top;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct FLASHWINFO
    {
        public int cbSize;
        public IntPtr hwnd;
        public int dwFlags;
        public int uCount;
        public int dwTimeout;
    }

    public delegate int EnumWindowsCallback( IntPtr hwnd, int lParam );

    public class User32Dll
    {
        // Constants & fields
        public const int FLASHW_STOP = 0;
        public const int FLASHW_CAPTION = 0x00000001;
        // lots, lots more, web search for them...

        // Self-added, don't know if correct
        [DllImport("user32")]
        public extern static bool CloseWindow( IntPtr hWnd );
        [DllImport("user32")]
        public extern static IntPtr GetDesktopWindow();
        [DllImport("user32")]
        public extern static IntPtr GetForegroundWindow();
        [DllImport("user32")]
        public extern static int GetDlgItem( IntPtr hWnd, int wMsg );
        [DllImport("user32")]
        public extern static int GetListBoxInfo( IntPtr hWnd );
        [DllImport("user32")]
        public extern static bool MoveWindow( IntPtr hWnd, int X, int Y, int Width, int Height, bool Repaint );
        [DllImport( "user32" )]
        public static extern int SendMessage( IntPtr hWnd, int uMsg, IntPtr wParam, StringBuilder lpString );
        [DllImport("user32")]
        public static extern bool SetWindowPos( IntPtr hWnd, IntPtr afterWnd, int X, int Y, int cX, int cY, uint uFlags );

        [DllImport("user32")]
        public extern static int BringWindowToTop (IntPtr hWnd);
        [DllImport("user32")]
        public extern static int EnumWindows( EnumWindowsCallback lpEnumFunc, int lParam );
        [DllImport("user32")]
        public extern static int EnumChildWindows( IntPtr hWndParent, EnumWindowsCallback lpEnumFunc, int lParam );
        [DllImport( "user32.dll" )]
        public static extern int EnumThreadWindows( IntPtr hWndParent, EnumWindowsCallback callback, int lParam );
        [DllImport( "user32.dll" )]
        public static extern int FindWindow( string lpClassName, string WindowName );
        [DllImport( "user32.dll" )]
        public static extern int FindWindowEx( IntPtr hWnd, IntPtr hWnd2, string lpsz, string lpsz2 );
        [DllImport("user32")]
        public extern static int FlashWindow ( IntPtr hWnd, ref FLASHWINFO pwfi);
        [DllImport("user32")]
        public extern static IntPtr GetAncestor( IntPtr hWnd, uint gaFlags );
        [DllImport("user32", CharSet = CharSet.Auto)]
        public extern static int GetClassName ( IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
        [DllImport("user32", CharSet = CharSet.Auto)]
        public extern static uint GetWindowLong( IntPtr hwnd, int nIndex);
        [DllImport("user32")]
        public extern static int GetClientRect( IntPtr hWnd, ref RECT lpRect);
        [DllImport("user32")]
        public extern static int GetWindowRect( IntPtr hWnd, ref RECT lpRect);
        [DllImport("user32", CharSet = CharSet.Auto)]
        public extern static int GetWindowText( IntPtr hWnd, StringBuilder lpString, int cch );
        [DllImport("user32", CharSet = CharSet.Auto)]
        public extern static int GetWindowTextLength( IntPtr hWnd );
        [DllImport("user32")]
        public extern static int IsIconic(IntPtr hWnd);
        [DllImport("user32")]
        public extern static int IsWindowVisible( IntPtr hWnd );
        [DllImport("user32")]
        public extern static int IsZoomed(IntPtr hwnd);
        [DllImport("user32", CharSet = CharSet.Auto)]
        public extern static int PostMessage( IntPtr hWnd, int wMsg, int wParam, int lParam);
        [DllImport( "user32.dll" )]
        public static extern int RealGetWindowClass( IntPtr hWnd, StringBuilder pszType, uint bufferSize );
        [DllImport("user32")]
        public extern static int ScreenToClient( IntPtr hWnd, ref POINT lpPoint);
        [DllImport("user32", CharSet = CharSet.Auto)]
        public extern static int SendMessage( IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll")]
        public extern static int SetForegroundWindow (IntPtr hWnd);
        [DllImport( "user32.dll" )]
        public static extern int SetWindowText( IntPtr hWnd, string lpsz );
    }
}
0

Check out the following SO question. There are numerous vendor and open-source tools to do this for you, so you don't have to code at to the Win32 API.

automated-testing-of-windows-forms

Community
  • 1
  • 1
Tom E
  • 2,519
  • 2
  • 17
  • 22