SendInput Always Returns "0"

G

Guest

Hello All,
I am writing a program that checks for the NumLock status and turns the NumLock on if it is off.
I'm not sure what I'm overlooking at this point, but the code will compile and run, but the SendInput call always returns "0".
Here is some of the code:

Beginning of Code...

[DllImport("user32.dll")]
static extern uint SendInput(uint nInputs, ref INPUT [] pInputs, int cbSize);

[StructLayout(LayoutKind.Explicit)]
public struct INPUT
{
[FieldOffset(0)] public int type;
[FieldOffset(4)] public KEYBDINPUT ki;
}

public struct KEYBDINPUT
{
public short wVk;
public short wScan;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
}

....Code Deleted...

INPUT [] input = new INPUT [1];
input[0].ki.wVk = 0x90;
input[0].type = 0x01;
uint result;
result = SendInput(1, ref input, Marshal.SizeOf(input));

....End of Code

result will always equal "0". Does anyone know what would cause this or, even better, how to get this to work? I'm at a complete loss.

Thank you in advance for your help,
-Tim
 
G

Guest

Haven't done this since the DOS dayzzzz!!!!

Anyway, I think there is an easier way to do this in .NET --> Lookup "Keys Enumeration" in MSDN. NumLock etal are all listed and there must be a sample somewhere that shows how to poke/peek NumLock state... {Remember that NumLock behaves like CapsLock and ScrollLock so sample may be for any of those...

--Richard
 
K

Ken Kolda

I don't do much with P/Invoke, but the definition of SendInput() includes a
LPINPUT (pointer-to-INPUT) for the second parameter. I would think you could
either declare this as:

[DllImport("user32.dll")]
static extern uint SendInput(uint nInputs, ref INPUT pInput, int cbSize);

or

[DllImport("user32.dll")]
static extern uint SendInput(uint nInputs, INPUT [] pInputs, int cbSize);

depending on whether you intend to pass one or more INPUT items. Either of
the above functions should pass a pointer-to-INPUT to the API. By using "ref
INPUT[]" you're creating a pointer-to-pointer-to-INPUT parameter, which
could certainly cause problems.

Again, that's just a guess -- I haven't tried this so I don't know if it
works or not.

Ken


Tim said:
Hello All,
I am writing a program that checks for the NumLock status and turns the NumLock on if it is off.
I'm not sure what I'm overlooking at this point, but the code will compile
and run, but the SendInput call always returns "0".
Here is some of the code:

Beginning of Code...

[DllImport("user32.dll")]
static extern uint SendInput(uint nInputs, ref INPUT [] pInputs, int cbSize);

[StructLayout(LayoutKind.Explicit)]
public struct INPUT
{
[FieldOffset(0)] public int type;
[FieldOffset(4)] public KEYBDINPUT ki;
}

public struct KEYBDINPUT
{
public short wVk;
public short wScan;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
}

...Code Deleted...

INPUT [] input = new INPUT [1];
input[0].ki.wVk = 0x90;
input[0].type = 0x01;
uint result;
result = SendInput(1, ref input, Marshal.SizeOf(input));

...End of Code

result will always equal "0". Does anyone know what would cause this or,
even better, how to get this to work? I'm at a complete loss.
 
K

Ken Kolda

By the way, don't you get an exception when you call Marshal.SizeOf(input)?
The variable "input" is an array, not a struct type, so the call should
fail.

Ken


Ken Kolda said:
I don't do much with P/Invoke, but the definition of SendInput() includes a
LPINPUT (pointer-to-INPUT) for the second parameter. I would think you could
either declare this as:

[DllImport("user32.dll")]
static extern uint SendInput(uint nInputs, ref INPUT pInput, int cbSize);

or

[DllImport("user32.dll")]
static extern uint SendInput(uint nInputs, INPUT [] pInputs, int cbSize);

depending on whether you intend to pass one or more INPUT items. Either of
the above functions should pass a pointer-to-INPUT to the API. By using "ref
INPUT[]" you're creating a pointer-to-pointer-to-INPUT parameter, which
could certainly cause problems.

Again, that's just a guess -- I haven't tried this so I don't know if it
works or not.

Ken


Tim said:
Hello All,
I am writing a program that checks for the NumLock status and turns the NumLock on if it is off.
I'm not sure what I'm overlooking at this point, but the code will
compile
and run, but the SendInput call always returns "0".
Here is some of the code:

Beginning of Code...

[DllImport("user32.dll")]
static extern uint SendInput(uint nInputs, ref INPUT [] pInputs, int cbSize);

[StructLayout(LayoutKind.Explicit)]
public struct INPUT
{
[FieldOffset(0)] public int type;
[FieldOffset(4)] public KEYBDINPUT ki;
}

public struct KEYBDINPUT
{
public short wVk;
public short wScan;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
}

...Code Deleted...

INPUT [] input = new INPUT [1];
input[0].ki.wVk = 0x90;
input[0].type = 0x01;
uint result;
result = SendInput(1, ref input, Marshal.SizeOf(input));

...End of Code

result will always equal "0". Does anyone know what would cause this
or,
even better, how to get this to work? I'm at a complete loss.
Thank you in advance for your help,
-Tim
 
W

Willy Denoyette [MVP]

1. You have to marshal the struct yourself.
You can do this by flatten the array and marshal the struct to an unmanaged
buffer, when calling SendInput you simply pass the pointer to the unmanaged
buffer as an IntPtr.
2. Also you need to be aware the the struct contains a union, so you need to
set the length of the longest element (the MOUSEINPUT struct) as third
argument.
3. You need to inject two structs ( one for keydown another for keyup) in
the stream.

Here's a working sample that sets numlock on.

class Tester
{
[StructLayout(LayoutKind.Sequential)]
public struct INPUT
{
public int type;
public short wVk;
public short wScan;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
public int type1;
public short wVk1;
public short wScan1;
public int dwFlags1;
public int time1;
public IntPtr dwExtraInfo1;

}
[DllImport("user32.dll")]
static extern int SendInput(uint nInputs, IntPtr pInputs, int cbSize);


static void Main()
{
INPUT input = new INPUT();
input.type = 0x01; //INPUT_KEYBOARD
input.wVk = 0x90; //VK_NUMLOCK
input.wScan = 0;
input.dwFlags = 0; //key-down
input.time = 0;
input.dwExtraInfo = IntPtr.Zero;

input.type1 = 0x01;
input.wVk1 = 0x90;
input.wScan1= 0;
input.dwFlags1 = 2; //key-up
input.time1 = 0;
input.dwExtraInfo1 = IntPtr.Zero;

IntPtr pI = Marshal.AllocHGlobal(28);
Marshal.StructureToPtr(input, pI, false);
int result;
result = SendInput(1, pI, 28); //Hardcoded size of the MOUSEINPUT tag !!!

if (result == 0 || Marshal.GetLastWin32Error() != 0)
Console.WriteLine(Marshal.GetLastWin32Error());;
}

Willy.
 
W

Willy Denoyette [MVP]

Small typeo in my previous post.

result = SendInput(2, pI, 28); // two structs

Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top