I am using the below code to block the taskbar which is working perfectly.
But since my application is running in background, the only way to exit the application
is by killing the .exe from task manager. So while exiting like this, the blocked task bar remains at the same state. But actually it shud resume the taskbar on exiting the application.
The reason i am doing this is, it is a kiosk application.
what is the way to overcome this.
public class Taskbar
{
[DllImport("user32.dll")]
public static extern int FindWindow(string className, string windowText);
[DllImport("user32.dll")]
public static extern int ShowWindow(int hwnd, int command);
public const int SW_HIDE = 0;
public const int SW_SHOW = 1;
public int _taskbarHandle;
protected static int Handle
{
get
{
return FindWindow("Shell_TrayWnd", "");
}
}
public Taskbar()
{
_taskbarHandle = FindWindow("Shell_TrayWnd", "");
}
public static void Show()
{
ShowWindow(Handle, SW_SHOW);
}
public static void Hide()
{
ShowWindow(Handle, SW_HIDE);
}
}
Why not just use this implementation to run completely fullscreen?
http://www.codeproject.com/KB/cs/FullScreenDotNetApp.aspx
Like the others have said when you killin the application no.
Your post is a bit sparse on why you cannot close your application gracefully, so il suggest this method.
1)
Hotkeys ( http://www.codeproject.com/KB/system/Hotkeys.aspx ) that can be pressed that will close down your application gracefully. I personaly like this method, as i use hotkeys in many of my apps.
2)
Starting a seperate application that will wake up every XXX and check if the main application is running, if its not running run the Show code and then kill itself. This method is very simular to how viruses often work, so its tried and works :)
If your only way to exit is by killing it, then I am afraid you can't reset the property back to normal.
There can be a workaround to this.
Create a service which monitors your application through polling and when it finds your application as 'not running', it restores the TaskBar to normal.
There can be other similar workarounds to this but I can't think of a way of doing this from within your application given the limitation.
For exiting the application, i am registering a hot key combination and resuming the task bar and kill the process from taskbar programatically.
you can make your application check for the existance of a file (or any other thing you can control from outside and the app have access to it), if found: dispose & exit.
it's dirty but gives a little bit more control of how your application terminate than killing it from the task manager.
Related
Why does the following code sometimes causes an Exception with the contents "CLIPBRD_E_CANT_OPEN":
Clipboard.SetText(str);
This usually occurs the first time the Clipboard is used in the application and not after that.
This is caused by a bug/feature in Terminal Services clipboard (and possible other things) and the .NET implementation of the clipboard. A delay in opening the clipboard causes the error, which usually passes within a few milliseconds.
The solution is to try multiple times within a loop and sleep in between.
for (int i = 0; i < 10; i++)
{
try
{
Clipboard.SetText(str);
return;
}
catch { }
System.Threading.Thread.Sleep(10);
}
Actually, I think this is the fault of the Win32 API.
To set data in the clipboard, you have to open it first. Only one process can have the clipboard open at a time. So, when you check, if another process has the clipboard open for any reason, your attempt to open it will fail.
It just so happens that Terminal Services keeps track of the clipboard, and on older versions of Windows (pre-Vista), you have to open the clipboard to see what's inside... which ends up blocking you. The only solution is to wait until Terminal Services closes the clipboard and try again.
It's important to realize that this is not specific to Terminal Services, though: it can happen with anything. Working with the clipboard in Win32 is a giant race condition. But, since by design you're only supposed to muck around with the clipboard in response to user input, this usually doesn't present a problem.
I know this question is old, but the problem still exists. As mentioned before, this exception occurs when the system clipboard is blocked by another process. Unfortunately, there are many snipping tools, programs for screenshots and file copy tools which can block the Windows clipboard. So you will get the exception every time you try to use Clipboard.SetText(str) when such a tool is installed on your PC.
Solution:
never use
Clipboard.SetText(str);
use instead
Clipboard.SetDataObject(str);
I solved this issue for my own app using native Win32 functions: OpenClipboard(), CloseClipboard() and SetClipboardData().
Below the wrapper class I made. Could anyone please review it and tell if it is correct or not. Especially when the managed code is running as x64 app (I use Any CPU in the project options). What happens when I link to x86 libraries from x64 app?
Thank you!
Here's the code:
public static class ClipboardNative
{
[DllImport("user32.dll")]
private static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll")]
private static extern bool CloseClipboard();
[DllImport("user32.dll")]
private static extern bool SetClipboardData(uint uFormat, IntPtr data);
private const uint CF_UNICODETEXT = 13;
public static bool CopyTextToClipboard(string text)
{
if (!OpenClipboard(IntPtr.Zero)){
return false;
}
var global = Marshal.StringToHGlobalUni(text);
SetClipboardData(CF_UNICODETEXT, global);
CloseClipboard();
//-------------------------------------------
// Not sure, but it looks like we do not need
// to free HGLOBAL because Clipboard is now
// responsible for the copied data. (?)
//
// Otherwise the second call will crash
// the app with a Win32 exception
// inside OpenClipboard() function
//-------------------------------------------
// Marshal.FreeHGlobal(global);
return true;
}
}
Actually there could be another issue at hand. The framework call (both the WPF and winform flavors) to something like this (code is from reflector):
private static void SetDataInternal(string format, object data)
{
bool flag;
if (IsDataFormatAutoConvert(format))
{
flag = true;
}
else
{
flag = false;
}
IDataObject obj2 = new DataObject();
obj2.SetData(format, data, flag);
SetDataObject(obj2, true);
}
Note that SetDataObject is always called with true in this case.
Internally that triggers two calls to the win32 api, one to set the data and one to flush it from your app so it's available after the app closes.
I've seen several apps (some chrome plugin, and a download manager) that listen to the clipboard event. As soon as the first call hits, the app will open the clipboard to look into the data, and the second call to flush will fail.
Haven't found a good solution except to write my own clipboard class that uses direct win32 API or to call setDataObject directly with false for keeping data after the app closes.
Use the WinForms version (yes, there is no harm using WinForms in WPF applications), it handles everything you need:
System.Windows.Forms.Clipboard.SetDataObject(yourText, true, 10, 100);
This will attempt to copy yourText to the clipboard, it remains after your app exists, will attempt up to 10 times, and will wait 100ms between each attempt.
Ref. https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.clipboard.setdataobject?view=netframework-4.7.2#System_Windows_Forms_Clipboard_SetDataObject_System_Object_System_Boolean_System_Int32_System_Int32_
This happen to me in my WPF application. I got OpenClipboard Failed (Exception from HRESULT: 0x800401D0 (CLIPBRD_E_CANT_OPEN)).
i use
ApplicationCommands.Copy.Execute(null, myDataGrid);
solution is to clear the clipboard first
Clipboard.Clear();
ApplicationCommands.Copy.Execute(null, myDataGrid);
The difference between Cliboard.SetText and Cliboard.SetDataObject in WPF is that the text is not copied to the clipboard, only the pointer. I checked the source code. If we call SetDataObject(data, true) Clipoard.Flush() will also be called. Thanks to this, text or data is available even after closing the application. I think Windows applications only call Flush() when they are shutting down. Thanks to this, it saves memory and at the same time gives access to data without an active application.
Copy to clipboard:
IDataObject CopyStringToClipboard(string s)
{
var dataObject = new DataObject(s);
Clipboard.SetDataObject(dataObject, false);
return dataObject;
}
Code when app or window is closed:
try
{
if ((clipboardData != null) && Clipboard.IsCurrent(clipboardData))
Clipboard.Flush();
}
catch (COMException ex) {}
clipboardData is a window class field or static variable.
That's not a solution, just some additional information on how to reproduce it when all solutions work on your PC and fail somewhere else. As mentioned in the accepted answer - clipboard can be busy by some other app. You just need to handle this failure properly, to explain user somehow why it does not work.
So, just create a new console app with few lines below and run it. And while it is running - test your primary app on how it is handles busy clipboard:
using System;
using System.Runtime.InteropServices;
namespace Clipboard
{
class Program
{
[DllImport("user32.dll")]
private static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll")]
private static extern bool CloseClipboard();
static void Main(string[] args)
{
bool res = OpenClipboard(IntPtr.Zero);
Console.Write(res);
Console.Read();
CloseClipboard();
}
}
}
I am working on a C# application which runs in the background without any Windows control.
I want to notify Windows that my application is still alive to prevent Windows from going into the idle state.
Are there any APIs available to call from my application which notify the Windows OS that my application is still alive?
Thanks in advance.
You've to use SetThreadExecutionState function. Something like this:
public partial class MyWinForm: Window
{
private uint fPreviousExecutionState;
public Window1()
{
InitializeComponent();
// Set new state to prevent system sleep
fPreviousExecutionState = NativeMethods.SetThreadExecutionState(
NativeMethods.ES_CONTINUOUS | NativeMethods.ES_SYSTEM_REQUIRED);
if (fPreviousExecutionState == 0)
{
Console.WriteLine("SetThreadExecutionState failed. Do something here...");
Close();
}
}
protected override void OnClosed(System.EventArgs e)
{
base.OnClosed(e);
// Restore previous state
if (NativeMethods.SetThreadExecutionState(fPreviousExecutionState) == 0)
{
// No way to recover; already exiting
}
}
}
internal static class NativeMethods
{
// Import SetThreadExecutionState Win32 API and necessary flags
[DllImport("kernel32.dll")]
public static extern uint SetThreadExecutionState(uint esFlags);
public const uint ES_CONTINUOUS = 0x80000000;
public const uint ES_SYSTEM_REQUIRED = 0x00000001;
}
You have a couple of options:
Use SetThreadExecutionState, which:
Enables an application to inform the system that it is in use, thereby preventing the system from entering sleep or turning off the display while the application is running.
Where you could use the ES_SYSTEM_REQUIRED flag to
Forces the system to be in the working state by resetting the system idle timer.
Use SendInput to fake keystroke, mouse motion/clicks
Another alternative would be to change your app to be a Windows service.
SetThreadExecutionState example
// Television recording is beginning. Enable away mode and prevent
// the sleep idle time-out.
SetThreadExecutionState(
ES_CONTINUOUS |
ES_SYSTEM_REQUIRED |
ES_AWAYMODE_REQUIRED);
// Wait until recording is complete...
// Clear EXECUTION_STATE flags to disable away mode and allow the system
// to idle to sleep normally.
SetThreadExecutionState(ES_CONTINUOUS);
You can use SetThreadExecutionState described here:
SetThreadExecutionState Function
Since it is a Win32 API function, to use it from C# you'll need to PInvoke it. The steps are described here, including a sample method PreventSleep to temporarily disable sleep mode:
PInvoke.net: setthreadexecutionstate (kernel32)
I don't think there's any way to do this directly in managed code.
A quick search reveals this post from 2 years ago. Basically you'd need to do some interop to call a raw windows API.
Here is SetThreadExecutionState C# implementation
I've got a console application that executes my code without user interaction. If the user clicks within the console window, on purpose or on accident, all execution stops.
This has something to do with copying text from the console window. The only way for the application to start executing again is if the user selects text and then right-clicks on the console window, copying it to the clipboard.
To see this in action, create a console application and add the following code.
class Program
{
static void Main(string[] args)
{
var task = Task.Run(async () =>
{
int i = 0;
while (true)
{
Console.WriteLine(i++);
await Task.Delay(1000);
}
});
Console.ReadLine();
}
}
When you click on the console window, the Task thread stops executing. This is not desirable behavior at all, and I want to prevent this from happening in my console application.
How can I prevent this? None of the properties/events on the console window have anything to do with controlling this behavior, as far as I can see.
As you can see, when i'm click within window appear cursor. When i press any key - cursor gone and app continue working
This happens if you have Quick Edit Mode enabled on the console window. If you right-click on the title bar and select Properties, then select the Options tab, you can check to see if Quick Edit Mode is enabled. If you disable Quick Edit Mode, then the scrolling doesn't stop when you click in the window.
The reason scrolling stops is because a mouse clicked in the window is used to select text.
You can disable Quick Edit Mode on the console in your program, but doing so requires calling the GetConsoleMode and SetConsoleMode API functions. Here's how you would do it:
[DllImport("kernel32.dll", SetLastError=true)]
public static extern IntPtr GetConsoleWindow();
[DllImport("kernel32.dll", SetLastError=true)]
public static extern bool GetConsoleMode(
IntPtr hConsoleHandle,
out int lpMode);
[DllImport("kernel32.dll", SetLastError=true)]
public static extern bool SetConsoleMode(
IntPtr hConsoleHandle,
int ioMode);
/// <summary>
/// This flag enables the user to use the mouse to select and edit text. To enable
/// this option, you must also set the ExtendedFlags flag.
/// </summary>
const int QuickEditMode = 64;
// ExtendedFlags must be combined with
// InsertMode and QuickEditMode when setting
/// <summary>
/// ExtendedFlags must be enabled in order to enable InsertMode or QuickEditMode.
/// </summary>
const int ExtendedFlags = 128;
void DisableQuickEdit()
{
IntPtr conHandle = GetConsoleWindow();
int mode;
if (!GetConsoleMode(conHandle, out mode))
{
// error getting the console mode. Exit.
return;
}
mode = mode & ~(QuickEditMode | ExtendedFlags);
if (!SetConsoleMode(conHandle, mode))
{
// error setting console mode.
}
}
void EnableQuickEdit()
{
IntPtr conHandle = GetConsoleWindow();
int mode;
if (!GetConsoleMode(conHandle, out mode))
{
// error getting the console mode. Exit.
return;
}
mode = mode | (QuickEditMode | ExtendedFlags);
if (!SetConsoleMode(conHandle, mode))
{
// error setting console mode.
}
}
If you go down this route, it's probably a good idea to save the original console mode setting when your program starts, and restore it when your program exits. So at startup:
GetConsoleMode(GetConsoleWindow(), ref saveConsoleMode);
and when your program terminates:
SetConsoleMode(GetConsoleWindow(), saveConsoleMode);
With appropriate error handling, of course. You wouldn't want to restore the console mode if the call to GetConsoleMode failed.
I just saw that this answer linked in the comments of OP's question contained what I found by myself. I will keep my answer because people might not see it, just like me, and it would spare them a lot of time.
Jim's answer did not work for me, I couldn't figure out why.
I dug around and found a solution that works, so I'll share my findings, hopefully helping someone in the same situation.
The problem was with the handle that I got from GetConsoleWindow(), it gave a Win32 error (0x6) where the handle is invalid when I tried to use it. The call to SetConsoleMode() did nothing.
To get a working handle, I used GetStdHandle() to get the Input handle for the console. Add this to Jim's code :
public const int STD_INPUT_HANDLE = -10;
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);
Then replace GetConsoleWindow() by GetStdHandle(STD_INPUT_HANDLE) in DisableQuickEdit() and EnableQuickEdit() in Jim's code.
After calling DisableQuickEdit(), the selection is disabled in the console.
Thanks Jim !
This question already has answers here:
Capture console exit C#
(10 answers)
Closed 7 years ago.
In my program I approaching text files in every iteration of loop to not lost any data from running. It is brutal uneffective and still I lost that data yesterday.
I have 2 Queues - "what have I done" and "what to do". After some time I need to end this application and remember these queues for next app run. I usually kill the applicatiaon with Ctrl+C.
Is there any way to run saving these Queues to files after app kill? Or how to End console application as a User correctly.
Is it possible to run piece of code atomically?
I mean when I update some "Queue file" by removing first line of it I need to copy whole file to tmp than delete original file and than copy tmp file to original. But sometimes I hit Ctrl+C right after orig. file delete and I lost one queue.
Ctrl+C doesn't necessarily kill the application - you can use the Console.CancelKeyPress event to handle the shutdown properly. As for when the user clicks the close button, you're out of luck - that actually does brutally kill the process.
Your application should have some support for a graceful shutdown. For example, you could have a cancellation token that's signalled in the Console.CancelKeyPress, and your code should check the token once in a while (when you're in a spot that's safe for termination) to see if a shutdown was requested.
As an extra measure, you could try using some safer measure of operation. For example, instead of deleting the original file, you could just rename it. If your processing fails in the middle, the file is still there, and you can recover it when the application is restarted. Only when a new file is completely processed and copied would you delete the original.
Is there any way to run saving these Queues to files after app kill?
No. You must implement exit command.
Here is the solution.
It looks like you can hook into the CTRL-C or CTRL-BREAK Signals in order to exit your application gracefully.
class Program
{
//https://msdn.microsoft.com/en-us/library/windows/desktop/ms683231(v=vs.85).aspx
private const int STD_INPUT_HANDLE = -10;
private const uint ENABLE_PROCESSED_INPUT = 0x0001;
[DllImport("Kernel32.dll")]
private static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("Kernel32.dll")]
private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
[DllImport("Kernel32.dll")]
private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint dwMode);
static void Main(string[] args)
{
IntPtr handle = GetStdHandle(STD_INPUT_HANDLE);
uint mode;
GetConsoleMode(handle, out mode);
mode &= ~ENABLE_PROCESSED_INPUT;
SetConsoleMode(handle, mode);
new Thread(() =>
{
while (true)
{
var chara = Console.ReadKey();
if (chara.KeyChar == 3)
{
Console.WriteLine("ctrl-c");
//signal to gracefully exit
}
Console.WriteLine("c:{0}", chara);
}
}).Start();
}
}
I am creating a scheduled task to run process monitor at its highest privileges. I have a windows service that executes the scheduled task on start. Thus on start of my service, process monitor.exe will be executed shown in a window. But I don't want to see the window. I just want the process monitor.exe to run in the background without displaying any windows.
In AutoIT, there is a command: Run (Procmon.exe,"",#SW_Hide) #SW_Hide = Hidden Window
I tried this:
foreach (Process pr in Process.GetProcesses())
{
if(pr.ProcessName == "procmon")
{
hWnd = pr.MainWindowHandle.ToInt32();
ShowWindow(hWnd, SW_HIDE);
}
}
It's better to tell the process to show no window in the first place, instead of hiding it afterwards.
When running a program from .net you usually already have a ProcessStartInfo. Then just set its WindowStyle property to ProcessWindowStyle.Hidden and that should take care of it.
I haven't tried this myself, but that's the way you usually do it when calling the WinApi functions directly.
http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.windowstyle.aspx
http://msdn.microsoft.com/en-us/library/system.diagnostics.processwindowstyle.aspx
You need to get Window Handle of Process Monitor first and then you need to call ShowWindow with SW_HIDE to hide it.
You can use FindWindow to get the Window Handle of the ProcMon window.
Edit:
After looking at your code, I tried at my end and it works with the following code:
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
public static void HideWindow()
{
int SW_HIDE = 0;
foreach (Process pr in Process.GetProcesses())
{
if (pr.ProcessName.Contains("Procmon"))
{
//Int32 hWnd = pr.MainWindowHandle.ToInt32();
ShowWindow(pr.MainWindowHandle, SW_HIDE);
}
}
}
static void Main(string[] args)
{
HideWindow();
}
Most likely, the problem with your code is that you are trying to find an exact match of the process name which isn't there.
Procmon has built-in functionality to automatically log at startup, if that's what you're trying to accomplish.