About using BCB6 to compile Windows Services

Source: Internet
Author: User
Tags service flag

The previous day, due to system issues, we had to re-open Borland C ++ Builder 6, which had not been used for a long time, and compile a Windows service. The original idea is to write something that can set such as the service name, display name, description, and configuration file path based on the specified parameters, and use a service program as the shell of a variety of different service content, it can be separately controlled in the Windows Service Manager. Because BCB service templates are not customized, you need to pay a weekly discount.

 

The service objects implemented by users in BCB are inherited from TService, which is tentatively set to TMyService. When a Global Object Svrmgr: Application (TServiceApplication) is used to create a service object, the user's service object is automatically one of the Application components.

Generally, you can create a service object as follows:

  1. Application-> CreateForm (_ classid (TMyService), & MyService );

BCB SvrMgr. hpp is actually a Statement of Delphi implementation. View SvrMgr. pas. You can see the code for creating the service:

  1. Svc: = CreateService (SvcMgr,
  2. PChar (Name), // <TMyService-> Name is used as the service Name
  3. PChar (DisplayName), // <TMyService-> DisplayName is used as the display name
  4. SERVICE_ALL_ACCESS,
  5. GetNTServiceType,
  6. GetNTStartType,
  7. GetNTErrorSeverity,
  8. PChar (Path ),
  9. PChar (LoadGroup ),
  10. PTag,
  11. PChar (GetNTDependencies ),
  12. PSSN,
  13. PChar (Password ));

We can see that when the/install parameter is used to register a service, BCB uses the Name attribute of TMyService as the service Name and DisplayName as the service display Name. To customize these two names, we can add additional parameters:/name and/displayname, which are used to specify the service name and service display name respectively. Example:

 

MyService/install/name: "ThisIsAnotherService"/displayname: "display name"

 

/Name and/displayname are followed by a ":" to separate the subsequent strings. During Parameter Parsing, the system treats the strings in double quotation marks as a whole. If you do not know this and have different opinions on the quotation marks, please refer to the help provided by Windows: command prompt.

 

