Hungry Mind , Blog about everything in IT - C#, Java, C++, .NET, Windows, WinAPI, ...

"Baptizer" или "Креститель"

Иллюстрация "Креститель".

Show repentance, sinners! (c) Agnet.

Home router with WAN, LAN, WiFi and Linux

Я долго собирался купить домой маленький маршрутизатор. Хотел WiFi, поддержку IDE диска и, самое главное, - Linux, который можно настроить из консоли. На форумах узнал, что лучшим решением является серия ASUS WL-500.

Уже несколько дней, как приобрел ASUS WL-500g Premium. ASUS WL-500g Premium

В наличии:
  • 1 100Mbit WAN
  • 4 100Mbit LAN
  • WiFi типа g (54Mbit)
  • 2 USB
  • Linux
С поддержкой IDE у него не сложилось, да и смысла нет - производительность такого решения крайне низкая.

Настраивается за несколько минут через веб интерфейс, позволяет принудительно установить MAC адрес сетевой карты WAN (я был очень доволен этой функцией т.к. мой провайдер привязывается к MAC сетевой карты). Есть проброс портов, простенький файрвол, поддержка USB-принтера, DHCP-сервер. Короче говоря, его функций хватит для рядового пользователя с головой. К примеру, если вы беспокоитесь о торрентах из-за внутреннего айпи, - не надо, рутер поддерживает UPnP, поэтому uTorrent заработает на отдачу без проблем.

Я, как бывший любитель UNIX, сразу же поставил на устройство альтернативную прошивку от Олега. Самым важным для меня оказалось наличие telnet сервера для доступа к консоли устройства. Дальше - интереснее, т.к. с архитектурой MIPS я не знаком и опыта работы с подобными железяками у меня не было. NVRAM, FlashFS и много нового. Благо, на форуме настройка девайса расписана очень прилично. Пока что я поднял лишь SSH сервер, в будущем планирую сделать из WL-500g полноценную качалку (*ttp, torrent). Но для этого нужно устройство хранения данных и много часов хардфакинга.

Напоследок, несколько неприятных моментов... Я расчитывал, что моя мама ASUS P5B Deluxe с встроенной карточкой WiFi сможет нормально работать без проводов. Но, не судьба, - при скорости больше 1М/с мышка начинает дергаться. Подозреваю, что плата генерирует слишком много прерываний.

Install Oracle 11g sample schemas

Недавно потребовались демо схемы БД в Oracle. Существует способ накатить их на существующую базу, но для этого потребуется для начала скачать Oracle Database 11g Examples (formerly Companion). Далее с помощью sqlplus нужно выполнить файл YOUR_PATH\demo\schema\mksample.sql:
SQL> @YOUR_PATH\demo\schema\mksample.sql passwd_system passwd_sys pw_hr pw_oe pw_pm pw_ix pw_sh pw_bi users temp x:\path\to\log\with\trailing\slash\
SQL> @d:\Oracle\Db\11.1.0\db0\demo\schema\mksample.sql sys_passwd sys_passwd hr_passwd oe_passwd pm_passwd ix_passwd sh_passwd bi_passwd users temp c:\temp\
Параметры можно указать как в командной строке, так и интерактивно.

Перед загрузкой нужно выполнить еще некоторые действия, поскольку в некоторых файлах (sale1v3.dat, например) в роли разделителя целой и дробной частей выступает точка, а параметры указывают на американскую локаль:
CREATE TABLE sales_transactions_ext
( PROD_ID         NUMBER,
  CUST_ID    NUMBER,
  TIME_ID    DATE,
  CHANNEL_ID  NUMBER,
  PROMO_ID    NUMBER,
  QUANTITY_SOLD   NUMBER,
  AMOUNT_SOLD  NUMBER(10,2),
  UNIT_COST  NUMBER(10,2),
  UNIT_PRICE  NUMBER(10,2)
)
ORGANIZATION external 
(
  TYPE oracle_loader
  DEFAULT DIRECTORY data_file_dir
  ACCESS PARAMETERS 
  (
    RECORDS DELIMITED BY NEWLINE CHARACTERSET US7ASCII
    TERRITORY AMERICAN
    BADFILE log_file_dir:'ext_1v3.bad'
    LOGFILE log_file_dir:'ext_1v3.log'
    FIELDS TERMINATED BY "|" OPTIONALLY ENCLOSED BY '^' LDRTRIM 
    ( PROD_ID         ,
      CUST_ID         ,
      TIME_ID         DATE(10) "YYYY-MM-DD", 
      CHANNEL_ID      ,
      PROMO_ID        ,
      QUANTITY_SOLD   ,
      AMOUNT_SOLD     ,
      UNIT_COST       ,
      UNIT_PRICE      
    ) 
 )
 LOCATION
 ('sale1v3.dat')
)
REJECT LIMIT 100;
Можно заменить все точки на запятые или вписать територию с нужным форматом дробных чисел. Я использовал первый вариант.

