воскресенье, 28 декабря 2008 г.

Поиск слов по шаблону в Lingvo

У многих кто изучает английский язык и активно пользуются  ПК стоит Lingvo. По крайней мере я и все мои знакомые пользуются именно этим словарем. Функции, которой мне нахватало был поиск слова по шаблону. Недавно, пролистывая брошюрку, которая идет с коробочной версией лингво обнаружил что такая функция есть и причем уже достаточно давно. Функция поиска по шаблону (в справке она называется поиск по маске) поддерживает известные символы подстановки “*” и “?” – любые буквы в любом количестве и одна любая буква соответственно.

Работает такой поиск следующим образом. В строку поиска надо ввести интересующий шаблон, например “he*o” и нажать Ctrl+F3. Программа запустит поиск по всем активным словарям и выведет окно с подходящими словами и словосочетаниями.

Search by Mask Result

четверг, 18 декабря 2008 г.

Интеллект Live Search

Давно знал, что поисковик Google может быть использован как простой калькулятор, но вот вчера с удивлением обнаружил, что майкрософтовский Live Search умеет решать уравнения. И что поразило меня еще больше, что нелинейные уравнение ему тоже по зубам. Вот парочка примеров (кликабельно):   

Единственный недостаток, что расширенным интеллектом обладает только англоязычная версия поисковика.

суббота, 23 августа 2008 г.

Sysinternals Desktops v1.0

«Широко известный в узких кругах» пакет утилит Sysinternals Suit пополнился еще одним приложением – Desktops v1.0. Эта утилита решает проблему переполненности панели задач и позволяет создавать до 4 виртуальных рабочих столов и работать раздельно с приложениями на каждом из них. Например, разрабатывать приложение в одном и просматривать почту и писать отчет в другом. Между приложениями на разных десктопах удобно переносить данные, так как они имеют один общий буфер обмена. Переключаться между десктопами можно по горячим клавишам или при помощи иконки в трэе.

В целом с приложением удобно работать, хотя есть определенные ограничения. Некоторые сочетания клавиш, например, Ctrl+Shif+ Esc (запуск Windows Task Manager) работают только в первом рабочем столе, (там, где была утилита запущена), не смотря на то, в каком рабочем столе такое сочетание клавиш было нажато, приложение запустится в первом.
Скачать утилиту можно здесь.

среда, 6 августа 2008 г.

Определение Integrity Level для процесса на c#

В Windows Vista появился дополнительный механизм защиты – Integrity Levels. В зависимости от его уровня различаются и возможности приложения по работе с защищенными ресурсами системы. Поэтому актуальной задачей является определение значения Integrity Level процесса. В MSDN есть пример по определению Integrity Level текущего процесса для неуправляемого кода (статья Appendix D: Getting the Integrity Level for an Access Token). Ниже я привел подобный код на C#. Я постарался сохранить стиль кода с оригиналом, что бы их было проще сравнивать. Так же, на мой взгляд, в оригинальном примере есть ошибка в определении уровней High и System. Поэтому я заменил фрагмент кода
else if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID) 
{
// High Integrity
...
}

на
else if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID && 
dwIntegrityLevel < SECURITY_MANDATORY_SYSTEM_RID)
{
// High Integrity
...
}

А вот и пример консольного приложения, которое определяет свой текущий Integrity Level.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Diagnostics;

