SendInput() PInvoke не работает, не знаю почему

По какой-то причине SendInput() Pinvoke не работает. SendInput() всегда возвращает 0, я пытался запустить его от имени администратора, но никаких изменений. он отлично работает в С++. Я искал часы, пожалуйста, помогите мне. Я использую компьютер с Windows 8 64x бит. Может быть, это как-то связано с моей операционной системой?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication6
{
    class Program
    {
        [DllImport("User32.dll", SetLastError = true)]
        public static extern int SendInput(int nInputs, INPUT[] inputs, int cbSize);

        public struct INPUT
        {
            public int type;
            public KEYBDINPUT ki;

        }

        private static KEYBDINPUT createKeybdInput(ushort wVK, uint flag)
        {
            KEYBDINPUT i = new KEYBDINPUT();

            i.wVk = wVK;
            i.wScan = 0;
            i.time = 0;
            i.dwExtraInfo = IntPtr.Zero;
            i.dwFlags = flag;
            return i;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct KEYBDINPUT
        {
            public ushort wVk;
            public ushort wScan;
            public uint dwFlags;
            public uint time;
            public IntPtr dwExtraInfo;
        }



        public static void sim_type()
        {

            INPUT[] inp = new INPUT[2];


            inp[0].type = 1;
            inp[0].ki = createKeybdInput(0x41, 0x0001);
            inp[1].type = 1;
            inp[1].ki = createKeybdInput(0x41, 0x0002);



            if (SendInput(2, inp, Marshal.SizeOf(typeof(INPUT))) == 0)
            {
                Console.WriteLine("error");
            }



        }

        static void Main(string[] args)
        {
            Console.ReadLine();
            sim_type();
            Console.ReadLine();

        }


    }
}

Спасибо!


person alcedo707    schedule 14.11.2013    source источник
comment
Используйте Marshal.GetLastWin32Error() для правильного сообщения об ошибках. Есть некоторые шансы, что вы также обнаружите, что ваше объявление INPUT совершенно неверно. Вы не можете просто оставлять вещи, которыми не пользуетесь. Используйте pinvoke.net для лучшего объявления. Использование KEYEVENTF_EXTENDEDKEY тоже неверно.   -  person Hans Passant    schedule 14.11.2013


Ответы (1)


Проблема в том, что ваш перевод INPUT неверен. Посмотрите на определение из MSDN. :

typedef struct tagINPUT {
  DWORD type;
  union {
    MOUSEINPUT    mi;
    KEYBDINPUT    ki;
    HARDWAREINPUT hi;
  } DUMMYUNIONNAME;
} INPUT, *PINPUT, *LPINPUT;

Ваше определение KEYBDINPUT прекрасно, но как насчет MOUSEINPUT и HARDWAREINPUT? Вы просто проигнорировали их. Это союз, поэтому все три члена лежат друг над другом. Таким образом, ваше объявление может работать только в том случае, если KEYBDINPUT является самым большим из трех. А умные деньги говорят, что это не так.

Итак, объявите MOUSEINPUT и HARDWAREINPUT и включите их в свой перевод INPUT. Вы можете получить готовые, работающие переводы на pinvoke.net. И обязательно обратите внимание на сообщения об ошибках, возвращаемые вызовом API. Вы указали SetLastError как true. Поэтому прочитайте значение и обратите на него внимание.

person David Heffernan    schedule 14.11.2013