Green Card Lottery

На одном из уроков английского речь зашла о лотереи Green Card. Я заинтересовался и решил заполнить форму. Поиск в гугле выдал тучу сайтов. Я нажал самую верхнюю ссылку, которая гласила "USA Green Card Lottery". Начал заполнять анкету и на каком-то шаге меня попросили заплатить 50 баксов! Я, понятное дело, послал это все к черту, но спросил у Джо насчет денег. Он сказал, что на 99% уверен в бесплатности лотереи. Только что я нашел настоящую форму заявления.

А вот тут, кстати, обращают внимание на сайты, выдающие себя за правительственные:

Please note: There have been instances of fraudulent websites posing as official U.S. Government sites. Some companies posing as the U.S. Government have sought money in order to "complete" lottery entry forms. There is no charge to download and complete the Electronic Diversity Visa Entry Form. The Department of State notifies successful Diversity Visa applicants by letter, and NOT be electronic mail. To learn more, see the Department of State Warning and the Federal Trade Commission Warning in the Related Links section of this page.

Да и адрес www.dvlottery.state.gov не асоциируется с Green Card. Вообще.

Visual Studio 2008 download

90-Day Trial Downloads
  • Visual Studio 2008 Professional Edition (Coming Soon)
  • Visual Studio Team System 2008 Team Suite
  • Visual Studio Team System 2008 Team Foundation Server
  • Visual Studio Team System 2008 Test Load Agent
In addition, you can download the free Visual Studio 2008 Express Editions.

Новость на блоге Scott Gu.

Visual Studio 2008 will be available for download THIS week

На блоге MSDN Subscriptions появилась информация, что Visual Studio будет доступна подписчикам на этой неделе уже сейчас. Ура!

Microsoft Corporation Integrates BCGControlBar Pro Technology for Future MFC Update

На Visual C++ Team Blog появился пост про грядущий апдейт всеми любимой библиотеки MFC. Вкратце, нам обещают support for the Office 2007 Ribbon Bar, Office-style menus, Visual Studio-style docking toolbars, tabbed documents and much more.

Правда есть и обратная сторона медали: это не разработка Microsoft. Да и глупо было бы на это расчитывать, ведь библиотеки, которыми пользуются создатели Microsoft Office или любого другого коммерческого решения, вероятно, никогда не выйдут за пределы компании because internal code isn't at the level required of a product, respectively. К тому же, эти продукты написаны не на MFC. Нам подсунут интегрированную в MFC библиотеку BCGControlBar Professional Edition. Это все, конечно, хорошо, но качество оставляет желать лучшего. С другой стороны, продукт уже много лет лучший на рынке и многие известные организации его используют. Надеюсь, парни поработают над кодом и сделают из него конфетку с качественной документацией.

Microsoft Line Of Code Counter

Microsoft Line Of Code Counter - порядочно полезная утилита!

Из названия понятно, что считает строчки кода. Но это не аналог Project Line Counter т.к. позволяет

  • использовать источник файлов (TFS, VSS или каталог файловой системы)
  • выполнять подсчет изменений содержимого файлов
  • считать метрики по различным методологиям

Гибко настраивается через XML файл. Изначально поддержка всех основных MS-языков. Работает как в составе Visual Studio 2005 так и отдельно.