namespace IntegrityLevel
{
class Program
{
static void Main(string[] args)
{
ShowProcessIntegrityLevel();
}

public static void ShowProcessIntegrityLevel()
{
IntPtr hProcess = Process.GetCurrentProcess().Handle;
IntPtr hToken;
if (!OpenProcessToken(hProcess,
TokenAccessLevels.MaximumAllowed,
out hToken))
{
return;
}

try
{
uint dwLengthNeeded;
if (GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenIntegrityLevel,
IntPtr.Zero,
0,
out dwLengthNeeded))

uint dwError = (uint)Marshal.GetLastWin32Error();
if (dwError == ERROR_INSUFFICIENT_BUFFER)
{
IntPtr pTIL = Marshal.AllocHGlobal((int)dwLengthNeeded);
try
{
if (!GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenIntegrityLevel,
pTIL,
dwLengthNeeded,
out dwLengthNeeded))
{
return;
}

TOKEN_MANDATORY_LABEL TIL =
(TOKEN_MANDATORY_LABEL)Marshal.PtrToStructure(pTIL,
typeof(TOKEN_MANDATORY_LABEL));

IntPtr SubAuthorityCount = GetSidSubAuthorityCount(TIL.Label.Sid);

IntPtr IntegrityLevelPtr = GetSidSubAuthority(TIL.Label.Sid,
Marshal.ReadByte(SubAuthorityCount) - 1);

int dwIntegrityLevel = Marshal.ReadInt32(IntegrityLevelPtr);

if (dwIntegrityLevel == SECURITY_MANDATORY_LOW_RID)
{
// Low Integrity
Console.WriteLine("Low Process");
}
else if (dwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID &&
dwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID)
{
// Medium Integrity
Console.WriteLine("Medium Process");
}
else if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID &&
dwIntegrityLevel < SECURITY_MANDATORY_SYSTEM_RID)
{
// High Integrity
Console.WriteLine("High Integrity Process");
}
else if (dwIntegrityLevel >= SECURITY_MANDATORY_SYSTEM_RID)
{
// System Integrity
Console.WriteLine("System Integrity Process");
}
}
finally
{
Marshal.FreeHGlobal(pTIL);
}
}
}
finally
{
CloseHandle(hToken);
}
}

// interop
const uint ERROR_INSUFFICIENT_BUFFER = 122;
const long SECURITY_MANDATORY_LOW_RID = 0x00001000L;
const long SECURITY_MANDATORY_MEDIUM_RID = 0x00002000L;
const long SECURITY_MANDATORY_HIGH_RID = 0x00003000L;
const long SECURITY_MANDATORY_SYSTEM_RID = 0x00004000L;

enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups = 2,
TokenPrivileges = 3,
TokenOwner = 4,
TokenPrimaryGroup = 5,
TokenDefaultDacl = 6,
TokenSource = 7,
TokenType = 8,
TokenImpersonationLevel = 9,
TokenStatistics = 10,
TokenRestrictedSids = 11,
TokenSessionId = 12,
TokenGroupsAndPrivileges = 13,
TokenSessionReference = 14,
TokenSandBoxInert = 15,
TokenAuditPolicy = 16,
TokenOrigin = 17,
TokenElevationType = 18,
TokenLinkedToken = 19,
TokenElevation = 20,
TokenHasRestrictions = 21,
TokenAccessInformation = 22,
TokenVirtualizationAllowed = 23,
TokenVirtualizationEnabled = 24,
TokenIntegrityLevel = 25,
TokenUIAccess = 26,
TokenMandatoryPolicy = 27,
TokenLogonSid = 28,
MaxTokenInfoClass = 29
}

[StructLayout(LayoutKind.Sequential)]
struct TOKEN_MANDATORY_LABEL
{
public SID_AND_ATTRIBUTES Label;
}

[StructLayout(LayoutKind.Sequential)]
struct SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public int Attributes;
}

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);

[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool OpenProcessToken(IntPtr ProcessHandle,
TokenAccessLevels DesiredAccess,
out IntPtr TokenHandle);

[DllImport("advapi32.dll", SetLastError = true)]
static extern bool GetTokenInformation(IntPtr TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
IntPtr TokenInformation,
uint TokenInformationLength,
out uint ReturnLength);

[DllImport("kernel32.dll")]
static extern IntPtr LocalAlloc(uint uFlags, UIntPtr uBytes);

[DllImport("advapi32.dll", SetLastError = true)]
static extern IntPtr GetSidSubAuthority(IntPtr pSid, int nSubAuthority);

[DllImport("advapi32.dll", SetLastError = true)]
static extern IntPtr GetSidSubAuthorityCount(IntPtr pSid);
}
}

