Службы Windows с формами Windows в одном процессе

У меня есть приложение C #, которое работает как служба Windows, контролирующая соединения сокетов и другие вещи. Кроме того, существует еще одно приложение Windows Forms для управления и настройки этой службы (системная панель с запуском, остановкой, отображением формы с параметрами конфигурации).

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

Вот в чем проблема:

Когда я запустил форму из службы Windows, ничего не произошло. Погуглил и обнаружил, что мне нужно щелкнуть службу правой кнопкой мыши, перейти в раздел «Вход в систему» ​​и установить флажок «Разрешить службе взаимодействовать с рабочим столом». Так как я не хочу просить своих пользователей делать это, я снова начал поиск в Google кода, чтобы установить эту опцию в пользовательском regedit во время установки. Проблема в том, что даже установка этой опции не работает. Мне нужно открыть параметры входа в систему службы (он отмечен), снять флажок и снова проверить.

Итак, как это решить? Как лучше всего сделать так, чтобы служба Windows с элементом управления на панели задач в одном процессе была доступна любому входящему в систему пользователю?

ОБНОВЛЕНИЕ: Спасибо за комментарии, ребята. Я согласен, что лучше использовать IPC, и я знаю, что смешивать службы Windows и пользовательские интерфейсы - это плохо. Хотя я хочу знать, как это сделать.


person andrecarlucci    schedule 01.10.2008    source источник
comment
Я знаю, что объединение пользовательского интерфейса с моей службой приведет к поломке моего программного обеспечения и, возможно, компьютера моих пользователей, но я все равно хочу это сделать. Сделайте 3–4 шага назад и еще раз оцените, следует ли вам делать то, что вы пытаетесь сделать. Это вообще имеет смысл?   -  person Greg D    schedule 21.10.2008
comment
@Greg D: Я не знаю, где вы взяли эти цитаты, но я никогда не говорил, что служба с пользовательским интерфейсом сломает компьютер пользователя. На самом деле любое программное обеспечение может наделать много проблем с компьютером пользователя, так что в этом нет никакого смысла. Во всяком случае, я никогда не спрашивал, стоит мне это делать или нет, я спрашивал, КАК это делать.   -  person andrecarlucci    schedule 29.10.2008


Ответы (8)


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

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

person Greg Hurlman    schedule 01.10.2008
comment
Я полностью согласен с этим. Если возможно, я бы посмотрел на какой-нибудь способ общения, не такой раздутый, как удаленное взаимодействие. розетки, трубы и т. д. - person mattlant; 01.10.2008
comment
@andrecarlucci: Когда мы говорим об услугах с UI, это не личные предпочтения, это архитектурный факт. Использование сокетов TCP / IP и простого, хорошо документированного протокола будет вашим лучшим способом добраться до этого отсюда без проблем, связанных с Service + UI в том же процессе. - person John Rudy; 01.10.2008
comment
Всем привет. Я согласен со всеми вами. Удаленное взаимодействие DotNet - это просто так. Но вопрос не в этом, вопрос в том, как лучше всего сделать это в том же процессе, а не лучшим способом. Я перефразирую свое обновление, чтобы оно не звучало грубо, извините за это. - person andrecarlucci; 01.10.2008
comment
Вы не можете сделать это безопасно в одном процессе. Проблема в том, что вы хотите, чтобы часть вашей программы была независимой от сеанса, а часть вашей программы - зависимой от сеанса. В современной среде это невозможно. - person Orion Adrian; 24.11.2008

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

person Quintin Robinson    schedule 01.10.2008

Я согласен с Грегом. Возможно, вы могли бы изучить другой механизм IPC. Возможно использование сокетов и собственного протокола. Или, если ваше приложение управления службами может управлять службой только на локальном компьютере, вы можете использовать именованные каналы (даже быстрее).

person Peter Meyer    schedule 01.10.2008

Вот способ смешивания Сервисов и Форм

http://www.codeproject.com/KB/system/SystemTrayIconInSvc.aspx

person Community    schedule 23.07.2009

Я понял, как это сделать, из этой статьи (щелкните ссылку «Изменить» в таблице методов).

