I have the following C++ to get information about a specific monitor using the EnumDisplaySettings WinAPI function.
#include <iostream>
#include <Windows.h>
int main()
{
DEVMODE dm;
dm.dmSize = sizeof dm;
EnumDisplaySettings(L"\\\\.\\DISPLAY1", ENUM_CURRENT_SETTINGS, &dm);
std::wcout << "Name: " << dm.dmDeviceName << std::endl;
std::wcout << "Width: " << dm.dmPelsWidth << std::endl;
std::wcout << "Height: " << dm.dmPelsHeight << std::endl;
}
I am trying to use the EnumDisplaySettings function in C#.
To do this, I have recreated DEVMODEW as a C# struct and pass it into the method.
static void Main()
{
DeviceModeStruct deviceMode = new DeviceModeStruct();
deviceMode.dmSize = (ushort)Marshal.SizeOf(deviceMode);
bool successfullyGotScale = EnumDisplaySettings("\\\\.\\DISPLAY1",
ENUM_CURRENT_SETTINGS,
ref deviceMode);
if (successfullyGotScale)
{
Console.WriteLine($#"Name: {deviceMode.dmDeviceName}");
Console.WriteLine($#"Width: {deviceMode.dmPelsWidth}");
Console.WriteLine($#"Height: {deviceMode.dmPelsHeight}");
}
}
The issue is, when I run the code, I get the following exception.
Unhandled Exception: System.TypeLoadException: Could not load type 'DeviceModeStruct'
from assembly 'DevModeSo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
because it contains an object field at offset 70 that is incorrectly aligned or
overlapped by a non-object field.
at DevModeSo.Program.Main()
As far as I can tell, the issue is relating to
[FieldOffset(70), MarshalAs(UnmanagedType.ByValTStr, SizeConst = STRING_SIZE)]
public string dmFormName;
and this answer to another similar Stack Overflow question seems to suggest I can split the string up to fix the issue.
However, when I tried to do that so that the code so that the values were aligned with "DWORDS" I got the same error.
[FieldOffset(70)]
public char dmFormName1;
[FieldOffset(71)]
public char dmFormName2;
[FieldOffset(72), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)]
public string dmFormName3;
How can this problem be resolved whilst still meeting the same data structure as defined by DEVMODEW?
Full C# code
using System;
using System.Runtime.InteropServices;
namespace DevModeSo
{
class Program
{
private const int ENUM_CURRENT_SETTINGS = -1;
static void Main()
{
DeviceModeStruct deviceMode = new DeviceModeStruct();
deviceMode.dmSize = (ushort)Marshal.SizeOf(deviceMode);
bool successfullyGotScale = EnumDisplaySettings("\\\\.\\DISPLAY1",
ENUM_CURRENT_SETTINGS,
ref deviceMode);
if (successfullyGotScale)
{
Console.WriteLine($#"Name: {deviceMode.dmDeviceName}");
Console.WriteLine($#"Width: {deviceMode.dmPelsWidth}");
Console.WriteLine($#"Height: {deviceMode.dmPelsHeight}");
}
}
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool EnumDisplaySettings(string deviceName,
int modeNum,
ref DeviceModeStruct deviceMode);
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
struct DeviceModeStruct
{
private const int STRING_SIZE = 32;
[FieldOffset(0), MarshalAs(UnmanagedType.ByValTStr, SizeConst = STRING_SIZE)]
public string dmDeviceName;
[FieldOffset(32)] public ushort dmSpecVersion;
[FieldOffset(34)] public ushort dmDriverVersion;
[FieldOffset(36)] public ushort dmSize;
[FieldOffset(38)] public ushort dmDriverExtra;
[FieldOffset(40)] public uint dmFields;
[FieldOffset(44)] public PrinterOnlyFields printerMode;
[FieldOffset(44)] public DisplayOnlyFields displayMode;
[FieldOffset(60)] public short dmColor;
[FieldOffset(62)] public short dmDuplex;
[FieldOffset(64)] public short dmYResolution;
[FieldOffset(66)] public short dmTTOption;
[FieldOffset(68)] public short dmCollate;
[FieldOffset(70), MarshalAs(UnmanagedType.ByValTStr, SizeConst = STRING_SIZE)]
public string dmFormName;
[FieldOffset(102)] public ushort dmLogPixels;
[FieldOffset(104)] public uint dmBitsPerPel;
[FieldOffset(108)] public uint dmPelsWidth;
[FieldOffset(112)] public uint dmPelsHeight;
[FieldOffset(116)] public uint dmDisplayFlags;
[FieldOffset(116)] public uint dmNup;
[FieldOffset(120)] public uint dmDisplayFrequency;
[FieldOffset(124)] public uint dmICMMethod;
[FieldOffset(128)] public uint dmICMIntent;
[FieldOffset(132)] public uint dmMediaType;
[FieldOffset(136)] public uint dmDitherType;
[FieldOffset(140)] public uint dmReserved1;
[FieldOffset(144)] public uint dmReserved2;
[FieldOffset(148)] public uint dmPanningWidth;
[FieldOffset(152)] public uint dmPanningHeight;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct PrinterOnlyFields
{
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct Point
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct DisplayOnlyFields
{
public Point dmPosition;
public uint dmDisplayOrientation;
public uint dmDisplayFixedOutput;
}
}
}
You should remove all the FieldOffset attributes and implement the unions outside of the DeviceModeStruct structure. Like this:
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
struct DeviceModeUnion
{
[FieldOffset(0)]
PrinterOnlyFields Printer;
[FieldOffset(0)]
Point Position;
[FieldOffset(0)]
DisplayOnlyFields Display;
}
....
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct DeviceModeStruct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public ushort dmSpecVersion;
public ushort dmDriverVersion;
public ushort dmSize;
public ushort dmDriverExtra;
public uint dmFields;
public DeviceModeUnion union;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public ushort dmLogPixels;
public uint dmBitsPerPel;
public uint dmPelsWidth;
public uint dmPelsHeight;
public uint dmDisplayFlags;
public uint dmDisplayFrequency;
public uint dmICMMethod;
public uint dmICMIntent;
public uint dmMediaType;
public uint dmDitherType;
public uint dmReserved1;
public uint dmReserved2;
public uint dmPanningWidth;
public uint dmPanningHeight;
}
I've not checked DeviceModeStruct carefully against the documentation, but I am sure you can do that. However, I can confirm that this struct definition at least has the correct size, when compared against the size of the struct defined in the C++ header file.
Related
I'm trying to use win32 EnumDisplaySettings to get all available resolutions and refresh rates. But when printing dmDisplayFrequency I always get 0 which means that it cannot get it. Is there any alternatives to enumDisplaySettings ? If windows is able to provide a list in display setting window then there must be another way ?
using System;
using System.Linq;
using System.Runtime.InteropServices;
namespace ListResolutions
{
class Program
{
[DllImport("user32.dll")]
public static extern bool EnumDisplaySettings(
string deviceName, int modeNum, ref DEVMODE devMode);
const int ENUM_CURRENT_SETTINGS = -1;
const int ENUM_REGISTRY_SETTINGS = -2;
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE
{
private const int CCHDEVICENAME = 0x20;
private const int CCHFORMNAME = 0x20;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public int dmPositionX;
public int dmPositionY;
public int dmDisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public string dmFormName;
public short dmLogPixels;
public int dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
public int dmPanningWidth;
public int dmPanningHeight;
}
static void Main(string[] args)
{
DEVMODE vDevMode = new DEVMODE();
int i = 0;
while (EnumDisplaySettings(null, i, ref vDevMode))
{
Console.WriteLine("Width:{0} Height:{1} Color:{2} Frequency:{3}",
vDevMode.dmPelsWidth,
vDevMode.dmPelsHeight,
1 << vDevMode.dmBitsPerPel, vDevMode.dmDisplayFrequency
);
i++;
}
}
}
}
Please excuse me if my terminology isn't correct I am new to P/Invoke & marshalling. I am trying to execute the NtQuerySystemInformation method from ntdll.dll. The P/Invoke website suggests [link]
[DllImport("ntdll.dll")]
public static extern NtStatus NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, IntPtr SystemInformation, uint SystemInformationLength, out uint ReturnLength);
However it is the information in IntPtr SystemInformation that I am interested in. So instead I am attempting to implement
NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, SYSTEM_PROCESS_INFORMATION SystemInformation, uint SystemInformationLength, out uint ReturnLength)
I am trying to marshal the SYSTEM_PROCESS_INFORMATION with a StructLayout attribute.
public struct UNICODE_STRING
{
public ushort Length;
public ushort MaximumLength;
public IntPtr buffer;
}
[StructLayout(LayoutKind.Explicit, Size = 8)]
struct LARGE_INTEGER
{
[FieldOffset(0)] public Int64 QuadPart;
[FieldOffset(0)] public UInt32 LowPart;
[FieldOffset(4)] public Int32 HighPart;
}
[StructLayout(LayoutKind.Sequential)]
struct SYSTEM_PROCESS_INFORMATION
{
public uint NextEntryOffset;
public uint NumberOfThreads;
>>public byte[48] Reserved1;<<
public UNICODE_STRING ImageName;
public long BasePriority;
public IntPtr UniqueProcessId;
public IntPtr Reserved2;
public ulong HandleCount;
public ulong SessionId;
public IntPtr Reserved3;
public Int64 PeakVirtualSize;
public Int64 VirtualSize;
public ulong Reserved4;
public Int64 PeakWorkingSetSize;
public Int64 WorkingSetSize;
public IntPtr Reserved5;
public Int64 QuotaPagedPoolUsage;
public IntPtr Reserved6;
public Int64 QuotaNonPagedPoolUsage;
public Int64 PageFileUsage;
public Int64 PeakPageFileUsage;
public Int64 PrivatePageCount;
>>public LARGE_INTEGER[6] Reserved7;<<
}
I am using this website to help me translate WinAPI types into C# built-in types. I derived as much using the struct definition in winternl.h
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
BYTE Reserved1[48];
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE UniqueProcessId;
PVOID Reserved2;
ULONG HandleCount;
ULONG SessionId;
PVOID Reserved3;
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG Reserved4;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
PVOID Reserved5;
SIZE_T QuotaPagedPoolUsage;
PVOID Reserved6;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved7[6];
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
But I am unsure as to how to deal with BYTE Reserved1[48] and LARGE_INTEGER Reserved[6]. My current code above does not work. I am not interested in their values so it does not matter to me if the data is unintelligible.
This is called an inline array. There are various ways of dealing with this. The official way is to use [MarshalAs(UnmanagedType.ByValArray, for example:
[StructLayout(LayoutKind.Sequential)]
struct SYSTEM_PROCESS_INFORMATION
{
public uint NextEntryOffset;
public uint NumberOfThreads;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]
public byte[48] Reserved1;
public UNICODE_STRING ImageName;
public int BasePriority;
public IntPtr UniqueProcessId;
public IntPtr Reserved2;
public uint HandleCount;
public uint SessionId;
public IntPtr Reserved3;
public IntPtr PeakVirtualSize;
public IntPtr VirtualSize;
public uint Reserved4;
public IntPtr PeakWorkingSetSize;
public IntPtr WorkingSetSize;
public IntPtr Reserved5;
public IntPtr QuotaPagedPoolUsage;
public IntPtr Reserved6;
public IntPtr QuotaNonPagedPoolUsage;
public IntPtr PageFileUsage;
public IntPtr PeakPageFileUsage;
public IntPtr PrivatePageCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public long[6] Reserved7;
}
Note that there are other type mismatches in your struct which I have corrected.
However this can lead to heavy copying of values. So for that you may wish to instead just embed a bunch of long fields. This is what is done in .NET itself when it uses this struct.
[StructLayout(LayoutKind.Sequential)]
struct SystemProcessInformation
{
public uint NextEntryOffset;
public uint NumberOfThreads;
long SpareLi1;
long SpareLi2;
long SpareLi3;
public long CreateTime;
public long UserTime;
public long KernelTime;
public UNICODE_STRING ImageName;
public int BasePriority;
public IntPtr UniqueProcessId;
public IntPtr InheritedFromUniqueProcessId;
public uint HandleCount;
public uint SessionId;
public IntPtr PageDirectoryBase;
public IntPtr PeakVirtualSize;
public IntPtr VirtualSize;
public uint PageFaultCount;
public IntPtr PeakWorkingSetSize;
public IntPtr WorkingSetSize;
public IntPtr QuotaPeakPagedPoolUsage;
public IntPtr QuotaPagedPoolUsage;
public IntPtr QuotaPeakNonPagedPoolUsage;
public IntPtr QuotaNonPagedPoolUsage;
public IntPtr PagefileUsage;
public IntPtr PeakPagefileUsage;
public IntPtr PrivatePageCount;
long ReadOperationCount;
long WriteOperationCount;
long OtherOperationCount;
long ReadTransferCount;
long WriteTransferCount;
long OtherTransferCount;
}
I have the below code to change my 2nd display screen resolution. It all works fine and changes as expected. However once it has been changed my mouse/cursor is offset. eg the active location is not where the pointer shows on the screen.
Thoughts?
using System;
using System.Windows;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE1
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public short dmLogPixels;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmPosition;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
public int dmPanningWidth;
public int dmPanningHeight;
};
class User_32
{
[DllImport("user32.dll")]
public static extern int EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE1 devMode);
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettings(ref DEVMODE1 devMode, int flags);
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettingsEx(string lpszDeviceName, ref DEVMODE1 lpDevMode, IntPtr hwnd, ChangeDisplaySettingsFlags dwflags, IntPtr lParam);
public const int ENUM_CURRENT_SETTINGS = -1;
public const int CDS_UPDATEREGISTRY = 0x01;
public const int CDS_TEST = 0x02;
public const int DISP_CHANGE_SUCCESSFUL = 0;
public const int DISP_CHANGE_RESTART = 1;
public const int DISP_CHANGE_FAILED = -1;
[Flags()]
public enum ChangeDisplaySettingsFlags : uint{
CDS_NONE = 0,
CDS_UPDATEREGISTRY = 0x00000001,
CDS_TEST = 0x00000002,
CDS_FULLSCREEN = 0x00000004,
CDS_GLOBAL = 0x00000008,
CDS_SET_PRIMARY = 0x00000010,
CDS_VIDEOPARAMETERS = 0x00000020,
CDS_ENABLE_UNSAFE_MODES = 0x00000100,
CDS_DISABLE_UNSAFE_MODES = 0x00000200,
CDS_RESET = 0x40000000,
CDS_RESET_EX = 0x20000000,
CDS_NORESET = 0x10000000
}
}
namespace Resolution
{
class CResolution
{
public CResolution(int iWidth, int iHeight)
{
DEVMODE1 dm = new DEVMODE1();
dm.dmFormName = new String(new char[32]);
dm.dmSize = (short)Marshal.SizeOf(dm);
dm.dmPosition = 2;
if (0 != User_32.EnumDisplaySettings(null, User_32.ENUM_CURRENT_SETTINGS, ref dm))
{
dm.dmPelsWidth = iWidth;
dm.dmPelsHeight = iHeight;
long result = User_32.ChangeDisplaySettingsEx("\\\\.\\DISPLAY2", ref dm, IntPtr.Zero, User_32.ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY, IntPtr.Zero);
}
}
}
}
-
static void Main(string[] args)
{
Resolution.CResolution ChangeRes = new Resolution.CResolution(2560, 1600);
}
I am trying parse .cat file via c#. For this i'm using CRYPTOCAT functions from winapi. But this method is very hard for me :( And I cant reflect some structs and methods from it. Can you help me? What I need to use, to this process will be simpler.
That is my code:
static IntPtr WrapperUse(string fileName)
{
var hCatalog = CryptCATOpen(fileName.ToCharArray(), 2, 0, 0x200, 0x00000001);
unsafe
{
var storePtr = CryptCATStoreFromHandle(hCatalog);
var store = Marshal.PtrToStructure(storePtr, typeof(CRYPTCATSTORE));
IntPtr pMemberPtr = IntPtr.Zero;
var pMember = CryptCATEnumerateMember(hCatalog, pMemberPtr);
}
return hCatalog;
}
[DllImport("Wintrust.dll")]
private static extern IntPtr CryptCATOpen(char[] pwszFileName, uint fdwOpenFlags, uint hProv,
uint dwPublicVersion, uint dwEncodingType);
[DllImport("Wintrust.dll")]
private unsafe static extern IntPtr CryptCATStoreFromHandle(IntPtr hCatalog);
[DllImport("Wintrust.dll")]
[return: MarshalAs(UnmanagedType.Struct)]
private static extern unsafe CRYPTCATMEMBER CryptCATEnumerateMember(IntPtr hCatalog,
IntPtr pPrevMember);
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct CRYPTCATSTORE
{
public UInt32 cbStruct;
public UInt32 dwPublicVersion;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszP7File;
public UIntPtr hProv;
public uint dwEncodingType;
public uint fdwStoreFlags;
public IntPtr hReserved;
public IntPtr hAttrs;
public IntPtr hCryptMsg;
public IntPtr hSorted;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct CRYPTCATMEMBER
{
public uint cbStruct;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszReferenceTag;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwszFileName;
//fixed byte gSubjectType[16]; //GUID
[MarshalAs(UnmanagedType.Struct)]
public GUID gSubjectType;
public uint fdwMemberFlags;
public IntPtr pIndirectData;
public uint dwCertVersion;
public uint dwReserved;
public IntPtr hReserved;
[MarshalAs(UnmanagedType.Struct)]
public CRYPT_ATTR_BLOB sEncodedIndirectData;
[MarshalAs(UnmanagedType.Struct)]
public CRYPT_ATTR_BLOB sEncodedMemberInfo;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct GUID
{
public UInt32 Data1;
public ushort Data2;
public ushort Data3;
public fixed byte Data4[8];
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct CRYPT_ATTR_BLOB
{
public uint cbData;
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
//[MarshalAs(UnmanagedType.AsAny)]
public byte[] pbData;
}
Thanks
I wrote program to sendInput to games and desktop applications instead of taking input from keyboard.This is the result:
Windows 7 (32 bit) : worked perfect in games and desktop applications.
Windows 8 (64 bit) : DID NOT work in games but worked in notepad.exe.
so Why it did not work with win 8 ?
Here is the code :
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
[StructLayout(LayoutKind.Explicit)]
struct MouseKeybdHardwareInputUnion
{
[FieldOffset(0)]
public MOUSEINPUT mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct INPUT
{
public uint type;
public MouseKeybdHardwareInputUnion mkhi;
}
enum SendInputFlags
{
KEYEVENTF_EXTENDEDKEY = 0x0001,
KEYEVENTF_KEYUP = 0x0002,
KEYEVENTF_UNICODE = 0x0004,
KEYEVENTF_SCANCODE = 0x0008,
}
[DllImport("user32.dll")]
static extern UInt32 SendInput(UInt32 nInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, Int32 cbSize);
public static void StrokeKey(ushort codeOfKey)
{
INPUT[] InputData = new INPUT[1];
ushort ScanCode = codeOfKey;
InputData[0].type = 1;
InputData[0].mkhi.ki.wScan = (ushort)ScanCode;
InputData[0].mkhi.ki.dwFlags = (uint)SendInputFlags.KEYEVENTF_SCANCODE;
if (SendInput(1, InputData, Marshal.SizeOf(InputData[0])) == 0)
{
String blad = "SendInput failed with code: " + Marshal.GetLastWin32Error().ToString();
System.Diagnostics.Debug.WriteLine(blad);
}
}
public static void ReleaseKey(ushort codeOfKey)
{
INPUT[] InputData = new INPUT[1];
ushort ScanCode = codeOfKey;
InputData[0].type = 1;
InputData[0].mkhi.ki.wScan = (ushort)ScanCode;
InputData[0].mkhi.ki.dwFlags = (uint)SendInputFlags.KEYEVENTF_KEYUP | (uint)SendInputFlags.KEYEVENTF_SCANCODE;
InputData[0].mkhi.ki.time = 0;
InputData[0].mkhi.ki.dwExtraInfo = IntPtr.Zero;
SendInput(1, InputData, Marshal.SizeOf(InputData[0]));
}
most likely pointersize is different on 32 bits its size 4 on 64 bits its size 8