пятница, 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.

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

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

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

Знаете ли вы, что…

… среди блогов MSDN появился блог Сары Форд, переведенный на русский (за что огромное спасибо Виталию Зайко). Сара Форд (ее оригинальный блог здесь) работает в инженером по тестированию Visual Studio, а так же ведет блог по различным How-to и Did you know по использованию различных версий студии. Сара экстремально активный блогер, каждый день она как правило публикует по статье, так что скучать не придется :).

четверг, 19 июня 2008 г.

Shell Extension Handlers на .NET

Вчера разбирался с Shell Extension-ами нашего проекта. Мне предстояло сделать что-бы контекстное меню для определённой иконки на десктопе формировалось динамически. Решил погуглить на счет примера реализации системного интерфейса IContextMenu на .net и вот какую вешь обнаружил. Оказывается Майкрософт крайне не рекомендует реализовывать Shell Extension Handler-ы на .net, и особенно те которые могут загружаться в процессы (in-process shell extensions). Вот ссылка на на оригинальное сообщение Jesse Kaplan, (одного из CLR Program Manager), а ниже мой вольный перевод его слов:

К сожалению, единственный способ реализовать их – это неуправляемый С++ . Создание расширителей оболочки, которые загружаются в процесс (in-process shell extensions), это в действительности очень опасная вешь, поскольку таким образом вы можете внедрить управляемый код (и .NET Framework) в каждое приложение на машине, у которого есть стандартный Windows-диалог для открытия файлов.

Проблемы возникают из-за того что только одна версия .NET Framework может быть загружена в процесс (другие компоненты предназначенные для совместного использования как java и msxml имеют те же свойства и как следствие те же ограничения).

Если вы напишете ваш расширитель оболочки на .NET Framework 2.0 , а приложение написанное на .NET Framework 1.1 создаст стандартный диалог для открытия файлов ваш расширитель сгенерирует ошибку, так как не сможет работать на младшей версии. Все может стать еще даже хуже если ваш расширитель загрузится в процесс раньше другого приложения на .net. Наличие вашего расширителя может привести к тому что приложению придётся работать на версии рантайма, на которую оно не было рассчитано и оно упадёт. Из-за всех этих проблем мы настоятельно рекомендуем не использовать исполняющие среды и библиотеки, которые поддерживают загрузку только единственной версии в процесс (такие как .NET Framework, java, or msxml) для разработки расширителей оболочки.

Вот такие дела. Тем не менее, если все таки кому-то надо реализовывать расширители оболочки, то хороший пример находится совсем рядом: VS2003Dir\SDK\v1.1\Samples\Technologies\Interop\Applications\ShellCmd,

где VS2003Dir – это каталог, где установлена 2003 студия.

Как стать экспертом

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

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

GUI Шпионы (информация к размышлению)

В этой статье я попытался сделать краткий обзор инструментов, которые помогают исследовать пользовательский интерфейс Windows-приложений, и с которыми мне в той или иной мере доводилось работать самому. Для иллюстрации работы инструментов я буду использовать простую форму с кнопкой и пустым (и по этому невидимым в рантайме) PictureBox. Вот как эта форма выглядит в дизайн-тайме (первый) и в рантайме (второй).


Итак, встречайте: Spy ++, The Customiser, Managed Spy и WfSpy. Первые два инструмента рассчитаны на работу с native Win32 приложениями, так как были созданы до появления технологии .NET, однако работу свою выполняют хорошо и с managed-приложениями. Естественно, всех свойств и событий для .NET контролов они не покажут, но наиболее важные, такие как: координаты, размеры, текст, доступность (enable/disable) - будут.