BCB only processes the/install and/uninstall parameters. The added parameters must be processed by yourself. Here, two BCB functions are used: ParamCount () and ParamStr (), for more information, see BCB Help. The following is the sample code:

 

 

 

  1. Bool isInstall = FindCmdLineSwitch ("install", true); // install the service flag
  2. Bool isUninstall = FindCmdLineSwitch ("uninstall", true); // uninstall the service flag
  3. AnsiString serviceName; // service name
  4. AnsiString serviceDispName; // service display name
  5. If (ParamCount ()> 1 & (isInstall | isUninstall) // specify the parameters and the installation and uninstall flag.
  6. {
  7. // Create it first
  8. Application-> CreateForm (_ classid (TMyService), & MyService );
  9. If (isInstall | isUninstall) // for installation or uninstall
  10. {
  11. For (int I = 1; I <= ParamCount (); I ++) // process all parameters cyclically
  12. {
  13. AnsiString param = ParamStr (I). LowerCase (); // converts the string to LowerCase for ease of comparison.
  14. Int pos; // parameter location
  15. If (param. Pos ("/name:") // match the service name: "/name: xxxxx"
  16. {
  17. Pos = param. Pos (":");
  18. ServiceName = param. SubString (pos + 1, param. Length ()-pos );
  19. If (pos = serviceName. Pos ("")> 0) // Delete spaces. This is not necessary. The system will point out that the name is invalid.
  20. {
  21. ServiceName. Delete (pos, 1 );
  22. }
  23. }
  24. Else
  25. If (param. Pos ("/dispname:") // match the service display name: "/serviceDispName: xxxxx"
  26. {
  27. Pos = param. Pos (":");
  28. Servicedispname = Param. substring (Pos + 1, Param. Length ()-Pos );
  29. }
  30. }
  31. If (servicename. Length ()> 0)
  32. Application-> components [0]-> name = servicename; // use the specified service name
  33. Else
  34. Servicename = Application-> components [0]-> name; // The default name of tmyservice: myservice is used if no service name is specified.
  35. If (serviceDispName. Length () = 0)
  36. ServiceDispName = serviceName; // if no display name is specified, use the service name instead.
  37. (TService *) Application-> Components [0])-> DisplayName = serviceDispName; // set the display name
  38. }
  39. }
  40. Application-> Run (); // <The service starts to Run

Now, compile and register our service. We can see that it is displayed in the service list in the specified way. Let's try to start it ...... And so on ..... Startup failed !!!! OOOOOOOH! SHIT !!!!!

Click here !?!?

 

Let's check SvrMgr. pas, BCB (or Delphi ?) To start the service:

 

 

 

  1. //.....
  2. Begin
  3. Forms. Application. OnException: = OnExceptionHandler; // exception handle
  4. ServiceCount: = 0; // number of service objects (TXXXService)
  5. For I: = 0 to componentcount-1 do // The number of components contained in the application is the number of service objects
  6. If components [I] Is tservice then Inc (servicecount );
  7. Setlength (servicestarttable, servicecount + 1); // you can specify the size of the Service Startup table.
  8. Fillchar (servicestarttable [0], sizeof (tservicetableentry) * (servicecount + 1), 0); // clear
  9. J: = 0;
  10. For I: = 0 to componentcount-1 do // fill in the service entry table
  11. If components [I] Is tservice then
  12. Begin
  13. ServiceStartTable [J]. lpServiceName: = PChar (Components [I]. Name); // The Name attribute is used here!
  14. ServiceStartTable [J]. lpServiceProc: = @ ServiceMain; // For the ServiceMain entry function, see Windows SDK help
  15. Inc (J );
  16. End;
  17. StartThread: = TServiceStartThread. Create (ServiceStartTable); // start the service
  18. //.....
  19. // TServiceStartThread thread function implementation
  20. Procedure TServiceStartThread. Execute;
  21. Begin
  22. If StartServiceCtrlDispatcher (FServiceStartTable [0]) then // use the service entry table to start the service
  23. ReturnValue: = 0
  24. Else
  25. Returnvalue: = getlasterror;
  26. End;

Windows API StartServiceCtrlDispatcher () uses the service entry table to start the service. This operation is name-related, and we have used the specified name to install the service. Therefore, when the system (TServiceApplication) when you use the original name (MyService here) to start the service, the service named MyService cannot be found (we have specified its name as ThisIsAnotherService), leading to startup failure. Because the system does not provide a context about the service name when starting the service, we need to create this context. A simple method is to modify the Service Startup path record and add the service name as a parameter when installing the service. When the service starts, parse this parameter and use this parameter to modify TMyService-> Name, so that the service can be started smoothly. The sample code is as follows:

 

Add additional parameters and save the service name:

 

  1. //.......
  2. Application-> Run ();
  3. // After running, the service has been successfully installed.
  4. If (isinstall)
  5. {
  6. // The simplest method is the hack registry.
  7. Tregistry * Reg = new Tregistry ();
  8. Ansistring key = "// system // CurrentControlSet // services //" + servicename; // registry path
  9. Reg-> rootkey = HKEY_LOCAL_MACHINE;
  10. If (reg-> openkey (Key, false) // open the referral
  11. {
  12. Ansistring ImagePath = reg-> readstring ("ImagePath"); // describes the path of the program image.
  13. Reg-> writestring ("ImagePath", ImagePath + "-" + servicename); // Add an additional parameter: Service name.
  14. }
  15. Reg-> closekey ();
  16. Delete reg;
  17. } // If isinstall then hack Registry

Then add the parameter processing:

  1. If (paramcount ()> 1 & (isinstall | isuninstall ))
  2. {
  3. //......
  4. }
  5. Else // start if it is not installed
  6. {
  7. // Check the number of parameters
  8. If (ParamCount ()> 0)
  9. {
  10. AnsiString extraParam = ParamStr (1). LowerCase (); // extra parameter, converted to lower case
  11. AnsiString specifiedServiceName;
  12. If (extraParam. Pos ("-") // locate "-"
  13. {
  14. Int pos = extraParam. Pos ("-");
  15. SpecifiedServiceName = extraParam. SubString (pos + 1, extraParam. Length ()-pos); // parse the service name
  16. }
  17. If (! SpecifiedServiceName. Length () // if the name is invalid, use the default name: MyService
  18. {
  19. Application-> CreateForm (_ classid (TMyService), & MyService); // use the default name
  20. }
  21. Else
  22. {
  23. Application-> CreateForm (_ classid (TMyService), & MyService );
  24. MyService-> Name = specifiedServiceName; // use the specified Name
  25. }
  26. }//
  27. } // If... else
  28. //...
  29. Application-> Run ();
  30. //...

 

Now, compile the program, reinstall the service, and try again to start ......

If there is no error, the Service should be able to start smoothly. (Nonsense)

 

BCB does not provide the description attribute of the service, which can be implemented by modifying the registry. The operation is very simple.

 

This is the final technique .....

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.