⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cb199910nt0602_f.asp.htm

📁 C++builder学习资料C++builder
💻 HTM
📖 第 1 页 / 共 5 页
字号:


<HTML>

  <HEAD>

 <TITLE>Writing NT Services</TITLE>

   

  </HEAD>

  <BODY>

 

<TABLE border=0 width="756" cellpadding=0 cellspacing=0>

<TR valign=top>

<TD width="10">



</TD>

<TD width="742">





<p class=ColumnTitle><font size="2">All 

Systems Go</font></p> 

 

<p class=ColumnSubtitle><font size="2">Windows 

NT / NT Services / Windows Registry</font></p> 

 

<p class=BodyText> &nbsp; </p> 

 

<p class=Byline><font size="2">By Kent  

Reisdorph</font></p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=StoryTitle><font size="2"><b>Writing  

NT Services</b></font></p>  

  

<p class=StorySubtitle><font size="2"><b>Part  

II:</b> Threads and Writing Interactive Services</font></p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=BodyText> In Part  

I, we began this series with a description of services and how they work under  

NT. In this installment, we'll begin by discussing how to write a simple  

service. We'll also try to understand the C++Builder-generated code for  

services, and talk about service threads and installing and testing services. </p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=Subheads>Writing a  

Simple Service</p>  

  

<p class=BodyText> The  

example program for this section is called BeepSrvc. This service does nothing  

more than beep the PC speaker once each second. A service that beeps every  

second (or some other interval) is sort of the "Hello World" of NT services.  

It's not exactly exciting, but it will show you how services work. The  

service's name is BeepService. The header and source for the BeepService unit  

is shown in Figures 1 and 2. </p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=Code><span class=Code><span Class=CodeGrn>#ifndef  

BeepSrvcUH</span></span></p>  

  

<p class=Code><span class=Code><span Class=CodeGrn>#define  

BeepSrvcUH</span></span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code><span Class=CodeGrn>#include  

&lt;SysUtils.hpp&gt; </span></span></p>  

  

<p class=Code><span class=Code><span Class=CodeGrn>#include  

&lt;Classes.hpp&gt; </span></span></p>  

  

<p class=Code><span class=Code><span Class=CodeGrn>#include  

&lt;SvcMgr.hpp&gt; </span></span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code><b>class</b>  

TBeepService : <b>public</b> TService</span></p>  

  

<p class=Code><span class=Code>{</span></p>  

  

<p class=Code><span class=Code><b>__published</b>:&nbsp;&nbsp;&nbsp;&nbsp;<i> <span Class=CodeBlue>// IDE-managed Components. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<b> void</b>  

<b>__fastcall</b> Service1Execute(TService  

*Sender); </span></p>  

  

<p class=Code><span class=Code><b>private</b>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> <span Class=CodeBlue>// User declarations. </span></i></span></p>  

  

<p class=Code><span class=Code><b>public</b>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i> <span Class=CodeBlue>// User declarations. </span></i></span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<b> __fastcall</b>  

TBeepService(TComponent* Owner); </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;PServiceController <b>__fastcall</b> GetServiceController(<b>void</b>);</span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<b> friend</b>  

<b>void</b> <b>__stdcall</b> ServiceController(<b>unsigned</b>  

CtrlCode); </span></p>  

  

<p class=Code><span class=Code>};</span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code><b>extern</b>  

PACKAGE TBeepService *BeepService; </span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code><span Class=CodeGrn>#endif</span></span></p>  

  

<p class=Captions><b>Figure  

1:</b> The header for  

the BeepService unit. </p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code><span Class=CodeGrn>#include  

&quot;BeepSrvcU.h&quot; </span></span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code><span Class=CodeGrn>#pragma  

package(smart_init) </span></span></p>  

  

<p class=Code><span class=Code><span Class=CodeGrn>#pragma  

resource &quot;*.dfm&quot; </span></span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code>TBeepService  

*BeepService; </span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code><b>__fastcall</b>  

TBeepService::TBeepService(TComponent* Owner) </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: TService(Owner) </span></p>  

  

<p class=Code><span class=Code>{</span></p>  

  

<p class=Code><span class=Code>}</span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code>PServiceController  

<b>__fastcall</b>  

TBeepService::GetServiceController(<b>void</b>)</span></p>  

  

<p class=Code><span class=Code>{</span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<b> return</b>  

(PServiceController) ServiceController; </span></p>  

  

<p class=Code><span class=Code>}</span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code><b>void</b> <b  

style='mso-bidi-font-weight:normal'>__stdcall</b> ServiceController(<b  

style='mso-bidi-font-weight:normal'>unsigned</b> CtrlCode) </span></p>  

  