Visual Studio 2008 release date is November 2007

Похоже, что Visual Studio 2008 релизнется в ноябре (в конце). Это стало известно на конференции TechEd в Барселоне. Жду с нетерпением!!!

Xtreme Toolkit Pro v11.20 ZWT

splash
Появился наконец после мучительных лет ожидания Xtreme Toolkit Pro v11.20 в исходниках. Щас посмотрю, что они там наделали. Прошлые версии уступали BCG по функциональности и, что более существенно, по качеству.

Using .NET Controls from WinAPI/MFC/WTL applications (Part 1)

До появления .NET графические приложения разрабатывались с использованием узкого круга инструментов и библиотек. Самыми популярными были Borland Delphi/C++ Builder (VCL), Microsoft Visual Studio (WinAPI, MFC, WTL) и QT. Инфраструктура Borland позволяла сторонним разработчикам создавать библиотеки графических елементов управления, которые хорошо интегрировались в IDE и позволяли быстро "рисовать" красивые, удобные интерфейсы. Microsoft Visual Studio на тот момент была по всем параметрам хуже - слабенький компилятор, не поддерживающий актуальные стандарты, отсутствие полноценного дизайнера форм, плохо спроектированная обьектная модель базовых библиотек (а их расширения можно перечислить на пальцах одной страусиной ноги). Выход Visual Studio 2002/2003 (официальное рождение .NET) сильно повлиял на чашу весов - все больше проектов пишут под .NET. Borland решил не отставать и включил поддержку управляемого кода в свою IDE, правда это не поменяет текущее аутсайдерское положение.

Единственный механизм, который позволяет подружить функционал различных платформ (речь о платформах разработки, а не ОС), - COM/ActiveX. Ни у кого не вызывает сомнений факт возможности интеграции компонента VCL-ActiveX в приложение MFC или наоборот. Оказывается, .NET тоже позволяет пользоваться этим механизмом на полную. Я рассмотрю лишь случай использования .NET-обьектов из неуправляемого кода (C++/CLI является управляемым!), так как обратный вариант взаимодействия прост и не нуждается в разжевывании. Существует 2 способа достижения поставленной цели:

  1. Классический - использование .NET через COM/ActiveX.
  2. Анальный - непосредственный хостинг CLR и использование COM-подобных механизмов взаимодействия.

Каждый рассмотрим детально. Для понимания того, что написано далее, необходимы твердые знания технологии COM! Мы напишем элемент управления .NET WinForms (ComplexControl), который попытаемся использовать из неуправляемого приложения следующим образом:

  1. Создать екземпляра обьекта
  2. Добавить элемент управления в форму или диалог
  3. Вызывать методы обьекта, читать и записывать его свойства
  4. Подписываться на уведомления и получать их через callback-интерфейс

Диаграмма классов следующая:

Часть первая. COM-Interop в .NET.


Любой тип MySuperDotNetType (класс MySuperDotNetClass, структура MySuperDotNetStruct, перечисление MySuperDotNetEnum, инртерфейс IMySuperDotNetInterface или делегат MySuperDotNetDelegate) при определенных условиях может быть доступен посредством COM. Эти условия также влияют на видимость полей структур, методов и свойств классов. Минимальный набор таков:
  1. Область видимости элемента - public.
  2. Наличие атрибута [ComVisible(true)] в обьявлении самого элемента либо в его родительской области (сборка в целом или тип, в котором находится обьявление).
    Также его можно использовать для сокрытия ([ComVisible(false)]) полей структуры, методов и свойств класса, а также внутренних типов.
Далее любой элемент CLR, удовлетворяющий этим требованиям, будем называть ComVisible.

