Данный модуль / библиотека (.dll) позволит Вам взаимодействовать с базой данных КАБИС
напрямую, при помощи функций экспорта, без использования графической обёртки, на которую помимо этого наложено множество ограничений.
На официальном сайте разработчика есть упоминание
про API, но более подробную информацию по этому поводу, кроме пункта с описанием этой возможности, мне найти не удалось :(
Но, так как эта возможность даёт выполнять ряд определённых задач с базой данных библиотеки, Вы и можете наблюдать решение данной проблемы
в виде модуля, где имеются все необходимые функции экспорта для манипуляции данными в базе данных.
База данных работает при помощи драйвера ODBC, поэтому решение данной проблемы не заставило себя долго ждать.
Так как я не смог открыть файл базы данных при помощи MS Access и других программ управления базами данных, этот драйвер оставался единственной надеждой.
В будущем планируется доработка модуля и последующее добавление новых функций для более гибкого взаимодействия с базой данных библиотеки.
Версия документации: 0.2
Версия библиотек (модулей): 0.2
P.S: Модуль kapi32u (utils).dll необходим для выполнения специфических задач, таких как получение пароля от БД из памяти программы.
Возможно это можно сделать каким-то иным путём, но пока я нашёл только это решение данной проблемы.
Начало работы с библиотеками kapi32.dll и kapi32u.dll
Все необходимые функции экспорта библиотек и их описание расположены в документации ниже.
Функции экспорта kapi32.dll:
Функции экспорта kapi32u.dll:
Заглавия
Разделы
string PtrToStr(IntPtr intPtr);
Преобразовывает указатель на массив из символов в текст.
Возвращаемый результат:
Аргументы:
C# - Пример импорта
[DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr);
C# - Пример кода
using System; using System.Text; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { //Импортировать функции необходимо именно так, как показано в примере, указывая согласование о вызове [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; //Присвоение строковой переменной результата выполнения функции PtrToStr string strDBPassword = PtrToStr(ScanForPass("C:\\KABIS\\KABIS.EXE")); Console.WriteLine("Пароль от базы данных: {0}", strDBPassword); Console.ReadKey(); } } }
bool OpenDataBase(string strDataBase, string strPassword);
Позволяет установить соединение с локальной базой данных.
Возвращаемый результат:
Аргументы:
C# - Пример импорта
[DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword);
C# - Пример кода
using System; using System.Text; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; if (OpenDataBase("C:\\KABIS\\Data\\Books.dbx", PtrToStr(ScanForPass("C:\\KABIS\\KABIS.EXE")))) { Console.WriteLine("База данных была успешно открыта!"); //Здесь можно выполнить какой-либо код перед закрытием базы данных... if (CloseDataBase()) Console.WriteLine("Соединение с базой данных было закрыто."); } Console.ReadKey(); } } }
ДОПОЛНИТЕЛЬНО:
Вы можете открывать базу данных, даже если она находится на каком-либо локальном компьютере в сети, либо по названию компьютера, либо
по его IP-адресу. Подробную инструкцию о том, как можно реализовать доступ к сетевой папке Вы сможете найти здесь [клик!].
Только учтите, если другая база данных на сервере использует другой пароль для авторизации, Вам необходимо будет удалить параметр DBPassword в реестре системы
по следующему пути: HKEY_CURRENT_USER\SOFTWARE\kapi32, чтобы функция ScanForPass смогла
его пересоздать.
Более подробно о данной информации можно узнать в описании к функции ScanForPass.
C# - Пример кода
using System; using System.Text; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; //Открываем базу данных по имени компьютера и пути к сетевой папке. if (OpenDataBase("\\\\DESKTOP-IQ3MQPS\\KABIS\\Data\\Books.dbx", PtrToStr( ScanForPass("\\\\DESKTOP-IQ3MQPS\\KABIS\\KABIS.EXE")))) { Console.WriteLine("База данных была успешно открыта через сетевую папку по имени компьютера!"); CloseDataBase(); } //Открываем базу данных по IP-адресу компьютера и пути к сетевой папке. if (OpenDataBase("\\\\192.168.100.72\\KABIS\\Data\\Books.dbx", PtrToStr( ScanForPass("\\\\192.168.100.72\\KABIS\\KABIS.EXE")))) { Console.WriteLine("База данных была успешно открыта через сетевую папку по IP-адресу компьютера!"); CloseDataBase(); } Console.ReadKey(); } } }
string EnumTables();
Позволяет перечислить все таблицы, которые находятся в базе данных. Функция возвращает строковый результат в формате JSON.
Все необходимые наименования таблиц можно спарсить по параметру "Tables" при помощи библиотеки Newtonsoft.JSON для платформы .NET.
Возвращаемый результат:
Аргументы: Функция не принимает аргументов.
C# - Пример импорта
[DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumTables();
C# - Пример кода
using System; using System.Text; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumTables(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; if (OpenDataBase("C:\\KABIS\\Data\\Books.dbx", PtrToStr(ScanForPass("C:\\KABIS\\KABIS.EXE")))) { Console.WriteLine("База данных была успешно открыта!"); string strTables = EnumTables(); if (!string.IsNullOrEmpty(strTables)) { Console.WriteLine(strTables); } else { Console.WriteLine("Не удалось получить перечень таблиц из базы данных!"); } if (CloseDataBase()) Console.WriteLine("Соединение с базой данных было закрыто."); } Console.ReadKey(); } } }
int GetTableCount();
Возвращает число таблиц в базе данных.
Возвращаемый результат:
Аргументы: Функция не принимает аргументов.
C# - Пример импорта
[DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableCount();
C# - Пример кода
using System; using System.Text; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumTables(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableCount(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; if (OpenDataBase("C:\\KABIS\\Data\\Books.dbx", PtrToStr(ScanForPass("C:\\KABIS\\KABIS.EXE")))) { Console.WriteLine("База данных была успешно открыта!"); int iTables = GetTableCount(); if (iTables != -1) { Console.WriteLine("Число таблиц в текущей базе данных: {0}", iTables); } else { Console.WriteLine("Не удалось получить число таблиц в базе данных."); } if (CloseDataBase()) Console.WriteLine("Соединение с базой данных было закрыто."); } Console.ReadKey(); } } }
string EnumFields(string strTable);
Позволяет перечислить все поля таблицы, указанной в аргументе функции. Функция возвращает строковый результат в формате JSON.
Возвращаемый результат:
Аргументы:
C# - Пример импорта
[DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumFields(string strTable);
C# - Пример кода
using System; using System.Text; using System.Linq; using Newtonsoft.Json.Linq; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumTables(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableCount(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumFields(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; if (OpenDataBase("C:\\KABIS\\Data\\Books.dbx", PtrToStr(ScanForPass("C:\\KABIS\\KABIS.EXE")))) { Console.WriteLine("База данных была успешно открыта!"); string strTables = EnumTables(); if (!string.IsNullOrEmpty(strTables)) { JToken jtTables = JObject.Parse(strTables)["Tables"]; for (int a = 0; a < jtTables.Count(); a++) { Console.WriteLine("[+] Поля для таблицы \"{0}\":\n-------------------------", jtTables[a].ToString()); string strFields = EnumFields(jtTables[a].ToString()); if (!string.IsNullOrEmpty(strFields)) { JToken jtFields = JObject.Parse(strFields)["Fields"]; for (int b = 0; b < jtFields.Count(); b++) Console.WriteLine((b + ": " + jtFields[b])); } Console.WriteLine("-------------------------\n"); } Console.WriteLine("Все поля всех таблиц были перечислены!"); } else Console.WriteLine("Не удалось получить перечень таблиц из базы данных!"); if (CloseDataBase()) Console.WriteLine("Соединение с базой данных было закрыто."); } Console.ReadKey(); } } }
int GetFieldCount(string strTable);
Возвращает число полей в таблице, указанной в аргументе функции.
Возвращаемый результат:
Аргументы:
C# - Пример импорта
[DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetFieldCount(string strTable);
C# - Пример кода
using System; using System.Text; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumTables(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableCount(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumFields(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetFieldCount(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; if (OpenDataBase("C:\\KABIS\\Data\\Books.dbx", PtrToStr(ScanForPass("C:\\KABIS\\KABIS.EXE")))) { Console.WriteLine("Кол-во поле в таблице \"Books\": {0}", GetFieldCount("Books")); if (CloseDataBase()) Console.WriteLine("Соединение с базой данных было закрыто."); } Console.ReadKey(); } } }
string SelectAllFrom(string strTable, bool bOutput);
Извлекает все данные таблицы, указанной в аргументе, вместе с полями через запрос "SELECT * FROM `%TableName%`;".
Возвращаемый результат:
Аргументы:
C# - Пример импорта
[DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string SelectAllFrom(string strTable, bool bOutput);
C# - Пример кода
using System; using System.Text; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumTables(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableCount(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumFields(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetFieldCount(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string SelectAllFrom(string strTable, bool bOutput); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; if (OpenDataBase("C:\\KABIS\\Data\\Books.dbx", PtrToStr(ScanForPass("C:\\KABIS\\KABIS.EXE")))) { string strResult = SelectAllFrom("Librarians", false); Console.WriteLine(strResult); if (CloseDataBase()) Console.WriteLine("Соединение с базой данных было закрыто."); } Console.ReadKey(); } } }
string CreateCustomQuery(string strQuery);
Позволяет выполнять кастомные запросы к базе данных. Для примера "SELECT `id`, `Password`, `UserPC` FROM `Librarians`;".
Возвращаемый результат:
Аргументы:
C# - Пример импорта
[DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string CreateCustomQuery(string strQuery);
C# - Пример кода
using System; using System.Text; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { /* Тут находятся все функции экспорта, которые содержит библиотека kapi32.dll и kapi32u.dll */ [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumTables(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableCount(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumFields(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetFieldCount(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string SelectAllFrom(string strTable, bool bOutput); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string CreateCustomQuery(string strQuery); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string UnloadTable(string strTable, string strFile, int iType, bool bOutput); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableRecords(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; if (OpenDataBase("C:\\KABIS\\Data\\Books.dbx", PtrToStr(ScanForPass("C:\\KABIS\\KABIS.EXE")))) { Console.WriteLine("База данных была успешно открыта!"); //Выполняем кастомный запрос, чтобы получить таблицу с указанными полями string strQuery = CreateCustomQuery("SELECT `id`, `Password`, `UserPC` FROM `Librarians`;"); if (!string.IsNullOrEmpty(strQuery)) Console.WriteLine("---------------------------------\n" + strQuery); else Console.WriteLine("Произошла ошибка во время выполнения кастомного запроса!"); if (CloseDataBase()) { Console.WriteLine("---------------------------------"); Console.WriteLine("Соединение с базой данных было закрыто."); } } else Console.WriteLine("Не удалось открыть базу данных."); Console.ReadKey(); } } }
РЕЗУЛЬТАТ ВЫЗОВА ФУНКЦИИ:
Ниже представлен результат успешного выполнения функции с указанным кастомным запросом к базе данных. Вы можете составлять любые запросы к базе данных, комбинируя их с другими ключевыми словами.
🛠️ Командная строка
База данных была успешно открыта! --------------------------------- id Password UserPC 1 kabis DESKTOP-AE57DMC 2 LIBRARY-PC 3 12345 LIB-LIBRARY 4 1234579 LIBRARY-PC 5 12345 KABIS 6 12345 PC-82178739E0 7 12345 User 10 12345 11 12345 12 12345 13 12345 14 12345 15 1234 16 1234 17 1234 18 1234 19 1234 20 1234 --------------------------------- Соединение с базой данных было закрыто. _
string UnloadTable(string strTable, string strFile, int iType, bool bOutput);
Позволяет выгрузить все записи таблицы вместе с полями в какой-либо файл с указанными разделителями.
Возвращаемый результат:
Аргументы:
C# - Пример импорта
[DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string UnloadTable(string strTable, string strFile, int iType, bool bOutput);
C# - Пример кода
using System; using System.Text; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumTables(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableCount(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumFields(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetFieldCount(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string SelectAllFrom(string strTable, bool bOutput); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string UnloadTable(string strTable, string strFile, int iType, bool bOutput); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; if (OpenDataBase("C:\\KABIS\\Data\\Books.dbx", PtrToStr(ScanForPass("C:\\KABIS\\KABIS.EXE")))) { Console.WriteLine("База данных была успешно открыта!"); if (!string.IsNullOrEmpty(UnloadTable("Librarians", "Users.txt", 1, false))) Console.WriteLine("Данные таблицы были успешно выгружены в файл \"Users.txt\"."); else Console.WriteLine("Не удалось выгрузить данные таблицы."); if (CloseDataBase()) Console.WriteLine("Соединение с базой данных было закрыто."); } Console.ReadKey(); } } }
int GetTableRecords(string strTable);
Получает количество записей в таблице, указанной в аргументе функции. Например, для получения количества книг во всех каталогах (для получения записей в определённом каталоге нужно делать кастомный запрос).
Возвращаемый результат:
Аргументы:
C# - Пример импорта
[DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableRecords(string strTable);
C# - Пример кода
using System; using System.Text; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumTables(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableCount(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumFields(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetFieldCount(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string SelectAllFrom(string strTable, bool bOutput); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string UnloadTable(string strTable, string strFile, int iType, bool bOutput); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableRecords(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; if (OpenDataBase("C:\\KABIS\\Data\\Books.dbx", PtrToStr(ScanForPass("C:\\KABIS\\KABIS.EXE")))) { Console.WriteLine("База данных была успешно открыта!"); int iRecords = GetTableRecords("Books"); if (iRecords != -1) Console.WriteLine("Кол-во книг в библиотечном фонде: {0}", iRecords); else Console.WriteLine("Не удалось получить кол-во записей для текущей таблицы."); if (CloseDataBase()) Console.WriteLine("Соединение с базой данных было закрыто."); } Console.ReadKey(); } } }
bool CloseDataBase();
Закрывает соединение с базой данных. Должна вызываться после завершения работы с базой данных.
Возвращаемый результат:
Аргументы: Функция не принимает аргументов.
C# - Пример импорта
[DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase();
C# - Пример кода
using System; using System.Text; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { /* Тут находятся все функции экспорта, которые содержит библиотека kapi32.dll и kapi32u.dll */ [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumTables(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableCount(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumFields(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetFieldCount(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string SelectAllFrom(string strTable, bool bOutput); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string CreateCustomQuery(string strQuery); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string UnloadTable(string strTable, string strFile, int iType, bool bOutput); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableRecords(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; if (OpenDataBase("C:\\KABIS\\Data\\Books.dbx", PtrToStr(ScanForPass("C:\\KABIS\\KABIS.EXE")))) { Console.WriteLine("База данных была успешно открыта!"); //Здесь можно что-то выполнить перед закрытием базы данных... if (CloseDataBase()) Console.WriteLine("Соединение с базой данных было закрыто."); } Console.ReadKey(); } } }
Модуль (библиотека) содержит в себе всего лишь одну экспортируемую функцию. Которая выполняет своё главное действие только один раз. Более подробнее написано в описании к функции.
IntPtr ScanForPass(string strAppName);
Извлекает из памяти процесса (программы) пароль для базы данных.
Так как данные о пароле не хранятся в реестре или в файловой системе компьютера, Вам необходимо будет вызывать эту функцию и результат её
выполнения передавать во второй аргумент функции OpenDataBase для корректного установления соединения с базой данных.
Возвращаемый результат:
Аргументы:
C# - Пример импорта
[DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName);
C# - Пример кода
using System; using System.Text; using System.Runtime.InteropServices; namespace KabisAPITest { internal class Program { /* Тут находятся все функции экспорта, которые содержит библиотека kapi32.dll и kapi32u.dll */ [DllImport("kapi32u.dll", CallingConvention = CallingConvention.StdCall)] extern public static IntPtr ScanForPass(string strAppName); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string PtrToStr(IntPtr intPtr); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool OpenDataBase(string strDataBase, string strPassword); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumTables(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableCount(); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string EnumFields(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetFieldCount(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string SelectAllFrom(string strTable, bool bOutput); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string CreateCustomQuery(string strQuery); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static string UnloadTable(string strTable, string strFile, int iType, bool bOutput); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static int GetTableRecords(string strTable); [DllImport("kapi32.dll", CallingConvention = CallingConvention.StdCall)] extern public static bool CloseDataBase(); static void Main(string[] args) { Console.InputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8; string strDBPassword = PtrToStr(ScanForPass("C:\\KABIS\\KABIS.EXE")); Console.WriteLine("Пароль от базы данных: {0}", strDBPassword); if (OpenDataBase("C:\\KABIS\\Data\\Books.dbx", strDBPassword)) { Console.WriteLine("База данных была успешно открыта!"); //Здесь можно что-то выполнить перед закрытием базы данных... if (CloseDataBase()) Console.WriteLine("Соединение с базой данных было закрыто."); } Console.ReadKey(); } } }
[+] Вызов функций экспорта на других языках
Также, Вы можете импортировать функции экспорта в свою программу и на других языках программирования, таких как C++ или Python, чтобы выполнять все доступные действия с базой данных КАБИС.
C++ - Пример кода
#include <iostream> #include <string> #include <string.h> #include <Windows.h> using namespace std; //Создаём прототипы импортируемых функций typedef const char* (__stdcall* ScanForPassFn)(const char* cchAppName); ScanForPassFn ScanForPass; typedef bool (__stdcall* OpenDataBaseFn)(const char* cchDataBase, const char* cchPassword); OpenDataBaseFn OpenDataBase; typedef const char* (__stdcall* UnloadTableFn)(const char* cchTable, const char* cchFile, int iType, bool bOutput); UnloadTableFn UnloadTable; typedef bool (__stdcall* CloseDataBaseFn)(); CloseDataBaseFn CloseDataBase; int main() { setlocale(LC_ALL, ""); HMODULE hKapi32 = LoadLibraryA("kapi32.dll"); HMODULE hKapi32u = LoadLibraryA("kapi32u.dll"); if (hKapi32 && hKapi32u) { ScanForPass = (ScanForPassFn)GetProcAddress(hKapi32u, "ScanForPass"); OpenDataBase = (OpenDataBaseFn)GetProcAddress(hKapi32, "OpenDataBase"); UnloadTable = (UnloadTableFn)GetProcAddress(hKapi32, "UnloadTable"); CloseDataBase = (CloseDataBaseFn)GetProcAddress(hKapi32, "CloseDataBase"); //Лучше сделать массив и проверить всё это в цикле if (ScanForPass && OpenDataBase && UnloadTable && CloseDataBase) { if (OpenDataBase("C:\\KABIS\\Data\\Books.dbx", ScanForPass("C:\\KABIS\\KABIS.EXE"))) { cout << "База данных была успешно открыта!\n"; string strTable = UnloadTable("Librarians", nullptr, 0, false); if (!strTable.empty()) cout << strTable << "\n"; else cout << "Не удалось выгрузить таблицу.\n"; if (CloseDataBase()) cout << "Соединение с базой данных было закрыто.\n"; } else cout << "Не удалось открыть базу данных.\n"; } else cout << "Не удалось получить адреса одной или нескольких функций.\n"; } else cout << "Не удалось загрузить один или несколько модулей в процесс.\n"; system("pause"); return 0; }
Python - Пример кода
import ctypes as lib kapi32 = lib.WinDLL("C:\\PyKapi32\\kapi32.dll") kapi32u = lib.WinDLL("C:\\PyKapi32\\kapi32u.dll") ScanForPass = kapi32u.ScanForPass ScanForPass.restype = lib.c_char_p ScanForPass.argtypes = [lib.c_char_p] OpenDataBase = kapi32.OpenDataBase OpenDataBase.restype = lib.c_bool OpenDataBase.argtypes = [lib.c_char_p, lib.c_char_p] UnloadTable = kapi32.UnloadTable UnloadTable.restype = lib.c_char_p UnloadTable.argtypes = [lib.c_char_p, lib.c_char_p, lib.c_int, lib.c_bool] CloseDataBase = kapi32.CloseDataBase CloseDataBase.restype = lib.c_bool if (ScanForPass != 0 and OpenDataBase != 0 and UnloadTable != 0 and CloseDataBase != 0): DataBase = b"C:\\KABIS\\Data\\Books.dbx" Password = ScanForPass(b"C:\\KABIS\\KABIS.EXE") if (len(Password) > 0): if (OpenDataBase(DataBase, Password)): print("База данных была успешно открыта!") Table = UnloadTable(b"Librarians", b"", 0, False).decode("cp1251") if (len(Table) > 0): print(Table) else: print("Не удалось выгрузить таблицу из базы данных.") if (CloseDataBase()): print("База данных была успешно закрыта!") else: print("Не удалось получить адрес одной или нескольких функций.") input("Нажмите клавишу Enter или Ctrl + C для завершения выполнения программы...\n")
ВНИМАНИЕ!
Ваше приложение должно быть x32-битной разрядности, иначе ни одна из библиотек не будет работать или при запуске
программы у Вас будет возникать ошибка различий совместимости библиотеки и приложения.
Вы можете использовать все функции экспорта так, как захотите, всё зависит только от Вашего воображения. Теперь, при помощи
данного инструмента у Вас появится возможность интеграции библиотечной системы KABIS с другими корпоративными системами, по крайней мере
у меня.
Также, в случае обнаружения проблем библиотеки или проблем при работе с ней, Вы можете задать мне любые вопросы по этому поводу в Discord.
Ну, вроде бы ничего не забыл описать. В любом случае, документация будет обновляться параллельно с добавлением нового функционала в
библиотеку (модуль).