string wmiPath = "Win32_Service.Name='" + SERVICE_NAME + "'";
using (ManagementObject service = new ManagementObject(wmiPath))
{
    object[] parameters = new object[11];
    parameters[5] = true;  // Enable desktop interaction
    service.InvokeMethod("Change", parameters);
}
person Phil    schedule 24.11.2009
comment
Да, я использовал здесь ваш код, и он работает. Но я создал новое консольное приложение, которое запускается после завершения установки службы ... так что, если кто-то попытался поместить это где-нибудь в OnStart(), это не сработает. - person Cipi; 11.08.2011
comment
И вы, вероятно, захотите отредактировать это и добавить: parameters[6] = "LocalSystem"; parameters[7] = "";, чтобы была выбрана учетная запись «Вход в качестве локальной системы». ;) - person Cipi; 11.08.2011
comment
Предполагая, что вам нужна учетная запись LocalSystem. В большинстве случаев я думаю, что люди захотят оставить учетную запись такой же, а не следить за тем, чтобы это была учетная запись LocalSystem. - person Phil; 11.08.2011

У меня есть решение в несколько шагов, это план

  1. мы не собираемся создавать проект службы с формой Windows, вместо этого мы собираемся создать решение Visual Studio, которое содержит проект службы Windows, проект формы Windows и проект установки.

  2. Идея состоит в том, чтобы иметь базу данных, или файл, или что-то еще, что вам удобно для хранения данных, в котором вы будете хранить параметры, которые ваша служба Windows всегда будет использовать для запуска. Таким образом, ваша служба Windows и приложение Windows Form должны иметь возможность изменять и извлекать из нее данные.

  3. В основную форму вашего приложения Windows перетащите NotifyIcon в форму, на вкладке свойств найдите и выберите изображение .ico (вы можете создать его в Visual Studio, но это еще одна тема, которую вы можете получить в Google или связаться со мной. ) Чтобы он отображался в системном трее, когда вы запускаете приложение, а основная форма активна или отображается, попробуйте, запустите приложение.

  4. Добавьте их обоих в качестве выходных данных в проект установки решения. Чтобы добавить проект в проект установки, они должны быть в одном решении. Щелкните правой кнопкой мыши проект установки в проводнике решений, выделите добавить, а затем выберите вывод проекта, добавьте службу Windows и выходные данные формы Windows, и вы увидите их в проводнике решений под проектом установки.

  5. добавление службы Windows идет дальше, но это еще одна тема в Google

  6. Создание ярлыка для приложения Windows и добавление его в папку автозагрузки - это еще одна тема гугла или свяжитесь со мной.

    ПРИМЕЧАНИЕ. Запрограммируйте форму таким образом, чтобы кнопка закрытия не отображалась, а форма отображалась как Me.visible = false, а двойной щелчок по значку на панели задач - единственный способ установить me.visible = true. Таким образом в любое время компьютер запускается, ваше приложение формы Windows также запускается, и для него сразу устанавливается значение false, но поскольку у него есть значок уведомления с изображением значка, он будет отображаться на панели задач, а двойной щелчок по нему делает форму видимой для редактирования настроек, которые вы хранятся для службы, служба также запускается автоматически, поскольку вы должны установить ее при настройке службы в проекте установки. моя почта - [email protected] для лучшей иллюстрации с использованием снимков экрана и объяснения полностью

person ekeolere olaide    schedule 18.03.2010

Это очень просто - вам нужно создать один поток для выполнения событий приложения. Вот так (исходный код для C ++ с CLR, но вы можете сделать это на C #):

ref class RunWindow{
public:
    static void MakeWindow(Object^ data)
    {
        Application::EnableVisualStyles();
        Application::SetCompatibleTextRenderingDefault(false); 

        Application::Run(gcnew TMainForm());
    };
};

И создайте поток в основном

int main(array<System::String ^> ^args)
{
    bool bService = RunAsService(L"SimpleServiceWithIconInTrayAndWindow");

    if (bService)
    {

        System::Threading::Thread ^thread = gcnew System::Threading::Thread(gcnew ParameterizedThreadStart(RunWindow::MakeWindow));
        thread->Start();

        ServiceBase::Run(gcnew simpleWinService());
        Application::Exit();
    }
    else
    {
        Application::EnableVisualStyles();
        Application::SetCompatibleTextRenderingDefault(false); 

        // Create the main window and run it
        Application::Run(gcnew TMainForm());
    }

    return 0;
}
person CoolMagic    schedule 21.10.2008

Основные проблемы с интерактивными сервисами:

  • Безопасность - другой процесс может отправлять ему сообщения через свой насос сообщений, тем самым получая доступ к СИСТЕМНОМУ / ЛОКАЛЬНОМУ процессу.

  • Неполнота - интерактивная служба никогда не видит сообщения оболочки, поэтому не может взаимодействовать со значками области уведомлений.

Мы регулярно используем TCP и UDP-соединения для передачи информации от сервисов другим бывшим, а в некоторых случаях и MSMQ.

person cookre    schedule 08.01.2009