Spy ++ (Microsoft, Win32)
Пожалуй, самый известный в своем роде. Этим инструментом я пользуюсь постоянно и по сей день, поскольку это самый надежный инструмент из перечисленных. Не так давно у него появился младший брат Remote Spy – ориентированный на работу с приложениями, написанными для мобильных устройств.Но это уже совсем другая история. Spy++ уже много лет входит в состав Visual Studio. Однако через меню кнопки Пуск (Start) вы его, скорее всего, не найдете и поэтому рекомендую самостоятельно поискать в каталоге установки студии через обычный файловый поиск spyxx.exe. У меня он находится здесь VSDir\Common7\Tools (VSDir – каталог, где установлена студия). На рисунке ниже представлено главное окно Spy++, как оно выглядит сразу же после старта.
Инструмент умеет показывать информацию о запущенных процессах, созданных окнах, потоках. Но работает только в режиме readonly – показывает различные свойства перечисленных объектов системы, но менять не дает, в отличие от The Customiser или Managed Spy. Позволяет так же отслеживать события, которые приходят к интересующему окну. Чтобы начать исследовать какую-нибудь сложную форму или контрол, вызовите команду Find Window из меню Spy.

В появившемся диалоге наведите курсор на иконку окна с прицелом и перетащите ее на интересующее окно или контрол.
Затем нажмите OK. В результате появится диалог со свойствами выбранного объекта. Пример такого окна ниже.
С этого диалога на закладке Windows можно быстро перейти к родительскому окну, на закладке Process можно быстро перейти к родительскому процессу или потоку исследуемого окна. Если нажать кнопку Synchronize, выбранный объект будет найден в дереве окон, которое отображается в центральной части главного окна.
Закроем окно свойств и перейдем к дереву окон. В контекстном меню узла дерева есть несколько команд, но расскажу только о Highlight. Эта команда позволяет подсветить мерцающей рамкой контрол или окно, соответствующее узлу дерева. Разумеется, чтобы ее увидеть, надо чтобы окно, в котором находится выбранный контрол, находилось в области видимости.
Ну, вот вкратце и все. У инструмента еще много возможностей и кого он заинтересует, найдет их самостоятельно. Дополнительное описание Spy++ можно найти на его страничке в MSDN.

The Customiser (Wanga International, Win32)
Это первый инструмент такого рода, с которым я познакомился. Настоящая игрушка для программистов (и не только). В изучении пользовательского интерфейса приложений намного удобней и интуитивней Spy++ или Managed Spy. Скачать его можно здесь. Позволяет во время работы приложения менять свойства его контролов – размеры, положение, надписи, видимость, доступность (enable/disable) и еще много чего. Посылать различные сообщения контролам и окнам. Например, любую кнопку, которая находится в состоянии disable можно сделать enable, потом нажать и посмотреть что произойдет :). Вообще The Customiser умеет много чего, всего и не перечесть. Весьма прикольно при помощи The Customiser модифицировать панель задач и кнопу Пуск/Start. На рисунке ниже показан результат работы над кнопкой Start и панелью задач.
После запуска The Customiser появится небольшое окошко с бегающим вправо-влево шариком. Кстати, после инсталляции The Customiser надо искать в корне меню All Programs, никаких папок с именем компании или приложения он не создает.
Нажмите кнопку Edit Window и появится основное окно для работы. Далее, надо нажать на кнопку On (после чего курсор поменяет свой вид на большой и желтый) и затем можно выбрать интересующее окно или контол.
После выбора компонента для исследования в диалоге появятся дополнительные закладки, на которых сгруппированы информация и действия по изменению компонента.
Коротко опишу назначение каждой закладки.
  • Size and Position – просмотр и изменение положения и размеров компонента.
  • Text – позволяет изменять текст компонента, например, заголовок окна или надпись на кнопке.
  • Misc. – закладка предназначена для изменения таких свойств компонента как enable, visibility. Также содержатся команды для посылки событий типа maximize, minimize.
  • API Message – закладка предназначена для послылки компоненту всевозможных событий.
Несмотря на богатые возможности и простоту работы с инструментом иногда отказывается работать и повисает. Порой еще и винду вешает.

