Is there any tool to send (mimic) a windows message like 'WM_ENDSESSION' to a windows service?
OR
How can I send a windows message to a process using C#?
(I know only C#)
EDIT: Purpose: Basically I have to debug a windows service for fixing a bug that occurs only on system shut down.
Services should be controlled using ServiceController class
Represents a Windows service and allows you to connect to a running or stopped service, manipulate it, or get information about it.
You can use it to start, stop and communicate with services using this class.
Generally, services don't have windows (let alone message pumps) to receive a windows message.
If the bug really does only happen on shutdown (as opposed to just stopping the service), it may be the case that something depends on a resource that is going away, which is not being handled gracefully (in which case, the bug fix might be to set up the service dependencies correctly). Have you tried using the remote debugging tools to attach to the process prior to shutdown?
It's worth investigating if you can get the problem to occur without shutting down, perhaps when just stopping the service with the Service Control Manager (no need to do this programmatically, as this is a debugging scenario), in which case, you can breakpoint OnStop() in your service (I'm assuming C#) and watch what happens.
Check out the answers to How to simulate windows shutdown while debugging?
Services have an 'event' called OnShutdown they can subscribe to, so it could be the problem is in that code. If the code is .net you could subclass it so you can call the protected OnShutdown method to debug. But the problem could also be as suggested by others that the service is expecting resources to be available which aren't because they've already been closed.
Also, if the service was written in .net 2.0 note that the Stop() command isn't called automatically on a service when the workstation is being shut down! This is very surprising and was fixed in .net 3.5, but if you're using .net 2.0 you need to call Stop() yourself within OnShutdown().
If you have the hwnd of a window you can send it messages. The only limitation is that you can't send messages that contain pointers like setting window text.
Simply call PostMessage() with the value of the hwnd and the message you want to send.
To find the hwnd you can use spy++.
I'm not sure how you connect all this to windows services since windows services don't have windows.
I would recommend Importing and defining the following:
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern bool PostMessage(IntPtr handleWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
const int WM_ENDSESSION = 0x0016,
WM_TRUE = 0x1,
WM_FALSE = 0x0;
Then send through 0x1 or 0x0 representing true or false as the wParam message.
So in your code you will use:
PostMessage(HandleToSendTo, WM_ENDSESSION, WM_TRUE, 0);
Where HandleToSendTo is the Window Handle of the window you would like to send the message to.
Edit
To get the windows handle if you don't know it, I'm assuming that you will know it's title or name. If so you can use this:
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
public static extern int FindWindowEx(int hwndParent, int hwndEnfant, int lpClasse, string lpTitre);
Which more information about can be found in this question.
Or maybe
I don't know if this is a similar handle, I doubt it, but someone could let me know if it is, but you can get a Process handle, which means you could get the process using Process.GetProcessesByName("MyAppName");, althought don't rely on this as I don't think that it will get the handle that you are after. Just a suggestion.
I don't think there is a tool to send arbitrary messages because each message can have arbitrary LPARAM and WPARAM values.
But the most useful tool surrounding windows messages is spy++. Spy++ is included with Visual Studio and it helps you see what messages are sent, window hierarchy, and more.
You can send messages via C# with the SendMessage Win32 API. You can get the window handle it asks for by using a Win32 API like FindWindow or FindWindowEx.
Edit (to match question's edit): Services are stopped by windows automatically on shutdown. So to fix your bug it sounds like you need to modify the code of the service itself to properly shut down.
Edit2: Or if you want to stop the service you should use the Win32 API ControlService passing in SERVICE_CONTROL_STOP 0x00000001.
I don't know if this is a similar handle, I doubt it, but someone could let me know if it is, but you can get a Process handle, which means you could get the process using Process.GetProcessesByName("MyAppName");, althought don't rely on this as I don't think that it will get the handle that you are after. Just a suggestion.
Actually this method will work...you just need to access the 'MainWindowHandle' property of the process object. For Instance...
Process myProcess;
Int handle;
myProcess = Process.GetProcessesByName("MyAppName");
handle = myProcess.MainWindowHandle;
Related
I'm trying to get Pointer Win32 messages of a specific window, by a hook on WH_CALLWNDPROC, WH_CALLWNDPROCRET and WH_GETMESSAGE.
I use SetWindowsHookEx in a c++ dll to hook and receive messages.
unsigned long processID = 0;
unsigned long threadID = GetWindowThreadProcessId(hWnd, &processID);
g_hhkGetMsg = SetWindowsHookEx(WH_GETMESSAGE,
GetMsgProc,
g_hinstDLL,
threadID);
This works for many windows, but not for CoreWindow of UWP windows.
Each UWP app window has a structure like this:
Hooking to ApplicationFrameWindow works correctly, but hooking to Windows.UI.Core.CoreWindow does not work. (SetWindowsHookEx shows success, but I don't get any messages in the callback)
However, Spy++ is able to capture the messages from the CoreWindow. (The CoreWindow receives WM_POINTER messages, so I need to subscribe to that window)
Thinking the issue might be on my code, I also tried the open source tool MyLiteSpy to see if that can capture messages from the CoreWindow. It can't capture anything, just like my sample code. (But MyLiteSpy is able to get messages from ApplicationFrameWindow of the same UWP app, and so can my code and Spy++)
Interestingly, this (old) blog post about Spy++ says that they use the same three hooks as me and MyLiteSpy, but it's getting messages that my code can't receive.
What is the difference here? Any idea why this is happening?
(Is Spy++ using hooks other than the three mentioned? The blog post is written in 2007, so things might have changed)
windows of class Windows.UI.Core.CoreWindow is usually immersive windows. for be able enumerate such, top level, windows, we need have disableWindowFiltering in manifest. it disables window filtering so you can enumerate (via EnumWindows) immersive windows from the desktop. but say direct call to FindWindowW(L"Windows.UI.Core.CoreWindow", L"Start"); - not fail even without disableWindowFiltering in manifest. however this part is only related to visibility immersive windows, via EnumWindows, for your application.
another task set WH_GETMESSAGE hook for such windows. problem here that this windows usually belong to Windows Store app (AppContainer ) process.
Windows Store app development: If dwThreadId is zero, then window hook DLLs are not loaded in-process for the Windows Store app
processes and the Windows Runtime broker process unless they are
installed by either UIAccess processes (accessibility tools).
so we need have or uiAccess set to true in manifest (say <requestedExecutionLevel level="requireAdministrator" uiAccess="true" />) or not 0 for dwThreadId in call SetWindowsHookEx. the dwThreadId we can got via GetWindowThreadProcessId
the WH_GETMESSAGE hook is always in process hook. so if we call it for another process - hook procedure must be located in dll, which will be loaded to target process. and here is main problem - how load dll to Windows Store app (AppContainer ) process.
i check this with self simply dll - try set hook for Windows.UI.Core.CoreWindow::Calculator window. the call for SetWindowsHookEx(WH_GETMESSAGE, ..) is ok, and in Calculator.exe called LoadLibraryExW for my dll, but this call fail inside NtQueryAttributesFile with error STATUS_ACCESS_DENIED. ok, Appcontainer is very restricted process, so i try change security descriptor on my dll. set it to "D:P(A;;FA;;;BA)(A;;FXFR;;;WD)(A;;FXFR;;;AC)S:P(ML;;NW;;;LW)" (give full access to Builtin (local ) administrators and read-execute access to all applications running in an app package context (SDDL_ALL_APP_PACKAGES - "AC") and Everyone ("WD"). with this LoadLibraryExW go forward, but anyway fail in call ZwCreateSection for my DLL with code STATUS_SYSTEM_NEEDS_REMEDIATION (C000047EL - An error in a system binary was detected) after which is LdrAppxHandleIntegrityFailure called (exported function from ntdll.dll)
so for load DLL to Windows Store app (Appcontainer) it must be signed. from kernel side call-stack is next
CI!KappxpNotifyNonPackagedFile
CI!KappxNotifyIntegrityFailureInPackagedProcess
CI!CipReportAndReprieveUMCIFailure
CI!CiValidateImageHeader
nt!SeValidateImageHeader
nt!MiValidateSectionCreate
nt!MiCreateNewSection
nt!MiCreateImageOrDataSection
nt!MiCreateSection
interesting that if check fail CI.DLL inside KappxpNotifyNonPackagedFile write file name and hash to registry under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModel\StateChange - BinaryName (REG_SZ) and BinaryHash (REG_BINARY)
in case Spyxx - it use signed dll - spyxxhk[_amd64].dll - this dll (if allow all app packages access to it) is loaded to process ok. so potentially Spy++ can collect messages from Appcontainer apps too. but in my research Spy++ call SetWindowsHookExW at begin with dwThreadId set to zero. as result spyxxhk[_amd64].dll will be not injected to Windows Store apps. need every time use not 0 dwThreadId and have special security descriptor on dll.
My apologies if this question has been asked and already answered, I have spent the best part of three days experimenting with WndProc() in WinPE (for Windows 10).
How do I "Catch" Messages through WndProc() (or a Handler Routine) in WinPE (Windows 10)?
I have a custom application(written in C# .Net 4.5.2) that is launched by WinPEShl.exe, on boot of WinPE. This is currently an Application that provides access to other applications to enable Windows deployment or Image Capture.
While this Application may not always be the current Windows Form, there a one or two routines that need to be completed before Windows PE has shutdown. I would like this to happen on either the WM_QUERYENDSESSION/WM_ENDSESSION or WTS_SESSION_CHANGE notifications through the overriden WndProc() function.
Currently this is my WndProc() function:
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message m)
{
// Listen for operating system messages.
if (m.Msg == WM_QUERYENDSESSION)
{
Program.WriteLogFile(4, 1, "WM_QUERYENDSISSION: received. Return Bool=True");
}
if (m.Msg == WTS.WM_WTSSESSION_CHANGE)
{
int wValue = m.WParam.ToInt32();
if (wValue == WTS.WTS_SESSION_LOGOFF)
{
//Write my darn Log file!
Program.WriteLogFile(4, 1, "WM_WTS_SESSION_LOGOFF: received. Return Bool=True");
}
if (wValue == WTS.WTS_CONSOLE_DISCONNECT)
{
Program.WriteLogFile(4, 1, "WM_WTS_SESSION_DISCONNECT: received. Return Bool=True");
}
}
base.WndProc(ref m);
}
Program.WriteLogFile() is a Log File writer (as it says!) that will be used to report that the system is shutting down.
From this Link I am aware that as WinPE is a Stream lined version of Windows, with only a small number of API's being available for usage. I have looked through both of the MinCore.lib sets for both Windows API Sets mentioned - resulting in nill success for finding any function in relation to the WndProc() holder function. I have evensearched OneCore.lib aswell.
I did however find the WTSRegiSessionNotifications() functions. Again even though they register fine in WinPE, my Shell App doesn't receive the messages if another application shuts down the system (such as Windows Setup on completion of the first phase).
Testing in Windows provides both results in the associated application log file.
Should I be using a hidden console app, to capture the CTRL_LOGOFF_EVENT/CTRL-SHUTDOWN_EVENT, or should i be using a service (and have all log writing routed through it)?
Log files from Windows 10 (working as should be) and WinPE available on request.
Thanks for any and all help in this matter.
Kind regards
Richie
I'm not sure why you're not using the regular winforms form lifetime events. I'm guessing you're somewhat more used to C-oriented ways of doing things?
If you've built a winpeshl.ini that starts your program, and it's the only program listed (beyond winpeinit.exe), then when it shuts down, PE shuts down. This is true even if you spawn other applications from your main program (via System.Diagnostics.Process).
So, don't list a lot of programs in winpeshl.ini. Let your one-and-only main program start the rest.
FWIW, I've got a similar app...does image capture, deploy and periodic maintenance. We put our winPE in it's own partition and do a lot of active BCD management to make it boot when we want. I've closed off all the "normal" shutdown routes. Yes, I suppose a persistent user can circumvent...but if they're determined, so be it...but we haven't had an issue with that.
I'm developing an application which has 2 parts:
1) A WPF application which runs from the system tray. It does have a GUI window, which can be brought up by right-clicking the sys-tray icon & choosing an option on the context menu, but it is not needed very frequently & the app will run from the sys-tray most of the time. Moreover, I've changed the Closing() event of the MainWindow, so as to minimize the app, if the user tries to close it.
2) A console application which runs without displaying a console & its purpose is to poll for launch/close of another application. As soon as the other application is launched/closed, the console application launches/closes the WPF application too. (Please don't tell me to do this using a Windows Service. I've already explored the route before. It doesn't work for me due to several reasons, which I won't enlist here).
PROBLEM: I am not able to close the WPF application from the console application. What I'm doing is as follows. First I obtain the process for my WPF application:
Process AppProcess = Process.GetProcessById((int)AppID);
After this I've tried a lot of options as follows:
1) Killing the process: AppProcess.Kill();
This is the only one which worked, but is very unelegant. It also leaves the SysTray icon undisposed, so it is not acceptable.
2) AppProcess.Close();
Doesn't work at all & I don't know why.
3) AppProcess.Dispose();
Doesn't work at all & I don't know why.
4) AppProcess.CloseMainWindow();
This only works if the user has kept the GUI of the WPF app opened, which is very rarely the case as I mentioned before. So, normally this also doesn't work. (You might say that I've hacked the Closing() event to prevent closing the window. Don't worry I've taken appropriate care to handle that. I've provided other measures to close the app. There is a boolean variable which decides whether the Closing action is to be cancelled or not.)
5) Passing custom/standard message to the WPF Application's main window.
This also works only if the main window (GUI) of the WPF app is open, else it doesn't receive the message.
So, all in all, no method is working. I need a reliable method to close the WPF app gracefully from the console app. Please suggest something.
The current way I'm doing it is as follows:
In the Console App:
const uint WM_CUSTOMCLOSE = 0xFE;
IntPtr hWnd = AppProcess.MainWindowHandle;
SendMessage(hWnd, WM_CUSTOMCLOSE, 0, 0);
In the WPF app:
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
source.AddHook(WndProc);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if(msg == 0xFE)
{
ExitFlag = true; //Exitflag is checked later to decide whether closing is to be cancelled.
this.Close();
}
return IntPtr.Zero;
}
Use IPC as JeffRSon suggested. MSMQ is a very easy and effective way when two processes are on the same machine.
Define a queue of your WPF application and when it starts, no matter showing UI or not, let it listen the queue. Console application can send a message to the queue with closing application message. You have to define the data contract. You can refer to:
http://www.codeproject.com/Articles/3944/Programming-MSMQ-in-NET-Part-1
Ok, I found a way to close the WPF app. The reason it wasn't receiving the message was that for some reason, AppProcess.MainWindowHandle was not giving the handle of the main window of the WPF app, when the WPF app ran from the system tray.
So, instead I'm using the user32.dll:FindWindow() method found in the Win32 APIs to find the main window of the WPF app. After that when I pass my custom message to it, the WPF app shuts down gracefully.
Background
I'm using SendKeys() to send keyboard commands to the active window, but I'm not having any luck finding the child window when the application is running through RemoteApp. It all works as expected when I run the application locally.
Microsoft RemoteApp allows users to connect to applications through the RDP protocol, but instead of showing the entire remote Virtual machine, it just shows the application window. To the end user, there is no difference between an application running under RemoteApp and it running on their desktop.
I've been using ManagedSpy to determine the class name of the .NET application window so that I can use the Win32 API function FindWindowEx to make one of the child windows active, and it works well. However, I'm having a problem when the application is running over RemoteApp.
I can still use the .NET Process.GetProcessesByName() to find the application, I just have to have it invoke mstsc.exe:
IntPtr hwndChild = IntPtr.Zero;
Process[] processess = Process.GetProcessesByName("mstsc");
IntPtr appHandle = IntPtr.Zero;
foreach (Process p in processess)
{
if ((p.MainWindowHandle != IntPtr.Zero))
{
appHandle = p.MainWindowHandle;
}
}
if (appHandle == IntPtr.Zero)
{
MessageBox.Show("Application is not Running.");
return;
}
However, I can't use FindWindowEx in the same way. This question revolves around that.
For the unmanaged code to tell me what windows mstsc.exe has active, I used Spy++, but for mstsc.exe it comes back with a different class name, called RAIL_WINDOW:
Here is the code I'm using to find the Child Window:
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
hwndChild = FindWindowEx(appHandle, IntPtr.Zero, "RAIL_WINDOW", "MyApplication (Remote)");
SetForegroundWindow(hwndChild);
Questions
I can use Spy++ to highlight the active child window in the RemoteApp version of the application, and I get RAIL_WINDOW, but I cannot seem to access this window programmatically. Given the code above, what am I missing to be able to do so?
Are there other ways of sending keyboard strokes to an application running over Remote App?
Knowing how Microsoft does things, I'll bet the "rail window" is nothing more than a dumb, local proxy that doesn't bother responding to what SendKeys is sending. I haven't looked, but I'll bet that ends up sending WM_CHAR messages, to which a dumb proxy probably wouldn't bother responding. Instead, try sending it WM_KEYUP and WM_KEYDOWN messages manually and see if that works, given that I expect it would transmit those and mouse clicks (and what not) rather than the translated versions.
What commands are you sending using SendKeys()?
It may be better to look for an alternative solution instead of using `SendKeys()'.
And you can probably take advantage of handling IMsTscAxEvents::OnRemoteWindowDisplayed event that gives you the proper window handle at the right time without calling FindWindowEx, etc.
currently I’m creating 2 applications (app A and B) for Windows Mobile 5.0 and using Compact Framework 2.0. App A is the main application and B is the sub application.
Below is the flow:
Start app A.
App A will start app B.
App B will do some process.
App B will kill app A.
App B will patch/upgrade app A. (ala update manager)
App B will restart app A.
App B will exit.
Now I’m stuck in killing app A. I did tried using OpenNETCF ProcessEntry Kill() function. When calling Kill(), it made the device crash.
I did tried using the SendMessage(hWnd, WM_CLOSE, 0, 0) funct where WM_CLOSE will have the ProcessEntry.ProcessID value and I didn’t assigned any value to hWnd variable. But it didn’t terminate app A. Did I assign the wrong value?
I also did tried using
Process.GetProcessById(processEntry.ProcessID).CloseMainWindow()
, but failed as GetProcessById only accepts int32 value. Note that processEntry.ProcessID value is larger than int32 value and GetProcessByName() is not supported in Compact Framework.
Could you help me in killing app A through app B?
Thanks.
You may try native code, using the TerminateProcess function:
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
success = TerminateProcess(processHandle, 0);
The above code is from a Task Manager at Code Project.
However if you are writing the code for both the applications, it will be better if you designed a communication mechanism between the two applications. In this way you will send a message from app B to app A and app A will kill itself.
Stormenet, I hardcoded the application's name. Then I generate an object to get all the available process using OpenNETCF.ToolHelp.ProcessEntry[ ] = ProcessEntry.GetProcesses();
then in a foreach loop, if the ProcessEntry object eg: processEntry.ExeFile matches with the "applicationName", i shall use processEntry.Kill().
I think you can get the OpenNETCF.ToolHelp dll from the OpenNETCF site.
Note that if the application you are trying to kill is holding open ports or other system resources then it might hang on exiting. Ensure everything is effectively disposed when the form closes.
This can be acheived by putting stuff in the:
public void Dispose(bool disposing)
{
}
block of code in the designer of your main form, or if you've chosen a less Windows Form centric architecture then just run your dispose calls following Application.Run(new YourForm()) and it will execute after the application has closed.
If you're feeling really lazy then just setup some destructors (otherwise known as finalizers ~) but be careful about navigating through relationships between managed objects at "destruct" time if you do this as there is no guarantee as to which order objects will be destroyed.
ctacke, I think app A crashes due to some of the running threads are not closed properly or still running at the background as app A will run multiple threads during app B executing the Kill( ) function.
If I use the SendMessage(hWnd, WM_CLOSE, 0, 0) function, it will not crash the device (which is a good thing)... it only closes the form. (app A contains multiple forms eg: frmLogin and frmMainMenu). hmmm maybe I need to point hWnd to the right form...
Now I'm taking a different route.
After downloading the patch and put it in a temp folder, I'll do a soft reset using OpenNETCF.WindowsCE.PowerManagement.SoftReset().
App B will be launched upon startup, then it will scan the temp folder and replace app A with the new version.