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

  • 問題

  • 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();
    
      }
     }
    }
    
    

     


    2011年6月5日 下午 12:04

解答

  • 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.


    2011年6月8日 上午 09:06

所有回覆

  • 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/
    2011年6月5日 下午 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)

    2011年6月5日 下午 01:22
  • FWIW:

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

     


    2011年6月5日 下午 05: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

    2011年6月6日 上午 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.


    2011年6月8日 上午 09:06
  • This does the trick! Many thanks!
    2011年6月9日 上午 06:44
  • Eric Yang You're such a life saver this think started to get me mad! thank you!
    • 已編輯 Nico442 2020年7月5日 下午 07:28
    2020年7月5日 下午 07:27