When I compile the below code into an executable and run it, the console windows appears. From the texts that I've read ShowWindow(hWnd,0) should hide the console window, but it doesn't.
This is the below code:
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;
using System.Threading;
namespace Foreground {
class GetForegroundWindowTest {
/// Foreground dll's
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
/// Console hide dll's
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_HIDE = 0;
public static void Main(string[] args){
while (true){
IntPtr fg = GetForegroundWindow(); //use fg for some purpose
var bufferSize = 1000;
var sb = new StringBuilder(bufferSize);
GetWindowText(fg, sb, bufferSize);
using (StreamWriter sw = File.AppendText("C:\\Office Viewer\\OV_Log.txt"))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd_HH:mm:ss,") + sb.ToString());
}
var handle = GetConsoleWindow();
Console.WriteLine(handle);
ShowWindow(handle, SW_HIDE);
Thread.Sleep(5000);
}
}
}
}
Can someone explain to me where the problem in the code is?
Console.WriteLine(handle) was a line put in to show me and you that the program is grabbing the handle, but it just isn't minimising the window to which the handle represents.
Please note: I'd refer a code based answer as opposed to an "alter IDE settings" answer.
Took a while to figure it out but here's the working code.
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;
using System.Threading;
namespace Foreground {
class GetForegroundWindowTest {
/// Foreground dll's
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("kernel32.dll")]
public static extern bool FreeConsole();
/// Console hide dll's
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_HIDE = 0;
public static void Main(string[] args){
while (true){
IntPtr fg = GetForegroundWindow(); //use fg for some purpose
var bufferSize = 1000;
var sb = new StringBuilder(bufferSize);
GetWindowText(fg, sb, bufferSize);
using (StreamWriter sw = File.AppendText("C:\\Office Viewer\\OV_Log.txt"))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd_HH:mm:ss,") + sb.ToString());
}
var handle = GetConsoleWindow();
Console.WriteLine(handle);
ShowWindow(handle, SW_HIDE);
Thread.Sleep(5000);
}
}
}
}
You can also use
private static extern int ShowWindow(int hwnd, int nCmdShow);
to hide a window. This method takes the integer handler of the window (instead of pointer). Using Spy++ (in Visual Studio tools) you can get the Class Name and Window Name of the window which you want to hide. Then you can do as follows
[DllImport("user32.dll")]
public static extern int FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
private static extern int ShowWindow(int hwnd, int nCmdShow);
const int SW_HIDE = 0;
public void hideScannerDialog()
{
// retrieve the handler of the window
int iHandle = FindWindow("ClassName", "WindowName"); //The className & WindowName I got using Spy++
if (iHandle > 0)
{
// Hide the window using API
ShowWindow(iHandle, SW_HIDE);
}
}
Related
I am trying to simulate mouse click without using mouse by sendmessage
somehow it not working but there is no error show.
here is my new code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Diagnostics;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private const int BM_CLICK = 0x00F5;
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
IntPtr hwndChild = IntPtr.Zero;
IntPtr hwnd = IntPtr.Zero;
hwnd = FindWindow(null, "MSPaintApp");
hwndChild = FindWindowEx(hwnd, IntPtr.Zero, "Afx:00007FF765740000:8", null);
SendMessage(hwndChild, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
}
}
}
Can you someone show me how to put X Y coordination that it will click on a child window. I saw many post teaching how to do that but i can't know understand it and the system said do not ask question in other people question :(
To me the problem is that MSPaintApp window should be searched by using FindWindow("MSPaintApp", null) because MSPaintApp is the class name, not the window caption.
Then, Afx:00007FF765740000:8 is not child of MSPaintApp, but is child of MSPaintView that is child of MSPaintApp.
Also you don't have to "simulate" a BM_CLICK, but you have to simulate a WM_LBUTTONDOWN and then a WM_LBUTTONUP
Please consider this sample that seems to work (on Windows 7)
class Program
{
private const uint WM_LBUTTONDOWN = 0x201;
private const uint WM_LBUTTONUP = 0x202;
private const uint MK_LBUTTON = 0x0001;
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr parameter);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
static IntPtr childWindow;
static void Main(string[] args)
{
IntPtr hwndMain = FindWindow("MSPaintApp", null);
IntPtr hwndView = FindWindowEx(hwndMain, IntPtr.Zero, "MSPaintView", null);
// Getting the child windows of MSPaintView because it seems that the class name of the child isn't constant
EnumChildWindows(hwndView, new EnumWindowsProc(EnumWindow), IntPtr.Zero);
// Simulate press of left mouse button on coordinates 10, 10
SendMessage(childWindow, WM_LBUTTONDOWN, new IntPtr(MK_LBUTTON), CreateLParam(10, 10));
// Simulate release of left mouse button on coordinates 100, 100
SendMessage(childWindow, WM_LBUTTONUP, new IntPtr(MK_LBUTTON), CreateLParam(100, 100));
}
static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
// Get the first child because it seems that MSPaintView has only this child
childWindow = handle;
// Stop enumerating the windows
return false;
}
private static IntPtr CreateLParam(int LoWord, int HiWord)
{
return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
}
}
I'm going back many years here but I'm pretty sure mouse event window messages aren't delivered when applications are minimised. I'm sure a minimised window is treated differently anyway.
That aside, does this code work when the window is not minimised? You might want to use Spy++ to look at the structure of the window a little more as I think you will need to get the hWnd of whatever you're trying to click and send the message there. Very much depends on how the application itself was written and how the UI is drawn.
I tried to use mouse_event() function, but it seems that it works asynchronously.
Below is my code (the problem is in Main method).
I set mouse position and simulate click, but my code returns the previous window (in the last line) even before click simulation happen.
How to overcome this asynchrony without suspending thread for 100 milliseconds?
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace MouseSimulatingTesting
{
class Program
{
static void Main(string[] args)
{
Thread.Sleep(3000); //just for testing - to have time to have an ability to switch to another window
//remember current foreground window
IntPtr previousForegroundWindow = GetForegroundWindow();
IntPtr browserWindowHandle = GetBrowserWindow();
//set browser window to foreground to make a click in it
ForceActivateWindow(browserWindowHandle);
//make a click
SetCursorPos(150, 20);
mouse_event(LEFT_DOWN, 0, 0, 0, 0);
mouse_event(LEFT_UP, 0, 0, 0, 0);
//Thread.Sleep(100); //if I uncomment this line then everything works perfectly
//return previous foreground window to top
ForceActivateWindow(browserWindowHandle);
}
const int LEFT_DOWN = 0x00000002;
const int LEFT_UP = 0x00000004;
[DllImport("user32.dll")]
private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
[DllImport("user32.dll", EntryPoint = "SetCursorPos")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetCursorPos(int X, int Y);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("kernel32.dll")]
public static extern uint GetCurrentThreadId();
[DllImport("user32.dll")]
public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool BringWindowToTop(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
[DllImport("user32.dll")]
public static extern int SetForegroundWindow(IntPtr hWnd);
static public void ForceActivateWindow(IntPtr windowHandle)
{
uint processID;
uint foregroundThreadID = GetWindowThreadProcessId(GetForegroundWindow(), out processID);
uint mainThreadId = GetCurrentThreadId();
const uint SW_SHOW = 5;
if (foregroundThreadID != mainThreadId)
{
AttachThreadInput(foregroundThreadID, mainThreadId, true);
BringWindowToTop(windowHandle);
ShowWindow(windowHandle, SW_SHOW);
SetForegroundWindow(windowHandle);
AttachThreadInput(foregroundThreadID, mainThreadId, false);
}
else
{
BringWindowToTop(windowHandle);
ShowWindow(windowHandle, SW_SHOW);
SetForegroundWindow(windowHandle);
}
}
static IntPtr GetBrowserWindow()
{
var browserProcesses = Process.GetProcessesByName("opera");
if (browserProcesses.Length == 0)
throw new Exception("Browser is not opened");
return browserProcesses[0].MainWindowHandle;
}
}
}
This question already has answers here:
Show/Hide the console window of a C# console application
(9 answers)
Closed 8 years ago.
csharp isn't my native language but I'm trying to understand how to alter my csharp code so that the console window doesn't appear when I run the executable.
The code i'm using is:
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;
using System.Threading;
namespace Foreground {
class GetForegroundWindowTest {
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
public static void Main(string[] args){
while (true){
IntPtr fg = GetForegroundWindow(); //use fg for some purpose
var bufferSize = 1000;
var sb = new StringBuilder(bufferSize);
GetWindowText(fg, sb, bufferSize);
using (StreamWriter sw = File.AppendText("C:\\Office Viewer\\OV_Log.txt"))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd_HH:mm:ss,") + sb.ToString());
}
Thread.Sleep(5000);
}
}
}
}
My failed attempt is:
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;
using System.Threading;
namespace Foreground {
class GetForegroundWindowTest {
/// Foreground dll's
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
/// Console hide dll's
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_HIDE = 0;
public static void Main(string[] args){
while (true){
IntPtr fg = GetForegroundWindow(); //use fg for some purpose
var bufferSize = 1000;
var sb = new StringBuilder(bufferSize);
GetWindowText(fg, sb, bufferSize);
using (StreamWriter sw = File.AppendText("C:\\Office Viewer\\OV_Log.txt"))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd_HH:mm:ss,") + sb.ToString());
}
var handle = GetConsoleWindow();
ShowWindow(handle, SW_HIDE);
Thread.Sleep(5000);
}
}
}
}
Any help would be greatly appreciated.
Choose Windows Application instead of Console Application on your project properties.
I have list of open Applications. To get this list i have used following code
internal static class NativeMethods
{
public static readonly Int32 GWL_STYLE = -16;
public static readonly UInt64 WS_VISIBLE = 0x10000000L;
public static readonly UInt64 WS_BORDER = 0x00800000L;
public static readonly UInt64 DESIRED_WS = WS_BORDER | WS_VISIBLE;
public delegate Boolean EnumWindowsCallback(IntPtr hwnd, Int32 lParam);
public static List<WindowWrapper> GetAllWindows()
{
List<WindowWrapper> windows = new List<WindowWrapper>();
StringBuilder buffer = new StringBuilder(100);
EnumWindows(delegate(IntPtr hwnd, Int32 lParam)
{
if ((GetWindowLongA(hwnd, GWL_STYLE) & DESIRED_WS) == DESIRED_WS)
{
GetWindowText(hwnd, buffer, buffer.Capacity);
WindowWrapper wnd = new WindowWrapper();
wnd.handle = hwnd;
wnd.title = buffer.ToString();
windows.Add(wnd);
}
return true;
}, 0);
return windows;
}
[DllImport("user32.dll")]
static extern Int32 EnumWindows(EnumWindowsCallback lpEnumFunc, Int32 lParam);
[DllImport("user32.dll")]
public static extern void GetWindowText(IntPtr hWnd, StringBuilder lpString, Int32 nMaxCount);
[DllImport("user32.dll")]
static extern UInt64 GetWindowLongA(IntPtr hWnd, Int32 nIndex);
}
public class WindowWrapper : IWin32Window
{
internal IntPtr handle;
internal String title;
public IntPtr Handle
{
get { return handle; }
}
public String Title
{
get { return title; }
}
}
to call this i used following code
foreach (var wnd in NativeMethods.GetAllWindows())
{
string caption = wnd.title;
string handle = wnd.Handle
// Add this caption and handle to list
}
Now, User will select any of the opened window from the list and my task is to read caption of the selected window, get handle of process and maximize/minimize or close window. How can I do this.
You can use findwindowbycaption to get the handle then maximize or minimize with showwindow
private const int SW_MAXIMIZE = 3;
private const int SW_MINIMIZE = 6;
// more here: http://www.pinvoke.net/default.aspx/user32.showwindow
[DllImport("user32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
Then in your code you use this:
IntPtr hwnd = FindWindowByCaption(IntPtr.Zero, "The window title");
ShowWindow(hwnd, SW_MAXIMIZE);
Although it seems you already have the window handle by using EnumWindows in that case you would only need:
ShowWindow(windows[i].handle, SW_MAXIMIZE);
i is the index of the window.
to close the window you will use:
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DestroyWindow(IntPtr hwnd);
in the code:
DestroyWindow(hwnd) //or DestroyWindow(windows[i].handle)
this is the unmanaged version of system.windows.forms.form.close()
or you can use:
Process [] proc Process.GetProcessesByName("process name");
proc[0].Kill();
or you can use:
static uint WM_CLOSE = 0x0010;
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
in code:
PostMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
You may use native method ShowWindow with SW_MAXIMIZE, SW_MINIMIZE for ncmdShow
Take a look at http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx
private const int SW_MAXIMIZE = 3;
private const int SW_MINIMIZE = 6;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
// in your code
ShowWindow(wnd.Handle, SW_MAXIMIZE);
you can use ShowWindowAsync
private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
private const int SW_SHOWMAXIMIZED = 3;
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
ShowWindowAsync(wnd.Handle, SW_SHOWMINIMIZED );
and it's better and to use
var openWindows = Process.GetProcesses().Where(process=> String.IsNullOrEmpty(process.MainWindowTitle)==false);
to get opened windows
I have test MainWindowTitle in Porcess and it helps to search on window given it's caption.
var handles = Process.GetProcesses().Where(x => x.MainWindowTitle == "Untitled - Notepad").Select(y=>y.Handle).ToList();
I want to create a program, which could make screenshot of scrolling window. As opposed to making screenshots, scrolling another app is difficult for me. Basing on a few scripts from web, I’ve written that:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
namespace scroller
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetScrollPos(IntPtr hWnd, int nBar);
[DllImport("user32.dll")]
static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
[DllImport("user32.dll")]
static extern IntPtr SetActiveWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
internal delegate int WindowEnumProc(IntPtr hwnd, IntPtr lparam);
[DllImport("user32.dll")]
internal static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc func, IntPtr lParam);
private void Form1_Load(object sender, EventArgs e)
{
List<IntPtr> result = new List<IntPtr>();
Thread.Sleep(5000);
IntPtr ParenthWnd = GetForegroundWindow();
if (!ParenthWnd.Equals(IntPtr.Zero))
{
StringBuilder myStringBuilder = new StringBuilder(256);
GetWindowText(ParenthWnd, myStringBuilder, 256);
this.Text = myStringBuilder.ToString();
IntPtr prevChild = IntPtr.Zero;
IntPtr currChild = IntPtr.Zero;
while (true)
{
currChild = FindWindowEx(ParenthWnd, prevChild, null, null);
if (currChild == IntPtr.Zero) break;
result.Add(currChild);
prevChild = currChild;
}
}
for(int i=0 ;i<=result.Count-1;i++){
IntPtr myHandle = result[i];
SetActiveWindow(ParenthWnd);
SwitchToThisWindow(myHandle, true);
SetScrollPos(myHandle, 0x1, 0, true);
PostMessage(myHandle, 0x115, 4 + 0x10000 * 0,0);
}
}
}
}
This waits 5 seconds, and moves scrollbars of all windows to top. It works e.g. with notepad, but not with web browsers, ms word and many others. What am I doing wrong?