Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Windows specifics

Setup for Windows Service
Multi-Service Process
Unicode on Services

Boost.Application have some specifics on each side, here the user that uses Windows system need be aware.

In this version the library don’t provide official support for "service or daemon" installation. This is because we need maintain symmetry between functionality provided on all platforms that the lib support, and on POSIX side, the installation process varies a lot. Thus the library provide installation functionality for major system as sample on examples folder. In future we have plan to bring these functionality to core library.

[Note] Note

For POSIX you need use some shell script to control a daemon, refer to:

\example\setup\posix\ubuntu

That has some samples from Ubuntu.

On Window we will use this sample code:

\example\setup\windows\setup\service_setup.hpp

Boost.Application provides a setup code, that can be added to to enable installation/uninstallation of windows service application.

class windows_service_setup
{
public:

   windows_service_setup(application::context& context)
      : context_(context)
   {
   }

   int operator()()
   {

#if !defined(__MINGW32__)

      std::cout << "Setup Windows Service "
         << "(Note that you need run this AS ADMIN!)" << std::endl;

      boost::shared_ptr<application::args> myargs
         = context_.find<application::args>();

      // define our simple installation schema options
      po::options_description install("service options");
      install.add_options()
         ("help", "produce a help message")
         (",i", "install service")
         (",c", "check service")
         (",u", "unistall service")
         ("path", po::value<std::string>(), "service path")
         ("name", po::value<std::string>(), "service name")
         ("user", po::value<std::string>()->default_value(""), "user logon (optional, installation only)")
         ("pass", po::value<std::string>()->default_value(""), "user password (optional, installation only)")
         ("display", po::value<std::string>()->default_value(""), "service display name (optional, installation only)")
         ("description", po::value<std::string>()->default_value(""), "service description (optional, installation only)")
         ;

      po::variables_map vm;
      po::store(po::parse_command_line(myargs->argc(), myargs->argv(), install), vm);
      boost::system::error_code ec;

      if (vm.count("help"))
      {
         std::cout << install << std::cout;
         return true;
      }

      if (vm.count("-i"))
      {
         std::string s = vm["name"].as<std::string>();
         application::example::install_windows_service(
         application::setup_arg(vm["name"].as<std::string>()),
         application::setup_arg(vm["display"].as<std::string>()),
         application::setup_arg(vm["description"].as<std::string>()),
         application::setup_arg(vm["path"].as<std::string>()),
         application::setup_arg(vm["user"].as<std::string>()),
         application::setup_arg(vm["pass"].as<std::string>())).install(ec);

         std::cout << ec.message() << std::endl;

         return true;
      }

      if (vm.count("-c"))
      {
         bool exist =
         application::example::check_windows_service(
            application::setup_arg(vm["name"].as<std::string>())).exist(ec);

         if(ec)
           std::cout << ec.message() << std::endl;
         else
         {
            if(exist)
               std::cout
                  << "The service "
                  << vm["name"].as<std::string>()
                  <<  " is installed!"
                  << std::endl;
            else
               std::cout
                  << "The service "
                  << vm["name"].as<std::string>()
                  <<  " is NOT installed!"
                  << std::endl;
         }

         return true;
      }

      if (vm.count("-u"))
      {
         application::example::uninstall_windows_service(
            application::setup_arg(vm["name"].as<std::string>()),
            application::setup_arg(vm["path"].as<std::string>())).uninstall(ec);
			
         std::cout << ec.message() << std::endl;

         return true;
      }

#endif

      return 0;
   }

private:
   application::context& context_;

};

int main(int argc, char *argv[])
{
   try
   {
      application::context app_context;
      windows_service_setup app(app_context);

      app_context.insert<application::args>(
         boost::make_shared<application::args>(argc, argv));

      return application::launch<application::common>(app, app_context);
   }
   catch(boost::system::system_error& se)
   {
      std::cerr << se.what() << std::endl;
      return 1;
   }
   catch(std::exception &e)
   {
      std::cerr << e.what() << std::endl;
      return 1;
   }
   catch(...)
   {
      std::cerr << "Unknown error." << std::endl;
      return 1;
   }

   return 0;
}

This example shows how to use windows service setup module to provide a installation system to application using program_options.

Installation
windows_service_setup.exe -i --name "My Service" --path "c:\myservice\service.exe"
windows_service_setup.exe -i --name "My Service" --path "c:\myservice\service.exe" --display "My Service"
windows_service_setup.exe -i --name "My Service" --path "c:\myservice\service.exe" --display "My Service" --description "Service Description"

Check Installation
windows_service_setup.exe -c --name "My Service"

Uninstallation
windows_service_setup.exe -u --name "My Service" --path "c:\myservice\service.exe"
[Important] Important

To install service you need have permission to do that. An easy way is execute installation as Admin.

[Note] Note

Note that when arg name are not priovided, the name will be the name of executable, in this case, service name will be: 'windows_service_setup'

[Note] Note

Note that you can provide “user login” to install the service for a specific Windows User.

windows_service_setup.exe -i --name "My Service" --path "c:\myservice\service.exe" --display "My Service" --description "Service Description" --user "Renato Forti" --pass "1c2c3c"

[Tip] Tip

The sample 'simple_server application.cpp' has the setup code embed on it. This shows a way to incorporate all required code into a single executable.

By definition, each Win32 service process can contain one or more services, running on separate threads.

Note that Boost.Application do not support more than one service at one executable. This limitation is imposed to maintain symmetry between Windows and POSIX sides.

Boost.Application supports both Unicode and ANSI char types to develop a server (service) mode application, but is highly recommended that you use Unicode.

Windows has two versions of every API function that takes a string parameter, one for wide chars that name ends with W, and another that name ends with A for ANSI. The native call is for 'W' functions, while the 'A' version function simply ends up calling the 'W' function.

Uing ANSI therefore makes extra function call, and aditional string conversion overhad.

To know how Boost.Application handle Unicode, refer to FAQ


PrevUpHomeNext