Exception when using console window in C# (Windows form application) - c#

I have a program WFA that also has and command Window. I open the window with AllocConsole(); When I close the console window, I use FreeConsole(); but when I open it again with AllocConsole(); I wanna write and read from it and it throws an exeption.
The code:
namespace WindowsFormsApplication2
{
class classx
{
[DllImport("kernel32.dll")]
public static extern Int32 AllocConsole();
[DllImport("kernel32.dll")]
public static extern bool FreeConsole();
[DllImport("kernel32")]
public static extern bool AttachConsole();
[DllImport("kernel32")]
public static extern bool GetConsoleWindow();
public static bool z = false;
[DllImport("kernel32")]
public static extern bool SetConsoleCtrlHandler(HandlerRoutine HandlerRoutine, bool Add);
public delegate bool HandlerRoutine(uint dwControlType);
}
public partial class Form1 : Form
{
NotifyIcon icontask;
Icon iconone_active;
Icon iconone_inactive;
/*Icon icontwo;
Icon iconthree;
Icon iconfour;
Icon iconfive;*/
Thread Threadworkermy;
public Form1()
{
InitializeComponent();
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
iconone_active = new Icon(".../iconone_active.ico");
iconone_inactive = new Icon(".../iconone_inactive.ico");
icontask = new NotifyIcon();
icontask.Icon = iconone_active;
icontask.Visible = true;
Threadworkermy = new Thread(new ThreadStart(checkActivityThread));
Threadworkermy.Start();
MenuItem Nameapp = new MenuItem("xr");
MenuItem quitappitem = new MenuItem("quit program");
MenuItem OpenGUI = new MenuItem("Open GUI");
MenuItem Advancedmodewindow = new MenuItem("x");
ContextMenu contextmenu = new ContextMenu();
quitappitem.Click += quitappitem_click;
OpenGUI.Click += OpenGUI_click;
Advancedmodewindow.Click += Advancedmodewindow_click;
contextmenu.MenuItems.Add(Nameapp);
contextmenu.MenuItems[0].Enabled = false;
contextmenu.MenuItems.Add("-");
contextmenu.MenuItems.Add(OpenGUI);
contextmenu.MenuItems.Add(Advancedmodewindow);
contextmenu.MenuItems.Add("-");
contextmenu.MenuItems.Add(quitappitem);
icontask.ContextMenu = contextmenu;
icontask.Icon = iconone_active;
icontask.Visible = true;
}
private void Advancedmodewindow_click(object sender, EventArgs e)
{
classx.AllocConsole();
Console.WriteLine("X");
classx.FreeConsole();
}
private void OpenGUI_click(object sender, EventArgs e)
{
this.ShowInTaskbar = true;
this.WindowState = FormWindowState.Normal;
}
private void quitappitem_click(object sender, EventArgs e)
{
Threadworkermy.Abort();
icontask.Dispose();
this.Close();
}
public void checkActivityThread()
{
try
{
while(true)
{
Thread.Sleep(100);
}
} catch(ThreadAbortException tbe)
{
}
}
private void button1_Click(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
}
}
}
Exception that it throws out 'System.IO.IOException' in mscorlib.dll
Additional information: The handle is invalid.
To those who will be saying to change the type, I can't. (it needs to be WFA application)

there seems to be an issue with destroying the consolewindow, so you could just hide it.
For hiding the window you need an additional DllImport from user32.dll and change the returnvalue of GetConsoleWindow to IntPtr:
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
Now check if a console-handle already exists. If it does show the console otherwise create the consolewindow:
private void Advancedmodewindow_click(object sender, EventArgs e)
{
IntPtr handle = classx.GetConsoleWindow();
if (handle == IntPtr.Zero)
{
classx.AllocConsole();
handle = classx.GetConsoleWindow();
}
else
{
//shows the window with the given handle
classx.ShowWindow(handle, 8);
}
Console.WriteLine("X");
//hides the window with the given handle
classx.ShowWindow(handle, 0);
}
The original solution can be found here:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/cdee5d88-3325-47ce-9f6b-83aa4447f8ca/console-exception-on-windows-8?forum=clr

Related

How to show a window on top of all windows one time in WPF?

