I am trying to access a TreeView running in another process. Many of the tree view messages work correctly. However, trying to use the TVM_GETITEM causes that other process to crash.
The code below is a simple program that illustrates the crash. To get it to run, you will need some CHM help file. I'm using a CHM help file because hh.exe uses a TreeView control for the table of contents.
The goal is to be able to get the a tree node's text.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace TreeViewTest {
public class TVForm : Form {
String chmFile = #"C:\temp\QuickGuide.chm"; // change this to some help file on local computer
Button btnOpenFile = new Button { Text = "Open File", AutoSize = true };
Button btnDeleteSelected = new Button { Text = "Delete Selected", AutoSize = true };
Button btnGetCount = new Button { Text = "Get Count", AutoSize = true };
Button btnGetText = new Button { Text = "Get Text", AutoSize = true }; // causes hh.exe process to crash
Button btnSelectNext = new Button { Text = "Select Next", AutoSize = true };
Process process = null;
IntPtr ptrTreeView = IntPtr.Zero;
public TVForm() {
FlowLayoutPanel p = new FlowLayoutPanel { FlowDirection = System.Windows.Forms.FlowDirection.TopDown, Dock = DockStyle.Fill };
p.Controls.Add(btnOpenFile);
p.Controls.Add(btnGetCount);
p.Controls.Add(btnDeleteSelected);
p.Controls.Add(btnGetText);
p.Controls.Add(btnSelectNext);
Controls.Add(p);
btnOpenFile.Click += buttonClicked; // works fine
btnDeleteSelected.Click += buttonClicked; // works fine
btnGetCount.Click += buttonClicked;
btnGetText.Click += buttonClicked;
btnSelectNext.Click += buttonClicked;
}
void buttonClicked(object sender, EventArgs e) {
if (!File.Exists(chmFile)) {
MessageBox.Show("Cannot find CHM file: " + chmFile);
return;
}
IntPtr hwndTreeView = GetTreeViewHandle();
if (hwndTreeView == IntPtr.Zero) {
MessageBox.Show("Cannot find TreeView handle.");
return;
}
if (sender == btnDeleteSelected) {
// get the handle to the selected node in the tree view
IntPtr hwndItem = SendMessage(hwndTreeView, (int) TVM.TVM_GETNEXTITEM, (int) TVGN.TVGN_CARET, 0);
if (hwndItem == IntPtr.Zero)
MessageBox.Show("no item selected");
else
SendMessage(hwndTreeView, (int) TVM.TVM_DELETEITEM, IntPtr.Zero, hwndItem);
}
else if (sender == btnGetCount) {
IntPtr count = SendMessage(hwndTreeView, (int) TVM.TVM_GETCOUNT, 0, 0);
MessageBox.Show(String.Format("There are {0} nodes in the tree view.", count.ToInt32()));
}
else if (sender == btnSelectNext) {
IntPtr hwndItem = SendMessage(hwndTreeView, (int) TVM.TVM_GETNEXTITEM, (int) TVGN.TVGN_CARET, 0);
if (hwndItem == IntPtr.Zero) {
MessageBox.Show("no item selected");
return;
}
hwndItem = SendMessage(hwndTreeView, (int) TVM.TVM_GETNEXTITEM, new IntPtr((int) TVGN.TVGN_NEXT), hwndItem);
if (hwndItem == IntPtr.Zero)
MessageBox.Show("there is no next item");
else
SendMessage(hwndTreeView, (int) TVM.TVM_SELECTITEM, new IntPtr((int) TVGN.TVGN_CARET), hwndItem);
}
else if (sender == btnGetText) { // crashes hh.exe
IntPtr hwndItem = SendMessage(hwndTreeView, (int) TVM.TVM_GETNEXTITEM, (int) TVGN.TVGN_CARET, 0);
if (hwndItem == IntPtr.Zero) {
MessageBox.Show("no item selected");
return;
}
var item = new TVITEMEX(); // have tried both TVITEM and TVITEMEX
item.hItem = hwndItem;
item.mask = (int) (TVIF.TVIF_TEXT | TVIF.TVIF_HANDLE);
item.cchTextMax = 260;
item.pszText = Marshal.AllocHGlobal(item.cchTextMax);
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(item));
Marshal.StructureToPtr(item, ptr, false);
// have tried TVM_GETITEM and TVM_GETITEMA
SendMessage(hwndTreeView, (int) TVM.TVM_GETITEM, IntPtr.Zero, ptr); // this line crashes hh.exe
String text = Marshal.PtrToStringAuto(item.pszText);
MessageBox.Show(text);
Marshal.FreeHGlobal(item.pszText);
Marshal.FreeHGlobal(ptr);
}
}
public Process GetProcess() {
if (process != null && !process.HasExited)
return process;
ptrTreeView = IntPtr.Zero;
process = Process.Start(chmFile);
Thread.Sleep(1000); // sleep a little to give the process time to open (otherwise cannot find the TreeView control)
return process;
}
public IntPtr GetTreeViewHandle() {
if (ptrTreeView != IntPtr.Zero && !process.HasExited)
return ptrTreeView;
var list = new List<IntPtr>();
Process p = GetProcess();
FindSysTreeView(p.MainWindowHandle, new Hashtable(), list);
if (list.Count == 0) {
return IntPtr.Zero;
}
ptrTreeView = list[0];
return ptrTreeView;
}
private static void FindSysTreeView(IntPtr p, Hashtable ht, List<IntPtr> list) {
var cn = GetClassName(p);
//var txt = GetWindowText(p);
if (cn == "SysTreeView32") {
if (!list.Contains(p))
list.Add(p);
}
if (ht[p] == null) {
ht[p] = p;
foreach (var c in GetChildWindows(p))
FindSysTreeView(c, ht, list);
}
}
public static String GetClassName(IntPtr hWnd) {
StringBuilder sb = new StringBuilder(256);
GetClassName(hWnd, sb, sb.Capacity);
return sb.ToString();
}
public static List<IntPtr> GetChildWindows(IntPtr parent) {
List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try {
Win32Callback childProc = new Win32Callback(EnumWindow);
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
} finally {
if (listHandle.IsAllocated)
listHandle.Free();
}
return result;
}
private static bool EnumWindow(IntPtr handle, IntPtr pointer) {
GCHandle gch = GCHandle.FromIntPtr(pointer);
List<IntPtr> list = gch.Target as List<IntPtr>;
if (list == null)
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
list.Add(handle);
return true;
}
[DllImport("user32.dll")]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.Dll")]
private static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);
private delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
private const int TV_FIRST = 0x1100;
public enum TVM {
TVM_GETNEXTITEM = (TV_FIRST + 10),
TVM_GETITEMA = (TV_FIRST + 12),
TVM_GETITEM = (TV_FIRST + 62),
TVM_GETCOUNT = (TV_FIRST + 5),
TVM_SELECTITEM = (TV_FIRST + 11),
TVM_DELETEITEM = (TV_FIRST + 1),
TVM_EXPAND = (TV_FIRST + 2),
TVM_GETITEMRECT = (TV_FIRST + 4),
TVM_GETINDENT = (TV_FIRST + 6),
TVM_SETINDENT = (TV_FIRST + 7),
TVM_GETIMAGELIST = (TV_FIRST + 8),
TVM_SETIMAGELIST = (TV_FIRST + 9),
TVM_GETISEARCHSTRING = (TV_FIRST + 64),
TVM_HITTEST = (TV_FIRST + 17),
}
public enum TVGN {
TVGN_ROOT = 0x0,
TVGN_NEXT = 0x1,
TVGN_PREVIOUS = 0x2,
TVGN_PARENT = 0x3,
TVGN_CHILD = 0x4,
TVGN_FIRSTVISIBLE = 0x5,
TVGN_NEXTVISIBLE = 0x6,
TVGN_PREVIOUSVISIBLE = 0x7,
TVGN_DROPHILITE = 0x8,
TVGN_CARET = 0x9,
TVGN_LASTVISIBLE = 0xA
}
[Flags]
public enum TVIF {
TVIF_TEXT = 1,
TVIF_IMAGE = 2,
TVIF_PARAM = 4,
TVIF_STATE = 8,
TVIF_HANDLE = 16,
TVIF_SELECTEDIMAGE = 32,
TVIF_CHILDREN = 64,
TVIF_INTEGRAL = 0x0080,
TVIF_DI_SETITEM = 0x1000
}
[StructLayout(LayoutKind.Sequential)]
public struct TVITEMEX {
public uint mask;
public IntPtr hItem;
public uint state;
public uint stateMask;
public IntPtr pszText;
public int cchTextMax;
public int iImage;
public int iSelectedImage;
public int cChildren;
public IntPtr lParam;
public int iIntegral;
public uint uStateEx;
public IntPtr hwnd;
public int iExpandedImage;
public int iReserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct TVITEM {
public uint mask;
public IntPtr hItem;
public uint state;
public uint stateMask;
public IntPtr pszText;
public int cchTextMax;
public int iImage;
public int iSelectedImage;
public int cChildren;
public IntPtr lParam;
}
}
}
Here is the code used to access the node text from a TreeView running in another process:
[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint dwFreeType);
// privileges
const int PROCESS_CREATE_THREAD = 0x0002;
const int PROCESS_QUERY_INFORMATION = 0x0400;
const int PROCESS_VM_OPERATION = 0x0008;
const int PROCESS_VM_WRITE = 0x0020;
const int PROCESS_VM_READ = 0x0010;
// used for memory allocation
const uint MEM_COMMIT = 0x00001000;
const int MEM_DECOMMIT = 0x4000;
const uint MEM_RESERVE = 0x00002000;
const uint PAGE_READWRITE = 4;
///<summary>Returns the tree node information from another process.</summary>
///<param name="hwndItem">Handle to a tree node item.</param>
///<param name="hwndTreeView">Handle to a tree view control.</param>
///<param name="process">Process hosting the tree view control.</param>
private static NodeData AllocTest(Process process, IntPtr hwndTreeView, IntPtr hwndItem) {
// code based on article posted here: http://www.codingvision.net/miscellaneous/c-inject-a-dll-into-a-process-w-createremotethread
// handle of the process with the required privileges
IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, process.Id);
// Write TVITEM to memory
// Invoke TVM_GETITEM
// Read TVITEM from memory
var item = new TVITEMEX();
item.hItem = hwndItem;
item.mask = (int) (TVIF.TVIF_HANDLE | TVIF.TVIF_CHILDREN | TVIF.TVIF_TEXT);
item.cchTextMax = 1024;
item.pszText = VirtualAllocEx(procHandle, IntPtr.Zero, (uint) item.cchTextMax, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // node text pointer
byte[] data = getBytes(item);
uint dwSize = (uint) data.Length;
IntPtr allocMemAddress = VirtualAllocEx(procHandle, IntPtr.Zero, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // TVITEM pointer
uint nSize = dwSize;
UIntPtr bytesWritten;
bool successWrite = WriteProcessMemory(procHandle, allocMemAddress, data, nSize, out bytesWritten);
var sm = SendMessage(hwndTreeView, (int) TVM.TVM_GETITEM, IntPtr.Zero, allocMemAddress);
UIntPtr bytesRead;
bool successRead = ReadProcessMemory(procHandle, allocMemAddress, data, nSize, out bytesRead);
UIntPtr bytesReadText;
byte[] nodeText = new byte[item.cchTextMax];
bool successReadText = ReadProcessMemory(procHandle, item.pszText, nodeText, (uint) item.cchTextMax, out bytesReadText);
bool success1 = VirtualFreeEx(procHandle, allocMemAddress, dwSize, MEM_DECOMMIT);
bool success2 = VirtualFreeEx(procHandle, item.pszText, (uint) item.cchTextMax, MEM_DECOMMIT);
var item2 = fromBytes<TVITEMEX>(data);
String name = Encoding.Unicode.GetString(nodeText);
int x = name.IndexOf('\0');
if (x >= 0)
name = name.Substring(0, x);
NodeData node = new NodeData();
node.Text = name;
node.HasChildren = (item2.cChildren == 1);
return node;
}
public class NodeData {
public String Text { get; set; }
public bool HasChildren { get; set; }
}
private static byte[] getBytes(Object item) {
int size = Marshal.SizeOf(item);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(item, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
private static T fromBytes<T>(byte[] arr) {
T item = default(T);
int size = Marshal.SizeOf(item);
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(arr, 0, ptr, size);
item = (T) Marshal.PtrToStructure(ptr, typeof(T));
Marshal.FreeHGlobal(ptr);
return item;
}
// Note: different layouts required depending on OS versions.
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb773459%28v=vs.85%29.aspx
[StructLayout(LayoutKind.Sequential)]
public struct TVITEMEX {
public uint mask;
public IntPtr hItem;
public uint state;
public uint stateMask;
public IntPtr pszText;
public int cchTextMax;
public int iImage;
public int iSelectedImage;
public int cChildren;
public IntPtr lParam;
public int iIntegral;
public uint uStateEx;
public IntPtr hwnd;
public int iExpandedImage;
public int iReserved;
}
Related
I am trying to add a crl to my cert store using Win32 api CertAddCRLContextToStore in C#. The below code is not working and failing while trying to parse the crl content to CRL_CONTEXT. Can we do this in any other way? Or am I missing something in my code?
private const int CERT_STORE_PROV_SYSTEM = 10;
private const int CERT_SYSTEM_STORE_LOCAL_MACHINE = (2 << 16);
public const int CERT_QUERY_OBJECT_FILE = 0x00000001;
public const int CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED = 1 << 8;
public const int CERT_QUERY_FORMAT_FLAG_BINARY = 1 << 1;
public const int CERT_STORE_ADD_REPLACE_EXISTING = 1 << 3;
[DllImport("CRYPT32.DLL", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CertOpenStore(
int storeProvider,
int encodingType,
IntPtr hcryptProv,
int flags,
string pvPara);
[DllImport("CRYPT32.DLL", EntryPoint = "CryptQueryObject", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptQueryObject(
int dwObjectType,
[MarshalAs(UnmanagedType.LPWStr)] String pvObject,
int dwExpectedContentTypeFlags,
int dwExpectedFormatTypeFlags,
int dwFlags,
IntPtr pdwMsgAndCertEncodingType,
IntPtr pdwContentType,
IntPtr pdwFormatType,
IntPtr phCertStore,
IntPtr phMsg,
ref IntPtr ppvContext);
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool CertAddCRLContextToStore(
IntPtr hCertStore,
IntPtr pCertContext,
uint dwAddDisposition,
IntPtr ppStoreContext);
IntPtr hLocalCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
IntPtr.Zero,
CERT_SYSTEM_STORE_LOCAL_MACHINE,
"CA");
IntPtr pvContext = IntPtr.Zero;
bool queryResult = CryptQueryObject(
CERT_QUERY_OBJECT_FILE,
#"sample.crl",
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
CERT_QUERY_FORMAT_FLAG_BINARY,
0,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero,
ref pvContext
);
// FAILS HERE
if (!queryResult)
{
throw new Exception("CryptQueryObject error #" + Marshal.GetLastWin32Error());
}
bool addResult = CertAddCRLContextToStore(
hLocalCertStore, pvContext, CERT_STORE_ADD_REPLACE_EXISTING, IntPtr.Zero);
if (!addResult)
{
throw new Exception("CryptQueryObject error #" + Marshal.GetLastWin32Error());
}
The code fails with the error
-2146885623. "Cannot find the requested
object"
I'm looking for an event that would happen when the screen saver become active or inactive. I want to be notified. I do not want to use any timer.
I do not want to poll for it. I don't want to use: SystemParametersInfo( SPI_GETSCREENSAVERRUNNING, 0, ref isRunning, 0 );
I tried that without success, I never receive the SC_SCREENSAVE...
// ************************************************************************
public MainWindow()
{
InitializeComponent();
}
// ************************************************************************
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;
HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
if (mainWindowSrc != null)
{
mainWindowSrc.AddHook(WndProc);
}
//HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
//source.AddHook(WndProc);
}
// ************************************************************************
private const Int32 WM_SYSCOMMAND = 0x112;
private const int SC_SCREENSAVE = 0xF140;
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_SYSCOMMAND)
{
Debug.Print("SysCommand : " + wParam);
if (wParam.ToInt32() == SC_SCREENSAVE)
{
Debug.Print(DateTime.Now.ToString());
}
}
return IntPtr.Zero;
}
Anybody has any other idea or does know what is wrong with my code ???
if (wParam.ToInt32() == SC_SCREENSAVE)
That's not correct. It is an odd quirk in the WM_SYSCOMMAND message, surely dating to a long gone era where they had to squeeze a GUI operating system in 640 kilobytes. The low 4 bits in the command value are used for internal purposes. You'll have to mask them out before you compare. Fix:
if ((wParam.ToInt32() & 0xfff0) == SC_SCREENSAVE)
You'd probably had figured this out yourself by using the proper Debug statement formatting :)
Debug.Print("SysCommand : 0x{0:X}", wParam);
Hans answer seems to not work for me on Windows 7 when it is activated normally by the timer (at least when your account is part of a domain and a policy make screen saver parameters as readonly).
Using SystemParametersInfo with SPI_GETSCREENSAVERRUNNING work fine but it require a timer (polling) which is to my point of view: horrible poorly designed code... but up to now, it is the only way I found that works all the time... :-(
I left my code as reference. It include many of my tests.
There is a lot more but just remove what you don't need.
You could consult the HotKey excellent class there (I couldn't found my initial source but this one is exactly the same): https://github.com/shellscape/Lumen/blob/master/Application/HotkeyHandler.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using HQ.Util.General;
using HQ.Util.Unmanaged;
using HQ.Wpf.Util;
using Microsoft.Win32;
using SpreadsheetGear;
namespace MonitorMe
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public enum HookType : int
{
WH_JOURNALRECORD = 0,
WH_JOURNALPLAYBACK = 1,
WH_KEYBOARD = 2,
WH_GETMESSAGE = 3,
WH_CALLWNDPROC = 4,
WH_CBT = 5,
WH_SYSMSGFILTER = 6,
WH_MOUSE = 7,
WH_HARDWARE = 8,
WH_DEBUG = 9,
WH_SHELL = 10,
WH_FOREGROUNDIDLE = 11,
WH_CALLWNDPROCRET = 12,
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
}
delegate IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam);
private HotKeyHandeler _hotKeyHandler = null;
private Timer _timerToMonitorScreenSaver = null;
// ************************************************************************
public MainWindow()
{
InitializeComponent();
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
Monitor.Instance.Add(SessionSwitchReason.SessionLogon);
_timerToMonitorScreenSaver = new Timer(TimerCallbackMonitorScreenSaver, this, 3000, 3000);
}
private void TimerCallbackMonitorScreenSaver(object state)
{
int active = 1;
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, ref active, 0);
if (active == 1)
{
Debug.Print("Timer detected Screen Saver activated on: " + DateTime.Now.ToString());
}
}
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr LoadLibrary(string lpFileName);
// Signatures for unmanaged calls
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool SystemParametersInfo(
int uAction, int uParam, ref int lpvParam,
int flags);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool SystemParametersInfo(
int uAction, int uParam, ref bool lpvParam,
int flags);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int PostMessage(IntPtr hWnd,
int wMsg, int wParam, int lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr OpenDesktop(
string hDesktop, int Flags, bool Inherit,
uint DesiredAccess);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseDesktop(
IntPtr hDesktop);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool EnumDesktopWindows(
IntPtr hDesktop, EnumDesktopWindowsProc callback,
IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool IsWindowVisible(
IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetForegroundWindow();
// Callbacks
private delegate bool EnumDesktopWindowsProc(
IntPtr hDesktop, IntPtr lParam);
// Constants
private const int SPI_GETSCREENSAVERACTIVE = 16;
private const int SPI_SETSCREENSAVERACTIVE = 17;
private const int SPI_GETSCREENSAVERTIMEOUT = 14;
private const int SPI_SETSCREENSAVERTIMEOUT = 15;
private const int SPI_GETSCREENSAVERRUNNING = 114;
private const int SPIF_SENDWININICHANGE = 2;
private const uint DESKTOP_WRITEOBJECTS = 0x0080;
private const uint DESKTOP_READOBJECTS = 0x0001;
private const int WM_CLOSE = 16;
[DllImport("User32.dll")]
public static extern int SendMessage
(IntPtr hWnd,
uint Msg,
uint wParam,
uint lParam);
public enum SpecialHandles
{
HWND_DESKTOP = 0x0,
HWND_BROADCAST = 0xFFFF
}
// Registers a hot key with Windows.
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
// Unregisters the hot key with Windows.
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
private IntPtr _hHook;
// ************************************************************************
void _hotKeyHandler_HotKeyPressed(object sender, HotKeyEventArgs e)
{
ActivateScreenSaver();
}
// ************************************************************************
private IntPtr MessageHookProc(int code, IntPtr wParam, IntPtr lParam)
{
if (code == WM_SYSCOMMAND)
{
Debug.Print("SysCommand : " + wParam);
if ((wParam.ToInt32() & 0xfff0) == SC_SCREENSAVE)
{
Debug.Print("MessageHookProc" + DateTime.Now.ToString());
}
}
return CallNextHookEx(_hHook, code, wParam, lParam);
}
// ************************************************************************
private const Int32 WM_SYSCOMMAND = 0x0112;
private const int SC_SCREENSAVE = 0xF140;
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_SYSCOMMAND)
{
Debug.Print("SysCommand : " + wParam);
if ((wParam.ToInt32() & 0xfff0) == SC_SCREENSAVE)
{
// Works fine in almost all cases. I already did some code in the past which activate the screen saver
// but I never receive any WM_SYSCOMMAND for that code, I do not have source code for it anymore).
Debug.Print("WndProc" + DateTime.Now.ToString());
}
}
return IntPtr.Zero;
}
// ************************************************************************
void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
Monitor.Instance.Add(e.Reason);
}
// ************************************************************************
private void CmdExportToExcel_Click(object sender, RoutedEventArgs e)
{
ExportToExcel();
}
// ************************************************************************
private void ExportToExcel()
{
IWorkbook wb = Factory.GetWorkbook();
IWorksheet workSheet = wb.Worksheets[0];
int col = 1;
for (int dayIndex = -30; dayIndex <= 0; dayIndex++)
{
DateTime day = DateTime.Today + new TimeSpan(dayIndex, 0, 0, 0);
Debug.Print(day.ToString("yyyy-MM-dd"));
workSheet.Cells[0, col].Value = day.DayOfWeek.ToString();
workSheet.Cells[1, col].Value = day;
DayMonitor dayMonitor = Monitor.Instance.DayMonitors.FirstOrDefault(dm => dm.Day == day);
if (dayMonitor != null)
{
workSheet.Cells[2, col].Value = "Last - First";
workSheet.Cells[2, col + 1].Value = dayMonitor.TotalHours;
workSheet.Cells[3, col].Value = "Has estimated time (7h00 or 18h00)";
workSheet.Cells[3, col + 1].Value = dayMonitor.HasSomeEstimatedHours;
int row = 5;
foreach (var state in dayMonitor.SessionLockStateChanges)
{
workSheet.Cells[row, col].Value = state.SessionSwitchReason.ToString();
workSheet.Cells[row, col + 1].Value = state.DateTime;
row++;
}
}
workSheet.Cells[1, col].ColumnWidth = 18;
workSheet.Cells[1, col + 1].ColumnWidth = 18;
col += 2;
}
if (wb != null)
{
if (FileAssociation.IsFileAssociationExistsForExtensionWithDot(".xlsx"))
{
string path = TempFolderAutoClean.GetTempFileName("xlsx", "Export ");
wb.SaveAs(path, FileFormat.OpenXMLWorkbook);
Process p = new Process();
p.StartInfo.UseShellExecute = true;
p.StartInfo.FileName = path;
p.Start();
}
else
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.InitialDirectory = Environment.CurrentDirectory;
saveFileDialog.Filter = "Excel file (*.xlsx)|*.xlsx";
saveFileDialog.DefaultExt = ".xlsx";
if (saveFileDialog.ShowDialog(Application.Current.MainWindow) == true)
{
string path = saveFileDialog.FileName;
wb.SaveAs(path, FileFormat.OpenXMLWorkbook);
}
}
}
}
// ************************************************************************
private void PrintOnExecuted(object sender, ExecutedRoutedEventArgs e)
{
ExportToExcel();
}
// ************************************************************************
private void ExitOnExecuted(object sender, ExecutedRoutedEventArgs e)
{
this.Close();
}
// ************************************************************************
private void PrintOnCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.ContinueRouting = false;
}
// ************************************************************************
private void ExitOnCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.ContinueRouting = false;
}
// ************************************************************************
private void CmdLaunchScreenSaver_Click(object sender, RoutedEventArgs e)
{
ActivateScreenSaver();
}
// ************************************************************************
private void ActivateScreenSaver()
{
// Next won't work in a secured Screen Saver by Account Policy (ex: by a domain policy)
//int nullVar = 0;
//SystemParametersInfo(SPI_SETSCREENSAVERACTIVE, 1, ref nullVar, SPIF_SENDWININICHANGE);
// This works fine all the time... and also send appropriate message to every top level window
SendMessage(new IntPtr((int)SpecialHandles.HWND_BROADCAST), WM_SYSCOMMAND, SC_SCREENSAVE, 0);
}
// ************************************************************************
private void MainWindow_OnInitialized(object sender, EventArgs e)
{
int error;
IntPtr hMod = LoadLibrary("user32.dll"); // Hans Passant info in stackOverflow
_hHook = SetWindowsHookEx(HookType.WH_GETMESSAGE, MessageHookProc, IntPtr.Zero, (uint)Thread.CurrentThread.ManagedThreadId);
error = Marshal.GetLastWin32Error(); // Error 87
_hHook = SetWindowsHookEx(HookType.WH_GETMESSAGE, MessageHookProc, hMod, (uint)Thread.CurrentThread.ManagedThreadId);
error = Marshal.GetLastWin32Error(); // Error 87
_hHook = SetWindowsHookEx(HookType.WH_GETMESSAGE, MessageHookProc, hMod, 0);
error = Marshal.GetLastWin32Error(); // Work fine, got a hook, but never receive the WM_SYSCOMMAND:SC_SCREENSAVE
}
// ************************************************************************
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
}
// ************************************************************************
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
// Method 1
//IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;
//HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
//if (mainWindowSrc != null)
//{
// mainWindowSrc.AddHook(WndProc);
//}
// Method 2
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
source.AddHook(WndProc);
_hotKeyHandler = new HotKeyHandeler(this);
_hotKeyHandler.HotKeyPressed += _hotKeyHandler_HotKeyPressed;
// _hotKeyHandler.RegisterHotKey(0, Key.NumPad0);
this.Visibility = Visibility.Hidden;
}
// ************************************************************************
}
}
I am using this code for scanning ,
this code is working perfectly on 32 bit Machine but I am switching my application to 64 Bit machine where I am getting an error .I searched a lot and found many solutions ,
common Solution I found that compile the application on 32 bit machine but it does not improve my application performance so i do not want to use this solution on 64-bit machine.
Error is :
An attempt was made to load a program with an incorrect format.
(Exception fromHRESULT: 0x8007000B)
Code is :
namespace TwainLib
{
public enum TwainCommand
{
Not = -1,
Null = 0,
TransferReady = 1,
CloseRequest = 2,
CloseOk = 3,
DeviceEvent = 4
}
public class Twain
{
private const short CountryUSA = 1;
private const short LanguageUSA = 13;
public Twain()
{
appid = new TwIdentity();
appid.Id = IntPtr.Zero;
appid.Version.MajorNum = 1;
appid.Version.MinorNum = 1;
appid.Version.Language = LanguageUSA;
appid.Version.Country = CountryUSA;
appid.Version.Info = "Hack 1";
appid.ProtocolMajor = TwProtocol.Major;
appid.ProtocolMinor = TwProtocol.Minor;
appid.SupportedGroups = (int)(TwDG.Image | TwDG.Control);
appid.Manufacturer = "NETMaster";
appid.ProductFamily = "Freeware";
appid.ProductName = "Hack";
srcds = new TwIdentity();
srcds.Id = IntPtr.Zero;
evtmsg.EventPtr = Marshal.AllocHGlobal(Marshal.SizeOf(winmsg));
}
~Twain()
{
Marshal.FreeHGlobal(evtmsg.EventPtr);
}
public void Init(IntPtr hwndp)
{
Finish();
TwRC rc = DSMparent(appid, IntPtr.Zero, TwDG.Control, TwDAT.Parent, TwMSG.OpenDSM, ref hwndp);
if (rc == TwRC.Success)
{
rc = DSMident(appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.GetDefault, srcds);
if (rc == TwRC.Success)
hwnd = hwndp;
else
rc = DSMparent(appid, IntPtr.Zero, TwDG.Control, TwDAT.Parent, TwMSG.CloseDSM, ref hwndp);
}
}
public void Select()
{
TwRC rc;
CloseSrc();
if (appid.Id == IntPtr.Zero)
{
Init(hwnd);
if (appid.Id == IntPtr.Zero)
return;
}
rc = DSMident(appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.UserSelect, srcds);
}
/// <summary>
/// Returns a list of twain sources
/// </summary>
/// <returns></returns>
public IEnumerable<TwIdentity> GetSources()
{
TwRC rc;
CloseSrc();
if (appid.Id == IntPtr.Zero)
{
Init(hwnd);
if (appid.Id == IntPtr.Zero)
return null;
}
List<TwIdentity> sources = new List<TwIdentity>();
TwIdentity identity = new TwIdentity();
rc = DSMident(appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.GetFirst, identity);
while (rc == TwRC.Success)
{
sources.Add(identity);
identity = new TwIdentity();
rc = DSMident(appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.GetNext, identity);
}
return sources;
}
/// <summary>
/// Sets the source from which images will be acquired
/// </summary>
/// <param name="Source_p"></param>
public void SetSource(TwIdentity Source_p)
{
srcds = Source_p;
}
public void Acquire()
{
TwRC rc;
CloseSrc();
if (appid.Id == IntPtr.Zero)
{
Init(hwnd);
if (appid.Id == IntPtr.Zero)
return;
}
rc = DSMident(appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.OpenDS, srcds);
if (rc != TwRC.Success)
return;
TwCapability cap = new TwCapability(TwCap.XferCount, 1);
rc = DScap(appid, srcds, TwDG.Control, TwDAT.Capability, TwMSG.Set, cap);
if (rc != TwRC.Success)
{
CloseSrc();
return;
}
TwUserInterface guif = new TwUserInterface();
guif.ShowUI = 1;
guif.ModalUI = 1;
guif.ParentHand = hwnd;
rc = DSuserif(appid, srcds, TwDG.Control, TwDAT.UserInterface, TwMSG.EnableDS, guif);
if (rc != TwRC.Success)
{
CloseSrc();
return;
}
}
public List<IntPtr> TransferPictures()
{
List<IntPtr> pics = new List<IntPtr>();
if (srcds.Id == IntPtr.Zero)
return pics;
TwRC rc;
IntPtr hbitmap = IntPtr.Zero;
TwPendingXfers pxfr = new TwPendingXfers();
do
{
pxfr.Count = 0;
hbitmap = IntPtr.Zero;
TwImageInfo iinf = new TwImageInfo();
rc = DSiinf(appid, srcds, TwDG.Image, TwDAT.ImageInfo, TwMSG.Get, iinf);
if (rc != TwRC.Success)
{
CloseSrc();
return pics;
}
rc = DSixfer(appid, srcds, TwDG.Image, TwDAT.ImageNativeXfer, TwMSG.Get, ref hbitmap);
if (rc != TwRC.XferDone)
{
CloseSrc();
return pics;
}
rc = DSpxfer(appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.EndXfer, pxfr);
if (rc != TwRC.Success)
{
CloseSrc();
return pics;
}
pics.Add(hbitmap);
}
while (pxfr.Count != 0);
rc = DSpxfer(appid, srcds, TwDG.Control, TwDAT.PendingXfers, TwMSG.Reset, pxfr);
return pics;
}
public TwainCommand PassMessage(ref Message m)
{
if (srcds.Id == IntPtr.Zero)
return TwainCommand.Not;
int pos = GetMessagePos();
winmsg.hwnd = m.HWnd;
winmsg.message = m.Msg;
winmsg.wParam = m.WParam;
winmsg.lParam = m.LParam;
winmsg.time = GetMessageTime();
winmsg.x = (short)pos;
winmsg.y = (short)(pos >> 16);
Marshal.StructureToPtr(winmsg, evtmsg.EventPtr, false);
evtmsg.Message = 0;
TwRC rc = DSevent(appid, srcds, TwDG.Control, TwDAT.Event, TwMSG.ProcessEvent, ref evtmsg);
if (rc == TwRC.NotDSEvent)
return TwainCommand.Not;
if (evtmsg.Message == (short)TwMSG.XFerReady)
return TwainCommand.TransferReady;
if (evtmsg.Message == (short)TwMSG.CloseDSReq)
return TwainCommand.CloseRequest;
if (evtmsg.Message == (short)TwMSG.CloseDSOK)
return TwainCommand.CloseOk;
if (evtmsg.Message == (short)TwMSG.DeviceEvent)
return TwainCommand.DeviceEvent;
return TwainCommand.Null;
}
public void CloseSrc()
{
TwRC rc;
if (srcds.Id != IntPtr.Zero)
{
TwUserInterface guif = new TwUserInterface();
rc = DSuserif(appid, srcds, TwDG.Control, TwDAT.UserInterface, TwMSG.DisableDS, guif);
rc = DSMident(appid, IntPtr.Zero, TwDG.Control, TwDAT.Identity, TwMSG.CloseDS, srcds);
}
}
public void Finish()
{
TwRC rc;
CloseSrc();
if (appid.Id != IntPtr.Zero)
rc = DSMparent(appid, IntPtr.Zero, TwDG.Control, TwDAT.Parent, TwMSG.CloseDSM, ref hwnd);
appid.Id = IntPtr.Zero;
}
private IntPtr hwnd;
private TwIdentity appid;
private TwIdentity srcds;
private TwEvent evtmsg;
private WINMSG winmsg;
// ------ DSM entry point DAT_ variants:
[DllImport("twain_32.dll", EntryPoint = "#1")]
private static extern TwRC DSMparent([In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, ref IntPtr refptr);
[DllImport("twain_32.dll", EntryPoint = "#1")]
private static extern TwRC DSMident([In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwIdentity idds);
[DllImport("twain_32.dll", EntryPoint = "#1")]
private static extern TwRC DSMstatus([In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwStatus dsmstat);
// ------ DSM entry point DAT_ variants to DS:
[DllImport("twain_32.dll", EntryPoint = "#1")]
private static extern TwRC DSuserif([In, Out] TwIdentity origin, [In, Out] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, TwUserInterface guif);
[DllImport("twain_32.dll", EntryPoint = "#1")]
private static extern TwRC DSevent([In, Out] TwIdentity origin, [In, Out] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, ref TwEvent evt);
[DllImport("twain_32.dll", EntryPoint = "#1")]
private static extern TwRC DSstatus([In, Out] TwIdentity origin, [In] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwStatus dsmstat);
[DllImport("twain_32.dll", EntryPoint = "#1")]
private static extern TwRC DScap([In, Out] TwIdentity origin, [In] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwCapability capa);
[DllImport("twain_32.dll", EntryPoint = "#1")]
private static extern TwRC DSiinf([In, Out] TwIdentity origin, [In] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwImageInfo imginf);
[DllImport("twain_32.dll", EntryPoint = "#1")]
private static extern TwRC DSixfer([In, Out] TwIdentity origin, [In] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, ref IntPtr hbitmap);
[DllImport("twain_32.dll", EntryPoint = "#1")]
private static extern TwRC DSpxfer([In, Out] TwIdentity origin, [In] TwIdentity dest, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwPendingXfers pxfr);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GlobalAlloc(int flags, int size);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GlobalLock(IntPtr handle);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern bool GlobalUnlock(IntPtr handle);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GlobalFree(IntPtr handle);
[DllImport("user32.dll", ExactSpelling = true)]
private static extern int GetMessagePos();
[DllImport("user32.dll", ExactSpelling = true)]
private static extern int GetMessageTime();
[DllImport("gdi32.dll", ExactSpelling = true)]
private static extern int GetDeviceCaps(IntPtr hDC, int nIndex);
[DllImport("gdi32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr CreateDC(string szdriver, string szdevice, string szoutput, IntPtr devmode);
[DllImport("gdi32.dll", ExactSpelling = true)]
private static extern bool DeleteDC(IntPtr hdc);
public static int ScreenBitDepth
{
get
{
IntPtr screenDC = CreateDC("DISPLAY", null, null, IntPtr.Zero);
int bitDepth = GetDeviceCaps(screenDC, 12);
bitDepth *= GetDeviceCaps(screenDC, 14);
DeleteDC(screenDC);
return bitDepth;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct WINMSG
{
public IntPtr hwnd;
public int message;
public IntPtr wParam;
public IntPtr lParam;
public int time;
public int x;
public int y;
}
} // class Twain
}
As per my analysis this error occurred because of 64 bit machine. Please suggest another solution for this error.
If you're using Twain 2.x (twaindsm.dll):
32-bit version installs in C:\Windows\SysWow64
64-bit version installs in C:\Windows\system32
these dlls don't register in the registry
If you're using Twain 1.x (twain_32.dll):
32-bit version installs in C:\Windows
there is no 64-bit version of twain_32.dll
Make sure your DllImport attributes refer to correct dll you're trying to load (twaindsm.dll or twain_32.dll).
Make sure your platform target in your build settings matches the twain dll you're trying to load (x86, x64).
Do you have TWAIN DSM on your machine? If not, please download & install it and try again.
Make sure your scanner has 64-bit TWAIN driver if you run your app as x64.
I'm working on writing a FileSystemWatcher using Mono but for some reason the callback i send to the FSEvents library isn't mantaining the this reference, it is always null inside the callback even tho the callback is an instance method.
Any idea why it happens?
using System;
using System.IO;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using MonoMac.Foundation;
using System.Threading;
using NUnit.Framework;
using System.Text;
namespace Test
{
class MainClass
{
public void Main ()
{
string testFolder = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "mono-test");
if (Directory.Exists (testFolder)) {
Directory.Delete (testFolder, true);
}
Directory.CreateDirectory (testFolder);
IntPtr path = CFStringCreateWithCString (IntPtr.Zero, testFolder, 0);
IntPtr paths = CFArrayCreate (IntPtr.Zero, new IntPtr [1] { path }, 1, IntPtr.Zero);
IntPtr stream = FSEventStreamCreate (IntPtr.Zero, this.Callback, IntPtr.Zero, paths, FSEventStreamEventIdSinceNow, 0, FSEventStreamCreateFlags.WatchRoot | FSEventStreamCreateFlags.FileEvents);
CFRelease (paths);
CFRelease (path);
Thread runLoop = new Thread (delegate() {
FSEventStreamScheduleWithRunLoop (stream, CFRunLoopGetCurrent (), kCFRunLoopDefaultMode);
FSEventStreamStart (stream);
CFRunLoopRun ();
});
runLoop.Name = "FSEventStream";
runLoop.Start ();
Thread.Sleep (3000);
string file1 = Path.Combine (testFolder, "file1.txt");
//Thread.Sleep(1000);
using (System.IO.File.Create(file1)) {
}
//Thread.Sleep(1000);
System.IO.File.WriteAllText (file1, "file1");
//Thread.Sleep(1000);
System.IO.File.Delete (file1);
}
public static void Main (string[] args)
{
new MainClass().Main();
}
private static IDictionary<IntPtr, MainClass> thisDict = new Dictionary<IntPtr, MainClass>();
private void Callback (IntPtr streamRef, IntPtr clientCallBackInfo, int numEvents, IntPtr eventPaths, IntPtr eventFlags, IntPtr eventIds)
{
MainClass thisObj;
if (this != null) {
thisDict.Add(streamRef, this);
thisObj = this;
} else {
thisObj = thisDict[streamRef];
}
Console.WriteLine("\n{0}", this != null ? "this is not null" : "this is null");
Console.WriteLine("{0}\n", thisObj != null ? "thisObj is not null" : "thisObj is null");
string[] paths = new string[numEvents];
UInt32[] flags = new UInt32[numEvents];
UInt64[] ids = new UInt64[numEvents];
unsafe
{
char** eventPathsPointer = (char**) eventPaths.ToPointer();
uint* eventFlagsPointer = (uint*) eventFlags.ToPointer();
ulong* eventIdsPointer = (ulong*) eventIds.ToPointer();
for (int i = 0; i < numEvents; i++)
{
paths[i] = Marshal.PtrToStringAuto(new IntPtr(eventPathsPointer[i]));
flags[i] = eventFlagsPointer[i];
ids[i] = eventIdsPointer[i];
}
}
Console.WriteLine("Number of events: {0}", numEvents);
for (int i = 0; i < numEvents; i++)
{
Console.WriteLine("{0} {1:x8} {2}", ids[i], flags[i], paths[i]);
Console.WriteLine("Modified: {0:x8}", (flags[i] & (uint) FSEventStreamEventFlagItem.Modified));
Console.WriteLine("Created: {0:x8}", (flags[i] & (uint) FSEventStreamEventFlagItem.Created));
Console.WriteLine("Removed: {0:x8}", (flags[i] & (uint) FSEventStreamEventFlagItem.Removed));
Console.WriteLine("Renamed: {0:x8}", (flags[i] & (uint) FSEventStreamEventFlagItem.Renamed));
Console.WriteLine();
}
}
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static IntPtr CFStringCreateWithCString (IntPtr allocator, string value, int encoding);
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static IntPtr CFArrayCreate (IntPtr allocator, IntPtr [] values, int numValues, IntPtr callBacks);
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static IntPtr CFArrayGetValueAtIndex(IntPtr array, int index);
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static void CFRelease(IntPtr cf);
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static IntPtr CFRunLoopGetCurrent ();
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static IntPtr CFRunLoopGetMain();
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static void CFRunLoopRun ();
[DllImport ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
extern static int CFRunLoopRunInMode (IntPtr mode, double seconds, int returnAfterSourceHandled);
delegate void FSEventStreamCallback (IntPtr streamRef, IntPtr clientCallBackInfo, int numEvents, IntPtr eventPaths, IntPtr eventFlags, IntPtr eventIds);
[DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]
extern static IntPtr FSEventStreamCreate (IntPtr allocator, FSEventStreamCallback callback, IntPtr context, IntPtr pathsToWatch, ulong sinceWhen, double latency, FSEventStreamCreateFlags flags);
[DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]
extern static int FSEventStreamStart (IntPtr streamRef);
[DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]
extern static void FSEventStreamStop (IntPtr streamRef);
[DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]
extern static void FSEventStreamRelease (IntPtr streamRef);
[DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]
extern static void FSEventStreamScheduleWithRunLoop (IntPtr streamRef, IntPtr runLoop, IntPtr runLoopMode);
[DllImport ("/System/Library/Frameworks/CoreServices.framework/CoreServices")]
extern static void FSEventStreamUnscheduleFromRunLoop (IntPtr streamRef, IntPtr runLoop, IntPtr runLoopMode);
const ulong FSEventStreamEventIdSinceNow = ulong.MaxValue;
private static IntPtr kCFRunLoopDefaultMode = CFStringCreateWithCString(IntPtr.Zero, "kCFRunLoopDefaultMode", 0);
[Flags()]
enum FSEventStreamCreateFlags : uint {
None = 0x00000000,
UseCFTypes = 0x00000001,
NoDefer = 0x00000002,
WatchRoot = 0x00000004,
IgnoreSelf = 0x00000008,
FileEvents = 0x00000010
}
[Flags()]
enum FSEventStreamEventFlag : uint {
None = 0x00000000,
MustScanSubDirs = 0x00000001,
UserDropped = 0x00000002,
KernelDropped = 0x00000004,
EventIdsWrapped = 0x00000008,
HistoryDone = 0x00000010,
RootChanged = 0x00000020,
FlagMount = 0x00000040,
Unmount = 0x00000080
}
[Flags()]
enum FSEventStreamEventFlagItem : uint {
Created = 0x00000100,
Removed = 0x00000200,
InodeMetaMod = 0x00000400,
Renamed = 0x00000800,
Modified = 0x00001000,
FinderInfoMod = 0x00002000,
ChangeOwner = 0x00004000,
XattrMod = 0x00008000,
IsFile = 0x00010000,
IsDir = 0x00020000,
IsSymlink = 0x00040000
}
}
}
UPDATE
The fixed code is here for anyone interested.
When you pass a delegate to a native method, the runtime has no way to know how long the native method will hold on to the function pointer, so it's up to you to keep the delegate alive. If you don't maintain a reference to it, the garbage collector might collect the delegate, resulting in undefined behaviour when the native code tries to call it.
Is it possible to set the height of a window using the window handle or process handle?
I have the following so far, assume the application in question is notepad.
Process[] processes = Process.GetProcessesByName("notepad");
foreach (Process p in processes)
{
if (p.MainWindowTitle == title)
{
handle = p.MainWindowHandle;
while ((handle = p.MainWindowHandle) == IntPtr.Zero)
{
Thread.Sleep(1000);
p.Refresh();
}
break;
}
}
Can I make use of handle or p to set the height of the window?
This is how I would do it:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT Rect);
[DllImport("user32.dll", SetLastError = true)]
static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int Width, int Height, bool Repaint);
static void Main(string[] args)
{
Process[] processes = Process.GetProcessesByName("notepad");
foreach (Process p in processes)
{
IntPtr handle = p.MainWindowHandle;
RECT Rect = new RECT();
if (GetWindowRect(handle, ref Rect))
MoveWindow(handle, Rect.left, Rect.right, Rect.right-Rect.left, Rect.bottom-Rect.top + 50, true);
}
}
}
}
While you can do it with SetWindowPos, and SetWindowPos is the newer and more capable API, MoveWindow is just easier to call.
You should be able to use the Win32 SetWindowPos function (use for both position and size). Here's a link for how to do it in C#.
Here's a quick sample. This will move notepad to (10,10) on the screen, and resize it to (450,450):
class Program
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
static void Main(string[] args)
{
Console.WriteLine("Start notepad and hit any key...");
Console.ReadKey(true);
Process[] processes = Process.GetProcessesByName("notepad");
foreach (Process p in processes)
{
var handle = p.MainWindowHandle;
SetWindowPos(handle, new IntPtr(SpecialWindowHandles.HWND_TOP), 10,10,450,450,SetWindowPosFlags.SWP_SHOWWINDOW);
break;
}
}
}
public enum SpecialWindowHandles
{
HWND_TOP = 0,
HWND_BOTTOM = 1,
HWND_TOPMOST = -1,
HWND_NOTOPMOST = -2
}
[Flags]
public enum SetWindowPosFlags : uint
{
SWP_ASYNCWINDOWPOS = 0x4000,
SWP_DEFERERASE = 0x2000,
SWP_DRAWFRAME = 0x0020,
SWP_FRAMECHANGED = 0x0020,
SWP_HIDEWINDOW = 0x0080,
SWP_NOACTIVATE = 0x0010,
SWP_NOCOPYBITS = 0x0100,
SWP_NOMOVE = 0x0002,
SWP_NOOWNERZORDER = 0x0200,
SWP_NOREDRAW = 0x0008,
SWP_NOREPOSITION = 0x0200,
SWP_NOSENDCHANGING = 0x0400,
SWP_NOSIZE = 0x0001,
SWP_NOZORDER = 0x0004,
SWP_SHOWWINDOW = 0x0040,
}