Службы Windows с Windows forms в одном процессе
-
03-07-2019 - |
Вопрос
У меня есть приложение на c #, которое работает как служба Windows, управляющая подключениями к сокетам и другими вещами.Кроме того, существует другое приложение Windows forms для управления и настройки этой службы (systray с start, stop, show form с параметрами конфигурации).
Я использую удаленный доступ .net для выполнения IPC, и это было нормально, но теперь я хочу показать реальный трафик и другие отчеты, а удаленный доступ не соответствует моим требованиям к производительности.Поэтому я хочу объединить оба приложения в одно.
Вот в чем проблема:
Когда я запустил форму из службы Windows, ничего не произошло.Погуглив, я обнаружил, что мне нужно щелкнуть правой кнопкой мыши службу, перейти к входу в систему и установить флажок "Разрешить службе взаимодействовать с рабочим столом".Поскольку я не хочу просить своих пользователей делать это, я снова погуглил код, чтобы установить эту опцию в regedit пользователя во время установки.Проблема в том, что даже установив эту опцию, она не работает.Я должен открыть параметры входа в систему сервиса (это проверено), снять флажок и проверить еще раз.
Итак, как это решить?Как наилучшим образом создать службу Windows с элементом управления systray в том же процессе, доступную любому пользователю, вошедшему в систему?
Обновить:Спасибо за комментарии, ребята.Я согласен, что лучше использовать IPC, и я знаю, что плохо смешивать службы Windows и пользовательские интерфейсы.Несмотря на это, я хочу знать, как это сделать.
Решение
Два отдельных процесса, которые взаимодействуют с использованием выбранной вами технологии.Сервисы с пользовательским интерфейсом - это плохая идея.Не идите по этому пути - вы пожалеете об этом.
Я добился очень хороших результатов при общении со службой через простое сокет-соединение - хорошо документируйте свой протокол обслуживания, сделайте его как можно более простым, и это будет проще, чем вы думаете.
Другие советы
На практике вам не следует связывать свой сервис с пользовательским интерфейсом управления.
Я согласен с Грегом.Возможно, вы могли бы изучить другой механизм IPC.Возможно, используйте сокеты и свой собственный протокол.Или, если ваше приложение service Control может управлять службой только на локальном компьютере, вы можете использовать именованные каналы (еще быстрее).
Вот способ смешивания Сервисов и Форм
http://www.codeproject.com/KB/system/SystemTrayIconInSvc.aspx
Я понял, как это сделать, исходя из эта статья (нажмите на ссылку "Изменить" в таблице методов).
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);
}
У меня есть решение в несколько шагов, вот план
мы не собираемся создавать сервисный проект с Windows form, вместо этого мы собираемся создать решение Visual Studio, которое содержит сервисный проект Windows, проект Windows form и проект установки.
Идея состоит в том, чтобы иметь базу данных, или файл, или что-нибудь, в чем вам удобно хранить данные, в чем вы могли бы хранить параметры, которые ваша служба Windows всегда будет использовать для запуска.Таким образом, ваша служба Windows и ваше приложение Windows form должны иметь возможность изменять и извлекать из нее данные.
В основную форму вашего приложения Windows перетащите значок уведомления на форму, на вкладке свойств просмотрите и выберите изображение .ico (вы можете создать его в Visual Studio, но это другая тема, которую вы можете найти в Google или связаться со мной). Чтобы он отображался в системном трее при запуске приложения и основная форма была активна или отображалась, попробуйте, запустите приложение.
Добавьте их оба в качестве выходных данных в проект установки решения.Чтобы добавить проект в проект установки, они должны быть в одном и том же решении.Щелкните правой кнопкой мыши проект установки в обозревателе решений, выделите добавить, а затем выберите выходные данные проекта, добавьте службу Windows и выходные данные Windows form, и вы увидите их в обозревателе решений в разделе проект установки.
добавление службы Windows выходит за рамки этого, но это тоже другая тема, погуглите
Создание ярлыка для приложения Windows и добавление его в папку автозагрузки - это тоже другая тема в Google или свяжитесь со мной.
ПРИМЕЧАНИЕ Запрограммируйте свою форму таким образом, чтобы кнопка закрытия не отображалась, а форма отображалась как Me.visible = false, и двойной щелчок по значку в системном трее - единственный способ установить me.visible = true.таким образом, при каждом запуске компьютера ваше приложение Windows form также запускается, и для параметра visible немедленно устанавливается значение false, но поскольку у него есть значок notifyicon с изображением значка, он будет отображаться в системном трее, и двойной щелчок по нему сделает видимой форму для редактирования настроек, которые вы сохраняете для службы, служба также запускается автоматически, поскольку вы установили бы ее при настройке службы в проекте установки.моя почта iamjavademon@gmail.com для лучшей иллюстрации используйте снимки экрана И объясните полностью
Это очень просто - вам нужно создать один поток для выполнения событий приложения.Вот так (исходный код для C ++ с CLR, но вы можете сделать это на C #):
ref class RunWindow{
public:
static void MakeWindow(Object^ data)
{
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Application::Run(gcnew TMainForm());
};
};
И создайте поток в main
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;
}
Основными проблемами, связанными с интерактивными сервисами, являются:
Безопасность - другой процесс может отправлять ему сообщения через свою перекачку сообщений, тем самым получая доступ к СИСТЕМНОМУ / ЛОКАЛЬНОМУ процессу.
Незавершенность - интерактивная служба никогда не видит сообщений оболочки, следовательно, она не может взаимодействовать со значками области уведомлений.
Мы регулярно используем TCP- и UDP-соединения для передачи информации от сервисов другим exes и, в некоторых случаях, MSMQ.