Re[3]: А как заставить MSI перезапускать сервис уже имеющийс
От: Rothmans  
Дата: 09.08.06 07:45
Оценка: 12 (2)
Здравствуйте, nesesser, Вы писали:


N>Я не работал с Wix, но в целом ситуаця видится так — выше в ветке был приведен очень полезный пример кода на VBS, который получает собственно процессы-сервисы системы.

N>Нужно код оформить в виде Custom Action.
N>В CA делаете так: првоеряете наличие нужного сервиса. Если есть, то objService.StopService. А далее должно пройти хорошо, по вашим словам.

Работа с сервисами через WMI, насколько я понимаю, далеко не лучшее решение просто потому что WMI должно быть сперва установлено и сконфигурировано отдельно, поправьте, если я ошибаюсь.
Для остановки/запуска сервиса вполне достаточно следующих функций:

DWORD stopService(LPCTSTR lpszServiceName)
{
    DWORD dwRet = ERROR_SUCCESS;
    SC_HANDLE hSCM;
    SC_HANDLE schSpooler;
    SERVICE_STATUS_PROCESS ssStatus;
    SERVICE_STATUS ss;
    DWORD dwBytesNeeded;
    DWORD dwStartTime = GetTickCount();
    DWORD dwTimeout = 10000; // was 30000
    DWORD dwWaitTime;
    __try
    {
        if ( !(hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT )) ) 
        {
            OUTPUT_SYSTEM_ERROR()
            dwRet = GetLastError();
            __leave;
        }

        schSpooler = OpenService(hSCM,lpszServiceName,SERVICE_ALL_ACCESS /*SERVICE_STOP | SERVICE_QUERY_STATUS*/);
        if(schSpooler == NULL)
        {
            OUTPUT_SYSTEM_ERROR()
            dwRet = SPOOLER_NO_SERVICE;
            __leave;
        }

        if(!QueryServiceStatusEx(schSpooler
            ,SC_STATUS_PROCESS_INFO
            ,(LPBYTE) &ssStatus
            ,sizeof(SERVICE_STATUS_PROCESS)
            ,&dwBytesNeeded))
        {
            OUTPUT_SYSTEM_ERROR()
            dwRet = SPOOLER_NO_SERVICE;
            __leave;
        }
        if ( ssStatus.dwCurrentState == SERVICE_STOPPED ) 
        {
            dwRet = SPOOLER_SUCCESS;
            __leave;
        }

        if( !ControlService( schSpooler, SERVICE_CONTROL_STOP, &ss ) )
        {
            OUTPUT_SYSTEM_ERROR()
            dwRet = GetLastError();
            __leave;
        }
        ssStatus.dwCurrentState = ss.dwCurrentState;
        ssStatus.dwWaitHint = ss.dwWaitHint;
        while ( ssStatus.dwCurrentState != SERVICE_STOPPED ) 
        {
            // Do not wait longer than the wait hint. A good interval is 
            // one tenth the wait hint, but no less than 1 second and no 
            // more than 10 seconds. 
            dwWaitTime = ssStatus.dwWaitHint / 10;

            if( dwWaitTime < 1000 )
                dwWaitTime = 1000;
            else if ( dwWaitTime > 10000 )
                dwWaitTime = 10000;

            Sleep( dwWaitTime );
            if ( !QueryServiceStatusEx( 
                    schSpooler, 
                    SC_STATUS_PROCESS_INFO,
                    (LPBYTE)&ssStatus, 
                    sizeof(SERVICE_STATUS_PROCESS),
                    &dwBytesNeeded ) )
            {
                dwRet = GetLastError();
                __leave;
            }
            if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
                break;

            if ( GetTickCount() - dwStartTime > dwTimeout )
            {
                dwRet = SPOOLER_ERROR_TIMEOUT;
                __leave;
            }
        }
    }
    __finally
    {
        if ( schSpooler )
            CloseServiceHandle( schSpooler );
        if ( hSCM )
            CloseServiceHandle( hSCM );
    }
    return dwRet;
}

