c# keybd_event Problem

Hi gang,

I have trawled the forums for an answer to this problem without success so here goes.

I have an application written in c# that must monitor and control 2 other application. In short I need to be able to send either a CTRL or ALT message to one of the applications. I have tried several approaches the most successful being the Keybd_event & PostMessage Combination set out below. The problem is that while the code below works fine on my development machine, it seems that the Keybd_event function fails 1 in 3 times on some machines in the production environment. What I need a is something that will guarantee delivery of the message.

Also note that the application to recieve the keystrokes may or may not always have focus.

public static void PostMacro(IntPtr hWnd, int nFunctionKey)
                  ulong lKeyStatus;
                  //Sends a predifined Macro
                  lKeyStatus = 0x1C << 16 | 0x1;
                  bool bOk = false;
                  int i = 0; // Ensure the function keybd_event does not iterate forever and lock the ctrl key
                        bOk = Win32API.keybd_event( (byte)Keys.VK_CONTROL, 0x45, KEYEVENTF_EXTENDEDKEY, UIntPtr.Zero );
                        bOk = false;
                  while(!bOk && i < 1000);
                  Win32API.PostMessage(hWnd, (uint) Keys.WM_KEYDOWN, nFunctionKey, lKeyStatus);
                  lKeyStatus ^= 0x80000000;
                  Win32API.PostMessage(hWnd, (uint) Keys.WM_KEYUP, nFunctionKey, lKeyStatus);
                  i = 0;
                        bOk = Win32API.keybd_event( (byte)Keys.VK_CONTROL, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, UIntPtr.Zero );
                  while(!bOk && i < 1000);

Any suggestions greatly appreciated.

Due to the amount of time I have aready wasted exploring alternatives time has become critical so I'm offering 500 points.
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Mike TomlinsonHigh School Computer Science, Computer Applications, and Mathematics TeachersCommented:
You should be able to depress/release the control using code like this:

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
        public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int extraInfo);

        static extern short MapVirtualKey(int wCode, int wMapType);

        private void button1_Click(object sender, EventArgs e)
            // Ctrl-V (paste) example
            keybd_event((int)Keys.ControlKey, (byte)MapVirtualKey((int)Keys.ControlKey, 0), 0, 0); // Control Down
            keybd_event((int)Keys.V, (byte)MapVirtualKey((int)Keys.V, 0), 0, 0); // V Down
            keybd_event((int)Keys.V, (byte)MapVirtualKey((int)Keys.V, 0), 2, 0); // V Up

            keybd_event((int)Keys.ControlKey, (byte)MapVirtualKey((int)Keys.ControlKey, 0), 2, 0); // Control Up                
JesusHatesMeAuthor Commented:
Thanks for the response and this approach does work however the application receiving the keystrokes must have focus. I was hoping to find a solution where by I could send the ctrl modifier key without the application having to be activated or have focus. The original code I posted does do this but seems to run into problems in our live environment. I guess what I need is something that will guarantee the delivery to a given handle such as PostMessage, however as I understand the PostMessage API function it is not possible to post modifier keys to an application.

The approach you have suggested here requires that the application have focus. Now approach would be fine however, I have run into problems trying to activate the application window to have focus. I have used SetActiveWindow, SetForgroundWindow and SetFocus all of which do work fine on my developement machine. However, once again in the live environment these API calls often fail and only cause the application window to flash in the task bar rather than actually activate and give focus to the application to recive the keystrokes, hence the keybd_event call fails to deliver the keystrokes.
Mike TomlinsonHigh School Computer Science, Computer Applications, and Mathematics TeachersCommented:
"only cause the application window to flash in the task bar rather than actually activate and give focus to the application to recive the keystrokes,"

The behaviour you are describing is a feature of windows that "prevents applications from stealing focus".  Instead of apps taking the focus, they instead blink either indefinitely or for a configured number of times in the taskbar.  These setttings are stored in the registry.  The easiest way to change these settings are through Microsofts Tweak UI utility.

Download the Tweak UI tools from Microsoft:

Here are the releveant registry values:

Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

JesusHatesMeAuthor Commented:
Thanks for the response IM, I didn't realise that those registry setting existed.... well that explains the reason for the SetActiveWindow problem, sadly though QA are not happy for me to go around changing the registry setting for all user in production so I'm back to square one...

If I could work out how to set the ALT modifier key with a letter key with PostMessage then the need for focus problem could be avoided.
It seems the AnzioWin terminal app processes messages differently to other apps such as IE when I check the messages sent via spy++
Mike TomlinsonHigh School Computer Science, Computer Applications, and Mathematics TeachersCommented:
I'll see what I can find...
JesusHatesMeAuthor Commented:
Hi IM,  I've finally worked out how to send a key with the alt modifier:

            public static void PostMacro(IntPtr hWnd, int nFunctionKey)
                  ulong lKeyStatus;
                  lKeyStatus = 536870912; //2^29 ALT Flag
                  Win32API.PostMessage(hWnd,(int)Keys.WM_SYSKEYDOWN, nFunctionKey, lKeyStatus );

Just like to thank you for your help and for enlightening me on a few things I didn't already know.

Please Take 200 points for trying...

Kind Regards
Mike TomlinsonHigh School Computer Science, Computer Applications, and Mathematics TeachersCommented:
Glad you figured it out!
Closed, 500 points refunded.
The Experts Exchange
Community Support Moderator of all Ages

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.