Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: служба+GUI  (Прочитано 37760 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« : 13-09-2016 07:07 » 

насколько я понял, в винде 7 из службы невозможно отобразить окно напрямую ?

Или это особенности Qt-шной реализации (пробую кутешное GUI-приложение запустить как службу через QtService)

Если это так, то как там окна, скажем, для настроек или мониторинга отображаются ?

Сама служба вроде работает
« Последнее редактирование: 13-09-2016 07:10 от Алексей++ » Записан

zubr
Гость
« Ответ #1 : 13-09-2016 07:48 » 

Алексей++, 2 варианта:
1. Сделать сервис интерактивным. Для этого в процедуре сервиса надо указать тип SERVICE_INTERACTIVE_PROCESS
   функция SetServiceStatus
2. Из сервиса запустить ГУИ-процесс. CreateProcessAsUser
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 13-09-2016 12:44 » 

zubr,
1 - в исходниках Qt вроде они так и указали
Код:
bool QtServiceBasePrivate::sysInit()
{
    sysd = new QtServiceSysPrivate();

    sysd->serviceStatus     = 0;
    sysd->status.dwServiceType     = SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
    sysd->status.dwCurrentState     = SERVICE_STOPPED;
    sysd->status.dwControlsAccepted         = sysd->serviceFlags(serviceFlags);
    sysd->status.dwWin32ExitCode     = NO_ERROR;
    sysd->status.dwServiceSpecificExitCode  = 0;
    sysd->status.dwCheckPoint     = 0;
    sysd->status.dwWaitHint     = 0;

    return true;
}

так что это не прокатывает, похоже

2 - тоже так подумал. Служба будет запускать процесс, если он не запущен


спасибо

Добавлено через 6 минут и 48 секунд:
ещё вот нашёл

https://msdn.microsoft.com/en-us/library/windows/desktop/ms683502(v=vs.85).aspx

флаг в реестре глянул - там 0, но всё равно не показывается окно . Но даже если  было бы значение 1, то ковыряться в чужом реесте, полагаю, было бы лишнее ))  Так что вариант №2 буду пробовать
« Последнее редактирование: 13-09-2016 12:51 от Алексей1153 » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 15-09-2016 11:59 » 

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

Код:
QString serverfullpath="C:/Windows/System32/calc.exe";
int result = (int)::ShellExecuteA(0, "open", serverfullpath.toUtf8().constData(), 0, 0, SW_SHOWNORMAL);
uint32_t err=GetLastError();

процесс не запускается, в диспетчере тоже ничего не отображается нового

result==42
в мсдн по ShellExecuteA непонятно, что за значение https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx


GetLastError==183
 - "Невозможно создать файл, так как он уже существует. "

что не так и куда смотреть ?

Добавлено через 11 минут и 11 секунд:
насчёт правильности пути - файл то он видит. Если подправить на неправильный путь - говорит, что файл не найден

Добавлено через 29 секунд:
из обычного приложение - не сервиса - запуск производится нормально
« Последнее редактирование: 15-09-2016 12:11 от Алексей1153 » Записан

Aether
Специалист

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 15-09-2016 12:11 » 

ShellExecuteA по идее должен принимать в качестве аргументов строки не UTF. Должно быть также ShellExecuteW. Возможна ли путаница в кодировках использующихся в Qt и WinAPI? То есть вместо Calc он что-то пытается запустить, не находит и всё.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 15-09-2016 12:18 » 

Aether, из "не сервиса" код запуска то работает. Но я пробовал и не utf8 , всё так же.

Тут хитрость именно в том, что запускаю из сервиса, но вот что именно ковырять ?
Записан

Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 15-09-2016 12:19 » 

CoInitializeEx было?
там что то про это... непонятное сказано вроде
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Aether
Специалист

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 15-09-2016 12:22 » 

Aether, из "не сервиса" код запуска то работает. Но я пробовал и не utf8 , всё так же.

Тут хитрость именно в том, что запускаю из сервиса, но вот что именно ковырять ?
Можно попробовать изменить SW_SHOWNORMAL на SW_HIDE просто для оценки результата?
Записан
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 15-09-2016 12:23 » 