Managed Spy (Microsoft, .NET 2.0)
Это бесплатный инструмент, написанный Benjamin Wulfe, участвовавшим в разработке Visual Studio, дизайнера Windows Forms, и ряда классов для Framework и Compact Framework. Скачать ManagedSpy можно здесь. Сразу после старта в левой части окна отображаются процессы с managed кодом, а справа – свойства выбранного процесса или его дочернего элемента.
В панели свойств отображаются свойства выбранного контрола, где их можно не только просматривать, но и менять (в отличие от Spy++). На рисунке ниже показан результат изменения свойства BackColor для невидного в рантайме PictureBox.
Есть функция, позволяющая на исследуемом окне подсветить исследуемый контрол (аналогично команде Highlight из Spy++). Для этого в меню View вызовите команду Show Window. В общем-то, простой и удобный использовании инструмент, но, к сожалению, не на всех окнах ManagedSpy работает. На простых все ОК, а вот на сложных иногда дает сбои. По крайней мере, у себя в проекте я им воспользоваться не смог. Более подробное описание ManagedSpy можно найти в статье в MSDN Magazine.

WfSpy (.NET 1.0, .NET 1.1)
Инструмент написан Rama Krishna Vavilala. Распространяется бесплатно и исходниками, которые прилагаются к его статье на CodeProject. Статья доступна вот здесь. К ней прилагается вариант, скомпилированный для .net 1.0. но для работы под .net 1.1 достаточно его просто перекомпилировать в VS 2003. В целом по внешнему виду очень похож на ManagedSpy. Сразу после старта в центральной части окна отображаются процессы с managed кодом. Чтобы посмотреть свойства заинтересовавшего компонента надо нажать кнопку Details. После чего откроется окно со списком свойств выбранного компонента, где можно как просматривать, так и изменять свойства компонента.
Заключение
Как видно из этого небольшого обзора, большинство инструментов достаточно просты и работа с ними интуитивно понятна. Самый сложный в использовании – это Spy++, однако, он, пожалуй, и самый функциональный. В статье приведены четыре инструмента, с другими мне сталкиваться не приходилось, так что если вы знакомы с каким-либо еще подобным инструментом - пожалуйста, напишите об этом в комментариях.

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

Скромный пожиратель ресурсов

В состав Visual Studio входит небольшая утилитка командной строки consume.exe, которая предназначена для загрузки ресурсов системы при нагрузочном тестировании. Найти ее можно по следующему пути: VSInstallDir\Common7\Tools\Bin. VSInstallDir – это путь где у Вас установлена студия. Основная задача этой утилиты – на определенное время основательно занаять какой-либо ценный ресурс системы (например, оперативную память, процессорное время, дисковое пространство и т.д). Формат работы утилиты следующий:

consume RESOURCE [-time SECONDS]

RESOURCE – как можно догадаться по имени параметра, это ресурс системы который надо занять. Он может принимать одно из следующих значений:
  • -physical-memory
  • -page-file
  • -disk-space
  • -cpu-time
  • -kernel-pool

SECONDS – а это время в секундах на которое надо занять ресурс.

воскресенье, 1 июня 2008 г.

Как быстро закрыть 23 Internet Explorer’а

Не знаю, кто как, а я для подобных целей использую утилиту Windows taskkill вот с такими параметрами:

taskkill /f /im iexplore.exe

Чтобы не ошибиться с набором имени процесса, можно вывести список всех процессов в консоль утилитой tasklist и потом воспользоваться командами Mark/Paste.

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

1. В System Tray найти иконку приложения.
2. Открыть у него контекстное меню.
3. В меню выбрать команду Exit.
4. И наконец, подтвердить, закрытие приложение.

И когда приходится по 20 раз на день запускать/закрывать клиента, я всегда держу открытым консольное окно с командой для запуска и закрытия приложения.

пятница, 30 мая 2008 г.

Смотрю в книгу – вижу буквы

