向 Windows 服务发送 Windows 消息

发布于 2024-07-30 03:32:11 字数 182 浏览 5 评论 0原文

有没有任何工具可以将“WM_ENDSESSION”等 Windows 消息发送(模仿)到 Windows 服务?

或者

如何使用 C# 向进程发送 Windows 消息?

(我只知道 C#)

编辑: 目的: 基本上我必须调试 Windows 服务来修复仅在系统关闭时发生的错误。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

盛装女皇 2024-08-06 03:32:11

应使用 ServiceController 类 控制服务

代表 Windows 服务,并允许您连接到正在运行或已停止的服务、对其进行操作或获取有关它的信息。

您可以使用它来启动、停止以及与使用此类的服务进行通信。

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.

天涯沦落人 2024-08-06 03:32:11

通常,服务没有窗口(更不用说消息泵)来接收窗口消息。

如果错误确实只在关闭时发生(而不是仅仅停止服务),则可能是某些东西依赖于正在消失的资源,而该资源没有得到妥善处理(在这种情况下,错误修复< em>可能是正确设置服务依赖项)。 您是否尝试过在关闭之前使用远程调试工具附加到进程?

值得研究一下是否可以在不关闭的情况下发生问题,也许只是使用服务控制管理器停止服务时(不需要以编程方式执行此操作,因为这是一个调试场景),在这种情况下,您可以在 OnStop 上设置断点() 在你的服务中(我假设是 C#)并观察会发生什么。

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.

灰色世界里的红玫瑰 2024-08-06 03:32:11

如果您有窗口的 hwnd,则可以向其发送消息。 唯一的限制是您无法发送包含指针的消息,例如设置窗口文本。
只需使用 hwnd 的值和您要发送的消息调用 PostMessage() 即可。
要找到hwnd,您可以使用spy++。

我不确定如何将所有这些连接到 Windows 服务,因为 Windows 服务没有窗口。

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.

夢归不見 2024-08-06 03:32:11

查看如何在调试时模拟 Windows 关闭?

答案他们可以订阅一个名为 OnShutdown 的“事件”,因此问题可能出在该代码中。 如果代码是 .net,您可以将其子类化,以便可以调用受保护的 OnShutdown 方法进行调试。 但问题也可能是正如其他人所建议的那样,该服务期望资源可用,但实际上资源并不可用,因为它们已经被关闭。

另外,如果服务是用 .net 2.0 编写的,请注意,当工作站关闭时,不会在服务上自动调用 Stop() 命令! 这是非常令人惊讶的,已在 .net 3.5 中修复,但如果您使用 .net 2.0,则需要在 OnShutdown() 中自行调用 Stop()。

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().

吻安 2024-08-06 03:32:11

我认为没有一个工具可以发送任意消息,因为每条消息都可以具有任意 LPARAM 和 WPARAM 值。

但围绕 Windows 消息最有用的工具是间谍++。 Spy++ 包含在 Visual Studio 中,它可以帮助您查看发送的消息、窗口层次结构等。

您可以使用 SendMessage 通过 C# 发送消息 Win32 API。 您可以使用 Win32 API 获取它所需的窗口句柄 FindWindowFindWindowEx

编辑(以匹配问题的编辑):服务在关闭时由窗口自动停止。 因此,要修复您的错误,听起来您需要修改服务本身的代码才能正确关闭。

Edit2:或者如果您想停止该服务,您应该使用 Win32 API ControlService 传入 SERVICE_CONTROL_STOP 0x00000001

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.

薄荷→糖丶微凉 2024-08-06 03:32:11

我不知道这是否是一个类似的句柄,我对此表示怀疑,但有人可以让我知道是否是,但是您可以获得一个进程句柄,这意味着您可以使用 Process.GetProcessesByName(" MyAppName");,尽管不要依赖于此,因为我认为它不会获得您想要的句柄。 只是一个建议。

实际上这个方法会起作用......你只需要访问进程对象的“MainWindowHandle”属性。 例如...

Process myProcess;
Int handle;
myProcess = Process.GetProcessesByName("MyAppName");
handle = myProcess.MainWindowHandle;

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;
不忘初心 2024-08-06 03:32:11

我建议导入并定义以下内容:

[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;

然后通过代表 true 或 false 的 0x1 或 0x0 作为 wParam 消息发送。

因此,在您的代码中,您将使用:

PostMessage(HandleToSendTo, WM_ENDSESSION, WM_TRUE, 0);

其中 HandleToSendTo 是您要将消息发送到的窗口的窗口句柄。

编辑
如果您不知道窗口句柄,为了获取它,我假设您知道它的标题或名称。 如果是这样,您可以使用以下内容:

[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
        public static extern int FindWindowEx(int hwndParent, int hwndEnfant, int lpClasse, string lpTitre);

有关更多信息,请参阅此问题。

或者也许

我不知道这是否是一个类似的句柄,我对此表示怀疑,但有人可以让我知道是否是,但你可以获得一个进程句柄,这意味着您可以使用 Process.GetProcessesByName("MyAppName"); 获取进程,尽管不要依赖于此,因为我认为它不会获取您想要的句柄。 只是一个建议。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文