private void SimulateKeystrokes(IntPtr windowHandle, InputBatch batch)
        {
            List<INPUT> inputList = new List<INPUT>();
            //INPUT[] inp = new INPUT[batch.InputActions.Count];

            for (int i = 0; i < batch.InputActions.Count; i++)
            {
                switch (batch.InputActions[i].InputAction)
                {
                    case InputActionTypes.KeyStroke:
                        KeyStroke keyStroke = batch.InputActions[i] as KeyStroke;
                        INPUT kbInput = new INPUT();

                        //inp[i].type = INPUT_KEYBOARD;
                        //if (keyStroke.Type == KeyStrokeTypes.Down)
                        //{
                        //    inp[i].ki = CreateKeyboardInput(keyStroke.Value, 0);
                        //}
                        //else
                        //{
                        //    inp[i].ki = CreateKeyboardInput(keyStroke.Value, KEYEVENTF_KEYUP);
                        //}


                        kbInput.type = INPUT_KEYBOARD;
                        if (keyStroke.Type == KeyStrokeTypes.Down)
                        {
                            kbInput.ki = CreateKeyboardInput(keyStroke.Value, 0);
                        }
                        else
                        {
                            kbInput.ki = CreateKeyboardInput(keyStroke.Value, KEYEVENTF_KEYUP);
                        }

                        inputList.Add(kbInput);
                        break;

                    case InputActionTypes.MouseClick:
                        MouseClick mouseClick = batch.InputActions[i] as MouseClick;
                        INPUT mouseInput = new INPUT();

                        int x = (mouseClick.Coordinates.X * 65536) / GetSystemMetrics(SystemMetric.SM_CXSCREEN);
                        int y = (mouseClick.Coordinates.Y * 65536) / GetSystemMetrics(SystemMetric.SM_CYSCREEN);

                        if (mouseClick.RelativeTo.ToLower() != "screen")
                        {
                            RECT windowRect = new RECT();
                            GetWindowRect(windowHandle, ref windowRect);

                            x = ((mouseClick.Coordinates.X + windowRect.Left) * 65536) / GetSystemMetrics(SystemMetric.SM_CXSCREEN);
                            y = ((mouseClick.Coordinates.Y + windowRect.Top) * 65536) / GetSystemMetrics(SystemMetric.SM_CYSCREEN);
                        }

                        mouseInput.type = INPUT_MOUSE;

                        switch (mouseClick.Type)
                        {
                            case MouseClickTypes.Move:
                                mouseInput.mi = CreateMouseInput(x, y, 0, 0, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE);
                                break;

                            case MouseClickTypes.Down:
                                mouseInput.mi = CreateMouseInput(x, y, 0, 0, MOUSEEVENTF_LEFTDOWN);
                                break;

                            case MouseClickTypes.Up:
                                mouseInput.mi = CreateMouseInput(x, y, 0, 0, MOUSEEVENTF_LEFTUP);
                                break;
                        }


                        SendInput((uint)1, ref mouseInput, Marshal.SizeOf(new INPUT()));
                        //inputList.Add(mouseInput);
                        break;

                }
            }

            //SendInput((uint)inp.Length, inp, Marshal.SizeOf(inp[0].GetType()));

            if (inputList.Count > 0)
            {
                INPUT[] inp = inputList.ToArray();
                SendInput((uint)inp.Length, inp, Marshal.SizeOf(new INPUT()));
            }
        }
        private static void ProcessInputActionsElement(XElement element, StringDictionary macros)
        {
            var inputBatchData = from batchEl in element.Elements()
                                 where batchEl.Name.LocalName == "InputBatch"
                                 select batchEl;

            foreach (XElement batchElement in inputBatchData)
            {
                InputBatch batch = new InputBatch();

                if (batchElement.Attribute("Timeout") != null)
                    batch.Timeout = int.Parse(batchElement.Attribute("Timeout").Value);

                var keyStrokeData = from strokeEl in batchElement.Elements()
                                    select strokeEl;

                foreach (XElement strokeElement in keyStrokeData)
                {
                    switch (strokeElement.Name.LocalName)
                    {
                        case "KeyStroke":
                            string strokeType = "downup";
                            string strokeValue = null;
                            //List<string> keys = new List<string>();
                            string[] keys = new string[1];
                            int strokeRepeat = 1;

                            if (strokeElement.Attribute("Type") != null)
                            {
                                strokeType = strokeElement.Attribute("Type").Value.ToLower();
                            }

                            if (strokeElement.Attribute("Value") != null)
                            {
                                strokeValue = strokeElement.Attribute("Value").Value.ToLower();

                                if (strokeValue.Contains("+"))
                                {
                                    keys = strokeValue.Split('+');
                                }
                                else if (strokeValue.StartsWith("{") && strokeValue.EndsWith("}"))
                                {
                                    keys[0] = strokeValue;
                                }
                                else
                                {
                                    keys = strokeValue.ToCharArray().Select(c => c.ToString()).ToArray();
                                }
                            }

                            if (strokeElement.Attribute("Repeat") != null)
                            {
                                strokeRepeat = int.Parse(strokeElement.Attribute("Repeat").Value);
                            }

                            if (macros != null && macros.ContainsKey(strokeValue))
                            {
                                char[] keyStrokeChars = macros[strokeValue].ToCharArray();

                                foreach (char keyStrokeChar in keyStrokeChars)
                                {
                                    KeyStroke macroKeystrokeDown = new KeyStroke();
                                    macroKeystrokeDown.Type = KeyStrokeTypes.Down;
                                    macroKeystrokeDown.Value = ConvertKeyStrokeToCode(keyStrokeChar.ToString());
                                    batch.InputActions.Add(macroKeystrokeDown);

                                    KeyStroke macroKeystrokeUp = new KeyStroke();
                                    macroKeystrokeUp.Type = KeyStrokeTypes.Up;
                                    macroKeystrokeUp.Value = ConvertKeyStrokeToCode(keyStrokeChar.ToString());
                                    batch.InputActions.Add(macroKeystrokeUp);
                                }
                            }
                            else
                            {
                                for (int i = 1; i <= strokeRepeat; i++)
                                {
                                    if (strokeType == "down" || strokeType == "downup")
                                    {
                                        for (int j = 0; j < keys.Length; j++)
                                        {
                                            KeyStroke keyStrokeDown = new KeyStroke();
                                            keyStrokeDown.Type = KeyStrokeTypes.Down;
                                            keyStrokeDown.Value = ConvertKeyStrokeToCode(keys[j]);
                                            batch.InputActions.Add(keyStrokeDown);
                                        }
                                    }

                                    if (strokeType == "up" || strokeType == "downup")
                                    {
                                        for (int j = keys.Length - 1; j >= 0; j--)
                                        {
                                            KeyStroke keyStrokeUp = new KeyStroke();
                                            keyStrokeUp.Type = KeyStrokeTypes.Up;
                                            keyStrokeUp.Value = ConvertKeyStrokeToCode(keys[j]);
                                            batch.InputActions.Add(keyStrokeUp);
                                        }
                                    }
                                }
                            }

                            break;

                        case "MouseClick":
                            string clickType = "click";
                            int clickRepeat = 1;
                            int x = 0;
                            int y = 0;
                            string relativeTo = "window";

                            if (strokeElement.Attribute("Type") != null)
                            {
                                clickType = strokeElement.Attribute("Type").Value.ToLower();
                            }

                            if (strokeElement.Attribute("RelativeTo") != null)
                            {
                                relativeTo = strokeElement.Attribute("RelativeTo").Value.ToLower();
                            }

                            if (strokeElement.Attribute("Repeat") != null)
                            {
                                clickRepeat = int.Parse(strokeElement.Attribute("Repeat").Value);
                            }

                            if (strokeElement.Attribute("X") != null)
                            {
                                x = int.Parse(strokeElement.Attribute("X").Value);
                            }

                            if (strokeElement.Attribute("Y") != null)
                            {
                                y = int.Parse(strokeElement.Attribute("Y").Value);
                            }

                            for (int i = 1; i <= clickRepeat; i++)
                            {
                                MouseClick mouseClickMoveTo = new MouseClick();
                                mouseClickMoveTo.Type = MouseClickTypes.Move;
                                mouseClickMoveTo.Coordinates = new Point(x, y);
                                mouseClickMoveTo.RelativeTo = relativeTo;
                                batch.InputActions.Add(mouseClickMoveTo);

                                if (clickType == "down" || clickType == "click")
                                {
                                    MouseClick mouseClick = new MouseClick();
                                    mouseClick.Type = MouseClickTypes.Down;
                                    mouseClick.Coordinates = new Point(x, y);
                                    mouseClick.RelativeTo = relativeTo;
                                    batch.InputActions.Add(mouseClick);
                                }

                                if (clickType == "up" || clickType == "click")
                                {
                                    MouseClick mouseClick = new MouseClick();
                                    mouseClick.Type = MouseClickTypes.Up;
                                    mouseClick.Coordinates = new Point(x, y);
                                    mouseClick.RelativeTo = relativeTo;
                                    batch.InputActions.Add(mouseClick);
                                }
                            }
                            break;
                    }


                }

                _uiAutomation.InputBatches.Add(batch);
            }
        }