микрософт пишет
          Scr_hDC = GetDesktopWindow()
          StartDoc = ShellExecute(Scr_hDC, "Open", DocName, "", "C:\", SW_SHOWNORMAL)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 15-09-2016 12:32 » 

Aether, без изменений

Ochkarik, хендл GetDesktopWindow() добавил, но изменений нету

про CoInitializeEx не знаю, почитаю, что там

Добавлено через 3 минуты и 21 секунду:
Ochkarik, в таком виде

Код:
::ShellExecuteA(Scr_hDC, "open", "calc.exe", 0, "C:/Windows/System32/", SW_SHOWNORMAL);

тоже всё по прежнему
« Последнее редактирование: 15-09-2016 12:35 от Алексей1153 » Записан

Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 15-09-2016 12:41 » 

http://stackoverflow.com/questions/8245540/execute-a-command-line-from-a-services-execute-thread
Цитата
A service runs inside another session and hence another win station so you cannot use ShellExecute beacuse the service win station has no shell at all; there might not be a logged in user etc etc. The only but is an interactive service but those are not supported anymore on the newer Windows version (from Vista and above if I recall correctly).
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #11 : 15-09-2016 12:48 » 

Ochkarik, так что ж делать то

Добавлено через 1 минуту и 35 секунд:
CreateProcess  попробовать предлагаешь ? Дома попробую )
« Последнее редактирование: 15-09-2016 12:50 от Алексей1153 » Записан

zubr
Гость
« Ответ #12 : 15-09-2016 13:47 » 

Алексей++, я же тебе написал CreateProcessAsUser.
Сервис работает под системой, естественно он не может запустить процесс под юзером, используя ShellExecut или CreateProcess.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #13 : 15-09-2016 15:51 » 

zubr, ага, я не заметил, оказывается. Уже с CreateProcess попробовал - ровно то же самое происходит.

Смотрю параметры CreateProcessAsUser - кроме первого всё понятно, откуда брать первый пытаюсь понять
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 15-09-2016 16:08 » 

https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa378184(v=vs.85).aspx

lpszUsername
lpszDomain
 - эти параметры откуда брать ?
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #15 : 15-09-2016 16:20 » 

Я не совсем понимаю ситуацию, зачем из под сервиса запускать GUI?
Сервис запускается еше до того, как пользователь залогинился. Следовательно куда он должен запускать GUI?
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #16 : 15-09-2016 16:23 » 

Finch, заказчик пожелал GUI-программы оформить в виде сервиса. И тут понеслось - пытаюсь хоть что-то из сервиса запустить

пусть даже сначала нет юзера, но когда система загрузилась - юзер же появился ? Где его хендл взять ?

Добавлено через 1 минуту и 10 секунд:
я к тому, что когда я наконец-то найду этот хендл  - тогда и запущу приложение. А если не нахожу - жду некоторое время, потом снова пытаюсь
« Последнее редактирование: 15-09-2016 16:24 от Алексей1153 » Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #17 : 15-09-2016 16:25 » 

А сделать отдельно сервис и отдельно GUI?
Пускай программа с GUI висит как Watchdog. И мониторить сервис. Тогда много проблем решаться сами собой.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #18 : 15-09-2016 16:29 » 

Finch, как раз наоборот - сервис как вачдог. Если программа не запущена, мне надо её запустить

Добавлено через 1 минуту:
до этого гуи сидел себе в автозагрузке. И тут заказчику захотелось как сервис запускать
« Последнее редактирование: 15-09-2016 16:30 от Алексей1153 » Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #19 : 15-09-2016 16:35 » 

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

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #20 : 15-09-2016 16:36 » 

Finch, вот сейчас я остановился на том, как правильно вызвать LogonUserW - где брать имя, домен и логин юзера ?

по ТЗ, юзер неважен. Значит, надо как-то текущего загруженного юзера туда указать
« Последнее редактирование: 15-09-2016 16:41 от Алексей++ » Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #21 : 15-09-2016 16:40 » 

