How to clear/kill tasks to not overload CPU in WPF application? - c#

I am currently building a kiosk application using WPF. I have one main window and several User Control (pages). After the last page, the app will redirect to the first page to start over the entire process.
I have noticed that after running the full flow for three times, the app will crash/hang due to CPU and Memory overload.
However i solve the memory overload issue by declaring the following
[DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetProcessWorkingSetSize(IntPtr pProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);
[DllImport("KERNEL32.DLL", EntryPoint = "GetCurrentProcess", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern IntPtr GetCurrentProcess();
and adding this code in the Unloaded() event.
IntPtr pHandle = GetCurrentProcess();
SetProcessWorkingSetSize(pHandle, -1, -1);
This code able to solve the Memory Overload issue, but the CPU overload issue is still there. Can anyone please help me with it please? What shall i add in the Unloaded() event to free the CPU?

Related

How to determine if Console is allocated in a winform application?

I'm developing a Windows Forms Application. At the startup I can choose if I want to show the console too or only the main form. This is achieved via the
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern int AllocConsole();
command. I can even dispose it via the
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern int FreeConsole();
command.
How can I determine at runtime if the console is disposed or not?

Calling WaitForSingleObject from C#

I am trying to call WaitForSingleObject method from C#, as documented here:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx
In order to call this function I need to create a Handle, or I need to get a Handle of type IntPtr, how can it be done?
I've tried this function that I found:
http://www.pinvoke.net/default.aspx/kernel32.WaitForSingleObject
[DllImport("coredll.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto)]
public static extern IntPtr CreateEvent(HANDLE lpEventAttributes, [In, MarshalAs(UnmanagedType.Bool)] bool bManualReset, [In, MarshalAs(UnmanagedType.Bool)] bool bIntialState, [In, MarshalAs(UnmanagedType.BStr)] string lpName);
Or for instance, when I am getting handle from console:
IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
It throws a DllNotFoundException.
What's the issue here?
I need it in order to run the process with this function call, and to take a dump form its process, for my ClrMd library learning.
Any help will be appreciated.
Code sample:
static void Main(string[] args)
{
var autoEvent = new AutoResetEvent(false);
//this is where I get the DllNotFoundException
WaitForSingleObject(autoEvent.Handle, WAIT_TIMEOUT );
}
[DllImport("kernel32.dll")]
static extern uint WaitForMultipleObjects(uint nCount, IntPtr[] lpHandles, bool bWaitAll, uint dwMilliseconds);
public const Int32 WAIT_TIMEOUT = 0x102;
I would not go through WinApi to get this from C#: you have EventWaitHandler and other synchronization objects in C#, use them:
WaitHandle wh = new EventWaitHandler();
//do whatever you need
...
WaitHandler.WaitOne(wh); // equivalent to WaitForSingleObject in WinApi
you can use wh.SafeWaitHandle if you really need to interop with WinApi
Also I suspect Process.GetCurrentProcess().MainWindowHandle cannot work in a Console Application, that has not any window at all
I want to call native method (WaitForMultipleObjects) which waits for some handle (don't really mind which one), then I want to see it on thread stack using ClrMd library, from dump file
OK, so what about new ManualResetEvent(false).WaitOne()? This should show up in the dump file. And it's reliable.
Just picking any existing handle is not reliable because it might be signaled or be destroyed at any time. Or, you might change its state by waiting. There is no need, a ManualResetEvent can create you a fresh handle.
My mistake I've posted WaitForMultipleObjects instead of WaitForSingleObject, the main issue was that WaitForSingleObject stayed with DllImport("coredll.dll"...) I don't know where did I found it but I did...
Sorry for the confusion

Are there any dangers of using Windows API calls in C#

I want to watermark a textbox, and found several different ways of doing it, but one that I liked uses SendMessage and an external DLL. However, I think I heard somewhere that doing it this way can cause BSOD since it isn't managed. Is this true, or is it just hear-say.
http://vidmar.net/weblog/archive/2008/11/05/watermarked-textbox-in-windows-forms-on-.net.aspx
private const uint ECM_FIRST = 0x1500;
private const uint EM_SETCUEBANNER = ECM_FIRST + 1;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, uint wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
The short answer is no. It won't cause a BSOD, although it could crash your program.
WinForms is basically built on top of Windows API calls, so when done right, custom API calls should work good as well.
One other thing to keep in mind is that if you do call the Windows API, it may create portability issues, such as when porting to Mono, as those DLLs will most likely not be available.

switch application and assigning them to instance

I'm having problems with switching application and assigning them to a variable. This is what I have so far.
[DllImport("user32.dll")]
public static extern void SwitchToThisWindow(IntPtr hWnd, bool b);
Process[] procs = Process.GetProcessesByName("Excel");
foreach (Process proc in procs)
{
SwitchToThisWindow(proc.MainWindowHandle, false);
}
In the end I want to assign that Excel window to be assigned to xlApp. I tried:
xlAppl = SwitchToThisWindow(proc.MainWindowHandle, false); but obviously this won't work because the interface is a void. I tried looking at GetActiveWindow I was thinking of getting active window and assign it but it's return value is not an Object it's IntPtr.
Is there a way out of this?
There are a couple things I want to point out about what you have so far:
For SwitchToThisWindow MSDN states - [This function is not intended for general use. It may be altered or unavailable in subsequent versions of Windows.]. So I personally wouldn't use that one if I were you.
Your Process.GetProcessByName call is going to return all excel processes. Then you're going to try to bring each one to the foreground. Only the last one of course will actually be in the foreground, since they can't all be in the foreground. You should probably decide on a more accurate way of choosing which one you want.
You are assuming that MainWindowHandle is not IntPtr.Zero which is not a valid assumption in all cases. MainWindowHandle will only have a value once there is a visible window that has been rendered.
If I were you I'd try using the SetForegroundWindow and SetActiveWindow APIs instead.
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool SetForegroundWindow(
IntPtr hWnd
);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SetActiveWindow(
IntPtr hWnd
);
Guys i found the solution. Pretty simple here is the answer if anyone else is looking for this:
Excel.Application xlApp = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");

Can WH_MOUSE catch global events?

I'm trying to develop a WPF C# application that captures mouse clicks even (especially) if it's in background in order to start another task.
On MSDN documentation ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx ) I can read that WH_MOUSE should have either a global or thread scope.
I instantiate my hook handle this way:
hHook = SetWindowsHookEx(WH_MOUSE,
MouseHookProcedure,
(IntPtr)0,
AppDomain.GetCurrentThreadId());
where MouseHookProcedure is the delegate of my callback function and WH_MOUSE value is 7 (following Winuser.h).
The code works but it can only catch local clicks (I just need WM_LBUTTONDOWN messages), the clicks inside the window. I need to catch clicks also outside the window, and when the window is in background.
I tried hooking to WH_MOUSE_LL (with a value of 14), but it's not working.
For the most part I followed this:
http://support.microsoft.com/kb/318804
with some changes since I am using WPF and not WinForms.
The documentation about Hooks is a bit confusing.
All in all I'd like to know:
Can WH_MOUSE detect mouse messages globally? If yes, what am I doing wrong?
Can I hook from a .NET C# code to a WH_MOUSE_LL? If yes, how?
Thanks in advance.
It's possible with WH_MOUSE_LL and you need it.
In my case I developed a global keyboard maybe this could help you.
I needed to call LoadLibrary in the third parameters.
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr LoadLibrary(string fileName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
void MyFunction(){
[...]
SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, LoadLibrary("user32.dll"), 0);
}
Technically you should be able to have a global mouse hook implemented in C#. You would then pass zero as the last arguments to SetWindowsHookEx and your hook procedure must reside in a DLL, not an EXE. That's because the DLL will be injected into every process that has windows belonging to the same desktop as the hooking application. For this same reason writing global hooks in .NET is not actually recommended by most because it causes the CLR to be loaded into every desktop process, which can carry substantial overhead.

Categories