Дополнительно можно использовать следующие атрибуты для более тонкой настройки взаимодействия:
  • [Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")] - CLSID CO-класса, IID интерфейса, ID библиотеки типов (в зависимости от контекста атрибута - класс, интерфейс, сборка)
  • [ProgId("MyHumanReadableTypeName")] позволяет задавать ProgID для типа MySuperDotNetType
  • [ClassInterface(ClassInterfaceType.XXX)] определяет вид экспортируемого интерфейса класса (далее - класс-интерфейс) MySuperDotNetClass. Перечисление ClassInterfaceType содержит 3 значения:
    1. AutoDispatch
      Означает, что класс будет явно поддерживать исключительно позднее связывание через свой dispinterface. Библиотека типов, которую создает утилита Tlbexp.exe (о ней - чуть позже), не содержит информацию о "начинке" этого интерфейса - свойствах и методах. Это сделано для предотвращения кеширования (когда они подставляются непосредственно в вызовы метода Invoke компилятором) клиентами значений DISPID. Является значением по умолчанию.
      Вот, как в этом случае выглядит IDL для CO-класса ComplexControl:
      [
        uuid(2D7FDCB4-6C3F-4529-A93D-10DFC72927B1),
        version(1.0),
        custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, NetControlsLibrary.ComplexControl)
      ]
      coclass ComplexControl {
          [default] interface _ComplexControl;
          interface _Object;
          interface IComponent;
          interface IDisposable;
          interface IWin32Window;
          interface IComplexView;
          [default, source] dispinterface IComplexView_Events;
      };
      
      
      Обратите внимание, что CO-класс ComplexControl явно поддерживает итерфейс _Object, который на самом деле - дуальный dispinterface:
      [
        uuid(65074F7F-63C0-304E-AF0A-D51741CB4A8D),
        hidden,
        dual,
        nonextensible,
        custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, System.Object)
      
      ]
      dispinterface _Object {
          properties:
          methods:
              [id(00000000), propget, custom(54FC8F55-38DE-4703-9C4E-250351302B1C, 1)]
              BSTR ToString();
              [id(0x60020001)]
              VARIANT_BOOL Equals([in] VARIANT obj);
              [id(0x60020002)]
              long GetHashCode();
              [id(0x60020003)]
              _Type* GetType();
      };
      
      
      Обратите внимание, что интерфейс _ComplexControl - это dispinterface, а в CO-классе обьявлен, как обычный:
      [
        uuid(6148B23F-BFFE-344F-809A-FF0915CC4C5B),
        hidden,
        dual,
        custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, NetControlsLibrary.ComplexControl)
      
      ]
      dispinterface _ComplexControl {
          properties:
          methods:
      };
      
      
      Важно:
      • Такой диспинтерфейс позволяет использовать исключительно ComVisible методы и свойства класса такие, что C#-выражение myClassInstance.SomeMemberIWantToUseFromIDispatch не вызывает ошибку компиляции. К примеру, методы интерфейсов с явной реализацией сюда не попадают. Другими словами, он еквивалентен общедоступному интерфейсу (здесь речь идет концепции, а не о ключевом слове interface) класса.
      • Возможности явно задать IID для него нет, поэтому во время разработки можно смело ожидать сюрпризов в виде E_NOINTERFACE.
    2. AutoDual
      Означает, что интерфейс класса будет дуальным дисп-интерфейсом (dual dispinterface). Анологично предыдущему варианту + возможность использовать интерфейс класса через стандартный vtbl-механизм + в библиотеку типов попадает информация об экспортируемых свойствах и методах (попадающих под вышеизложенное правило). Использовать этот механизм не рекомендуют из-за проблем с версионностью (изменение таблицы виртуальных функций после добавления или удаления методов класса).
      IDL для CO-класса ComplexControl анологичен, а вот интерфейс _ComplexControl выглядит монстрообразно:
      [
        uuid(6148B23F-BFFE-344F-809A-FF0915CC4C5B),
        hidden,
        dual,
        custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, NetControlsLibrary.ComplexControl)
      
      ]
      dispinterface _ComplexControl {
          properties:
          methods:
              [id(0x60020000), propget,
                custom(54FC8F55-38DE-4703-9C4E-250351302B1C, 1)]
              BSTR ToString();
              [id(0x60020001)]
              VARIANT_BOOL Equals([in] VARIANT obj);
              [id(0x60020002)]
              long GetHashCode();
              [id(0x60020003)]
              _Type* GetType();
              [id(0x60020004)]
              VARIANT GetLifetimeService();
              [id(0x60020005)]
              VARIANT InitializeLifetimeService();
              [id(0x60020006)]
              _ObjRef* CreateObjRef([in] _Type* requestedType);
              [id(0x60020007), propget]
              ISite* Site();
              [id(0x60020007), propputref]
              void Site([in] ISite* rhs);
              [id(0x60020009)]
              void add_Disposed([in] _EventHandler* value);
              // Last 1000000 lines omited for brevity... :)
      };
      
    3. None
      Означает, что интерфейс для класса не генерируется. Рекомендуемое значение.
  • [InterfaceType(ComInterfaceType.XXX)] - по аналогии с предыдущим, только касательно .NET-интерфейсов.
  • [ComDefaultInterface(typeof(IMySuperDotNetInterface))] указывает на интерфейс по-умолчанию CO-класса. В IDL - default.
  • [ComSourceInterfaces(typeof(IMySuperDotNetInterface_Events))] присоединяет Sink-интерфейс (добавляет в класс Connection Point). В IDL - source. О связи этих интерфейсов с классом - далее.
  • [DispId(1234)] - явно заданный DISPID для элемента дисп-интерфейса (свойства или метода).
  • Прочие атрибуты из пространства имен System.Runtime.InteropServices.