Недавно нашел интересную статью Стива Макконелла «How To Read a Technical Article». Эту статью он написал 10 лет назад, когда занимал должность главного редактора в IEEE Software. Макконелл обобщает свой опыт чтения статей на компьютерную тематику и объясняет, как можно извлечь из статьи максимум пользы при лимите времени. Несмотря на то, что статья Макконелла прежде всего ориентирована на чтение статей в традиционных журналах, уверен, что его советы окажутся полезными и для статей блогосферы.

Он выделяет 4 типа чтения:
  • Базовый – распознавание отдельных слов. Приобретается, как правило, в детском саду. Название этой статьи характеризует данный стиль чтения.
  • Обзорное – более продвинутый уровень. Ориентирован на получение максимума информации за ограниченное время. Его еще называют «чтение по диагонали».
  • Аналитический – еще более продвинутый уровень. Извлечение максимума информации при неограниченном количестве времени.
  • Синтезирующий – самый крутой уровень. Получение информации из нескольких литературных источников, которой может и не быть в явном виде в каждом из них отдельно. Описание запутанное, но уровень обязывает :).
Начинать чтение Макконелл рекомендует с получения общей информации о статье: прочитать аннотацию, введение, заключение, название разделов статьи, затем прочитать статью по диагонали и, наконец, повторно прочитать заинтересовавшие разделы статьи – ещё более внимательно.

Также Макконелл рекомендует вступить в диалог с автором статьи и ответить на ряд вопросов, которые помогут понять статью лучше. Вот некоторые из них:
• О чем эта статья в целом?
• На чем автор хотел заострить внимание читателей?
• Не привирает ли автор в целом и в мелочах?
• Почему он пишет о A, а не о B?

P.S. В начале статьи я привел ссылку, где статью можно скачать совершенно бесплатно, а здесь ее предлагают купить за 19$ и вот что интересно: обе ссылки мне выдал Google и оба ресурса принадлежат IEEE Software. Странный бизнес.

вторник, 27 мая 2008 г.

Ложка меда в бочке дегтя

Недавно Сергей Розовик описывал неудобства связвнные с новым MSDN Magazine Online. Однако не все так плохо, есть и положительные мометны. Об одном из них я и хочу написать. Я не сам ее обнаружил :), об этой фиче написал в своем блоге Mike Stall.
Суть ее в том, что статью из MSDN для класса из BCL можно открыть по урлам такого вот вида:

http://msdn.microsoft.com/en-us/library/system.io.
filesystemwatcher
.aspx – для класса

http://msdn.microsoft.com/en-us/library/system.io.
filesystemwatcher.waitforchanged
.aspx – для метода класса

http://msdn.microsoft.com/en-us/library/system.io.
filesystemwatcher.path
.aspx – для свойства.

По моему, это очень удобно.

воскресенье, 25 мая 2008 г.

Моя любимая комбинация из трех пальцев

Нет, это не Ctr+Alt+Del, как некоторые могли подумать ;). Это – Ctrl+Shift+G. Уж больно часто в последнее время я использую эту команду. Она почему-то недокументированная и поэтому уверен, что многие о ней не знают. Это клавиатурное сочетание действует для комбобокса поиска, расположенного на панели инструментов Standard.


Если вы введете в этот комбобох имя файла (например, Class1.cs или app.config) и нажмете Ctrl+Shift+G, то команда пробежит по всем проектам открытого солюшена, найдет файл с таким именем и откроет его на редактирование. Эта функция существенно экономит время (и нервы) в случае сложных солюшенов с большим количеством проектов и файлов в них.

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

P.S. Кстати, попасть на эту панель, не снимая рук с клавиатуры, можно клавишами Ctrl+/ (VS 2005 и старше) и Ctrl+D (VS 2003).

суббота, 24 мая 2008 г.

Делегаты и события

Как вы думаете, где подвох в нижеприведенном коде?

button1.Click += new EventHandler(new EventHandler(OnBtnClick));
button1.Click -= new EventHandler(new EventHandler(OnBtnClick));

