15 февраля 2009 г.

Разработка службы Windows на Microsoft Visual Studio 2008 Express

Часто нам приходится писать приложения, в которых нужно написать Windows службу, которая будет следить за какими-то процессами или выполнять какую-то работу в фоновом режиме. Например, при создании сайта, часто возникает такая потребность как подтверждение email адреса только, что зарегистрировавшегося пользователя. В основе своем для реализации данного решения, мы создаем таблицу, в которой прописаны идентификаторы пользователей, их email адреса и коды подтверждения сгенерированные самим сайтом для каждого. Но вот проблема, если пользователь не прошел авторизацию, то в таблице остаются данные о его регистрации, что не очень хорошо, так как, во-первых, база данных хранит много ненужной информации (ведь таких пользователей может быть не один и не два), во-вторых, так как повторения логинов не допустимо, то может оказаться, что вновь регистрирующийся пользователь не сможет зарегистрироваться под своим любимым ником из-за "мертвой души", которой собственно и нет на сайте. Как поступить в этом случае?

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

Но как же быть, если мы пишем сайт с помощью Microsoft Visual Studio 2008 Express в которой нету проекта для создания службы. Покупать другую версию? Не всегда есть на это деньги, да и если нужно написать всего-то одну службу и все, то это не самый лучший выход. Самым лучшим выходом из этого положения будет создать шаблон приложения Windows сервиса и просто всегда им пользоваться. При этом нам не понадобиться ни новой IDE ни установки каких-то дополнений.

Дело в том, что все, что мы пишем под .NET Framework на любом языке содержится в самой среде. Т.е. для написания ЛЮБОГО приложения не понадобиться абсолютно ничего, кроме рук, головы и соответствующих знаний.

И так, для создания нашего шаблона, запустим Visual C# 2008 Express и создадим новый пустой проект.
File-New Project...->Empty Project

Теперь необходимо добавить нужные файлы и сборки.
Первым делом добавьте в созданный нами проект файл, который будет содержать полную информацию о сборке – Assembly Information File. Назовем его AssemblyInfo.cs. Сразу после добавления его в проект, его можно просто закрыть, так как ничего изменять в этом файле мы не будем.
Далее нужно добавить файл, содержащий весь код нашей службы. Для этого добавьте в проект простой класс с именем WindowsService.cs и отредактируйте его как показано в листинге 1.
Листинг 1.
using System;
using System.Collections.Generic;
using System.Text;

namespace WindowsService
{
public class WindowsService : System.ServiceProcess.ServiceBase
{
public WindowsService()
{
InitializeComponent();
}

private void InitializeComponent()
{

}
}
}

Не забудьте добавить в Reference сборку System.ServiceProcess.
Для этого щелкните правой кнопкой мышки по папке Reference и выберите пункт Add Reference.… На вкладке .NET найдите сборку System.ServiceProcess, выделите её и нажмите кнопку OK.
Теперь нам осталось добавить класс для регистрации службы. Для этого также добавим класс с именем ProjectInstaller.cs. Исходный код данного класса приведен в листинге 2.
Листинг 2.
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

namespace WindowsService
{
[RunInstallerAttribute(true)]
public class ProjectInstaller : System.Configuration.Install.Installer
{
public ProjectInstaller()
: base()
{
InitializeComponent();
}

private void InitializeComponent()
{

}
}
}

Не забудьте добавить ссылку в раздел Reference на сборку System.Configuration.Install.
Теперь нам осталось только экспортировать проект как шаблон. Для этого выберите File-Export Template…
Перед нами появляется первое окно мастера экспорта, в котором нам предлагается выбрать одно значение из двух:
1.Project template – шаблон проекта, который нам и нужен
2.Item template – шаблон одного файла. Т.е. это один из тех шаблонов, которые мы видим, выбирая пункт Add New Item, когда работаем с текущим проектом.

Жмем Next и видим новое окно мастера, в котором нам предлагается выбрать:
Template Icon: иконку шаблона (она будет ассоциироваться с этим шаблоном при создании нового проекта). Я оставил по умолчанию.
Template name: Имя шаблона. Желательно указать все же имя, по которому можно понять, шаблон какого проекта мы создаем. В данном случае я указал WindowsService.
Template description: Описание шаблона. Я ничего не указывал.
Output location: Папка, в которой будет храниться шаблон. Это значение изменить нельзя, так что после создания шаблона лучше скопируйте данный шаблон в папку, которая точно останется целой даже после переустановке операционной системы, так как каждый раз создавать один и тот же шаблон, все же не так и весело.
Жмем кнопку Finish и все. Наш шаблон готов. Теперь вы можете писать службы Windows и не задумываться о том, что вам нужно покупать новую версию любимой программы.

6 комментариев:

Анонимный комментирует...

В Visual Basic такое пробовали?

MasDen комментирует...

На самом деле на чем делать язык тут совершенно не важен. :)

Unknown комментирует...

хотел бы проконсультироваться. В последнем листинге (VSE2010 C#) using System.ComponentModel; кидало ошибку на отсутствие ссылки, это победил добавил ссылку System.ComponentModel.Composition при этом ругаться ругаться начало на [RunInstallerAttribute(true)]
Собственно вот ошибка ->>
Не удалось найти имя типа или пространства имен "RunInstallerAttribute" (пропущена директива using или ссылка на сборку?) помогите советом!!! уже долго капаюсь в гугле подобного не могу найти((

MasDen комментирует...

Не забудьте добавить ссылку в раздел Reference на сборку System.Configuration.Install.

Если не поможет пишите)

Unknown комментирует...

Все именно так и сделано.( но это еще более печально...

Unknown комментирует...

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Configuration.Install;
namespace WindowsService
{
[RunInstallerAttribute(true)]
public class ProjectInstaller : System.Configuration.Install.Installer
{
public ProjectInstaller() : base()
{
InitializeComponent();
}
private void InitializeComponent()
{
}
}
}

вот мой код... ругается только на RunInstallerAtribute