Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Запуск внешней программы (pscp) из службы Windows не работает

Автор вопроса: Augusto CaringiОтветов: 4

Я пишу службу Windows на C ++ (Visual Studio 2010), и эта служба должна отправлять файл на удаленный сервер через безопасную копию (для этого я использую pscp.exe).

Итак, я использую функцию system для запуска pscp.exe, и при запуске в качестве обычного приложения все работает нормально.

Но если я пытаюсь запустить как службу, служба запускает pscp.exe (я вижу это в диспетчере задач), но pscp.exe зависает и ничего не отправляет на удаленный хост. И даже если я остановлю службу, мне придется самому убить процесс pscp.

Я читал на некоторых форумах, чтобы разрешить службе "взаимодействовать с рабочим столом", но это не решило мою проблему.

Я также попытался изменить учетную запись пользователя, с которой служба входит в систему, но безрезультатно.

Любые идеи?

Кажется, что очень сложно запустить внешнюю программу из службы Windows, даже если эта внешняя программа не имеет графического интерфейса пользователя, например pscp.exe.

Спасибо!

- Аугусто Каринги

  • Какую учетную запись вы пытаетесь использовать? Большинство служб работают как локальная система. Очевидно, этого недостаточно для pscp, если он должен подключаться к удаленному хосту. MSalters 10.12.2010

c++windows-servicesexternal-process

Ответы

Ответ 1 · Steve Townsend

Каковы ваши варианты pscp вызова? Если есть опция "без звука", используйте ее, чтобы избежать взаимодействия с консолью. Часто это -q или /q.

Имейте в виду, что любое запущенное приложение будет работать под той же учетной записью, что и ваша служба. Есть ли у этой учетной записи разрешения делать то, что вы от нее просите? Правильный ли контекст (каталог выполнения, путь) для pscp, чтобы делать то, что вы хотите?

Ответ 2 · Raiv

Вы можете попробовать использовать олицетворение. Что-то вроде этого...

    wchar_t* cmPath=readRegistryString(L"Software\\" TO_WCHAR(ORG_NAME) L"\\" TO_WCHAR(APP_NAME) L"\\" TO_WCHAR(APPLICATION_GROUP),TO_WCHAR(APPLICATION_EXEC_PATH));
if (!cmPath)
{
    return false;
}
HANDLE userToken=NULL;
DWORD sessId=WTSGetActiveConsoleSessionId ();
if((long)sessId==-1)
{
    sessId=0;
}
WTSQueryUserToken (sessId, &userToken);
bool result=false;
if(userToken/**/ )
{
    SECURITY_ATTRIBUTES sa;
    ZeroMemory(&sa,sizeof(SECURITY_ATTRIBUTES));
    sa.nLength=sizeof(SECURITY_ATTRIBUTES);
    STARTUPINFOW si;
    ZeroMemory(&si,sizeof(STARTUPINFOW));
    si.cb=sizeof(STARTUPINFOW);
    PROCESS_INFORMATION pi;
    ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
    CStringW str= L"\"";
    str=str+cmPath;
    str=str+L"\"";
    str.Replace(L"/",L"\\");

    if(CreateProcessAsUserW(userToken,NULL,str.GetBuffer(),NULL,NULL,false,NULL,NULL,NULL,&si,&pi))
    {
            result=true;
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
    }
    else
    {
        DWORD err = GetLastError();
        //nop;
    }
}
if(userToken)
    CloseHandle(userToken);
delete[] cmPath;

этот фрагмент кода я использую для вызова приложения с графическим интерфейсом пользователя из службы, но я думаю, что для консольного приложения особых изменений не требуется.

Ответ 3 · Alain

Вам следует запускать ваше приложение pscp, используя функцию CreateProcess, а не system. Последний передает вашу команду интерпретатору команд (cmd.exe), который может быть недоступен из службы.

Ответ 4 · Augusto Caringi

Я исправил проблему!

pscp.exe не работает при запуске из службы. Не знаю почему.

Но curl.exe (из libcurl) поддерживает безопасное копирование!

Спасибо.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы