пятница, 18 июля 2008 г.

Взаимодействие процессов по IpcChannel

Недавно столкнулся с необходимостью организовать взаимодействие двух .NET процессов в рамках одного компьютера. Немного покумекав, решил для этих целей воспользоваться «родной» для платформы .NET технологией – Remoting. Первоначально в качестве канала для «общения» процессов планировал выбрать протокол TCP (TcpChannel), но затем обнаружил что во втором фреймворке появился новый канал ремоутинга, который идеально подходит для мой задачи – IpcChannel. Этот канал использует в своей работе именованные каналы (named pipes) и был разработан специально для организации взаимодействия нескольких процессов в рамках одного компьютера и согласно MSDN, работает намного быстрее TCP и HTTP. Использование технологии Remoting крайне просто и ниже я привел пример сервера и клиента взаимодействующих по каналу IpcChannel.
Ниже приведен код для сервера.
class ServerHost
{
static void Main( string[] args )
{
IDictionary settings = new Hashtable();
settings["portName"] = "IPC_Test";
settings["exclusiveAddressUse"] = false;

IChannel channel = new IpcChannel(settings, null, null);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof( GreetingService ),
"GreetingService",
WellKnownObjectMode.Singleton );

Console.WriteLine("Server started. Press ENTER to shutdown.");
Console.ReadLine();
ChannelServices.UnregisterChannel( channel );
}
}

Далее идет код для клиента этого сервера
class ClientApp
{
static void Main( string[] args )
{
IGreetingService service = (IGreetingService)Activator.GetObject(
typeof( IGreetingService ),
"ipc://IPC_Test/GreetingService" );

Console.WriteLine(service.GetGreeting("IPC Tester"));
Console.ReadLine();
}
}

И наконец, пример интерфейса и реализация сервиса, который используемых как клиентом, так и сервером.
public interface IGreetingService
{
string GetGreeting(string userName);
}

class GreetingService: MarshalByRefObject, IGreetingService
{
public string GetGreeting( string userName )
{
return "Hello, " + userName;
}
}
Обратите внимание на установку параметра exclusiveAddressUse в false. В MSDN есть предупреждение, что установка его в false позволит нескольким серверам использовать одни и тот же порт, что может привести к брешам в безопасности такой архитектуры, однако если его не установить в false используемый сервером порт может быть недоступным еще около 1 секунды после завершения работы сервера.
Ниже приведен еще один пример реализации хоста сервера, но настройка ремоутинга произведена посредством конфигурационного файла.
class ConfigServerHost
{
static void Main( string[] args )
{
RemotingConfiguration.Configure( "ConfigServerHost.exe.config", false );

Console.WriteLine( "Server started. Press ENTER to shutdown" );
Console.ReadLine();
}
}

И наконец, app.config, который после компиляции проекта преврацается в ConfigServerHost.exe.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application name="IPC Sample">
<service>
<wellknown mode="Singleton" type="ServerHost.GreetingService, ServerHost" objectUri="GreetingService" />
</service>

<channels>
<channel ref="ipc" portName="IPC_Test" exclusiveAddressUse="false" />
</channels>
</application>
</system.runtime.remoting>
</configuration>

суббота, 12 июля 2008 г.

«Незаметный» запуск внешних процессов

Иногда возникает необходимость запустить внешний процесс, получить от него какие-либо данные (либо просто дать ему возможность отработать) и затем его закрыть. В .NET Framework для этих целей служит класс System.Diagnostics.Process и с этим классом запуск процессов весьма прост. Однако внешний процесс становится виден пользователю (часто это можно наблюдать при работе инсталляторов), что, вообще-то говоря, нежелательно. А вот чтобы запустить внешний процесс незаметно для пользователя, надо в классе настроек запуска процесса ProcessStartInfo свойству WindowStyle присвоить значение ProcessWindowStyle.Hidden. Но, как гласит русская народная пословица, лучше один раз увидеть, чем сто раз услышать, и поэтому ниже представлен небольшой пример «незаметного» запуска процессов. Приведенный фрагмент кода запускает утилиту Reg.exe (Console Registry Tool for Windows) и делает бэкап ветки реестра HKEY_CLASSES_ROOT\mailto в файл.

static void Main()
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "reg";
startInfo.Arguments = @"save HKEY_CLASSES_ROOT\mailto c:\mailto.reg";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(startInfo);

}

