0

I have been using some code from https://github.com/cerebrate/mousejiggler to keep a Windows PC from going idle. It worked find, but when I ported it to a new app it started crashing when ever it executed. Specifically at the line:

if (SendInput(1, ref inp, 28) != 1)
    throw new Win32Exception();

The new app was running as a x64 application, where as the old one was x86. Building the new app for x86 fixed this issue. The full code is below. I am struggling to work out why this is the case. There is one IntPtr in the strut that will change from 4 bytes to 8 bytes depending on the platform, but as far as I'm aware there isn't a way to change this. I guess I could create a 32 bit int pointer and use unsafe code, but I'm not even sure this is actually the problem yet.

Any ideas on how I can fix it for x64 platforms?

[StructLayout(LayoutKind.Sequential)]
struct LASTINPUTINFO
{
    public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO));

    [MarshalAs(UnmanagedType.U4)]
    public UInt32 cbSize;
    [MarshalAs(UnmanagedType.U4)]
    public UInt32 dwTime;
}

[DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

static uint GetLastInputTime()
{
    uint idleTime = 0;
    LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
    lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo);
    lastInputInfo.dwTime = 0;

    uint envTicks = (uint)Environment.TickCount;

    if (GetLastInputInfo(ref lastInputInfo))
    {
        uint lastInputTick = lastInputInfo.dwTime;

        idleTime = envTicks - lastInputTick;
    }

    return ((idleTime > 0) ? (idleTime / 1000) : 0);
}

public static class Jiggler
{
    internal const int INPUT_MOUSE = 0;
    internal const int MOUSEEVENTF_MOVE = 0x0001;

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

    public static void Jiggle(int dx, int dy)
    {
        var inp = new INPUT();
        inp.TYPE = Jiggler.INPUT_MOUSE;
        inp.dx = dx;
        inp.dy = dy;
        inp.mouseData = 0;
        inp.dwFlags = Jiggler.MOUSEEVENTF_MOVE;
        inp.time = 0;
        inp.dwExtraInfo = (IntPtr)0;

        if (SendInput(1, ref inp, 28) != 1)
            throw new Win32Exception();
    }
}

[StructLayout(LayoutKind.Sequential)]
internal struct INPUT
{
    public int TYPE;
    public IntPtr dwExtraInfo;
    public int dwFlags;
    public int dx;
    public int dy;
    public int mouseData;
    public int time;
}
MikeS159
  • 1,884
  • 3
  • 29
  • 54
  • "Building the new app for x86 fixed this issue"... If there's no need for your program to be compiled for 64bit then you're good to go, no? To run in 64bit, most likely you'll need a DLL compiled for 64 bit platforms. – spender Oct 31 '18 at 16:39
  • There is no need for it to run as x64, but since it is using a standard Windows dll, I would be surprised if there was no way to use it under a x64 application. – MikeS159 Oct 31 '18 at 16:42

1 Answers1

2

Its not going to work as the Windows functions are architecture specific, in this case 32 bit specific.

To make SendInput work for 64bit see SendInput and 64bits

However there is not an equivalent 64 bit function for GetLastInputInfo but see Is there a 64 bit equivalent to GetLastInputInfo / LASTINPUTINFO? for how you might be able to do it if you need to be running in 64 bit.

PhilS
  • 624
  • 3
  • 5