С помощью интроспекции CLR способен спроектировать обьектную модель на COM и создать на лету объект (так называемый CCW - COM Callable Wrapper), совместимый с конвенциями вызова __stdcall и по структуре памяти совпадающий с vtbl-интерфейсами. CCW выглядит, как обычный COM-объект, но транслирует все вызовы в упраыляемую среду. А утилита Tlbexp.exe (Type Library Exporter) способна создать для сборки библиотеку типов (Type Library) в виде tlb-файла, который можно просмотреть с помощью программы OleView (идет в комлекте со студией по адресу C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin\OleView.Exe).
Алгоритм отображения сборки на IDL сложен и часто просто непонятен. Более полную модель можно увидеть с помощью OleView, заглянув в категорию ".NET Category" (насколько я понимаю, эту информацию .NET-обьекты отдают непосредственно через IDispatch::GetTypeInfo). Вот несколько интересных и важных моментов, которые стоит знать:

  • Информация tlb-файла является порядочно урезанной версией реальной обьектной модели, которую строит CLR.
  • Каждый .NET COM-обьект поддерживает интерфейсы IUnknown, IDispatch, _Object, IConnectionPointContainer, IProvideClassInfo, ISupportErrorInfo, IManagedObject.
  • ComplexControl дополнительно поддерживает интерфейсы _Component, _ContainerControl, _Control, _MarshalByRefObject, _ScrollableControl, _UserControl, IComponent, IOleControl, IOleInPlaceActiveObject, IOleInPlaceObject, IOleObject, IOleWindow, IPersist, IPersistPropertyBag, IPersistStorage, IPersistStreamInit, IQuickActivate, IViewObject, IViewObject, IWin32Window. Судя по этому списку можно сделать следующие выводы.
  • Каждый .NET COM-обьект поддерживает все ComVisible интерфейсы своих предков.
  • Каждый .NET COM-обьект поддерживает все ComVisible класс-интерфейсы своих предков (с учетом атрибута ClassInterfaceType, конечно-же).
  • Каждый .NET WinForms Control COM-обьект поддерживает множество интерфейсов (если не все) OLE/ActiveX. Соответственно, может быть использован, как OLE/ActiveX.