понедельник, 7 июля 2008 г.

P/Invoke Interop Assistant

Команда CLR Interop недавно выпустила новый инструмент под названием P/Invoke Interop Assistant. Как можно догадаться из названия, он умеет генерировать код на С# и VB.NET для вызова native функций в .net приложениях. На рисунке ниже представлено главное окно P/Invoke Interop Assistant.

Если сравнивать его с другим популярным инструментом подобного рода – PInvoke.net, то в целом они очень похожи, хотя и есть некоторые отличия. На рисунке ниже изображено главное окно PInvoke.net.

P/Invoke Interop Assistant реализован отдельным инструментом и более функционален: в нем реализован контекстный поиск, есть генерация для типов и что особенно удобно есть генерация кода констант. Однако большая функциональность делает его несколько более сложным в использовании.
PInvoke.net существенно проще в использовании, и интегрируется в студию (в главном меню появляется пункт PInvoke.net). Ко всему прочему, PInvoke.net генерирует более простой код.

среда, 2 июля 2008 г.

Отладка с исходниками .NET Framework в VS 2005 или краткое руководство по NetMassDownloader

Многие знают, что Microsoft открыла существенную часть исходного кода .NET Framework 2.0. Автоматическое скачивание исходников и отладочных файлов из интернета стало доступно с VS 2008 (здесь можно прочитать подробнее) Однако воспользоваться удобством отладки с исходным кодом можно и на VS 2005. Kerem Kusmezer и John Robbins написали приложение, которое скачивает на вашу машину все исходники и файлы для отладки для нужных вам сборок .NET 2.0. (Для справки: Джон Роббинс – известный эксперт в области отладки приложений и автор большого количества книг на эту тему под Windows и .NET, второго чела не знаю :)). Этой утилитой удобно пользоваться и при работе на VS 2008, поскольку она автоматически скачивает все исходники и файлы отладки, и затем вам не потребуется постоянный коннект с интернетом при отладке.

Итак, ближе к делу. Называется утилита NetMassDownloader, а скачать ее можно здесь.

Далее: краткая инструкция, как скачать исходники .NET 2.0. и файлы отладки, как настроить 2005 студию и пару советов от меня. Описание от авторов, как работать с утилитой, можно найти на CodePlex (на странице загрузки NetMassDownloader) или на блоге Джеффри Роббинса).

Чтобы скачать исходники и отладочные файлы, запустите NetMassDownloader со следующими параметрами:

NetMassDownloader.exe –d C:\Windows\Microsoft.NET\Framework\v2.0.50727 –output c:\.NETSource

Как можно догадаться из параметров, C:\Windows\Microsoft.NET\Framework\v2.0.50727 – это путь, где установлены библиотеки фреймворка, а c:\.NETSource – путь, куда надо сохранить исходники и файлы отладки.

После того, как исходники скачаны (у меня их размер составил около 130Mb, так что наберитесь терпения), можно перейти к настройке студии. В окне Options (Tools -> Options) найдите узел Debugging, раскройте его и откройте свойства узла Symbols. В списке Symbol file (.pdb) locations добавьте каталог, куда были скачаны исходники. Пример того, как это сделано у меня, на рисунке ниже.

Далее, в том же узле Debugging откройте свойства узла General и снимите флаг с опции Require source files to exactly match the original version (см. рисунок ниже).

Если вы ранее уже скачивали pdb-файлы фреймворка, то их надо удалить, т.к. есть вероятность, что он возьмет их, а не те, что вы скачали при помощи NetMassDownloader.

Чтобы проверить, всё ли у вас работает, создайте новый проект, например, WindowsApplication, в конструкторе формы поставьте брейкпоинт (до вызова InitializeComponent) и запускайте отладку. Как только отладчик остановится на конструкторе вашей формы, нажимайте F11. Затем появится диалог, чтобы вы указали, где находится код файла Form.cs. В моем случае это следующий путь:

c:\.NetSource\RedBits\ndp\fx\src\WinForms\Managed\System\WinForms\Form.cs

После этого у вас в IDE должен открыться исходный код класса Form.cs.

В дальнейшем, для этого сеанса работы студия будет автоматически находить исходники. Если вас напрягает искать первый файл с исходником, то можно каталог исходников добавить в свойства проекта:

Ну вот и все, легкой вам отладки!