С подобным кодом я недавно встретился при отладке. Разумеется, он был не в таком очевидном виде. Подписка/отписка методов была завуалирована использованием разных делегатов, но с одинаковой сигнатурой и цепочкой вызовов методов, где эти делегаты и передавались, а на отладку проблемы мной было потрачено несколько часов.

Итак, вернемся к примеру. Этот код компилируется без ошибок и предупреждений. Метод, подписанный на событие, вызывается при генерации события, а вот отписка от события не работает.

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

public object Target
public MethodInfo Method

Target – это ссылка на объект, которому принадлежит метод, передаваемый в конструктор делегата. Он может быть null, если подписывается статический метод.
Method – содержит ссылку на подписываемый метод. При обычной подписке метода на событие, пример которой приведен ниже,

button1.Click += new EventHandler (form.OnBtnClick);

свойство Target будет содержать ссылку на form, а свойство Method – ссылку на подписываемый метод OnBtnClick.

Для случая, когда при создании делегата ему передается другой делегат (как в исходном примере), свойство Target ссылается на передаваемый делегат, а Method содержит ссылку на метод Invoke, который генерируется для каждого делегата.

При отписке делегата от события, для которого вызывается статический метод Delegate.Remove, у делегатов (уже подписанного и используемого для отписки) вызывается метод Equals, чтобы убедиться что они обертывают собой один и тот же метод одного и того же объекта. У делегатов (классы Delegate и MulticastDelegate) операторы равенства и методы Equals перегружены (их код можно посмотреть, например, в Reflector). В методе Equals сравниваются свойства Target и Method, а операторы равенства вызывают Equals. Сравнение свойства Target выполняется оператором ==, а поскольку свойство Target имеет тип object, то вызывается оператор сравнения для object. Оператор == для object в свою очередь сравнивает значения ссылок (Reference Equals), которые для нашего примера очевидно не совпадают. Делегаты, подписанный и используемый для отписки, считаются разными и, как следствие, отписка метода не происходит.

Надеюсь, эта статья поможет вам сэкономить время при отладке подобного кода и избежать таких ловушек при написании собственного.

среда, 23 апреля 2008 г.

Every build you break

Просто гениальная вещь. Песня про наши суровые будни. Посмотрите, не пожалеете!

P.S. Спасибо моей сестренке за присланную ссылку.

А где же фокус?

На днях знакомый спросил, есть ли у формы метод, при помощи которого можно узнать, у какого контрола находится фокус ввода. Конечно, его нетрудно написать и самому, но зачем изобретать велосипед, если можно украсть у соседа :). Быстренко пробегаюсь в Reflector'е по методам и свойствам со словом Focus. Ничего подходящего не нахожу. Но вроде же было!.. К счастью, свойство я таки припомнил. Называется оно ActiveControl и находится у ContainerControl. К сожалению, в описании этого свойства в MSDN не указывается, что оно связано с текущим фокусом ввода.

вторник, 22 апреля 2008 г.

Do you speak english?

Английcкий - важная составляющая нашей профессии. Как бы банально это ни звучало, это так. И поэтому каждый в той или иной степени владеет языком. Конечно, не все довольны своим уровнем и многие совершенствуют свои знания. Мой друг, принадлежащий к этой группе, разработал небольшой сайт и программу, помогающую нам в этом правильном деле. Программа предназначена для чтения книг на английском. Там также есть англо-русский словарь с пояснениями слов и их синонимами. Программа распространяется бессплатно, никаких регистраций не требует, рекламой не перегружена (ее там вовсе нет :)). Всех, кому эта тема интересна, приглашаю попробовать http://www.forcemem.com.

понедельник, 21 апреля 2008 г.

Ахтунг!

Ну вот, дожили. Сегодня и я пополнил список счастливчиков у которых украли ICQ логин. Пришел утром на работу и получил сообщение от ICQ клиента, что мой логин использовался на другом компьютере, и залогиниться уже не удается. Видимо, пароль оказался слабым. Написал в поддрежку ICQ, но как показал поиск в Google, дело это безнадежное. Так что если кто-то будет верещать какие-нибудь гадости от моего имени – не верьте, это не я, я белый и пушистый :).