DWORD startService(LPCTSTR lpszServiceName)
{
    DWORD dwRet = SPOOLER_SUCCESS;
    SC_HANDLE hSCM;
    SC_HANDLE schSpooler;
    SERVICE_STATUS_PROCESS ssStatus;
    DWORD dwWaitTime;
    DWORD dwStartTime = GetTickCount();
    DWORD dwTimeout = 10000; // was 30000
    DWORD dwBytesNeeded;
    __try
    {
        if ( !(hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT )) ) 
        {
            OUTPUT_SYSTEM_ERROR()
            dwRet = GetLastError();
            __leave;
        }

        schSpooler = OpenService(hSCM,lpszServiceName,SERVICE_ALL_ACCESS);
        if(schSpooler == NULL)
        {
            OUTPUT_SYSTEM_ERROR()
            dwRet = SPOOLER_NO_SERVICE;
            __leave;
        }

        if (!StartService(schSpooler, 0, NULL) )
        {
            dwRet = SPOOLER_NO_SERVICE; 
            __leave;
        }
        
        if (!QueryServiceStatusEx( 
                schSpooler,             // handle to service 
                SC_STATUS_PROCESS_INFO, // info level
                (LPBYTE)&ssStatus,               // address of structure
                sizeof(SERVICE_STATUS_PROCESS), // size of structure
                &dwBytesNeeded ) )              // if buffer too small
        {
            dwRet = SPOOLER_NO_SERVICE; 
            __leave;
        }
        while (ssStatus.dwCurrentState != SERVICE_RUNNING) 
        { 
            // Do not wait longer than the wait hint. A good interval is 
            // one tenth the wait hint, but no less than 1 second and no 
            // more than 10 seconds. 
            dwWaitTime = ssStatus.dwWaitHint / 10;

            if( dwWaitTime < 1000 )
                dwWaitTime = 1000;
            else if ( dwWaitTime > 10000 )
                dwWaitTime = 10000;

            Sleep( dwWaitTime );
            // Check the status again. 
             if (!QueryServiceStatusEx( 
                schSpooler,             // handle to service 
                SC_STATUS_PROCESS_INFO, // info level
                (LPBYTE)&ssStatus,               // address of structure
                sizeof(SERVICE_STATUS_PROCESS), // size of structure
                &dwBytesNeeded ) )              // if buffer too small
            {
                dwRet = SPOOLER_NO_SERVICE; 
                __leave;
            }
    
            if(ssStatus.dwCurrentState == SERVICE_STOPPED || ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
                if (!StartService(schSpooler, 0, NULL) )
                {
                    dwRet = SPOOLER_NO_SERVICE; 
                    __leave;
                }
     
            if ( GetTickCount() - dwStartTime > dwTimeout )
            {
                // No progress made within the wait hint
                break;
            }
        } 
        if (ssStatus.dwCurrentState == SERVICE_RUNNING) 
            dwRet = SPOOLER_SUCCESS;
        else 
            dwRet = SPOOLER_NOT_STARTED;
    }
    __finally
    {
        if(schSpooler)
            CloseServiceHandle(schSpooler); 
        if(hSCM)
            CloseServiceHandle(hSCM); 
    }
    return dwRet;
}

BOOL checkServiceRunning(LPCTSTR lpszServiceName)
{
    return getServiceStatus(lpszServiceName) == SERVICE_RUNNING;
}

DWORD getServiceStatus(LPCTSTR lpszServiceName)
{
    DWORD dwRet = 0;
    SC_HANDLE hSCM;
    SC_HANDLE schService;
    SERVICE_STATUS_PROCESS ssStatus;
    DWORD dwBytesNeeded;
    __try
    {
        if ( !(hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT )) ) 
        {
            __leave;
        }

        schService = OpenService(hSCM,lpszServiceName,SERVICE_QUERY_STATUS);
        if(schService == NULL)
        {
            __leave;
        }

        if(!QueryServiceStatusEx(schService
            ,SC_STATUS_PROCESS_INFO
            ,(LPBYTE) &ssStatus
            ,sizeof(SERVICE_STATUS_PROCESS)
            ,&dwBytesNeeded))
        {
            __leave;
        }
        dwRet = ssStatus.dwCurrentState;
    }
    __finally
    {
        if ( schService )
            CloseServiceHandle( schService );
        if ( hSCM )
            CloseServiceHandle( hSCM );
    }
    return dwRet;
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.