Winapi F#System.Runtime.InteropServices对SendInput的本机库调用在.net framework中有效,但在.net core中无效

Winapi F#System.Runtime.InteropServices对SendInput的本机库调用在.net framework中有效,但在.net core中无效,winapi,f#,user32,sendinput,Winapi,F#,User32,Sendinput,我正在将我为keybindings编写的一个小应用程序移植到.NETCore,我遇到了一个行为不同的实例。我用这份声明打电话给F# open System.Runtime.InteropServices [<StructLayout(LayoutKind.Sequential)>] type private MOUSEINPUT = struct val dx: int32 val dy:int32 val mouseData:uint32 val

我正在将我为keybindings编写的一个小应用程序移植到.NETCore,我遇到了一个行为不同的实例。我用这份声明打电话给F#

open System.Runtime.InteropServices

[<StructLayout(LayoutKind.Sequential)>]
type private MOUSEINPUT = struct
    val dx: int32
    val dy:int32
    val mouseData:uint32
    val dwFlags: uint32
    val time: uint32
    val dwExtraInfo: int
    new(_dx, _dy, _mouseData, _dwFlags, _time, _dwExtraInfo) = {dx=_dx; dy=_dy; mouseData=_mouseData; dwFlags=_dwFlags; time=_time; dwExtraInfo=_dwExtraInfo}
end

[<StructLayout(LayoutKind.Sequential)>]
type private KEYBDINPUT = struct
    val wVk: uint16
    val wScan: uint16
    val dwFlags: uint32
    val time: uint32
    val dwExtraInfo:int
    new(_wVk, _wScan, _dwFlags, _time, _dwExtraInfo) = {wVk =_wVk; wScan = _wScan; dwFlags = _dwFlags; time = _time; dwExtraInfo = _dwExtraInfo}
end

[<StructLayout(LayoutKind.Sequential)>]
type private HARDWAREINPUT = struct
    val uMsg: uint32
    val wParamL: uint16
    val wParamH: uint16
    new(_uMsg, _wParamL, _wParamH) = {uMsg = _uMsg; wParamL = _wParamL; wParamH = _wParamH}
end

[<StructLayout(LayoutKind.Explicit)>]
type private LPINPUT  = struct
    [<FieldOffset(0)>]
    val mutable ``type``:int // 1 is keyboard

    [<FieldOffset(4)>]
    val mutable mi : MOUSEINPUT

    [<FieldOffset(4)>]
    val mutable ki : KEYBDINPUT

    [<FieldOffset(4)>]
    val mutable hi : HARDWAREINPUT
end

module private NativeMethods =
    [<DllImport("user32.dll", SetLastError=true)>]
    extern uint32 SendInput(uint32 nInputs, LPINPUT* pInputs, int cbSize)

let appSignature = 0xA8969

let private createPressInput (code: int) =
    let mutable input = LPINPUT()
    input.``type`` <- InputModes.INPUT_KEYBOARD
    input.ki <- KEYBDINPUT(uint16  code, uint16 0, Dwords.KEYEVENTF_KEYDOWN, uint32 0, appSignature)
    input

let pressKey (code: int) =
    let input = createPressInput code
    NativeMethods.SendInput(uint32 1, &&input, Marshal.SizeOf(input)) |> ignore

最后我打开了一个关于这个的bug

这在.net中不是一个问题。显然,我的.NETFramework应用程序是以32位的速度运行的。我已经将
dwExtraInfo
字段声明为
int
,这对于32位来说很好。我的.net核心应用程序以64位运行,我应该使用
UIntPtr
来处理该字段长度的平台差异。更新到这个代码,它的工作

[<StructLayout(LayoutKind.Sequential)>]
type private MOUSEINPUT = struct
    val dx: int32
    val dy:int32
    val mouseData:uint32
    val dwFlags: uint32
    val time: uint32
    val dwExtraInfo: UIntPtr
    new(_dx, _dy, _mouseData, _dwFlags, _time, _dwExtraInfo) = {dx=_dx; dy=_dy; mouseData=_mouseData; dwFlags=_dwFlags; time=_time; dwExtraInfo=_dwExtraInfo}
end

[<StructLayout(LayoutKind.Sequential)>]
type private KEYBDINPUT = struct
    val wVk: uint16
    val wScan: uint16
    val dwFlags: uint32
    val time: uint32
    val dwExtraInfo: UIntPtr
    new(_wVk, _wScan, _dwFlags, _time, _dwExtraInfo) = {wVk =_wVk; wScan = _wScan; dwFlags = _dwFlags; time = _time; dwExtraInfo = _dwExtraInfo}
end

[<StructLayout(LayoutKind.Sequential)>]
type private HARDWAREINPUT = struct
    val uMsg: uint32
    val wParamL: uint16
    val wParamH: uint16
    new(_uMsg, _wParamL, _wParamH) = {uMsg = _uMsg; wParamL = _wParamL; wParamH = _wParamH}