Ну логины скорее всего есть в реестре. А вот с паролями у тебя будет засада. В реестре скорее всего будут хранится хеши паролей.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #22 : 15-09-2016 16:42 » 

Finch, допустим, пароль у них будет пустой. А домен - это что и где ?
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #23 : 15-09-2016 16:43 » 

Тоже должен быть в реестре. По умолчанию localdomain:localhost
Может быть есть фунуция по типу GetLocalDomainName. Точнее нужно искать в MSDN.
« Последнее редактирование: 15-09-2016 16:46 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #24 : 15-09-2016 17:01 » 

ну вот, к примеру, зашёл я под юзером "xxx" . Пароля нет.

Код:
HANDLE hToken=0;
int res=LogonUserW(L"xxx", 0, 0, LOGON32_LOGON_SERVICE, LOGON32_PROVIDER_DEFAULT, &hToken);

res==0
hToken==0

 Должен же быть выход!!!

Такое чуйство, что фигнёй занимаюсь какой-то. Наверное, нужно предложить заместо сервиса в автозапуск положить минимальную простейшую апликуху, которая будет ту же функцию выполнять - а виснуть там нечему, потому что она элементарнейшая Отлично
« Последнее редактирование: 15-09-2016 17:15 от Алексей++ » Записан

Aether
Специалист

ru
Offline Offline
Пол: Мужской

« Ответ #25 : 15-09-2016 17:35 » 

По идее, как это видится: запущенный сервис, помимо своей основной роли также следит: залогинился ли какой-нибудь пользователь? Если пользователь обнаружен, то он создаёт процесс в его пространстве, а тот уже открывает окно или что нужно.

Интересно: чем заказчик аргументирует своё желание к конечному исполнению? Главное же в том, чтобы работало и просто настраивалось.
Записан
Aether
Специалист

ru
Offline Offline
Пол: Мужской

« Ответ #26 : 15-09-2016 17:37 » 

Тоже должен быть в реестре. По умолчанию localdomain:localhost
Может быть есть фунуция по типу GetLocalDomainName. Точнее нужно искать в MSDN.
А если пользователь зашёл через RDP, например? Тут должен быть какой-то механизм опроса: сколько пользователей подключено и кто они.
Записан
zubr
Гость
« Ответ #27 : 15-09-2016 17:49 » 

Делал когда то:
Код:
BOOL Gl::CreateUserProcess(PWCHAR commandLine, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
{
    DWORD sid;
HANDLE hToken = NULL, hNewToken = NULL;
BOOL result = FALSE;
PVOID lpEnvironment;    

    sid = WTSGetActiveConsoleSessionId();   
    if(!WTSQueryUserToken(sid, &hToken))
{       
        return FALSE;   
}   

while(1)
{
        if(!DuplicateTokenEx(hToken, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, NULL, SecurityAnonymous, TokenPrimary, &hNewToken))
        break;                 

        if(!CreateEnvironmentBlock(&lpEnvironment, hNewToken, FALSE))
break;       
       
    RtlZeroMemory(lpStartupInfo, sizeof(STARTUPINFO));
        RtlZeroMemory(lpProcessInformation, sizeof(PROCESS_INFORMATION));
    lpStartupInfo->cb = sizeof(STARTUPINFO);
lpStartupInfo->lpDesktop = L"Winsta0\\Default";       
        result = CreateProcessAsUser(hNewToken, NULL, commandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, lpEnvironment, NULL, lpStartupInfo, lpProcessInformation);
        break;
}
    if(hToken)
CloseHandle(hToken);
    if(hNewToken)
CloseHandle(hNewToken);

return result;
}
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #28 : 16-09-2016 05:13 » 

zubr, а что тут делается ?
Записан

zubr
Гость
« Ответ #29 : 16-09-2016 06:07 » 

1. Получаем индентификатор активной сессии
2. По полученному индентификатору получаем токен текущего юзера.
3. Создаем новый токен на основе полученного со своими параметрами доступа. Нужно, чтобы выделить блок окружения для процесса.
4. Создаем блок окружения под созданным токеном. Нужно для создания процесса под юзером.
5. Запускаем процесс под текущим юзером.
Записан
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines