I don't get any error or exception.
Button in one Window:
private void button1_Click(object sender, EventArgs e)
{
ControlPort.Output(0x378, 0xff);
}
and inpout.dll interface:
class ControlPort
{
[DllImport("inpout32.dll", EntryPoint = "Out32")]
public static extern void Output(int adress, int value);
}
What is wrong?
LED on D2 is on all the time.
I have Windows 7 x64 Ultimate.
For x64 you should use "InpOutx64.dll".
Visit: http://www.highrez.co.uk/Downloads/InpOut32/default.htm
There you can read more and find samples.
Working code if somebody needs it.
using System;
using System.Runtime.InteropServices;
namespace ParallelPort
{
public class PortAccess
{
//inpout.dll
[DllImport("inpout32.dll")]
private static extern UInt32 IsInpOutDriverOpen();
[DllImport("inpout32.dll")]
private static extern void Out32(short PortAddress, short Data);
[DllImport("inpout32.dll")]
private static extern char Inp32(short PortAddress);
[DllImport("inpout32.dll")]
private static extern void DlPortWritePortUshort(short PortAddress, ushort Data);
[DllImport("inpout32.dll")]
private static extern ushort DlPortReadPortUshort(short PortAddress);
[DllImport("inpout32.dll")]
private static extern void DlPortWritePortUlong(int PortAddress, uint Data);
[DllImport("inpout32.dll")]
private static extern uint DlPortReadPortUlong(int PortAddress);
[DllImport("inpoutx64.dll")]
private static extern bool GetPhysLong(ref int PortAddress, ref uint Data);
[DllImport("inpoutx64.dll")]
private static extern bool SetPhysLong(ref int PortAddress, ref uint Data);
//inpoutx64.dll
[DllImport("inpoutx64.dll", EntryPoint = "IsInpOutDriverOpen")]
private static extern UInt32 IsInpOutDriverOpen_x64();
[DllImport("inpoutx64.dll", EntryPoint = "Out32")]
private static extern void Out32_x64(short PortAddress, short Data);
[DllImport("inpoutx64.dll", EntryPoint = "Inp32")]
private static extern char Inp32_x64(short PortAddress);
[DllImport("inpoutx64.dll", EntryPoint = "DlPortWritePortUshort")]
private static extern void DlPortWritePortUshort_x64(short PortAddress, ushort Data);
[DllImport("inpoutx64.dll", EntryPoint = "DlPortReadPortUshort")]
private static extern ushort DlPortReadPortUshort_x64(short PortAddress);
[DllImport("inpoutx64.dll", EntryPoint = "DlPortWritePortUlong")]
private static extern void DlPortWritePortUlong_x64(int PortAddress, uint Data);
[DllImport("inpoutx64.dll", EntryPoint = "DlPortReadPortUlong")]
private static extern uint DlPortReadPortUlong_x64(int PortAddress);
[DllImport("inpoutx64.dll", EntryPoint = "GetPhysLong")]
private static extern bool GetPhysLong_x64(ref int PortAddress, ref uint Data);
[DllImport("inpoutx64.dll", EntryPoint = "SetPhysLong")]
private static extern bool SetPhysLong_x64(ref int PortAddress, ref uint Data);
private bool _X64;
private short _PortAddress;
public PortAccess(short PortAddress)
{
_X64 = false;
_PortAddress = PortAddress;
try
{
uint nResult = 0;
try
{
nResult = IsInpOutDriverOpen();
}
catch (BadImageFormatException)
{
nResult = IsInpOutDriverOpen_x64();
if (nResult != 0)
_X64 = true;
}
if (nResult == 0)
{
throw new ArgumentException("Unable to open InpOut32 driver");
}
}
catch (DllNotFoundException)
{
throw new ArgumentException("Unable to find InpOut32.dll");
}
}
//Public Methods
public void Write(short Data)
{
if (_X64)
{
Out32_x64(_PortAddress, Data);
}
else
{
Out32(_PortAddress, Data);
}
}
public byte Read()
{
if (_X64)
{
return (byte)Inp32_x64(_PortAddress);
}
else
{
return (byte)Inp32(_PortAddress);
}
}
}
}
You are not going to get an exception when you get this wrong, at most a blue screen. Pick one of:
you are using the wrong address (0x3bc, 0x2f8)
you wired the LED wrong
you broke into the wrong museum to get the hardware
The question is too poorly documented to help you beyond this.
I resolved a problem with LPT port on Windows 2000 on my old laptop, where the data port (pin2-pin9) could not be set.
Using this imported function:
[DllImport("inpout32.dll", EntryPoint = "Out32")]
public static extern void Out32(int address, int value);
after every reboot or restart of Windows I have to call this line:
Out32(0x378 + 2, 0x00);
so that the port works properly. I think the problem is in the bi-directional settings (control port at 6th bit on 0x37A).
Related
"Failed converting from System.IntPtr to byte[]"
I was trying to code an DLL injection but I didn´t workes as shown in the video...
Does anybody know how to fix this or if I need to add anything to the code???
I spent like 2 hours looking for a fix but I cant find it and I don´t know what I could do so I was thinking one of you could solve this problem?
This is my second Program I have programmed, show some specs of my Computer
using System;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
namespace Process_Hijacker
{
public partial class ProcessHijacker : Form
{
public ProcessHijacker()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Process[] processes = Process.GetProcesses();
foreach (Process p in processes)
{
processlist.Items.Add(p.ProcessName);
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
{
DLLP = textBox1.Text;
}
private static string DLLP { get; set; }
private static string PN { get; set; }
private void button1_Click(object sender, EventArgs e)
{
DialogResult result = this.openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
this.textBox1.Text = this.openFileDialog1.FileName;
}
}
private void button2_Click(object sender, EventArgs e)
{
}
//Injection Define
static readonly IntPtr INTPTR_ZERO = (IntPtr)0;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(uint dwDesireAccess, int bintheritHandle, uint dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpBAseAddress, byte[] Buffer, uint size, int lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, int lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateRemoteThread(IntPtr hprocess, IntPtr lpThreadAttribute, IntPtr dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadID);
public static int Injection(string PN, string DLLP)
{
// 1 = Datei existiert nicht
// 2 = Prozess nicht aktiv
// 3 = Injektion Fehlgeschlagen
// 4 = Injektion Erfolgreich
if (!File.Exists(DLLP)) { return 1; }
uint _procid = 0;
Process[] _procs = Process.GetProcesses();
for (int i = 0; i < _procs.Length; i++)
{
if (_procs[i].ProcessName == PN)
{
_procid = (uint)_procs[i].Id;
}
}
if (_procid == 0) { return 2; }
if (!SI(_procid, DLLP))
{
return 3;
}
return 4;
}
public static bool SI(uint P, string DLLP)
{
IntPtr hndProc = OpenProcess((0x2 | 0x8 | 0x10 | 0x20 | 0x400), 1, P);
if (hndProc == INTPTR_ZERO) { return false; }
IntPtr lpAddress = VirtualAllocEx(hndProc, (IntPtr)null, (IntPtr)DLLP.Length, (0x1000 | 0x2000), 0x40);
if (lpAddress == INTPTR_ZERO)
{
return false;
}
byte[] bytes = Encoding.ASCII.GetBytes(DLLP);
if (WriteProcessMemory(hndProc, lpAddress, bytes, (uint)bytes.Length, 0) == 0)
{
return false;
}
CloseHandle(hndProc);
return true;
}
}
}
Given a Windows 8 (.1) computer with the following power options:
And screensaver configured as:
The goal is to programmatically turn the display on and "kill" the screensaver (so that it will be re-activated after idle time).
(Note, that according to the settings it's possible that only the screensaver is on, or, that the display is off completely after the screensaver was on for about one minute).
What i have tried is:
SendMessage(HWND_Broadcast, WM_SysCommand, SC_MONITORPOWER, (LPARAM) - 1);
in combination with
// From Microsoft's Knowledge Base article #140723:
// http://support.microsoft.com/kb/140723
// "How to force a screen saver to close once started
// in Windows NT, Windows 2000, and Windows Server 2003"
public static void KillScreenSaver()
{
IntPtr hDesktop = OpenDesktop("Screen-saver", 0, false, DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS);
if (hDesktop != IntPtr.Zero)
{
if (!EnumDesktopWindows(hDesktop, KillScreenSaverFunc, IntPtr.Zero) || !CloseDesktop(hDesktop))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
else
{
TerminateWindow(GetForegroundWindow());
}
}
private static bool KillScreenSaverFunc(IntPtr hWnd, IntPtr lParam)
{
if (IsWindowVisible(hWnd))
{
TerminateWindow(hWnd);
}
return true;
}
private static void TerminateWindow(IntPtr hWnd)
{
if (!PostMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
And
public static void ActivateScreensaver()
{
SetScreenSaverActive(TRUE);
}
private static void SetScreenSaverActive(uint active)
{
IntPtr nullVar = IntPtr.Zero;
// Ignoring error since ERROR_OPERATION_IN_PROGRESS is expected.
// Methode is called to reset timer and to prevent possible errors as mentioned in Microsoft's Knowledge Base article #140723:
// http://support.microsoft.com/kb/140723
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, active, ref nullVar, SPIF_SENDWININICHANGE);
}
Which worked, partially. However, the display was turned off immediately again (as a matter of fact, most times one couldn't even see that the monitor was turned again apart from the power-led going "steady on" instead of "flashing on off = power safe" for a short time).
So i guess i'm missing a crucial part of the picture like reliably resetting system idle timer to make sure the screen is not immediately being turned off, again.
Edit: According to my investigations SetThreadExecutionState(ES_DISPLAY_REQUIRED) seems to do the trick in regards to resetting the idle-timer. However, i still don't know the correct sequence of calls. I'll self-answer when i figure it out...
The following code will:
interrupt a running screensaver
turn on a turned-off screen ("turn off" as mentioned in power options)
private static readonly ILog Log = LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
public void TurnOnScreenAndInterruptScreensaver()
{
TryTurnOnScreenAndResetDisplayIdleTimer();
TryInterruptScreensaver();
}
/// <summary>
/// Moves the mouse which turns on a turned-off screen and also resets the
/// display idle timer, which is key, because otherwise the
/// screen would be turned off again immediately.
/// </summary>
private static void TryTurnOnScreenAndResetDisplayIdleTimer()
{
var input = new SendInputNativeMethods.Input {
type = SendInputNativeMethods.SendInputEventType.InputMouse, };
try
{
SendInputNativeMethods.SendInput(input);
}
catch (Win32Exception exception)
{
Log.Error("Could not send mouse move input to turn on display", exception);
}
}
private static void TryInterruptScreensaver()
{
try
{
if (ScreensaverNativeMethods.GetScreenSaverRunning())
{
ScreensaverNativeMethods.KillScreenSaver();
}
// activate screen saver again so that after idle-"timeout" it shows again
ScreensaverNativeMethods.ActivateScreensaver();
}
catch (Win32Exception exception)
{
Log.Error("Screensaver could not be deactivated", exception);
}
}
SendInputNativeMethods:
public static class SendInputNativeMethods
{
public static void SendInput(params Input[] inputs)
{
if (SendInput((uint)inputs.Length, inputs, Marshal.SizeOf<Input>())
!= (uint)inputs.Length)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern uint SendInput(
uint nInputs,
[MarshalAs(UnmanagedType.LPArray), In] Input[] pInputs,
int cbSize);
[StructLayout(LayoutKind.Sequential)]
public struct Input
{
public SendInputEventType type;
public MouseKeybdhardwareInputUnion mkhi;
}
[StructLayout(LayoutKind.Explicit)]
public struct MouseKeybdhardwareInputUnion
{
[FieldOffset(0)]
public MouseInputData mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
public struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
public struct MouseInputData
{
public int dx;
public int dy;
public uint mouseData;
public MouseEventFlags dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[Flags]
public enum MouseEventFlags : uint
{
MOUSEEVENTF_MOVE = 0x0001,
MOUSEEVENTF_LEFTDOWN = 0x0002,
MOUSEEVENTF_LEFTUP = 0x0004,
MOUSEEVENTF_RIGHTDOWN = 0x0008,
MOUSEEVENTF_RIGHTUP = 0x0010,
MOUSEEVENTF_MIDDLEDOWN = 0x0020,
MOUSEEVENTF_MIDDLEUP = 0x0040,
MOUSEEVENTF_XDOWN = 0x0080,
MOUSEEVENTF_XUP = 0x0100,
MOUSEEVENTF_WHEEL = 0x0800,
MOUSEEVENTF_VIRTUALDESK = 0x4000,
MOUSEEVENTF_ABSOLUTE = 0x8000
}
public enum SendInputEventType : int
{
InputMouse,
InputKeyboard,
InputHardware
}
ScreensaverNativeMethods:
internal static class ScreensaverNativeMethods
{
private const int SPI_GETSCREENSAVERRUNNING = 0x0072;
private const int SPI_SETSCREENSAVEACTIVE = 0x0011;
private const int SPIF_SENDWININICHANGE = 0x0002;
private const uint DESKTOP_WRITEOBJECTS = 0x0080;
private const uint DESKTOP_READOBJECTS = 0x0001;
private const int WM_CLOSE = 0x0010;
private const int TRUE = 1;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SystemParametersInfo(
uint uiAction,
uint uiParam,
ref IntPtr pvParam,
uint fWinIni);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool PostMessage(
IntPtr hWnd,
uint msg,
IntPtr wParam,
IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr OpenDesktop(
string lpszDesktop,
uint dwFlags,
[In, MarshalAs(UnmanagedType.Bool)]bool fInherit,
uint dwDesiredAccess);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseDesktop(IntPtr hDesktop);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumDesktopWindows(
IntPtr hDesktop,
EnumDesktopWindowsProc callback,
IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetForegroundWindow();
private delegate bool EnumDesktopWindowsProc(IntPtr hDesktop, IntPtr lParam);
public static bool GetScreenSaverRunning()
{
IntPtr isRunning = IntPtr.Zero;
if (!SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, ref isRunning, 0))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
return isRunning != IntPtr.Zero;
}
public static void ActivateScreensaver()
{
SetScreenSaverActive(TRUE);
}
private static void SetScreenSaverActive(uint active)
{
IntPtr nullVar = IntPtr.Zero;
// Ignoring error since ERROR_OPERATION_IN_PROGRESS is expected.
// Methode is called to reset timer and to prevent possible errors
// as mentioned in Microsoft's Knowledge Base article #140723:
// http://support.microsoft.com/kb/140723
SystemParametersInfo(
SPI_SETSCREENSAVEACTIVE,
active,
ref nullVar,
SPIF_SENDWININICHANGE);
}
// From Microsoft's Knowledge Base article #140723:
// http://support.microsoft.com/kb/140723
// "How to force a screen saver to close once started
// in Windows NT, Windows 2000, and Windows Server 2003"
public static void KillScreenSaver()
{
IntPtr hDesktop = OpenDesktop(
"Screen-saver",
0,
false,
DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS);
if (hDesktop != IntPtr.Zero)
{
if (!EnumDesktopWindows(hDesktop, KillScreenSaverFunc, IntPtr.Zero)
|| !CloseDesktop(hDesktop))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
else
{
TerminateWindow(GetForegroundWindow());
}
}
private static bool KillScreenSaverFunc(IntPtr hWnd, IntPtr lParam)
{
if (IsWindowVisible(hWnd))
{
TerminateWindow(hWnd);
}
return true;
}
private static void TerminateWindow(IntPtr hWnd)
{
if (!PostMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
}
I am using 2 Windows API exported functions from c#.NET 4.0.
private const string WINDOW_EXCEL7 = "XLMAIN";
private const string CHILDWINDOW_XLMAIN = "EXCEL7";
I am searching for windows titles of Excel main windows' child windows (Excel has an MDI window of class XLMAIN containing 0, 1 or more child windows with EXCEL7 window class).
The goal is to find if a an excel workbook is being opened in any instances of Excel application. I did it by finding all XLMAIN IntPtr (pointers) and traversing children until I get a IntPtr with EXCEL7 window class at which point I can read child windows title and determine if a file is opened.
Basically this works on Windows XP, but not on Windows 7. I didn't try in Windows Vista.
What has changed? Can someone debug the issue since I don't have Windows 7.
Thanks
Rad
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ExcelChildWindowsTitle
{
public static void Main(string[] args)
{
//XLMAIN/EXCELDESK/EXCEL7 as seen by Spy++ VS 2010 utility
//IntPtr hWnd = WndSearcher.SearchForWindow("XLMAIN", "EXCEL7", "icui-20110331.xls", ref workbookTitle);
//bool excelProofFound = WindowTitleSearcher.SearchForWindow("XLMAIN", "EXCEL7", "testfileopenedinEXCEL.xls", ref workbookTitle);
bool excelProofFound = WindowTitleSearcher.SearchForWindow("icui-20110331.xls");
if (excelProofFound)
Console.Write(":)))))))) Proof File opened in an Excel process;");
else
{
Console.Write(":|Proof File not found");
}
}
public static class WindowTitleSearcher
{
private const string WINDOW_EXCEL7 = "XLMAIN";
private const string CHILDWINDOW_XLMAIN = "EXCEL7";
public static bool SearchForWindow(string title)
{
SearchData sd = new SearchData { Wndclass = WINDOW_EXCEL7, ChildWndclass = CHILDWINDOW_XLMAIN, ChildTitle = title, WorkbookTitle = String.Empty};
EnumWindows(new EnumWindowsProc(EnumProc), ref sd);
return (int)sd.hWnd > 0;
}
private static bool EnumProc(IntPtr hWnd, ref SearchData data)
{
const bool directOnly = false;
// Check classname and title
// This is different from FindWindow() in that the code below allows partial matches
StringBuilder sb1 = new StringBuilder(1024);
GetClassName(hWnd, sb1, sb1.Capacity);
Debug.WriteLine(sb1.ToString());
if (sb1.ToString().StartsWith(data.Wndclass))
{
RecursiveEnumChildWindows(hWnd, directOnly, ref data);
if ((int)data.hWnd > 0)
{
// Found the wnd, halt enumeration
return false;
}
}
return true;
}
private static void RecursiveEnumChildWindows(IntPtr parentHwnd, bool directOnly, ref SearchData data)
{
EnumChildWindows(parentHwnd, delegate(IntPtr hwnd, ref SearchData data1)
{
bool add = true;
if (directOnly)
{
add = GetParent(hwnd) == parentHwnd;
}
StringBuilder sb1 = new StringBuilder(1024);
GetClassName(hwnd, sb1, sb1.Capacity);
Debug.WriteLine("Child:" + sb1.ToString());
if (add)
{
if (sb1.ToString().StartsWith(data1.ChildWndclass))
{
sb1 = new StringBuilder(1024);
//Window Caption
GetWindowText(hwnd, sb1, sb1.Capacity);
if (sb1.ToString().Contains(data1.ChildTitle))
{
data1.hWnd = hwnd;
data1.WorkbookTitle = sb1.ToString();
return false; // Found the wnd, halt enumeration
}
}
}
return true;
}, ref data);
}
private struct SearchData
{
// You can put any vars in here...
public string Wndclass;
public string ChildWndclass;
public string ChildTitle;
public IntPtr hWnd;
public string WorkbookTitle;
}
# region Windows API declarations
private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ref SearchData data);
//private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, [MarshalAsAttribute(UnmanagedType.Struct)] ref SearchData data);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, ref SearchData data);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
private static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
# endregion
}
}
Why use hacks like this when MS Office has documented automation support?
You can use .NET, the older COM/OLE automation interfaces or the super old DDE interface.
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ExcelChildWindowsTitle
{
class Program
{
static void Main(string[] args)
{
//XLMAIN/EXCELDESK/EXCEL7 as seen by Spy++ VS 2010 utility
//IntPtr hWnd = WndSearcher.SearchForWindow("XLMAIN", "EXCEL7", "icui-20110331.xls", ref workbookTitle);
//bool excelProofFound = WindowTitleSearcher.SearchForWindow("XLMAIN", "EXCEL7", "testfileopenedinEXCEL.xls", ref workbookTitle);
bool excelProofFound = WindowTitleSearcher.SearchForWindow("file name here");
if (excelProofFound)
Console.Write(":)))))))) Proof File opened in an Excel process;");
else
{
Console.Write(":|Proof File not found");
}
}
public static class WindowTitleSearcher
{
private const string WINDOW_EXCEL7 = "XLMAIN";
private const string CHILDWINDOW_XLMAIN = "EXCEL7";
public static bool SearchForWindow(string title)
{
SearchData sd = new SearchData { Wndclass = WINDOW_EXCEL7, ChildWndclass = CHILDWINDOW_XLMAIN, ChildTitle = title, WorkbookTitle = String.Empty };
EnumWindows(new EnumWindowsProc(EnumProc), ref sd);
return (int)sd.hWnd > 0;
}
private static bool EnumProc(IntPtr hWnd, ref SearchData data)
{
const bool directOnly = false;
// Check classname and title
// This is different from FindWindow() in that the code below allows partial matches
StringBuilder sb1 = new StringBuilder(1024);
GetClassName(hWnd, sb1, sb1.Capacity);
Debug.WriteLine(sb1.ToString());
if (sb1.ToString().StartsWith(data.Wndclass))
{
RecursiveEnumChildWindows(hWnd, directOnly, ref data);
if ((int)data.hWnd > 0)
{
// Found the wnd, halt enumeration
return false;
}
}
return true;
}
private static void RecursiveEnumChildWindows(IntPtr parentHwnd, bool directOnly, ref SearchData data)
{
EnumChildWindows(parentHwnd, delegate(IntPtr hwnd, ref SearchData data1)
{
bool add = true;
if (directOnly)
{
add = GetParent(hwnd) == parentHwnd;
}
StringBuilder sb1 = new StringBuilder(1024);
GetClassName(hwnd, sb1, sb1.Capacity);
Debug.WriteLine("Child:" + sb1.ToString());
if (add)
{
if (sb1.ToString().StartsWith(data1.ChildWndclass))
{
sb1 = new StringBuilder(1024);
//Window Caption
GetWindowText(hwnd, sb1, sb1.Capacity);
if (sb1.ToString().Contains(data1.ChildTitle))
{
data1.hWnd = hwnd;
data1.WorkbookTitle = sb1.ToString();
return false; // Found the wnd, halt enumeration
}
}
}
return true;
}, ref data);
}
private struct SearchData
{
// You can put any vars in here...
public string Wndclass;
public string ChildWndclass;
public string ChildTitle;
public IntPtr hWnd;
public string WorkbookTitle;
}
# region Windows API declarations
private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ref SearchData data);
//private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, [MarshalAsAttribute(UnmanagedType.Struct)] ref SearchData data);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, ref SearchData data);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
private static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
# endregion
}
}
}
/////////////////////Work good on Windows 10 64 bit
I have to use this external functions "GetOpenedFiles" (more info to: http://www.codeproject.com/KB/shell/OpenedFileFinder.aspx) into my C# application.
I don't know as I can write a wrapper of this function:
void GetOpenedFiles(LPCWSTR lpPath, OF_TYPE Filter, OF_CALLBACK CallBackProc, UINT_PTR pUserContext);
ORIGINAL C++ CODE (OpenFilefinder.h)
enum OF_TYPE
{
FILES_ONLY = 1,
MODULES_ONLY = 2,
ALL_TYPES = 3
};
struct OF_INFO_t
{
DWORD dwPID;
LPCWSTR lpFile;
HANDLE hFile;
};
typedef void (CALLBACK* OF_CALLBACK)(OF_INFO_t OpenedFileInf0, UINT_PTR uUserContext );
extern "C" __declspec(dllexport) void ShowOpenedFiles( LPCWSTR lpPath );
extern "C" __declspec(dllexport) void GetOpenedFiles( LPCWSTR lpPath,
OF_TYPE Filter,
OF_CALLBACK CallBackProc,
UINT_PTR pUserContext );
MY C# APPLICATION:
public enum OF_TYPE : int
{
FILES_ONLY = 1,
MODULES_ONLY = 2,
ALL_TYPES = 3
}
public struct OF_INFO_t
{
?????? dwPID;
?????? lpFile;
?????? hFile;
}
[DllImport("OpenFileFinder.dll", EntryPoint = "GetOpenedFiles")]
static extern void GetOpenedFiles(??????? lpPath, OF_TYPE filter, ????? CallBackProc, ????? pUserContext);
How can I use this dll function correctly in my C# app?
EDIT:
This is my latest snippet, but never invoke callback function:
namespace Open64
{
class Program
{
public Program()
{
GetOpenedFiles("C:\\", OF_TYPE.ALL_TYPES, CallbackFunction, UIntPtr.Zero);
}
//void GetOpenedFiles(LPCWSTR lpPath, OF_TYPE Filter, OF_CALLBACK CallBackProc, UINT_PTR pUserContext);
public enum OF_TYPE : int
{
FILES_ONLY = 1,
MODULES_ONLY = 2,
ALL_TYPES = 3
}
public struct OF_INFO_t
{
Int32 dwPID;
String lpFile;
IntPtr hFile;
}
public delegate void CallbackFunctionDef(OF_INFO_t info, IntPtr context);
[DllImport("OpenFileFinder.dll", EntryPoint = "GetOpenedFiles")]
static extern void GetOpenedFiles(string lpPath, OF_TYPE filter, CallbackFunctionDef CallBackProc, UIntPtr pUserContext);
public void CallbackFunction(OF_INFO_t info, IntPtr context)
{
Console.WriteLine("asd");
}
[STAThread]
static void Main()
{
new Program();
}
}
}
This is how you would marshal the following types:
DWORD => Int32
LPCWSTR => String
HANDLE => IntPtr
UINT_PTR => UIntPtr
public struct OF_INFO_t
{
Int32 dwPID;
String lpFile;
IntPtr hFile;
}
public delegate void CallbackFunctionDef(OF_INFO_t info, UIntPtr context);
[DllImport("OpenFileFinder.dll", EntryPoint = "GetOpenedFiles")]
static extern void GetOpenedFiles(string lpPath, OF_TYPE filter, CallbackFunctionDef CallBackProc, UIntPtr pUserContext);
EDIT: Here's the complete program
class Program
{
public Program()
{
GetOpenedFiles("C:\\", OF_TYPE.ALL_TYPES, CallbackFunction, UIntPtr.Zero);
Console.ReadKey();
}
//void GetOpenedFiles(LPCWSTR lpPath, OF_TYPE Filter, OF_CALLBACK CallBackProc, UINT_PTR pUserContext);
public enum OF_TYPE : int
{
FILES_ONLY = 1,
MODULES_ONLY = 2,
ALL_TYPES = 3
}
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)]
public struct OF_INFO_t
{
public Int32 dwPID;
public String lpFile;
public IntPtr hFile;
}
public delegate void CallbackFunctionDef(OF_INFO_t info, IntPtr context);
[DllImport("OpenFileFinder.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, EntryPoint = "GetOpenedFiles")]
static extern void GetOpenedFiles(string lpPath, OF_TYPE filter, CallbackFunctionDef CallBackProc, UIntPtr pUserContext);
public void CallbackFunction(OF_INFO_t info, IntPtr context)
{
//List the files
Console.WriteLine(info.lpFile);
}
[STAThread]
static void Main()
{
new Program();
}
}
I am attempting to write code to extract the contents of a CAB file, however I am having trouble using the SetupIterateCabinet routine.
Please see doc here http://msdn.microsoft.com/en-us/library/aa377404(v=vs.85).aspx
I can import it properly like this
private const uint SPFILENOTIFY_CABINETINFO = 0x00000010;
private const uint SPFILENOTIFY_FILEINCABINET = 0x00000011;
private const uint SPFILENOTIFY_NEEDNEWCABINET = 0x00000012;
private const uint SPFILENOTIFY_FILEEXTRACTED = 0x00000013;
private const uint SPFILENOTIFY_FILEOPDELAYED = 0x00000014;
private const uint NO_ERROR = 0;
private const uint FILEOP_ABORT = 0;
private const uint FILEOP_DOIT= 1;
private const uint FILEOP_SKIP= 2;
private const uint FILEOP_NEWPATH= 4;
static void Main(string[] args)
{
SetupIterateCabinet("c:\\SomeCab.cab", 0, new PSP_FILE_CALLBACK(CallBack), 0);
Console.ReadKey();
}
[DllImport("SetupApi.dll", CharSet = CharSet.Auto)]
public static extern bool SetupIterateCabinet(string cabinetFile,
uint reserved, PSP_FILE_CALLBACK callBack, uint context);
public delegate uint PSP_FILE_CALLBACK(uint context, uint notification,
IntPtr param1, IntPtr param2);
private static uint CallBack(uint context, uint notification, IntPtr param1,
IntPtr param2)
{
uint rtnValue = NO_ERROR;
switch (notification)
{
case SPFILENOTIFY_FILEINCABINET:
rtnValue = OnFileFound(context, notification, param1, param2);
break;
case SPFILENOTIFY_FILEEXTRACTED:
rtnValue = OnFileExtractComplete(param1);
break;
case SPFILENOTIFY_NEEDNEWCABINET:
rtnValue = NO_ERROR;
break;
}
return rtnValue;
}
private static uint OnFileExtractComplete(IntPtr param1)
{
Console.WriteLine("Complete");
return FILEOP_DOIT;
}
[StructLayout(LayoutKind.Sequential)]
struct _FILE_IN_CABINET_INFO {
IntPtr NameInCabinet;
int FileSize;
int Win32Error;
int DosDate;
int DosTime;
int DosAttribs;
StringBuilder FullTargetName;
};
static private uint OnFileFound(uint context, uint notification, IntPtr param1, IntPtr param2)
{
_FILE_IN_CABINET_INFO fc = new _FILE_IN_CABINET_INFO() ;
Marshal.PtrToStructure(param1, fc);
return 1;
}
However the problem comes when attempting to process the SPFILENOTIFY_FILEINCABINET event in the callback. According to the documentation this is a struct, that I need to put the name of where I want to have the file extracted to in. I am having trouble figuring out what the struct should look like and maybe how to convert the param to a struct.
I think you have a problem with the return values of your callback function. On SPFILENOTIFY_FILECABINET, you should be returning FILEOP_DOIT. Before returning you should be setting up the filename in the FILE_IN_CABINTE_INFO. Please check the codeproject post http://www.codeproject.com/Articles/7165/Iterate-and-Extract-Cabinet-File
I might add some code sample later. GTG now
EDIT:
Code sample below. I haven't tried it, but I believe it should work. I have tried to keep the structure similar to your code. This should show you how to define the FILE_IN_CABINET_INFO class and the correct values to be set and returned in the callback
public delegate uint PSP_FILE_CALLBACK(uint context, uint notification, IntPtr param1, IntPtr param2);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class FILE_IN_CABINET_INFO {
public String NameInCabinet;
public uint FileSize;
public uint Win32Error;
public ushort DosDate;
public ushort DosTime;
public ushort DosAttribs;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public System.String FullTargetName;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class FILEPATHS {
public String Target;
public String Source;
public uint Win32Error;
public uint Flags;
}
public const uint SPFILENOTIFY_FILEINCABINET = 0x00000011; // The file has been extracted from the cabinet.
public const uint SPFILENOTIFY_NEEDNEWCABINET = 0x00000012; // file is encountered in the cabinet.
public const uint SPFILENOTIFY_FILEEXTRACTED = 0x00000013; // The current file is continued in the next cabinet.
public const uint NO_ERROR = 0;
public const uint FILEOP_ABORT = 0; // Abort cabinet processing.
public const uint FILEOP_DOIT = 1; // Extract the current file.
public const uint FILEOP_SKIP = 2; // Skip the current file.
[DllImport("SetupApi.dll", CharSet = CharSet.Auto)]
public static extern bool SetupIterateCabinet(string cabinetFile, uint reserved, PSP_FILE_CALLBACK callBack, uint context);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern uint GetLastError();
static void Main(string[] args) {
IterateCabinet(#"c:\SomeCab.cab");
}
public static void IterateCabinet(string filePath) {
PSP_FILE_CALLBACK callback = new PSP_FILE_CALLBACK(CallBack);
if (!SetupIterateCabinet(filePath, 0, callback, 0))
throw new Win32Exception((int)GetLastError());
}
static uint CallBack(uint context, uint notification, IntPtr param1, IntPtr param2) {
if (notification == SPFILENOTIFY_FILEINCABINET)
return OnFileFound(context, notification, param1, param2);
else if (notification == SPFILENOTIFY_FILEEXTRACTED)
return OnFileExtractComplete(param1);
else if (notification == SPFILENOTIFY_NEEDNEWCABINET)
return NO_ERROR;
return NO_ERROR;
}
static uint OnFileFound(uint context, uint notification, IntPtr param1, IntPtr param2) {
FILE_IN_CABINET_INFO fileInCabinetInfo = (FILE_IN_CABINET_INFO)Marshal.PtrToStructure(param1, typeof(FILE_IN_CABINET_INFO));
fileInCabinetInfo.FullTargetName = fileInCabinetInfo.NameInCabinet; // extract to current directory
return FILEOP_DOIT;
}
static uint OnFileExtractComplete(IntPtr param1) {
FILEPATHS filePaths = (FILEPATHS)Marshal.PtrToStructure(param1, typeof(FILEPATHS));
if (filePaths.Win32Error == NO_ERROR)
Console.WriteLine("File {0} extracted to {1} " + filePaths.Source, filePaths.Target);
else
Console.WriteLine("Errors occurred while extracting cab File {0} to {1} ", filePaths.Source, filePaths.Target);
return filePaths.Win32Error;
}