end


[<StructLayout(LayoutKind.Explicit)>]
type private InputUnion = struct
    [<FieldOffset(0)>]
    val mutable mi : MOUSEINPUT

    [<FieldOffset(0)>]
    val mutable ki : KEYBDINPUT

    [<FieldOffset(0)>]
    val mutable hi : HARDWAREINPUT 
end

[<StructLayout(LayoutKind.Sequential)>]
type private LPINPUT  = struct
    val mutable ``type``: int // 1 is keyboard
    val mutable u: InputUnion
end
[]
键入private MOUSEINPUT=struct
val-dx:int32
瓦迪:int32
瓦尔·穆塞达塔:uint32
val dwFlags:uint32
val时间:uint32
val dwExtraInfo:UINTPTTR
新建(_dx,_dy,_mouseData,_dwFlags,_time,_dwExtraInfo)={dx=_dx;dy=_dy;mouseData=_mouseData;dwFlags=_dwFlags;time=_time;dwExtraInfo=_dwExtraInfo}
结束
[]
键入private-KEYBDINPUT=struct
val wVk:uint16
val wScan:uint16
val dwFlags:uint32
val时间:uint32
val dwExtraInfo:UINTPTTR
新建(_wVk,_wScan,_dwFlags,_time,_dwExtraInfo)={wVk=_wVk;wScan=_wScan;dwFlags=_dwFlags;time=_time;dwExtraInfo=_dwExtraInfo}
结束
[]
类型private HARDWAREINPUT=struct
val uMsg:uint32
val wParamL:uint16
val wParamH:uint16
新的({uMsg,{wParamL,{wParamH)={uMsg={uMsg;wParamL={wParamL;wParamH=}
结束
[]
类型private InputUnion=struct
[]
val可变mi:鼠标输入
[]
val可变ki:KEYBDINPUT
[]
val可变高:硬件输入
结束
[]
类型private LPINPUT=struct
val可变``type`:int//1是键盘
val可变u:InputUnion
结束

主要区别在于
dwExtraInfo
字段定义。此外,现在有一个用于联合的显式类型,而不是将其全部滚动到一个
LPINPUT
。这样,我就不必为3个可选字段指定字段偏移量,这3个字段也因平台而异。

我根据您的代码构建了一个最小的复制。可以找到它。很抱歉,我没有更多的帮助。我还使用Csharp构建了一个复制程序。我把你的fsharp代码翻译成了csharp。同样的事情在dotnet框架中也可以很好地工作,但是显示了dotnet核心的错误代码87。很好,谢谢。我想这意味着这不是一个F#问题,而是一个.net核心问题。我确实设法找到了一个我不满意的解决方案。我将使用此解决方案更新原始问题。错误代码5可能与。您需要满足一些特定的要求。这是一条线索。
[<StructLayout(LayoutKind.Sequential)>]
type private MOUSEINPUT = struct
    val dx: int32
    val dy:int32
    val mouseData:uint32
    val dwFlags: uint32
    val time: uint32
    val dwExtraInfo: UIntPtr
    new(_dx, _dy, _mouseData, _dwFlags, _time, _dwExtraInfo) = {dx=_dx; dy=_dy; mouseData=_mouseData; dwFlags=_dwFlags; time=_time; dwExtraInfo=_dwExtraInfo}
end

[<StructLayout(LayoutKind.Sequential)>]
type private KEYBDINPUT = struct
    val wVk: uint16
    val wScan: uint16
    val dwFlags: uint32
    val time: uint32
    val dwExtraInfo: UIntPtr
    new(_wVk, _wScan, _dwFlags, _time, _dwExtraInfo) = {wVk =_wVk; wScan = _wScan; dwFlags = _dwFlags; time = _time; dwExtraInfo = _dwExtraInfo}
end

[<StructLayout(LayoutKind.Sequential)>]
type private HARDWAREINPUT = struct
    val uMsg: uint32
    val wParamL: uint16
    val wParamH: uint16
    new(_uMsg, _wParamL, _wParamH) = {uMsg = _uMsg; wParamL = _wParamL; wParamH = _wParamH}
end


[<StructLayout(LayoutKind.Explicit)>]
type private InputUnion = struct
    [<FieldOffset(0)>]
    val mutable mi : MOUSEINPUT

    [<FieldOffset(0)>]
    val mutable ki : KEYBDINPUT

    [<FieldOffset(0)>]
    val mutable hi : HARDWAREINPUT 
end

[<StructLayout(LayoutKind.Sequential)>]
type private LPINPUT  = struct
    val mutable ``type``: int // 1 is keyboard
    val mutable u: InputUnion
end