locked
SendInput won't work when compiled with x64 option RRS feed

  • Pergunta

  • The following is a complete SendInput example ready for test. Just simply create a console project and paste the code. When running, press space key and if SendInput works then two 'a's will be printed on the console; otherwise nothing will appear.

    My problem is this code works only when compiled with x86 option (Right click the project root in the Solution Explorer, click Properties, and select Build tab. The problem is about a combobox with 4 options : Any CPU, x64, x86, Itanium). I want to get the code to work also with x64 option. If anyone could help me. Thanks a lot!

    By the way, I'm using vs2010, win7 x64, uac turned off

    using System;
    using System.Runtime.InteropServices;
    
    namespace SETest
    {
     [StructLayout(LayoutKind.Sequential)]
     internal struct KEYBDINPUT
     {
      public ushort wVk;
      public short wScan;
      public uint dwFlags;
      public int time;
      public int dwExtraInfo;
     }
    
     [StructLayout(LayoutKind.Sequential)]
     internal struct MOUSEINPUT
     {
      public int dx;
      public int dy;
      public int mouseData;
      public uint dwFlags;
      public int time;
      public int dwExtraInfo;
     }
    
     [StructLayout(LayoutKind.Sequential)]
     internal struct HARDWAREINPUT
     {
      public int uMsg;
      public short wParamL;
      public short wParamH;
     }
    
     [StructLayout(LayoutKind.Explicit)]
     internal struct INPUT
     {
      [FieldOffset(0)]
      public uint type;
      [FieldOffset(4)]
      public MOUSEINPUT mi;
      [FieldOffset(4)]
      public KEYBDINPUT ki;
      [FieldOffset(4)]
      public HARDWAREINPUT hi;
     }
    
     class Program
     {
      [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
      internal static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
    
      static void Main(string[] args)
      {
       Console.ReadKey();
    
       INPUT[] keyInput = new INPUT[4];
       keyInput[0].type = 1;
       keyInput[1].type = 1;
       keyInput[2].type = 1;
       keyInput[3].type = 1;
    
       KEYBDINPUT[] key = new KEYBDINPUT[4];
       key[0].wVk = 65;
       key[0].wScan = 65;
       key[0].dwFlags = 0;
       key[1].wVk = 65;
       key[1].wScan = 65;
       key[1].dwFlags = 0;
       key[2].wVk = 65;
       key[2].wScan = 65;
       key[2].dwFlags = 0x02;
       key[3].wVk = 65;
       key[3].wScan = 65;
       key[3].dwFlags = 0x02;
    
    
       keyInput[0].ki = key[0];
       keyInput[1].ki = key[1];
       keyInput[2].ki = key[2];
       keyInput[3].ki = key[3];
    
       SendInput(4, keyInput, Marshal.SizeOf(typeof(INPUT)));
    
       Console.ReadKey();
       Console.ReadKey();
       Console.ReadKey();
    
      }
     }
    }
    
    

     


    domingo, 5 de junho de 2011 12:04

Respostas

  • Consider different alignment value and pointer's size of 64bit process (4 in 32bit process, and 8 in 64bit process), you may want to redefine those structures as following:

        [StructLayout(LayoutKind.Sequential, Pack = 8)]

        internal struct KEYBDINPUT

        {

            public ushort wVk;

            public short wScan;

            public uint dwFlags;

            public int time;

            public IntPtr dwExtraInfo;

        }

     

        [StructLayout(LayoutKind.Sequential, Pack = 8)]

        internal struct MOUSEINPUT

        {

            public int dx;

            public int dy;

            public int mouseData;

            public uint dwFlags;

            public int time;

            public IntPtr dwExtraInfo;

        }

     

        [StructLayout(LayoutKind.Sequential, Pack = 8)]

        internal struct HARDWAREINPUT

        {

            public int uMsg;

            public short wParamL;

            public short wParamH;

        }

     

        [StructLayout(LayoutKind.Explicit)]

        internal struct INPUT

        {

            [FieldOffset(0)]

            public uint type;

            [FieldOffset(8)]

            public MOUSEINPUT mi;

            [FieldOffset(8)]

            public KEYBDINPUT ki;

            [FieldOffset(8)]

            public HARDWAREINPUT hi;

        }


    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    • Marcado como Resposta Tony_rivermsfly quinta-feira, 9 de junho de 2011 06:44
    quarta-feira, 8 de junho de 2011 09:06

Todas as Respostas

  • Hello Tony_rivermsfly,

    the fact that you do not do as running x64 I think dependent on the use of user32.dll, in fact compiling under x86 32bit operation and adapt programs to run 64-bit operating systems.


    Hello


    Carmelo La Monica  http://community.visual-basic.it/carmelolamonica/
    domingo, 5 de junho de 2011 12:28
  • Thanks for you kind reply:), but I found this by google:

    The name user32.dll is misleading. It's the 64 bit version of user32.dll you're calling. The 64 bit version is located at %windir%\System32\user32.dll.

    A 32-bit version is included for compatibility with 32-bit applications. It's located at %windir%\SysWOW64\user32.dll. You can inspect them using the dumpbin utility:

    System32\user32.dll:

    FILE HEADER VALUES

            8664 machine (x64)

    SysWOW64\user32.dll:

    FILE HEADER VALUES

             14C machine (x86)

    domingo, 5 de junho de 2011 13:22
  • FWIW:

    I've used keybd_event SendKeys for XP through Win7 on 32 and 64 bit systems (targeting Any Cpu) without problem.

     


    domingo, 5 de junho de 2011 17:39
  • The principal difference between x86 and x64 is the size of a pointer - in x86, pointers are 32 bits.

    It's also important to understand that in order to maintain compatability with 32 bit applications your operating system keeps 32 bit versions of all native assembles even in x64 versions of assemblies.

    When you build a CLR assembly with the x86 option, the CLR process will be constrained to 32 bit mode - you will be able to see this in task manager.  Your process name will be (yourname)*32.  This means that you are in fact loading the 32 bit version of user32.dll.

    Evan

    segunda-feira, 6 de junho de 2011 03:01
  • Consider different alignment value and pointer's size of 64bit process (4 in 32bit process, and 8 in 64bit process), you may want to redefine those structures as following:

        [StructLayout(LayoutKind.Sequential, Pack = 8)]

        internal struct KEYBDINPUT

        {

            public ushort wVk;

            public short wScan;

            public uint dwFlags;

            public int time;

            public IntPtr dwExtraInfo;

        }

     

        [StructLayout(LayoutKind.Sequential, Pack = 8)]

        internal struct MOUSEINPUT

        {

            public int dx;

            public int dy;

            public int mouseData;

            public uint dwFlags;

            public int time;

            public IntPtr dwExtraInfo;

        }

     

        [StructLayout(LayoutKind.Sequential, Pack = 8)]

        internal struct HARDWAREINPUT

        {

            public int uMsg;

            public short wParamL;

            public short wParamH;

        }

     

        [StructLayout(LayoutKind.Explicit)]

        internal struct INPUT

        {

            [FieldOffset(0)]

            public uint type;

            [FieldOffset(8)]

            public MOUSEINPUT mi;

            [FieldOffset(8)]

            public KEYBDINPUT ki;

            [FieldOffset(8)]

            public HARDWAREINPUT hi;

        }


    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    • Marcado como Resposta Tony_rivermsfly quinta-feira, 9 de junho de 2011 06:44
    quarta-feira, 8 de junho de 2011 09:06
  • This does the trick! Many thanks!
    quinta-feira, 9 de junho de 2011 06:44
  • Eric Yang You're such a life saver this think started to get me mad! thank you!
    • Editado Nico442 domingo, 5 de julho de 2020 19:28
    domingo, 5 de julho de 2020 19:27