How can I bring a console application window to front in C# (especially when running the Visual Studio debugger)?
It's hacky, it's horrible, but it works for me (thanks, pinvoke.net!):
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
public class Test
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", EntryPoint="FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr zeroOnly, string lpWindowName);
public static void Main()
{
string originalTitle = Console.Title;
string uniqueTitle = Guid.NewGuid().ToString();
Console.Title = uniqueTitle;
Thread.Sleep(50);
IntPtr handle = FindWindowByCaption(IntPtr.Zero, uniqueTitle);
if (handle == IntPtr.Zero)
{
Console.WriteLine("Oops, cant find main window.");
return;
}
Console.Title = originalTitle;
while (true)
{
Thread.Sleep(3000);
Console.WriteLine(SetForegroundWindow(handle));
}
}
}
This is what I would do.
[DllImport("kernel32.dll", ExactSpelling = true)]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
public void BringConsoleToFront()
{
SetForegroundWindow(GetConsoleWindow());
}
Get two monitors (at least) and open VisualStudio in the secondary monitor. When you run your app from within VisualStudio it will start up by default on the primary monitor. Since it's the last app to be opened, it starts on top and changing over to VisualStudio doesn't affect it. Works for me anyway.
If you don't already have a second monitor, IMHO, you should.
Related
I want to attach a console to an monogame application. I used .Net Framework at first and everything worked fine, then I switched to .Net Core 3.1 and the console stopped attaching to the process.
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AttachConsole(int dwProcessId);
[DllImportAttribute("kernel32.dll", SetLastError = true, EntryPoint = "AllocConsole")]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
private static extern bool AllocConsole();
[DllImportAttribute("kernel32.dll", SetLastError = true, EntryPoint = "GetStdHandle")]
private static extern IntPtr GetStdHandle(Int32 nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool FreeConsole();
[DllImport("kernel32.dll", EntryPoint = "GetLastError")]
private static extern int GetLastError();
private void InitializeConsole() {
if (AttachConsole(Process.GetCurrentProcess().Id) && AllocConsole()) {
GetStdHandle(Process.GetCurrentProcess().Id);
_isInitializeConsole = true;
} else {
_isInitializeConsole = false;
throw new Exception($"Console alloc error code: {GetLastError()}");
}
}
When trying to attach a console from the AttachConsole method, I get result "false" and last error code - 5 (Access is denied). I ran the application as administrator and getting error code - 6 (The handle is invalid).
Is there a way to fix this error?
I'm making a c# overlay for a game.
It appears on the game but it won't hide if the game is minimized so I'm wondering if there's any way to check if a window is minimized/out of focus. I searched about it on google but I couldn't find anything useful.
To check the state of a window (normal, maximized or minimized) when you have the windows caption name or the windows handle, you can use this code:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsIconic(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsZoomed(IntPtr hWnd);
enum WinState
{
None,
Maximized,
Minimized,
Normal,
}
private static WinState GetWindowState(IntPtr hWnd)
{
WinState winState = WinState.None;
if (hWnd != IntPtr.Zero)
{
if (IsIconic(hWnd))
{
winState = WinState.Minimized;
}
else if (IsZoomed(hWnd))
{
winState = WinState.Maximized;
}
else
{
winState = WinState.Normal;
}
}
return winState;
}
private static WinState GetWindowState(string windowCaption)
{
return GetWindowState((IntPtr)FindWindow(null, windowCaption));
}
Usage:
string windowCaption = "New Tab - Google Chrome";
WinState winState = GetWindowState(windowCaption);
When I have an application opened and I try to open again it, i want to restore the application launched with the actual size.
The code used is this:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
private const int SW_SHOW = 5;
public static void SetForegroundMyWindow(IntPtr windowHandle)
{
SetForegroundWindow(windowHandle);
ShowWindow(windowHandle, SW_SHOW);
}
With this code, when the window is maximized, the application is shown with the size without maximize.
Only with SetForegroundWindow, the application is not shown when it is minimized.
What is the way to get my window with the actual size?
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);
}
}
I have a buggy third-party DLL files that, after some time of execution, starts throwing the access violation exceptions. When that happens I want to reload that DLL file. How do I do that?
Try this
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string libname);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool FreeLibrary(IntPtr hModule);
//Load
IntPtr Handle = LoadLibrary(fileName);
if (Handle == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
throw new Exception(string.Format("Failed to load library (ErrorCode: {0})",errorCode));
}
//Free
if(Handle != IntPtr.Zero)
FreeLibrary(Handle);
If you want to call functions first you must create delegate that matches this function and then use WinApi GetProcAddress
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
IntPtr funcaddr = GetProcAddress(Handle,functionName);
YourFunctionDelegate function = Marshal.GetDelegateForFunctionPointer(funcaddr,typeof(YourFunctionDelegate )) as YourFunctionDelegate ;
function.Invoke(pass here your parameters);
Create a worker process that communicates via COM or another IPC mechanism. Then when the DLL dies, you can just restart the worker process.
Load the dll, call it, and then unload it till it's gone.
I've adapted the following code from the VB.Net example here.
[DllImport("powrprof.dll")]
static extern bool IsPwrHibernateAllowed();
[DllImport("kernel32.dll")]
static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32.dll")]
static extern bool LoadLibraryA(string hModule);
[DllImport("kernel32.dll")]
static extern bool GetModuleHandleExA(int dwFlags, string ModuleName, ref IntPtr phModule);
static void Main(string[] args)
{
Console.WriteLine("Is Power Hibernate Allowed? " + DoIsPwrHibernateAllowed());
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
private static bool DoIsPwrHibernateAllowed()
{
LoadLibraryA("powrprof.dll");
var result = IsPwrHibernateAllowed();
var hMod = IntPtr.Zero;
if (GetModuleHandleExA(0, "powrprof", ref hMod))
{
while (FreeLibrary(hMod))
{ }
}
return result;
}