How to programmatically launch a service on Windows 7?

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?
tullheadAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
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
DanRollinsCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
tullheadAuthor Commented:
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
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

tullheadAuthor Commented:
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
jkrCommented:
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
tullheadAuthor Commented:
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
tullheadAuthor Commented:
I guess I give the points to Dan, but thanks also JKR!
0
DanRollinsCommented:
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Windows 7

From novice to tech pro — start learning today.