I have a singletone instance of window in my WPF application (which is not main window). Due to it's structure, this window only closes when the main window is closed; If the user closes this window, it becomes hidden. When I click on some image in main window, I want the following behaviour of second window:
If window is hidden and image was clicked, I want to show it on top of all windows (but NOT by setting Topmost = true, I want just SHOW it on top, rather than fix it on top forever).
If window is shown on top, there is nothing to do.
If window is open, but covered by other window or minimized, I also want to show it on top only ONCE.
What I have at the moment:
// In some application class
private void Image_MouseDown(object sender, MouseButtonEventArgs e)
{
if (App.Current.MyWindow == null)
{
App.Current.MyWindow = WeightImageWindowView.Instance;
}
App.Current.MyWindow.ShowTop();
}
...
// in MyWindow class
public void ShowTop()
{
this.Topmost = true;
this.Show();
if (this.WindowState == WindowState.Minimized)
{
this.WindowState = WindowState.Normal;
}
var a = this.Activate();
var b = this.Focus();
this.Topmost = false;
}
I tried to use all these commands one by one, in pairs and all together, but didn't get the behaviour described above.
WndHelper.BringToFront(this);
Use the helper below and just call bringtofront
public class WndHelper
{
[DllImport("User32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsIconic(IntPtr hWnd);
public static void HideWindow(Window window)
{
var wih = new WindowInteropHelper(window);
WndHelper.ShowWindow(wih.Handle, 0);
}
public static void BringToFront(Window window)
{
var wih = new WindowInteropHelper(window);
BringToFront(wih.Handle);
}
//If the window is minimized, then Restore must be run first
//Windows that are in the background are enough to set as Foreground
public static void BringToFront(IntPtr hWnd)
{
if (hWnd == IntPtr.Zero)
return;
try
{
if (WndHelper.IsIconic(hWnd)) //the window is minimized
{
WndHelper.ShowWindow(hWnd, 9); // SW_RESTORE = 9
WndHelper.SetForegroundWindow(hWnd); // set window to foreground
}
else
WndHelper.SetForegroundWindow(hWnd);
}
catch { }
}
}
Thanks #Villiam! I found the following solution:
Set MyWindow.ShowActivated = true;
Rewrite ShowTop method as:
public void ShowTop()
{
if (this.WindowState == WindowState.Minimized)
{
this.WindowState = WindowState.Normal;
}
this.Topmost = true;
this.Show();
this.Topmost = false;
}

c# Detect if specific window (IE Browser, file explorer etc) closes/user presses X button?

Currently doing a WPF app where you will be able to open apps suchs as IE and file explorer (more to come), and when you start it, a button is created and put in a custom appbar/taskbar.
So to the problem, we are using Process.Start() to start the apps, so we are currently checking this
this.ProgramProcess.EnableRaisingEvents = true;
this.ProgramProcess.Exited += (sender, e) => { RemoveRunningProgram((Process)sender); };
and the RemoveRunningProgram method looks like this
private void RemoveRunningProgram(Process process)
{
App.Current.Dispatcher.Invoke((Action)delegate { TaskbarWindow.RunningPrograms.Remove(this); });
}
So the main thought is, if you close a window by the user pressing the X button in the top right corner to close the window, the appbar button/icon will disappear.
So couple of the problems;
If you open 1 IE browser, it works fine, but if you open more than one, you will have to close all windows, for all the icons to disappear.
It takes a LONG time for the computer to see if the file explorer is closed or not, sometimes not even notice it.
Am I thinking at the right spot where I should make adjustments?
RunningProgram.cs:
public class RunningProgram : Button
{
private IntPtr ProgramHandle { get; set; }
private string ProgramName { get; set; }
public Process ProgramProcess { get; set; }
public List<Process> procList = new List<Process>();
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int lParam);
[DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hwnd);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
public RunningProgram(IntPtr programHandle, string programName, Thickness margin, string imagePath, Process programProcess)
{
this.ProgramHandle = programHandle;
this.ProgramName = programName;
this.Margin = margin;
this.Background = SetButtonBackground(imagePath);
this.Width = 70;
this.Height = 70;
this.Click += new RoutedEventHandler(ShowWindow_Click);
this.BorderBrush = Brushes.Transparent;
this.ProgramProcess = programProcess;
this.procList.Add(ProgramProcess);
this.ProgramProcess.EnableRaisingEvents = true;
this.ProgramProcess.Exited += (sender, e) => { RemoveRunningProgram((Process)sender); };
}
private void p_Exited(object sender, EventArgs e)
{
RemoveRunningProgram((Process)sender);
}
private void RemoveRunningProgram(Process process)
{
App.Current.Dispatcher.Invoke((Action)delegate { TaskbarWindow.RunningPrograms.Remove(this); });
}
private void ShowWindow_Click(object sender, RoutedEventArgs e)
{
ShowWindow(ProgramHandle, 3);
SetForegroundWindow(ProgramHandle);
GetForegroundWindow();
}
}
Thanks in advance

how to change main window state in a single instance using .Net Core

I am trying to leave my application with just one instance.
The code works fine, but I want to manipulate the window that is already open.
How can I bring the window already open to the front when I open more than one instance.
public partial class App : Application {
private static Mutex _mutex = null;
protected override void OnStartup(StartupEventArgs e)
{
const string appName = "MyAppName";
bool createdNew;
_mutex = new Mutex(true, appName, out createdNew);
if (!createdNew)
{
Application.Current.Shutdown();
}
base.OnStartup(e);
}
}
in OnStartup I tried to call the window using MainWindow.WindowState = WindowState.Normal; but it fails in that call noting the error System.Windows.Application.MainWindow.get returned null.
I created a sample project for single instance application in WPF. Maybe helpful:
Wpf Single Instance Application
You need the following native methods:
public static class NativeMethod
{
public static IntPtr BroadcastHandle => (IntPtr)0xffff;
public static int ReactivationMessage => RegisterWindowMessage("WM_SHOWME");
[DllImport("user32")]
public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
[DllImport("user32")]
public static extern int RegisterWindowMessage(string message);
}
In app main window add hook to window messages and when you got activation message you should bring the main window in top of other windows. Like this:
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
RegisterWndProcCallback();
}
private void RegisterWndProcCallback()
{
var handle = new WindowInteropHelper(this).EnsureHandle();
var hock = new HwndSourceHook(WndProc);
var source = HwndSource.FromHwnd(handle);
source.AddHook(hock);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == NativeMethod.ReactivationMessage)
ReactivateMainWindow();
return IntPtr.Zero;
}
private void ReactivateMainWindow()
{
if (WindowState == WindowState.Minimized)
WindowState = WindowState.Normal;
Topmost = !Topmost;
Topmost = !Topmost;
}
}
And in app startup you should check for app instances and if needed you should send a message to the old instance and activate that. Like this:
public partial class App
{
private static readonly Mutex _singleInstanceMutex =
new Mutex(true, "{40D7FB99-C91E-471C-9E34-5D4A455E35E1}");
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
if (_singleInstanceMutex.WaitOne(TimeSpan.Zero, true))
{
Current.MainWindow = new MainWindow();
Current.MainWindow.Show();
Current.MainWindow.Activate();
_singleInstanceMutex.ReleaseMutex();
}
else
{
NativeMethod.PostMessage(
NativeMethod.BroadcastHandle,
NativeMethod.ReactivationMessage,
IntPtr.Zero,
IntPtr.Zero);
Current.Shutdown();
}
}
}