<p class=Code><span class=Code>{</span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;BeepService-&gt;Controller(CtrlCode); </span></p>  

  

<p class=Code><span class=Code>}</span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code><b>void</b> <b  

style='mso-bidi-font-weight:normal'>__fastcall</b>  

TBeepService::Service1Execute(TService *Sender) </span></p>  

  

<p class=Code><span class=Code>{</span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<b> while</b>  

(!Terminated) </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;{ </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;MessageBeep(0); </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;Sleep(1000); </span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;&nbsp;&nbsp;ServiceThread-&gt;ProcessRequests(<b  

style='mso-bidi-font-weight:normal'>false</b>);</span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;} </span></p>  

  

<p class=Code><span class=Code>}</span></p>  

  

<p class=Captions><b>Figure  

2:</b> The source code  

for the BeepService unit. </p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=BodyText> As you  

can see from these listings, this simple service contains very little code.  

Most of the hard stuff is handled behind the scenes by the <i>TService</i> and <i>TServiceApplication</i>  

classes. In fact, I wrote only four lines of code for this service. The rest of  

the code was generated by C++Builder. I'll address the code generated by  

C++Builder in the following section. </p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=BodyText> This  

service uses default values for all of the service's properties except for the <i  

style='mso-bidi-font-style:normal'>Name</i> and <i>DisplayName</i> properties, both of which I have set to <i>BeepService</i>.            </p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=BodyText> This  

service uses the default values for all other properties, allowing the service  

to be stopped, paused, and continued from the SCP or by using one of the  

service command-line utilities. The defaults also specify that this is a Win32  

service, that it is not interactive (it cannot display a dialog box to the  

user), and that it is set to auto-start when NT boots. </p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=Subheads>Tip</p>  

  

<p class=BodyText> You will  

save yourself some headaches if you set the <i>Name</i>  

and <i>DisplayName</i> properties to the  

same value. In fact, you'll notice that when you set the <i>Name</i> property in the Object Inspector, the <i>DisplayName</i> property changes to match. It's easier to manage your  

service during development when both the <i>DisplayName</i>  

and <i>Name</i> have the same value. </p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=BodyText> When I  

first wrote this service, I set the <i>DisplayName</i>  

property to <i>BeepService </i>and the <i>Name</i>  

property to <i>BeepSrvc</i>. I then used the SC.EXE utility to start and stop  

the service. I typed the following from the command line: </p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=Code><span class=Code>sc stop  

BeepService</span></p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=BodyText> I kept  

getting an error from SC.EXE when using this syntax. It took me a couple of  

minutes to realize that I was passing the service's display name to SC.EXE when  

I should have been passing the service's actual name. The display name is  

simply the text that is displayed in the SCP for the service. The service name  

is the text that the SCM uses to refer to the service. The proper command-line  

syntax for stopping the service should have been the following: </p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=Code><span class=Code>sc stop  

BeepSrvc</span></p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=BodyText> By  

setting the <i>Name</i> and <i  

style='mso-bidi-font-style:normal'>DisplayName</i> properties to the same  

value, I eliminated the confusion caused by using two different values for  

these properties. </p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=Subheads>Understanding  

the C++Builder-generated Code for Services</p>  

  

<p class=BodyText> Before  

we get into what little code this service contains, I want to spend a moment  

discussing the code that C++Builder generates. You will find this code near the  

top of the main source unit: </p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=Code><span class=Code>PServiceController  

<b>__fastcall</b>  

TBeepService::GetServiceController(<b>void</b>)</span></p>  

  

<p class=Code><span class=Code>{</span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;<b> return</b>  

(PServiceController) ServiceController; </span></p>  

  

<p class=Code><span class=Code>}</span></p>  

  

<p class=Code><span class=Code>&nbsp; </span></p>  

  

<p class=Code><span class=Code><b>void</b> <b  

style='mso-bidi-font-weight:normal'>__stdcall</b> ServiceController(<b  

style='mso-bidi-font-weight:normal'>unsigned</b> CtrlCode) </span></p>  

  

<p class=Code><span class=Code>{</span></p>  

  

<p class=Code><span class=Code>&nbsp;&nbsp;BeepService-&gt;Controller(CtrlCode); </span></p>  

  

<p class=Code><span class=Code>}</span></p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=BodyText> Each  

service must have a function that processes service control requests. This  

function is commonly called the <i>service handler</i>. The service handler is  

registered with Windows by the <i>TService</i>  

class. As with many Windows callbacks, the service handler must be a standalone  

function. (It can't be a class member function.) The code you see here is the  

mechanism the VCL uses to implement the service handler. The implementation in  

SvcMgr.pas looks like this: </p>  

  

<p class=BodyText> &nbsp; </p>  

  

<p class=Code><span class=Code>FStatusHandle  

:= </span></p>  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -