?
Solved

How to programmatically launch a service on Windows 7?

Posted on 2010-04-06
8
Medium Priority
?
609 Views
Last Modified: 2012-05-09
On Windows XP, I have code to install and launch a service, and this code is very simple,
basically it is this:

    // Install
    HINSTANCE h1 = ShellExecute(NULL, _T("open"), "Mets", "-i", "C:\\Foo\\Dics", NULL);  
    Sleep(2000);
    // Start
    HINSTANCE h2 = ShellExecute(NULL, _T("open"), "Mets", "-s", "C:\\Foo\\Dics", NULL);  

This launches C:/Foo/Dics/Mets.exe to run as a service.

But this seems not to work on Windows 7.  The service does not start running.  It is a service
without a GUI.

So, how to do this for windows 7?  Ideally, one set of code that would work for both XP
and win7.  What am I missing?
0
Comment
Question by:tullhead
  • 4
  • 2
  • 2
8 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 29955117
Starting services is quite straightfoward on all Windows platforms using the Service Control Manager APIs. Take a look at http://www.codeproject.com/KB/system/serviceskeleton.aspx ("Beginner's introductory guide to writing, installing, starting, stopping NT services"). The scoop is to
void    MYSVCStartService   (   int                 argc, 
                                const wchar_t**     argv
                            )
{
    SC_HANDLE   schService;
    SC_HANDLE   schSCManager;

    schSCManager    =   OpenSCManager   (   NULL,                   // machine (NULL == local)
                                            NULL,                   // database (NULL == default)
                                            SC_MANAGER_ALL_ACCESS   // access required
                                        );
    if  (   schSCManager)
        {
            schService  =   OpenService (   schSCManager,
                                            TEXT    (   MYSVC_SERVICE_NAME), 
                                            SERVICE_ALL_ACCESS
                                        );

            if  (   schService)
                {
                    // try to start the service
                    if  (   StartService    (   schService, 
                                                argc, 
                                                argv 
                                            ) 
                        )
                        {
                            wprintf (   TEXT    (   "Starting %s."), 
                                        TEXT    (   MYSVC_SERVICE_DISPLAY_NAME)
                                    );

                            Sleep   (   1000 );

                            while   (   QueryServiceStatus  (   schService, 
                                                                &g_ssStatus
                                                            )
                                    )
                                    {
                                        if  (       SERVICE_START_PENDING   
                                                ==  g_ssStatus.dwCurrentState
                                            )
                                            {
                                                wprintf (   TEXT    (   "."));
                                                Sleep( 1000 );
                                            }
                                        else
                                                break;
                                    }

                            if  (   SERVICE_RUNNING ==  g_ssStatus.dwCurrentState)
                                    wprintf (   TEXT    (   "\n%s started.\n"), 
                                                TEXT    (   MYSVC_SERVICE_DISPLAY_NAME)
                                            );
                            else
                                    wprintf (   TEXT    (   "\n%s failed to start.\n"), 
                                                TEXT    (   MYSVC_SERVICE_DISPLAY_NAME)
                                            );

                        }

                CloseServiceHandle  (   schService);
            }
            else
                wprintf (   TEXT    (   "OpenService failed - %s\n"),
                            GetLastErrorText    (   g_szErr,    MYSVC_ERROR_BUFSZ)
                        );

            CloseServiceHandle  (   schSCManager);
        }
    else
            wprintf (   TEXT    (   "OpenSCManager failed - %s\n"), 
                        GetLastErrorText    (   g_szErr,    MYSVC_ERROR_BUFSZ)
                    );
}



void    MYSVCStopService    ()
{
    SC_HANDLE   schService;
    SC_HANDLE   schSCManager;

    schSCManager    =   OpenSCManager   (   NULL,                   // machine (NULL == local)
                                            NULL,                   // database (NULL == default)
                                            SC_MANAGER_ALL_ACCESS   // access required
                                        );
    if  (   schSCManager)
        {
            schService  =   OpenService (   schSCManager,
                                            TEXT    (   MYSVC_SERVICE_NAME), 
                                            SERVICE_ALL_ACCESS
                                        );

            if  (   schService)
                {
                    // try to stop the service
                    if  (   ControlService  (   schService, 
                                                SERVICE_CONTROL_STOP, 
                                                &g_ssStatus 
                                            ) 
                        )
                        {
                            wprintf (   TEXT    (   "Stopping %s."), 
                                        TEXT    (   MYSVC_SERVICE_DISPLAY_NAME)
                                    );

                            Sleep   (   1000 );

                            while   (   QueryServiceStatus  (   schService, 
                                                                &g_ssStatus
                                                            )
                                    )
                                    {
                                        if  (       SERVICE_STOP_PENDING    
                                                ==  g_ssStatus.dwCurrentState
                                            )
                                            {
                                                wprintf (   TEXT    (   "."));
                                                Sleep( 1000 );
                                            }
                                        else
                                                break;
                                    }

                            if  (   SERVICE_STOPPED ==  g_ssStatus.dwCurrentState)
                                    wprintf (   TEXT    (   "\n%s stopped.\n"), 
                                                TEXT    (   MYSVC_SERVICE_DISPLAY_NAME)
                                            );
                            else
                                    wprintf (   TEXT    (   "\n%s failed to stop.\n"), 
                                                TEXT    (   MYSVC_SERVICE_DISPLAY_NAME)
                                            );

                        }

                CloseServiceHandle  (   schService);
            }
            else
                wprintf (   TEXT    (   "OpenService failed - %s\n"),
                            GetLastErrorText    (   g_szErr,    MYSVC_ERROR_BUFSZ)
                        );

            CloseServiceHandle  (   schSCManager);
        }
    else
            wprintf (   TEXT    (   "OpenSCManager failed - %s\n"), 
                        GetLastErrorText    (   g_szErr,    MYSVC_ERROR_BUFSZ)
                    );
}

Open in new window

0
 
LVL 49

Accepted Solution

by:
DanRollins earned 2000 total points
ID: 29961388
Did you try that sequence as an administrator?
Open a DOS box:  And start it as an administrator (right-click the shortcut and choose "Run As administrator"
Then type those commands.
0
 

Author Comment

by:tullhead
ID: 29967297
So there is nothing particular about win7 ?    I've got 500 customer installs on XP with no reports of issues, and 2 win7 users today with this issue.  Hmmmm.....  so I thought it must be a win7 thing.
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 

Author Comment

by:tullhead
ID: 29967602
jkr - what are argc and argv used for here?  and what is MYSVC_SERVICE_NAME ?  The service itself is something that I wrote and I have available as an *.exe file.
0
 
LVL 86

Expert Comment

by:jkr
ID: 29969830
The service name is just a string literal, so that could just be

#define MYSVC_SERVICE_NAME _T("MyService")

BTW, the same for all the other constants here (took that sample out of production code). But, Dan has a good point, it might be a permission problem.

Oh, and both 'argc' and 'argv' are just passed through to 'StartService()', nothing fancy.
0
 

Author Comment

by:tullhead
ID: 29972274
Jkr & Dan ---

OK, I have 3 *.exe - one which "launches" the service, one that "kills" the service, and the service
itself.  In win7 I went in, right clicked, set each of these 3 to "Run as Administrator", and now it works.
Reboot the computer, the service starts on its own as it should.  So, I guess thats it!  Mystery solved.

So, I'm still a little confused about the fact that I can just use "ShellExecute" with the -i and -s option
to do all this, but I see various code (like what jkr posted) which uses other "fancy" commands such as
OpenSCManager and OpenService -- these sound like the sort of stuff that perhaps I should be using!
But it works with my simple code.... should I learn about "OpenService" etc?
0
 

Author Comment

by:tullhead
ID: 29972399
I guess I give the points to Dan, but thanks also JKR!
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 29977393
The -i is telling the program (the service) to install itself
The -s is telling the program (the service) to start itself.
Both actions are adminstrative-level operations in Win7 (as are the API functions described by jkr).  
With Win7, a lot of things that could previously be done by just anyone (such as using Spy++ or Regedit) are now flagged as "too dangerous for regular folks")
0

Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

IF you are either unfamiliar with rootkits, or want to know more about them, read on ....
Unable to change the program that handles the scan event from a network attached Canon/Brother printer/scanner. This means you'll always have to choose which program handles this action, e.g. ControlCenter4 (in the case of a Brother).
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The Task Scheduler is a powerful tool that is built into Windows. It allows you to schedule tasks (actions) on a recurring basis, such as hourly, daily, weekly, monthly, at log on, at startup, on idle, etc. This video Micro Tutorial is a brief intro…

598 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question