четверг, 13 марта 2008 г.

5 инструментов

Эстафетную палочку про мои 5 инструментов для эффективной работы я получил от Сергея Розовика (Stump's Workshop). Хотя это больше похоже не на эстафету, а сетевой маркетинг или на механизм распространение вируса :). Что касается эффективной работы, то могу сказать Сергей умеет сам работать эффективно и другим не даст бездельничать :). Однако, на мой взгляд, эффективность Сергея не в инструментах, а прежде всего в склонности к порядку и четкости в работе.
Итак, 5 инструментов, которые делают мою работу более эффективной. Порядок, в котором они перечислены не имеет значения так как каждый из них используется на определенном этапе работы. Хочу подчеркнуть что это не список инструментов с которыми я работаю больше всего, а именно те которые, по моему мнению, помогают мне работать эффективней.
1. Reflector – постоянно и много :). Зачастую его даже удобней использовать вместо MSDN, т.к. показывает краткое описание классов и методов из Class Reference. Наиболее часто используемые команды – конечно же Search и Analyze. Даже код, на который есть исходники порой удобней анализировать рефлектором.
2. Средство для рефакторинга кода. Без разницы какое. В VS 2003 это может быть, например, Resharper или CodeRush, в VS 2005 подойдет и встроенные возможности, хоть и его возможности существенно слабее вышеназванных средств. Особенно большой скачок в продуктивности происходит при использовании Rename.
Правильный дебаггер. В 95% случаев использую VS 2003/2005, DbgClr , в 5% других WinDBG + SOS.dll. Дебаггер помогает не только при отладке кода, но и при изучении как работает неизвестный код. Брейкпоинт в правильном методе и при помощи Call Stack легко понять, как вы в него попали, посмотреть поля интересующего объекта, а при помощи SOS.dll узнать какие объекты есть в памяти, кто и почему держит тот или иной объект. Интернет и поисковик. Поиск дополнительной информации по функциональности и по не понятными ошибкам различных инструментов, сервисов и серверов.
Лист бумаги и карандаш. С листом бумаги и карандашом удобно думать над новыми фичами. Придумывать чудо-абстракции и анализировать чужие.

P.S. Хочу передать отдельное спасибо, Сергею Федоренко, который взывал к моей совести, что бы я не затягивал с этим постом.

вторник, 8 января 2008 г.

Mysteries of .NET 2.0 Configuration

Не так давно наткнулся на СodeProject на серию замечательных статей под общим названием Mysteries of .NET 2.0 Configuration про System.Configuration 2.0. В net 2.0 работа с конфигурационными файлами приложения была существенно переработана, но единого и полноценного описания секций различного уровня сложности и архитектуры System.Configuration 2.0 мне встречать не приходилось.

Далее вкратце пройдусь по статьям.

Unraveling the Mysteries of .NET 2.0 Configuration – описываются основные сведения про System.Configuration. Есть полноценное описание того, как создавать и регистрировать секции и группы, как создавать настройки и коллекции настроек различного уровня сложности. В большинстве случаев этой статьи для работы с конфигурационными файлами будет предостаточно. Автор дает рекомендации, основанные на собственном опыте, по повышению производительности и организации кода.

Decoding the Mysteries of .NET 2.0 Configuration – описываются валидаторы и конверторы типов данных. Валидаторы позволяют организовывать различного рода проверки что данные попадают в определенный диапазон. Конверторы преобразовывают данные из строкового вида в .NET объект и обратно. В статье описываются возможности стандартных валидаторов и конверторов, описываются способы создания собственных.

Cracking the Mysteries of .NET 2.0 Configurationпоследняя статья из серии. Описывает более подробно внутреннюю архитектуру System.Configuration. Особенности работы для Web и Windows приложений.