Для того, чтобы использовать библиотеки посредством классического COM, их нужно зарегистрировать.
  1. Статической регистрацией занимается утилита RegAsm.exe (C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe). Она выполняет инструментирование сборки (аналогичным Tlbexp.exe образом) и вносит записи в системный реестр. Запуск RegAsm.exe можно возложить на Visual Studio - в настройках проекта в разделе Build поставить галочку [Register for COM interop]. Запись в реестре для CO-класса ComplexControl выглядит следующим образом:
    [HKEY_CLASSES_ROOT\CLSID\{2D7FDCB4-6C3F-4529-A93D-10DFC72927B1}]
    @="NetControlsLibrary.ComplexControl"
    [HKEY_CLASSES_ROOT\CLSID\{2D7FDCB4-6C3F-4529-A93D-10DFC72927B1}\Implemented Categories]
    [HKEY_CLASSES_ROOT\CLSID\{2D7FDCB4-6C3F-4529-A93D-10DFC72927B1}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}]
    [HKEY_CLASSES_ROOT\CLSID\{2D7FDCB4-6C3F-4529-A93D-10DFC72927B1}\InprocServer32]
    @="mscoree.dll"
    "Assembly"="NetControlsLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
    "Class"="NetControlsLibrary.ComplexControl"
    "CodeBase"="file:///D:/Development/Projects/NETComInterop/Debug/NetControlsLibrary.dll"
    "RuntimeVersion"="v2.0.50727"
    "ThreadingModel"="Both"
    [HKEY_CLASSES_ROOT\CLSID\{2D7FDCB4-6C3F-4529-A93D-10DFC72927B1}\InprocServer32\1.0.0.0]
    "Assembly"="NetControlsLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
    "Class"="NetControlsLibrary.ComplexControl"
    "CodeBase"="file:///D:/Development/Projects/NETComInterop/Debug/NetControlsLibrary.dll"
    "RuntimeVersion"="v2.0.50727"
    [HKEY_CLASSES_ROOT\CLSID\{2D7FDCB4-6C3F-4529-A93D-10DFC72927B1}\ProgId]
    @="NetControlsLibrary.ComplexControl"

    Здесь {2D7FDCB4-6C3F-4529-A93D-10DFC72927B1} - CLSID моего класса ComplexControl, {62C8FE65-4EBB-45e7-B440-6E39B2CDBF29} в ключе "Implemented Categories" - GUID категории компонента (".NET Category" в нашем случае), 1.0.0.0 в ключе "InprocServer32" - версия класса (поддержка нескольких версий компонента). Стоит отметить, что InprocServer32 указывает на mscoree.dll! Именно там находится точка входа в фабрику классов - функция DllGetClassObject. Ну, а остальные записи ниже InprocServer32 служат для нахождения нужной сборки с типом (читает их, конечно-же, не подсистема COM, а CLR).
  2. Динамически зарегистрировать поможет класс TypeLibConverter.
  3. Утилита regsvcs.exe тоже годится, но это другой конек, связанный с COM+.
Для добавдения в CO-класс точки подключения (эта часть была самая сложная в инвестигации!) необходимо выполнить следующие действия:
  1. Создать интерфейс IMySuperDotNetClass_Events
  2. Настроить COM-аспекты - [ComVisible(true)], [Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")] и [InterfaceType(ComInterfaceType.XXX)] (рекомендуется использовать InterfaceIsIDispatch, обьяснение дальше).
  3. Наполнить интерфейс обьявлениями методов, совместимыми с типами-делегатами поддерживаемых событий.
  4. Добавить в класс MySuperDotNetClass определения событий с именами, которые соответствуют именам функций интерфейса IMySuperDotNetClass_Events.
Лучше это показать на примере:
Интерфейс (открытый) и делегат (область видимости не имеет значения).
internal delegate void PropertyChangedEventHandler(Object src, String propertyName);

[ComVisible(true)]
[Guid("FD9AEC7A-3688-4394-B4D0-636E4A7FE3B9")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] // if InterfaceIsDual then SinkObj must also be dual!
public interface IComplexView_Events
{
   [DispId(0x01)]
   void PropertyChanged(Object src, String propertyName);
}
Тело класса ComplexControl.
#region IComplexView_Events Mappings

private PropertyChangedEventHandler _propertyChanged;
internal event PropertyChangedEventHandler PropertyChanged {
   add {
      _propertyChanged += value;
      Trace.WriteLine("PropertyChanged.add(...)");
   }
   remove {
      _propertyChanged -= value;
      Trace.WriteLine("PropertyChanged.remove(...)");
   }
}

#endregion
Copyright 2007-2011 Chabster