TreeView CheckBoxes=true and ShowNodeToolTips=true GDI objects leak

TreeView leaks resource (2 DC handles and 2 Bitmap handles) when TreeView CheckBoxes=true because of a bug, and I dealt with it:
public class TreeViewCustom : TreeView
{
public new bool CheckBoxes
{
get
{
return base.CheckBoxes;
}
set
{
if (base.CheckBoxes == false)
{
base.CheckBoxes = true;
IntPtr handle = SendMessage(this.Handle, TVM_GETIMAGELIST, new IntPtr(TVSIL_STATE), IntPtr.Zero);
if (handle != IntPtr.Zero)
_checkboxImageList = handle;
}
}
}
/// <summary>
/// The handle to the state ImageList
/// </summary>
private IntPtr _checkboxImageList = IntPtr.Zero;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x203) // double click
m.Result = IntPtr.Zero;
else
base.WndProc(ref m);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left || e.Button == MouseButtons.Right)
{
Focus();
SelectedNode = GetNodeAt(e.X, e.Y);
}
}
[DllImport("comctl32.dll", CharSet = CharSet.Auto)]
public static extern bool ImageList_Destroy(IntPtr hImageList);
[DllImport("comctl32.dll", CharSet = CharSet.Auto)]
public static extern bool ImageList_RemoveAll(IntPtr hImageList);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern System.IntPtr SendMessage(IntPtr hWnd, uint Msg,
IntPtr wParam, IntPtr lParam);
const uint TV_FIRST = 0x1100;
const uint TVM_GETIMAGELIST = TV_FIRST + 8;
const int TVSIL_NORMAL = 0;
const int TVSIL_STATE = 2;
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_checkboxImageList != IntPtr.Zero)
{
ImageList_Destroy(_checkboxImageList);
}
base.Dispose(disposing);
this.DestroyHandle();
}
else base.Dispose(disposing);
}
}
And everything is OK, except when treeview.ShowNodeToolTips is set to true, then the resources still leak, even with the fix. I think the tooltip is a problem (ToolTips also leak handles if you don't dispose of them properly)
EDIT:
(Why the leak happens when CheckBoxes = true)
When CheckBoxes is set to true, the style is set to the TreeView, and it can be done only once. This causes an CheckBoxImageList to be created. The list contains 2 bitmaps: the checked and unchecked box, every object in the list has a DC handle and a BITMAP handle (that's why 4 handles are leaked for each instance). When the TreeView is disposed, the list of images isn't destroyed, hence the leak.
(Why the leak happens when ShowNodeToolTips=true - my suspicions, http://reflector.webtropy.com/default.aspx/DotNET/DotNET/8#0/untmp/whidbey/REDBITS/ndp/fx/src/WinForms/Managed/System/WinForms/TreeView#cs/2/TreeView#cs)
The TootTip holds the reference to the control, if the ToolTip is not disposed, the control stays in the memory too. When ShowNodeToolTips = true, the ToolTip is created and associated with the TreeView, and it isn't disposed when TreeView is disposed.
The code I use for testing:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form_Tv form = new Form_Tv();
form.StartPosition = FormStartPosition.CenterParent; ;
form.ShowDialog();
form.Dispose();
GC.Collect();
}
}
public partial class Form_Tv : Form
{
public Form_Tv()
{
InitializeComponent();
for (int i = 0; i < 100; i++)
{
TreeViewCustom tv = new TreeViewCustom();
tv.CheckBoxes = true;
tv.ShowNodeToolTips = true;
this.Controls.Add(tv);
}
this.FormClosed += new FormClosedEventHandler(Form_Tv_FormClosed);
this.ControlRemoved += new ControlEventHandler(Form_Tv_ControlRemoved);
}
void Form_Tv_ControlRemoved(object sender, ControlEventArgs e)
{
e.Control.Dispose();
}
void Form_Tv_FormClosed(object sender, FormClosedEventArgs e)
{
this.Controls.Clear();
}
}
Test results (Windows 7):
Form1 is the main form of the application. After it's shown:
DC: 7 Bitmap: 3
After Form_Tv is shown:
DC: 409 Bitmap: 405
After Form_Tv is closed:
DC: 209 Bitmap: 205
My question:
How can I get a hold of the ToolTip that is set for the TreeView when ShowNodeToolTips is set to true, and how can I properly dispose of it?

WinForm enter fullscreen mode [duplicate]

This question already has answers here:
How do I make a WinForms app go Full Screen
(10 answers)
C# Fullscreen, hiding the taskbar
(2 answers)
Closed 9 years ago.
I have WinForm application and i want to enter fullscreen mode and remove all bars and the task bar.
i done it with this:
this.WindowState = FormWindowState.Maximized;
this.FormBorderStyle = FormBorderStyle.None;
this.TopMost = true;
The top bar is really hidden but the Windows TaskBar is still visible.
Any idea what can be the trouble?
Run with full screen you can use this method..
private void Form1_Load(object sender, EventArgs e)
{
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
}
To Hide TaskBar Just add this class into your project .it works as you expected.
using System;
using System.Runtime.InteropServices;
public class Taskbar
{
[DllImport("user32.dll")]
private static extern int FindWindow(string className, string windowText);
[DllImport("user32.dll")]
private static extern int ShowWindow(int hwnd, int command);
[DllImport("user32.dll")]
public static extern int FindWindowEx(int parentHandle, int childAfter, string className, int windowTitle);
[DllImport("user32.dll")]
private static extern int GetDesktopWindow();
private const int SW_HIDE = 0;
private const int SW_SHOW = 1;
protected static int Handle
{
get
{
return FindWindow("Shell_TrayWnd", "");
}
}
protected static int HandleOfStartButton
{
get
{
int handleOfDesktop = GetDesktopWindow();
int handleOfStartButton = FindWindowEx(handleOfDesktop, 0, "button", 0);
return handleOfStartButton;
}
}
private Taskbar()
{
// hide ctor
}
public static void Show()
{
ShowWindow(Handle, SW_SHOW);
ShowWindow(HandleOfStartButton, SW_SHOW);
}
public static void Hide()
{
ShowWindow(Handle, SW_HIDE);
ShowWindow(HandleOfStartButton, SW_HIDE);
}
}
USAGE:
Taskbar.Hide();
Reorder lines to maximize the form after will will be marked with FormBorderStyle.None and TopMost
this.FormBorderStyle = FormBorderStyle.None;
this.TopMost = true;
this.WindowState = FormWindowState.Maximized;
You need to reorder your statements, try:
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;

Categories

Resources