I have develop a program which turns off the monitor by standard sendmassage api call:
public int WM_SYSCOMMAND = 0x0112;
public int SC_MONITORPOWER = 0xF170;
const int HWND_BROADCAST = 0xFFFF;
SendMessage(-1, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
My question is I dont want it to be a windows form, but a windows service instead... The sendmessage doesnt not in a windows service. How can I get it to work?
Regards,
Christian
Using HWND_BROADCAST / -1 is so wrong I don't even know where to begin, see this blog post for details
If for whatever reason you can't create a window, you could try to PInvoke the DefWindowProc function directly
Are you even sure it is possible to do this from a service? You might have to call CreateProcessAsUser and start a helper app
You can use GetDesktopWindow method and send the message to that window. Or you can use FindWindow and FindWindowEx methods to get the currently active window and send message there. Or you can add a reference to System.Windows.Forms in your service and instantiate a Form object and use that handle to send the message.
Related
I am searching for alternatives to the old User32.dll version of switching to a different application with FindWindow() and SetForegroundWindow().
I did find an alternative to the first with the usage of Process.GetProcessesByName() but I do not see the corresponding method to switch (set active/foreground) to that application.
Is there a way of doing that without using the old way with the User32.dll?
Thank you for your help.
EDIT
I accepted the answer of #Sorceri although it is not the answer I was looking for.
Answer: No.
But, to help the next wonderer looking to find a window and activate it from C# here's what you have to do:
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
void ActivateApp(string processName)
{
Process[] p = Process.GetProcessesByName(processName);
// Activate the first application we find with this name
if (p.Count() > 0)
SetForegroundWindow(p[0].MainWindowHandle);
}
To bring notepad to the front, for example, you would call:
ActivateApp("notepad");
As a side note - for those of you who are trying to bring a window within your application to the foreground just call the Activate() method.
You could use SetActiveWindow as an alternative to SetForeGroundWindow. I'd say you should go through all the Windows Manipulation Api Functions and see if there's something you're missing out.
Also, note that you can obtain the handle of the System.Diagnostics.Process object via the Process.Handle property.
An alternative to SetForeGroundWindow is VisualBasic's AppActivate
Call it like this
Microsoft.VisualBasic.Interaction.AppActivate("WindowTitle")
Just because it is in the VisualBasic namespace doesn't mean you can't use it in C#.
Full Documentation here
You can use System.Diagnostics.Process Object for a FindWindow equivalent. There currently is no equivalent for SetForegroundWindow. You will want use Pinvoke with SetForgroundWindow.
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
In order to get the application name of the foreground Window (or the name of application file) I want to use GetActiveWindow with GetWindowModuleFileName.
I found a similar question relating to GetWindowText here
That implementation of GetWindowText works fine, but GetWindowModuleFileName only returns a value for visual studio (when I click inside the devenv) for all other applications it stays blank.
Any hint how I can find out what goes wrong? Might this have to do with permission/security of my application querying the applicationfilename of another process?
EDIT: http://support.microsoft.com/?id=228469 looks like this doesn't work under Win >=XP
Any alternatives how to get the application file name?
In order to get the application name of the foreground Window (or the name of application file) I want to use GetActiveWindow with GetWindowModuleFileName.
... querying the applicationfilename of another process ...
In my opinion your problem with use of GetActiveWindow() function. It is used for gathering information from the calling thread/process only. If calling thread is inactive GetActiveWindow return 0;
From MSDN:
GetActiveWindow Retrieves the window handle to the active window attached to the calling thread's message queue.
Try to use GetForegroundWindow() function instead of GetActiveWindow()
By chance do you have UAC turned off?
Starting with Vista, if your code touches an HWND in another process, your process needs to be run at the same privilege level.
In other words, if the window is hosted in a process running as administrator, your app must also run as administrator.
I found a workaround using this:
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
IntPtr handle = IntPtr.Zero;
handle = GetForegroundWindow();
uint processId;
if (GetWindowThreadProcessId(handle, out processId) > 0)
{
Console.WriteLine(Process.GetProcessById((int)processId).MainModule.FileName);
}
Does anybody know a way to deactivate the autoplay function of windows using c#/.NET?
A little summary, for all the others looking for a good way to disable/supress autoplay.
So far I've found 3 methods to disable autoplay programatically:
Intercepting the QueryCancelAutoPlay message
Using the Registry
Implementing the COM Interface IQueryCancelAutoPlay
In the end I chose the 3rd method and used the IQueryCancelAutoPlay interface because the others had some signifcant disadvantages:
The first method
(QueryCancelAutoPlay) was only able
to suppress autoplay if the
application window was in the foreground, cause only the foreground window receives the message
Configuring autoplay in the registry worked even if the application window was in the background. The downside: It required a restart of the currently running explorer.exe to take effect...so this was no solution to temporarily disable autoplay.
Examples for the implementation
1. QueryCancelAutoPlay
Suppressing AutoRun Programmatically (MSDN article)
CodeProject: Preventing a CD from Auto-Playing
Canceling AutoPlay from C#
Note: If your application is using a dialog box you need to call SetWindowLong (signature) instead of just returning false. See here for more details)
2. Registry
Using the registry you can disables AutoRun for specified drive letters (NoDriveAutoRun) or for a class of drives (NoDriveTypeAutoRun)
Using the Registry to Disable AutoRun (MSDN article)
How to Enable / Disable Autorun for a Drive (using Registry)
Windows 7 AutoPlay Enable | Disable
3. IQueryCancelAutoPlay
Reference for the IQueryCancelAutoPlay interface on MSDN
IQueryCancelAutoPlay only called once? (Example implementatio, also read comments)
AutoPlayController (another implementation, not tested)
Some other links:
Enabling and Disabling AutoRun (MSDN article)
Autoplay in Windows XP: Automatically Detect and React to New Devices on a System (an old but extensive article on Autoplay)
RegisterWindowMessage is a Win32 API call. So you will need to use PInvoke to make it work..
using System.Runtime.InteropServices;
class Win32Call
{
[DllImport("user32.dll")]
public static extern int RegisterWindowMessage(String strMessage);
}
// In your application you will call
Win32Call.RegisterWindowMessage("QueryCancelAutoPlay");
From here (The Experts-Exchange link at the top). There is additional help on that site with some more examples that may be a little more comprehensive than the above. The above does however solve the problem.
Some additional links that might be helpful:
Preventing a CD from
Auto-Playing shows some example
vb.net code, showing the usage of
"QueryCancelAutoPlay" on CodeProject.
Enabling and Disabling AutoRun on MSDN.
Try this code work for me :) For more info check out this reference link : http://www.pinvoke.net/default.aspx/user32.registerwindowmessage
using System.Runtime.InteropServices;
//provide a private internal message id
private UInt32 queryCancelAutoPlay = 0;
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
/* only needed if your application is using a dialog box and needs to
* respond to a "QueryCancelAutoPlay" message, it cannot simply return TRUE or FALSE.
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
*/
protected override void WndProc(ref Message m)
{
//calling the base first is important, otherwise the values you set later will be lost
base.WndProc (ref m);
//if the QueryCancelAutoPlay message id has not been registered...
if (queryCancelAutoPlay == 0)
queryCancelAutoPlay = RegisterWindowMessage("QueryCancelAutoPlay");
//if the window message id equals the QueryCancelAutoPlay message id
if ((UInt32)m.Msg == queryCancelAutoPlay)
{
/* only needed if your application is using a dialog box and needs to
* respond to a "QueryCancelAutoPlay" message, it cannot simply return TRUE or FALSE.
SetWindowLong(this.Handle, 0, 1);
*/
m.Result = (IntPtr)1;
}
} //WndProc
I have a window which is hidden and I would like to send a keypress to it. An example of what I'm trying to achieve is an app that will send the key F5 to a web browser which wasn't the active window. The web browser would know to refresh the current page when the F5 keystroke is received.
I would also like to send a combination of keys to an application, e.g. Ctrl+S. One example of this usage could be a timed auto-save feature to use with applications which don't have autosave. This would spare me having to remember to save every 5 mins.
C# is my technology, does this sound realistic?
This CodeProject article shows how to send keystrokes to an external application (with C# source code).
You can use WinApi for this purpose. SendMessage or PostMessage method to send desired message to your application.
Here's C# definition of SendMessage
[DllImport("user32.dll")]
public static extern int SendMessage(
int hWnd, // handle to destination window
uint Msg, // message
long wParam, // first message parameter
long lParam // second message parameter
);
and define the message that you want to send like:
public const uint %WM_MESSAGE_HERE% = %value%;
Check PInvoke - great resource containing WinApi method definitions for .NET
This should be possible, look at www.pinvoke.net and search for sendinput, that page should tell you everything you need to know, also how to find the window (look for findwindow)
I'm writing a .NET wrapper around an old MFC-based library we have. It's based around a class that sends notifications using window messages; it has a function that lets the user pass in a handle to a window, and that window will receive the messages.
I could just require the users of my wrapper to subclass Control and pass their control's handle in order to receive messages, but that's horrible. I want my wrapper class to have events which fire whenever the old library sends a message, and then I can do the decoding of the message into something sensible. But, I don't want my wrapper class to have to be a control.
Is there a way for me to create a 'dummy' window handle, and receive the messages sent to that handle, without creating a window?
There is a concept of MessageOnly Windows which can help you. You may create an internal message only window in your wrapper class and pass this handle to the old library.
You could try creating a thread with a message pump and sending your messages to that. The thread then raises any necessary events that you want to handle in your C# code.
You can't create a window handle without having a window, since the window handle is the window as far Windows is concerned, but you can make a window without the WS_VISIBLE flag set, and use it for message relaying only. I use that technique sometimes to do cross-thread communication in MFC-only applications (don't tell anyone ;) ). You could derive a (c++) class from CWnd, let it process the messages, and call functions or emit signals for every message that is received. I guess that would make it work with your C# code although I don't have experience with that.
To create a window that does not display, but receives messages, use the following code.
The header file:
#pragma once
#include <afxwin.h>
#define ID_NOTHING_MGS WM_USER + 1001
class control : public CWnd
{
public:
control();
LRESULT control::nothing(WPARAM wp, LPARAM lp);
DECLARE_MESSAGE_MAP()
};
Function implementation in header file.
#include "control.h"
BEGIN_MESSAGE_MAP(control, CWnd)
ON_MESSAGE(ID_NOTHING_MGS, nothing)
END_MESSAGE_MAP()
control::control()
{
// ref1:https://codeantenna.com/a/s6NmJb6YD8
// ref2:https://www.cnblogs.com/greatverve/archive/2012/11/04/mfc-message.html
this->CreateEx(WS_EX_NOACTIVATE, AfxRegisterWndClass(0), _T("windowName"),
WS_CAPTION | WS_OVERLAPPEDWINDOW | WS_EX_NOPARENTNOTIFY,// | WS_VISIBLE,
0, 0, 400, 350, NULL, NULL, NULL);
}
LRESULT control::nothing(WPARAM wp, LPARAM lp)
{
MessageBox(TEXT("control receive message"));
return 0;
}
Since control inherit from the CWnd class, it can receive messages。CreateEx function,creates the specified window and appends it to the CWnd object. If you do not call CreateEx, the window handle value of the created Control object is 0.
No 'WS_VISIBLE' is used, so the window is not visible.