IBProvider, Registration Free COM и AnyCPU.

Привет всем.

В дистрибутив .NET провайдера добавлен пример #23, в котором продемонстрирована работа с IBProvider-ом без регистрации в системе из .NET приложения, откомпилированного для AnyCPU платформы.

Общие положения.

1. Нужно модифицировать 32-битную и 64-битную сборки IBProvider-a. Они должны обрабатывать разные CLSID-ы.

Для этого нужно модифицировать ресурс PROG_REG_PARAMS.

Данные для 32-битного бинарника:

provider_file_ext        =ibp;
provider_clsid           ={638BA021-35CB-43AE-83EF-D1907793E9A8};
error_service_clsid      ={CE3D5A70-C784-4862-8FB4-3B554CBAC350};
data_link_page_clsid     ={52D99D84-7A2F-4B5A-98BE-C2BA7D8334E1};
adv_data_link_page_clsid ={EBEC27FE-12E6-4DA9-B4EA-BCA8DEE196F5};
provider_prog_id         ="LCPI.IBProvider.3.32bit.Private";
provider_prog_id_no_ver  ="LCPI.IBProvider.32bit.Private";
provider_descr           ="LCPI OLE DB Provider for InterBase [v3] [32bit] [Private]";
error_service_descr      ="LCPI.IBProvider Error Lookup [v3] [32bit] [Private]";
data_link_page_descr     ="LCPI.IBProvider Data Link Page [v3] [32bit] [Private]";
adv_data_link_page_descr ="LCPI.IBProvider Advanced Data Link Page [v3] [32bit] [Private]";

Данные для 64-битного бинарника:

provider_file_ext        =ibp;
provider_clsid           ={B770F2BC-BEDC-4B88-8315-7F1E11B5F536};
error_service_clsid      ={434FC88D-B928-4F19-A0EA-F282EEFEBD52};
data_link_page_clsid     ={07793F79-8AF2-4EDA-B753-999BD19AC5CA};
adv_data_link_page_clsid ={EA135F17-A1E5-408E-9B7C-2B6B9F55DDA4};
provider_prog_id         ="LCPI.IBProvider.3.64bit.Private";
provider_prog_id_no_ver  ="LCPI.IBProvider.64bit.Private";
provider_descr           ="LCPI OLE DB Provider for InterBase [v3] [64bit] [Private]";
error_service_descr      ="LCPI.IBProvider Error Lookup [v3] [64bit] [Private]";
data_link_page_descr     ="LCPI.IBProvider Data Link Page [v3] [64bit] [Private]";
adv_data_link_page_descr ="LCPI.IBProvider Advanced Data Link Page [v3] [64bit] [Private]";

Для модификации можно воспользоваться утилитой командной строки _Win32ResUpdater.exe из дистрибутива 32-битного IBProvider-a. В 64-битном провайдере лежит 64-битная версия этой утилиты — _Win32ResUpdater_w64.exe

Команда для модификации 32-битного провайдера будет выглядеть вот так:

_Win32ResUpdater.exe -write -file IBProvider.32bit.txt -module _IBProvider_v3_32bit_private.dll -id 1 -lang 1033 -type PROG_REG_PARAMS

64-битный провайдер, модифицируется аналогичным образом:

_Win32ResUpdater.exe -write -file IBProvider.64bit.txt -module _IBProvider_v3_64bit_private.dll -id 1 -lang 1033 -type PROG_REG_PARAMS

Утилита может еще выгружать/удалять/добавлять ресурсы из исполняемых модулей. Справка параметров командной строки прилагается.

2. Модифицированные DLL-и провайдера имеет смысл положить в подкаталоги исполняемого файла, который и будет использовать провайдер. В примере предлагается положить эти файлы в подкаталоги «private\32bit» и «private\64bit».

В эти же каталоги можно закинуть DLL-и Visual Studio CRT: msvcp120.dll и msvcr120.dll. Естественно, правильной разрядности.

3. Нужно модифицировать манифест исполняемого файла. В него добавляются такие элементы:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <file name = "private\64bit\_IBProvider_v3_64bit_private.dll">
   <comClass progid="LCPI.IBProvider.3.64bit.Private" clsid="{B770F2BC-BEDC-4B88-8315-7F1E11B5F536}" threadingModel = "Both" />
  </file>
  <file name = "private\32bit\_IBProvider_v3_32bit_private.dll">
   <comClass progid="LCPI.IBProvider.3.32bit.Private" clsid="{638BA021-35CB-43AE-83EF-D1907793E9A8}" threadingModel = "Both" />
  </file>
</assembly>

Для модификации следует воспользоваться утилитой из Windows SDK — mt.exe. Командная строка выглядит так:

mt.exe -updateresource:<путь к исполняемому файлу>;#1 -manifest ibprovider.manifest

Здесь ibprovider.manifest — это файл с вышеуказанными дополнительными данными для манифеста.

Отмечу, что операция модификации манифеста выполняется автоматически в процессе компиляции примера.

4. Собственно сам код работы с провайдером, в котором ключевым элементом является выбор идентификатора (ProgID) IBProvider-a в зависимости от разрядности процесса:

using System;
using lcpi.data.oledb;

namespace Sample_0023{
////////////////////////////////////////////////////////////////////////////////
//class Program

class Program
{
 private const string c_cn_str
   ="location=localhost:d:\\database\\employee.fdb;"
   +"user id=gamer;"
   +"password=vermut;";

 //-----------------------------------------------------------------------
 static int Main()
 {
  int resultCode=0;

  try
  {
   var cnsb=new OleDbConnectionStringBuilder(c_cn_str);

   switch(IntPtr.Size)
   {
    case 4: cnsb.Provider="LCPI.IBProvider.3.32bit.Private"; break;
    case 8: cnsb.Provider="LCPI.IBProvider.3.64bit.Private"; break;

    default:
     throw new ApplicationException("Unexpected platform!");
   }//switch

   using(var cn=new OleDbConnection(cnsb.ConnectionString))
   {
    Console.WriteLine("Try to connect ...");

    cn.Open();

    Console.WriteLine("OK!");

    var t=cn.GetSchema(OleDbMetaDataCollectionNames.DataSourceInformation);

    Console.WriteLine
     ("provider: {0}",
      t.Rows[0][OleDbMetaDataCollectionColumnNames
                 .DataSourceInformation
                 .LCPI_OleDbProviderFriendlyName]);
   }//using cn
  }
  catch(Exception exc)
  {
   resultCode=1;

   Console.WriteLine("ERROR: {0} - {1}",exc.Source,exc.Message);
  }//catch

  return resultCode;
 }//Main
}//class Program

////////////////////////////////////////////////////////////////////////////////
}//namespace Sample_0023

Leave a Comment