how to debug a windows service before its starting on windows server 2008
first let’s look at the kb on msdn on how to configure windbg for such purpose:
http://support.microsoft.com/kb/824344
here list a compact steps from kb above, and will it really solve my problem?:
1.Configure the "Image File Execution" options. To do this, use one of the following methods:
- Click Start, and then click Run. The Run dialog box appears.
- In the Open box, type regedit, and then click OK to start Registry Editor.
- Important This section, method, or task contains steps that tell you how to modify the registry. However, serious problems might occur if you modify the registry incorrectly. Therefore, make sure that you follow these steps carefully. For added protection, back up the registry before you modify it. Then, you can restore the registry if a problem occurs. For more information about how to back up and restore the registry, click the following article number to view the article in the Microsoft Knowledge Base:
322756 How to back up and restore the registry in Windows
In Registry Editor, locate, and then right-click the following registry subkey:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
- Point to New, and then click Key. In the left pane of Registry Editor, notice that New Key #1(the name of a new registry subkey) is selected for editing.
- Type ImageName to replace New Key #1, and then press ENTER.
Note ImageName is a placeholder for the image name of the process that hosts the service that you want to debug. For example, if you want to debug a service that is hosted by a process that has MyService.exe as the image name, type MyService.exe. - Right-click the registry subkey that you created in step e.
- Point to New, and then click String Value. In the right pane of Registry Editor, notice thatNew Value #1, the name of a new registry entry, is selected for editing.
- Replace New Value #1 with Debugger, and then press ENTER.
- Right-click the Debugger registry entry that you created in step h, and then click Modify. The Edit String dialog box appears.
- In the Value data text box, type DebuggerPath, and then click OK.
Note DebuggerPath is a placeholder for the full path of the debugger that you want to use. For example, if you want to use the WinDbg debugger to debug a service, you can type a full path that is similar to the following:C:\Progra~1\Debugg~1\windbg.exe
2.For the debugger window to appear on your desktop, and to interact with the debugger, make your service interactive. If you do not make your service interactive, the debugger will start but you cannot see it and you cannot issue commands. To make your service interactive, use one of the following methods:
- Click Start, and then point to Programs.
- On the Programs menu, point to Administrative Tools, and then click Services. TheServices console appears.
- In the right pane of the Services console, right-click ServiceName, and then clickProperties.
Note ServiceName is a placeholder for the name of the service that you want to debug. - On the Log On tab, click to select the Allow service to interact with desktop check box under Local System account, and then click OK.
3.When a service starts, the service communicates to the Service Control Manager how long the service must have to start (the time-out period for the service). If the Service Control Manager does not receive a "service started" notice from the service within this time-out period, the Service Control Manager terminates the process that hosts the service. This time-out period is typically less than 30 seconds. If you do not adjust this time-out period, the Service Control Manager ends the process and the attached debugger while you are trying to debug. To adjust this time-out period, follow these steps:
- In Registry Editor, locate, and then right-click the following registry subkey:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
- Point to New, and then click DWORD Value. In the right pane of Registry Editor, notice that New Value #1 (the name of a new registry entry) is selected for editing.
- Type ServicesPipeTimeout to replace New Value #1, and then press ENTER.
- Right-click the ServicesPipeTimeout registry entry that you created in step c, and then clickModify. The Edit DWORD Value dialog box appears.
- In the Value data text box, type TimeoutPeriod, and then click OK
Note TimeoutPeriod is a placeholder for the value of the time-out period (in milliseconds) that you want to set for the service. For example, if you want to set the time-out period to 24 hours (86400000 milliseconds), type 86400000. - Restart the computer. You must restart the computer for Service Control Manager to apply this change.
4.Start your Windows service. To do this, follow these steps:
- Click Start, and then point to Programs.
- On the Programs menu, point to Administrative Tools, and then click Services. The Servicesconsole appears.
- In the right pane of the Services console, right-click ServiceName, and then click Start.
Note ServiceName is a placeholder for the name of the service that you want to debug.
unfortunately !!!!!!!
this way does not work on Vista and Windows after Vista, like environment here:Windows server 2008,
and while starting the service, SCM will launch the debugger, but crashed!
here provide a screen snapshot for the crash dialog with message(a program can’t display a meesage on your desktop):
if you click the “Show me the message”, the windbg will display but only for few seconds, if you click the “Remind me in a few minutes”, the windbg will never launched!
ok,切换中文。此处省略RCA探索过程,我找到一篇博客提到导致此问题的Root Cause,
此处我把博客内容贴出方便上下文阅读:
Services and Session Zero in Vista and Windows Server 2008
If you've been running vista you might have come across this message: "A program can't display a message on your desktop" with the options to show the message or remind you later. So what's the deal with this?
Gone over in detail in this doc, its because services that runs in session0 run separately from the user’s session and therefore can't display popups directly to the user.
Windows Vista isolates services in Session 0 and runs applications in other sessions, so services are protected from attacks that originate in application code. In Windows Server 2003 and earlier versions of Windows, all services run in Session 0 along with applications, which poses a security risk because services run at elevated privilege and therefore are targets for malicious agents who are looking for a means to elevate their own privilege level.
The popup itself is Windows Vista playing nice with legacy services that send user interaction dialog boxes to session zero instead of the corresponding user session, this is called the "interactive service detection service". This workaround will be removed from the next version of Windows, at which time all applications and drivers must handle Session 0 isolation properly.
Proving that Microsoft devs are smart (IMHO), on a TS server in LH, these popups will only be displayed to the administrative sessions and not to the user sessions that are present on the TS server.
The whitepaper linked above has what devs should be doing these days to take into account this isolation.
注意红色部分给出了原因,详细的细节参加给出的链接this doc(http://msdn.microsoft.com/en-us/windows/hardware/gg463353.aspx)
把Session0Changes.docx下下来之后详细阅读了一番,方知:
Because Session 0 is no longer a user session, services that are running in Session 0 do not have access to the video driver. This means that any attempt that a service makes to render graphics fails.
那麽怎麽办呢,因为操作系统在此处策略的转变会导致一些老的service不能正常工作,文档里这麽解释Potential Issues的:
Any functionality in a service or a service-hosted driver that assumes the user is running in Session 0 does not work correctly in Windows Vista, Windows Server 2008, and later versions. Some examples of places where this assumption might occur are:
· A service attempts to create a user interface (UI), such as a dialog box, in Session 0. Because the user is not running in Session 0, he or she never sees the UI and therefore cannot provide the input that the service is looking for. The service appears to stop functioning because it is waiting for a user response that does not occur.
For example, if a device installer runs in Session 0 and the installation program creates a dialog box in Session 0 that requires user input to continue, the device installation never completes because the user does not see the dialog box. From the user’s perspective, the device installer is hung because it has stopped progressing and the user has no way to resume it.
· A service tries to use window message functions such as SendMessage and PostMessage to communicate with an application. This does not work because the application is running in a different session and therefore has a different message queue. The messages never arrive at their destination. The same is true for applications that try to communicate with services through window messages.
· Because services run in Session 0, named objects that they create or open are usually in \BaseNamedObjects\. However, if a user application assumes that it is running in the same session as the service and synchronizes with the service by creating or opening objects with the Local\ prefix (or no prefix, which defaults to Local\), the application no longer works as expected. The reason is that the Local\ prefix indicates that the create or open request is specific to that session and the objects that the application creates or opens are in \Sessions\<n>\BaseNamedObjects instead of \BaseNamedObjects\. The correct way for user applications to synchronize with a service is to explicitly use the Global\ prefix when the application creates or opens objects in \BaseNamedObjects\.
These implications for services are also exposed through FUS in Windows XP because every user on a FUS-enabled machine runs in a different session. Services that assume that the user is running in Session 0 encounter the same issues when the second user logs on to a FUS-enabled machine. However, services that were not fixed to work with FUS encounter problems in Windows Vista, Windows Server 2008, and later versions even if only one user is logged on.
并且给出了在此种情况下正确的service实现Guidelines:
In Windows Vista, Windows Server 2008, and later versions of Windows, drivers that are hosted within a service should follow these guidelines to work properly:
· Use a client/server mechanism such as remote procedure call (RPC) or named pipes rather than window messages to communicate with applications.
· Implement any necessary user interface for the service as follows:
· Use the WTSSendMessage function to create a simple message box on the user’s desktop. This allows the service to give the user a notification and request a simple response.
· For more complex interactions, developers should move their UI code into an agent that runs in the user’s session and handles all UI requirements. The agent communicates with the service through RPC or named pipes. If the user initiates the UI interaction by using Control Panel, Internet Explorer, or a similar UI experience, that UI experience should start the agent. The agent then handles all UI interactions. If UI is required but is not initiated by the user, the service must request the agent to start any required UI, instead of attempting to launch that UI by itself. In the rare situation where the service must initiate a user interaction and the agent is not already running, the service should call the CreateProcessAsUser API to start the agent. The agent can then initiate all UI interactions. It is important for developers to carefully review all possible usage scenarios and consider moving all UI code into an agent that runs in the user session.
· Query display properties in the user’s session, not in Session 0, because the resolution and color depth that are reported in Session 0 are unlikely to reflect the actual display properties.
· Explicitly choose either the Local\ or Global\ namespace for any named objects, such as events or mapped memory, that the service makes available. If an object must be accessible to user applications, it must be created in the Global\ namespace to be accessible to other sessions. The following Microsoft Win32® functions all accept named objects: OpenEvent, OpenMutex, OpenSemaphore, OpenWaitableTimer, OpenJobObject, and OpenFileMapping. Care should be taken when using these functions to ensure that the named object is accessible within the current session.
· Test the driver in Windows Vista, Windows 2008, or a later version to ensure that it runs properly. If that is not possible, test the driver in Windows XP with FUS enabled and multiple users logged on. If the driver works correctly for second and subsequent logged-on users, it is not likely to be affected by the Session 0 changes. The only issues that this test does not detect are those related to the absence of the video driver in Session 0.
那文档有没有针对我所碰到的问题(相信还有其他人也会碰到)给出work around呢,有的,那就是Interactive Service Detection Service,也就是之前我给出那幅crash截图,就是这所谓的Detection Service,其功效:
The service detects these visible dialog boxes or windows and sends a notification to the user. Users may choose to:
· Respond to the dialog box immediately by clicking a button to switch to Session 0, interact with the task dialog box, and then return to their session.
· Be reminded again in 5 minutes. They continue to be reminded until the dialog box closes.
但是根本不能让windbg继续调试下去,只不过提供了一个错误通知,而文档也说了,如此一来:
This helps ensure that testers are aware of legacy services in their environment and have the opportunity to contact the vendors for updated services.
我靠,高,实在是高,难不成还要联系windbg团队从新给我开发一个版本不成?但是你想啊,再牛逼的windbg也得有display窗口不。。。。黯然神伤了。。
正值绝望之际,一根救命稻草拂来,我得紧紧抓住它:来自Chris Jackson在MSDN上的blog一篇文章Debugging a Service on Windows Vista
链接:http://blogs.msdn.com/b/cjacks/archive/2006/12/12/debugging-a-service-on-windows-vista.aspx
Chris Jackson也碰到了同样恼人的问题,和我不同的是人家给出了可行方案:
Here is how you can set up and debug a service on Vista and have everything appear in your default desktop:
- Configure the service control manager to be a bit more patient. It likes to detect hung services and restart them, and if you are debugging you are intentionally hanging the service in the debugger and you don't want it restarted. So you can add a new DWORD value called ServicesPipeTimeout to HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control, and set the value as the number of milliseconds you want to configure the timeout for. Set this guy to 28,800,000 and you'll get 8 hours of interruption-free debugging. (Obviously, you probably want to set this back or remove it when you are done, because it's nice not to have hung services just stay hung for 8 hours.)
- Tell the SCM to start the debugger. But, instead of launching WinDBG, launch NTSD and set up a remote. In the registry again, configure HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Image File Execution Options \ <name of the service exe> \ Debugger, and instead of directly feeding it WinDBG, tell it to launch NTSD and set up a remote. On my machine, I have my debugging tools installed to c:\debuggers, so I provide the value of C:\Debuggers\ntsd.exe -server tcp:port=1234 -noio. (Any unused TCP port will do - pick your favorite.)
- Reboot the machine, so the SCM will pick up the new information.
- Attach WinDBG to the remote you now have running using windbg.exe -remote tcp:server=localhost,port=1234
- Start debugging!
soga!remote debugging!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
尝试了一把,成功!要注意的是如果是调试service 启动不了的情况,需要确保在service启动的时候using windbg.exe -remote tcp:server=localhost,port=1234,否则windbg将会出现server没有注册的错误。
关于Remote debugging with WinDbg and NTSD,还可以参见:http://www.debuginfo.com/articles/debugstartup.html