На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
  
> Интерактивный сервис (служба) , Хочу создавать окна!
    std::cout << "Привет всем!";

    Хочу сделать так, чтобы сервис мог создавать окна GUI.

    Просто простановка флага SERVICE_INTERACTIVE_PROCESS (вместе с SERVICE_WIN32_OWN_PROCESS) в CreateService ничего не даёт.

    Подскажите, плиз, каким образом это делается?
      Цитата Jin X @
      Просто простановка флага SERVICE_INTERACTIVE_PROCESS (вместе с SERVICE_WIN32_OWN_PROCESS) в CreateService ничего не даёт.


      А что именно не получается? https://docs.microsoft.com/en-us/windows/de...active-services
        Jin X, создаёшь новую нить, получаешь сессию текущего юзера, которого, к слову, может и не быть, имперсонируешь нитку под этого юзера, внедряешь в его сессию – и вуаля, делов-то :lol: . Так ты точно не скомпрометируешь систему.
        Сообщение отредактировано: Qraizer -
          Олег М, ну вот у меня lpServiceStartName = NULL, флаг SERVICE_INTERACTIVE_PROCESS указан, значение NoInteractiveServices в реестре установлено в 0.
          В импотенте Importent'е сказано, но отображение идёт только в 0-й сессии. Но я тут один, никаких юзеров больше нет. Значит ли это, что я в 0-й сессии? И как понять фразу "do not configure a service to run as an interactive service under Terminal Services" ?

          Qraizer, можешь чуть поконкретнее рассказать, как это всё делать?
          1. Как получить сессию текущего юзера (без привязки к текущему процессу).
          2. Как имперсонировать нитку под сессию?
          3. Как внедрить в сессию?
          :)
            Цитата Jin X @
            Но я тут один, никаких юзеров больше нет. Значит ли это, что я в 0-й сессии?

            А под какой учётной записью запускается сервис?
            Вообще, на мой взгляд - не самая лучшая идея делать гуи в сервисе. Проще сделать отдельное приложение, которое будет работать с этим сервисом, например по DCOM
              Jin X, ну, я слишком утрировано описал. Это было возможно в XP. Нынче, нулевая сессия больше недоступна для пользовательских сеансов, так что интерактивные сервисы ты сможешь сделать, только если будешь запускаться под учёткой какого-нибудь пользователя. Вряд ли это проще интеракции с неинтерактивным сервисом, т.к. ты получишь больше проблем с отслеживанием пользовательских сессий, их список же может меняться по ходу дела, + ты получишь те же ограничения, что учётная запись пользователя. В целом же, если ориентироваться на неинтерактивные сессии, Олег М правильно написал:
              Цитата Олег М @
              Вообще, на мой взгляд - не самая лучшая идея делать гуи в сервисе. Проще сделать отдельное приложение, которое будет работать с этим сервисом, например по DCOM
              . Это не сложно, нужно лишь получить текущую активную сессию пользователя – на сервере терминалов могут быть сложности, там все сессии активны одновременно, так что нужно изобретать другие алгоритмы для выбора сеанса для внедрения – получить токен её юзера и запустить процесс от его имени. Взаимодействие с дочерним процессом наладить можно сильно по-разному, не обязательно DCOM.

              Добавлено
              Как-то так у меня экспериментировалось:
              ExpandedWrap disabled
                unsigned __stdcall threadFunc(void*)
                {
                  DWORD res;
                 
                  // Ждём сигналов: выход или окошко
                  while ((res = WaitForMultipleObjects(events.size(), &events[0], FALSE, INFINITE)) == WAIT_OBJECT_0+1)
                  {
                    // Подстроиться под текущий логин
                 
                    // Получить текущий сеанс.
                    // Это для WinXP с её Fast User Switch. В реальной терминалсерверной среде лучше оперировать
                    // иными критериями, например, перечислить все сеансы функцией WTSEnumerateSessions()
                    DWORD  sessionID = WTSGetActiveConsoleSessionId();
                    HANDLE ppToken;
                 
                    if (!WTSQueryUserToken(sessionID, &ppToken))
                    {
                      DWORD res=GetLastError();
                 
                      MessageBox(NULL, static_cast<std::tostringstream&&>(std::tostringstream() << res << _T(" - WTSQueryUserToken() fail")).str().c_str(), _T("RehostStatus"), MB_SERVICE_NOTIFICATION | MB_OK);
                      SetEvent(hStart);
                      continue;
                    }
                 
                    // Подготовка к старту процесса
                    STARTUPINFO         startInfo = { sizeof(startInfo), NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                      NULL, NULL, NULL, NULL };
                    // Запускаем себя же, но с параметром "startGUI"
                    PROCESS_INFORMATION processInfo;
                    std::tstring        commandLine(GetCommandLine());
                  
                    commandLine += _T(" startGUI\0");
                    commandLine += _T('\0');
                 
                    if (!CreateProcessAsUser(ppToken, NULL, &commandLine[0], NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL,
                                             &startInfo, &processInfo))
                    {
                      DWORD res=GetLastError();
                 
                      MessageBox(NULL, static_cast<std::tostringstream&&>(std::tostringstream() << res << _T(" - CreateProcessAsUser() fail")).str().c_str(), _T("RehostStatus"), MB_SERVICE_NOTIFICATION | MB_OK);
                      SetEvent(hStart);
                      continue;
                    }
                 
                    // Подчищаем за собой
                    CloseHandle(ppToken);
                    CloseHandle(processInfo.hProcess);
                    // Ждём завершения запущенного себя
                    WaitForSingleObject(processInfo.hThread, INFINITE);
                    CloseHandle(processInfo.hThread);
                    // Сигналим главной нити
                    SetEvent(hStart);
                  }
                 
                  return res == WAIT_OBJECT_0;
                }
                Смотрите. У меня есть сервис и есть конфигуратор. Конфигуратор - это GUI, который меняет параметры. И далее, по сути, ему нужно только уведомить сервис об изменениях, чтобы тот прочёл конфигурацию заново.
                Что если сделать 2 отдельные проги: сервис и конфигуратор, а взаимодействие с ними через shared memory сделать? CreateFileMapping + MapViewOfFile + event'ы, к примеру.
                Это если что-то передать. А если просто уведомить, то и event'ов достаточно...
                Это нормально будет работать между обычной прогой и сервисом?

                Добавлено
                Даже так: вторая прога - это не прога, а батник, который будет запускать прогу с ключом /config, к примеру :)
                  Из проги сигналишь эвентом, который слушает служба. Нормально. Проблема лишь в том, чтобы и прога, и сервис – они оба имели права на доступ в эвенту. Проще всего – прога регистрирует именованный эвент, сервис после проги его открывает по тому же имени, пока та не завершилась и т.с. не убила созданный эвент. Если наоборот, то сервис должен будет заморочиться правильным токеном для эвента, чтобы проге хватило прав его пользовать.
                    Ясно, спасибо, буду экспериментировать :)
                      Цитата Jin X @
                      Что если сделать 2 отдельные проги: сервис и конфигуратор, а взаимодействие с ними через shared memory сделать?

                      В сервисе - UDP сервер. В конфигураторе - UDP клиент.
                      Можно будет по-рулить и удалённо.
                      Сообщение отредактировано: ЫукпШ -
                        Цитата Jin X @
                        CreateFileMapping + MapViewOfFile

                        Избыточно. Именованного пайпа должно быть достаточно, если приёмник всего один
                          Цитата B.V. @
                          Именованного пайпа должно быть достаточно, если приёмник всего один
                          Было бы, конечно, удобнее, если бы именованное что-либо было создано сервисом, а не гуем, т.к. гуй будет запускаться, ясное дело, позже.
                          Но в принципе, если сделать просто триггер (по сути, мне триггера даже достаточно в данном случае), то можно создать именованный ивент в гуе, а в сервисе периодически пытаться его открыть и проверять наличие "сигнала" в нём.
                          Это прям вообще просто будет.
                            Всё правильно говорят - интерактивный GUI должен быть ВНЕ сервиса, потому что Microsoft планомерно перекрывает кислород интерактивным сервисам.
                            Связь между сервисом и GUI - через любой доступный inter-process communication (IPC): sockets, pipes, memory mapped files. Для уменьшения проблем конфигурирования можно задействовать UPnP.
                              Цитата Jin X @
                              Было бы, конечно, удобнее, если бы именованное что-либо было создано сервисом, а не гуем, т.к. гуй будет запускаться, ясное дело, позже.
                              Та можно. Только намаешься токен создавать, который был бы доступен для несервисов.
                                Я же правильно понимаю, что имя event'а нужно обязательно начинать с "Global\" ?

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


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0388 ]   [ 17 queries used ]   [ Generated: 28.03.24, 10:59 GMT ]