Skip to content

Instantly share code, notes, and snippets.

@rsyuzyov
Created July 12, 2016 21:06
Show Gist options
  • Save rsyuzyov/b2c4421cf8cf192cf05002b88eb62760 to your computer and use it in GitHub Desktop.
Save rsyuzyov/b2c4421cf8cf192cf05002b88eb62760 to your computer and use it in GitHub Desktop.
#Использовать logos
#Использовать tempfiles
Перем Лог;
Перем ЭтоWindows;
Перем Базы;
Перем ОшибкиПоиска;
///////////////////////////////////////////////////////////////////////////////////////////////////
// ОСНОВНЫЕ МЕТОДЫ
// Главная функция. Ищет базы, результат складывает в "bases.csv". Ошибки поиска (например отказы в доступе) складывает в "bases.err"
// Параметры:
// Каталоги - Строка: каталоги поиска, разделенные запятыми
// ИскатьВКаталогах - Булево: если Истина, то осуществляется поиск файлов с расширением ".1CD"
// ИскатьВСпискахБаз - Булево: если Истина, то осуществляется поиск списков баз с расширением ".v8i", в них ищутся файловые базы
// ПолучатьОписаниеБазы - Булево: если Истина, то для каждой базы получается имя и версия конфигуарции
// Исключения - Строка: список слов через запятую, если одно из слов входит в путь, то он пропускается (используется в момент рекурсивного поиска файлов)
Функция НайтиБазы(Знач Каталоги = "", Знач ИскатьВКаталогах = Истина, Знач ИскатьВСпискахБаз = Истина, Знач ПолучатьОписаниеБазы = Истина, Знач Исключения = "")
Лог.Информация("Время начала: " + ТекущаяДата());
ЭтоWindows = ЭтоWindows();
// Создадим таблицы для баз, списков баз и исключений
Базы = Новый ТаблицаЗначений;
Базы.Колонки.Добавить("Путь");
Базы.Колонки.Добавить("Имя");
Базы.Колонки.Добавить("Конфигурация");
Базы.Колонки.Добавить("Версия");
СпискиБаз = Новый ТаблицаЗначений;
СпискиБаз.Колонки.Добавить("Путь");
СпискиБаз.Колонки.Добавить("Имя");
СпискиБаз.Колонки.Добавить("Конфигурация");
СпискиБаз.Колонки.Добавить("Версия");
ОшибкиПоиска = Новый ТаблицаЗначений;
ОшибкиПоиска.Колонки.Добавить("Путь");
ОшибкиПоиска.Колонки.Добавить("Описание");
// Подготовим каталоги поиска: сформируем в виде сыписка
Каталоги = ПривестиСлэшиПодОС(Каталоги);
Каталоги = РазложитьСтрокуВМассивПодстрок(Каталоги, ",", Истина, Истина);
// Подготовим исключения: добавим vrs-cache, сформируем в виде списка
Если СтрЧислоВхождений(Исключения, "vrs-cache") = 0 Тогда
Исключения = Исключения + ",vrs-cache";
КонецЕсли;
Если СтрЧислоВхождений(Исключения, "1cv8tmp.1cd") = 0 Тогда
Исключения = Исключения + ",1cv8tmp.1cd";
КонецЕсли;
Исключения = ПривестиСлэшиПодОС(Исключения);
Исключения = РазложитьСтрокуВМассивПодстрок(Исключения, ",", Истина, Истина);
// Поищем базы
Если ИскатьВКаталогах Тогда
Для каждого Каталог Из Каталоги Цикл
НайтиФайлыВКаталоге(Каталог, Базы, ОшибкиПоиска, Исключения, ".1cd");
КонецЦикла;
КонецЕсли;
Если ИскатьВСпискахБаз Тогда
Для каждого Каталог Из Каталоги Цикл
НайтиФайлыВКаталоге(Каталог, СпискиБаз, ОшибкиПоиска, Исключения, ".v8i");
КонецЦикла;
НайтиБазыВСпискахБаз(СпискиБаз, Базы);
КонецЕсли;
// Посмотрим, что за базы такие
Если ПолучатьОписаниеБазы Тогда
Для каждого База Из Базы Цикл
Описание = ПолучитьОписаниеБазы(База.Путь);
Если Описание.Получено Тогда
База.Конфигурация = Описание.Конфигурация;
База.Версия = Описание.Версия;
Иначе
Ошибка = ОшибкиПоиска.Добавить();
Ошибка.Путь = База.Путь;
Ошибка.Описание = Описание.ОписаниеОшибки;
КонецЕсли;
КонецЦикла;
КонецЕсли;
// Свернем и отсортируем таблицы
Базы.Свернуть("Путь, Имя, Конфигурация, Версия");
Базы.Сортировать("Путь");
ОшибкиПоиска.Свернуть("Путь", "Описание");
Базы.Сортировать("Путь");
// Запишем результаты в файлы
Сообщение = "";
Если Базы.Количество() > 0 Тогда
Сообщение = "Найдено " + Базы.Количество() + " баз";
ЗаписатьСписокБаз(Базы);
Иначе
Сообщение = "Базы не найдены";
КонецЕсли;
Если ОшибкиПоиска.Количество() > 0 Тогда
Сообщение = Сообщение + ", при поиске произошло " + ОшибкиПоиска.Количество() + " ошибок.";
ЗаписатьСписокОшибок(ОшибкиПоиска);
Иначе
Сообщение = Сообщение + ", поиск завершен.";
КонецЕсли;
Лог.Информация(Сообщение);
Лог.ИНформация("Время окончания: " + ТекущаяДата());
КонецФункции // НайтиБазы
Процедура НайтиФайлыВКаталоге(Знач Путь, Таблица, ОшибкиПоиска, Знач Исключения, Знач Маска)
Попытка
//в отличие от 1С, НайтиФайлы в односкрипте падает при отказе в доступе
Файлы = НайтиФайлы(Путь, "*", Ложь);
Для каждого Файл Из Файлы Цикл
Если ПутьЕстьВИсключениях(Файл.ПолноеИмя, Исключения) Тогда
Продолжить;
ИначеЕсли НРег(Файл.Расширение) = Маска Тогда
стр = Таблица.Добавить();
Если ЭтоWindows Тогда //компенсация регистронезависимости
стр.Путь = НРег(Файл.ПолноеИмя);
Иначе
стр.Путь = Файл.ПолноеИмя;
КонецЕсли;
Лог.Отладка("Найден файл: " + стр.Путь);
ИначеЕсли Файл.ЭтоКаталог() Тогда
НайтиФайлыВКаталоге(Файл.ПолноеИмя, Таблица, ОшибкиПоиска, Исключения, Маска);
КонецЕсли;
КонецЦикла;
Исключение
//скорее всего банально нет прав
стр = ОшибкиПоиска.Добавить();
стр.Путь = Путь;
стр.Описание = ОписаниеОшибки();
Возврат;
КонецПопытки;
КонецПроцедуры // НайтиБазыВКаталоге
Процедура НайтиБазыВСпискахБаз(Знач СпискиБаз, Базы)
Перем Чтение, Строка, Файл;
Для каждого СписокБаз Из СпискиБаз Цикл
Лог.Отладка("Чтение баз из списка: " + СписокБаз.Путь);
Чтение = Новый ЧтениеТекста(СписокБаз.Путь);
Строка = Чтение.ПрочитатьСтроку();
Пока НЕ Строка = Неопределено Цикл
Если Лев(Строка, 1) = "[" Тогда //начинается описание базы или группы
Имя = СтрЗаменить(Строка, "]", "");
Имя = СтрЗаменить(Имя, "[", "");
Строка = Чтение.ПрочитатьСтроку();
Если НРег(Лев(Строка, 13)) = "connect=file=" Тогда // это файловая база, если "", то серверная, иначе группа
Путь = Сред(Строка, 15);
Путь = СтрЗаменить(Путь, """", "");
Путь = СтрЗаменить(Путь, ";", "") + "\1Cv8.1CD";
Путь = ПривестиСлэшиПодОС(Путь);
Файл = Новый Файл(Путь); //если файла нет, то и базы нет
Если Файл.Существует() Тогда
Если ЭтоWindows Тогда //компенсация регистронезависимости
Путь = НРег(Файл.ПолноеИмя);
КонецЕсли;
стр = Базы.Найти(Путь, "Путь");
Если стр = Неопределено Тогда
стр = Базы.Добавить();
стр.Путь = Путь;
КонецЕсли;
стр.Имя = Имя;
Лог.Отладка(Символы.Таб + Имя + ": " + Путь);
КонецЕсли;
ИначеЕсли НРег(Лев(Строка, 13)) = "connect=srvr=" Тогда // это серверная база
Лог.Отладка(Символы.Таб + Имя + ": " + Строка + " (пропущено)");
КонецЕсли;
КонецЕсли;
Строка = Чтение.ПрочитатьСтроку();
КонецЦикла;
КонецЦикла;
КонецПроцедуры // НайтиБазыВСпискахБаз
Функция ПолучитьОписаниеБазы(Знач Путь)
Перем ФайлОписания, КодВозврата, Описание, Чтение, стр;
Инфо = Новый Структура("Получено, ОписаниеОшибки, Конфигурация, Версия");
Попытка
ФайлОписания = ВременныеФайлы.НовоеИмяФайла("txt");
СтрокаЗапуска = "getcfname.exe" + " """ + Путь + """ > " + ФайлОписания;
Если НЕ ЭтоWindows Тогда
СтрокаЗапуска = "wine " + СтрокаЗапуска;
КонецЕсли;
КодВозврата = 0;
Лог.Отладка(СтрокаЗапуска);
//TODO: по какой-то причине файл описания не формируется, хотя из командной строки все отрабабатывает правильно
//ЗапуститьПриложение(СтрокаЗапуска, "", Истина, КодВозврата);
//Обход:
ФайлСкрипта = ОбъединитьПути(ТекущийСценарий().Каталог, "getcfname.cmd");
Запись = Новый ЗаписьТекста(ФайлСкрипта, "cp866");
Запись.ЗаписатьСтроку("cd ../bin");
Запись.ЗаписатьСтроку(СтрокаЗапуска);
Запись.Закрыть();
ЗапуститьПриложение(ФайлСкрипта, "", Истина, КодВозврата);
Если КодВозврата <> 0 Тогда
ВызватьИсключение "Ошибка запуска приложения: " + СтрокаЗапуска;
КонецЕсли;
Чтение = Новый ЧтениеТекста(ФайлОписания, "cp866");
Строка = Чтение.Прочитать();
Чтение.Закрыть();
Лог.Отладка(Строка);
ПозицияВерсии = Найти(Строка, "(");
Лог.Отладка(ПозицияВерсии);
Если ПозицияВерсии = 0 Тогда
Инфо.Конфигурация = Строка;
Иначе
Инфо.Конфигурация = СокрЛП(Лев(Строка, ПозицияВерсии-1));
//Инфо.Версия = Сред(Строка, ПозицияВерсии+1, СтрДлина(Строка)-1); - не работает
Инфо.Версия = Сред(Строка, ПозицияВерсии+1);
Инфо.Версия = СтрЗаменить(Инфо.Версия, ")", "");
КонецЕсли;
Инфо.Получено = Истина;
ВременныеФайлы.УдалитьФайл(ФайлОписания);
Исключение
Инфо.Получено = Ложь;
Инфо.ОписаниеОшибки = ОписаниеОшибки();
ВременныеФайлы.УдалитьФайл(ФайлОписания);
КонецПопытки;
Возврат Инфо;
КонецФункции // ОписаниПолучитьОписаниеБазы(Путь)
Процедура ЗаписатьСписокБаз(Базы)
Запись = Новый ЗаписьТекста("bases.csv");
Для каждого База Из Базы Цикл
Запись.ЗаписатьСтроку(База.Путь + "; " + СтрЗаменить(База.Имя, ";", "") + "; " + СтрЗаменить(База.Конфигурация, ";", "") + "; " + База.Версия);
КонецЦикла;
Запись.Закрыть();
КонецПроцедуры
Процедура ЗаписатьСписокОшибок(Ошибки)
Запись = Новый ЗаписьТекста("bases.err");
Для каждого Ошибка Из Ошибки Цикл
Запись.ЗаписатьСтроку(Ошибка.Путь + "; " + Ошибка.Описание);
КонецЦикла;
Запись.Закрыть();
КонецПроцедуры
///////////////////////////////////////////////////////////////////////////////////////////////////
// ВСПОМОГАТЕЛЬНЫЕ МЕТОДЫ
// Взято из БСП
Функция РазложитьСтрокуВМассивПодстрок(Знач Строка, Знач Разделитель = ",", Знач ПропускатьПустыеСтроки = Неопределено, Знач СокращатьНепечатаемыеСимволы = Ложь)
Результат = Новый Массив;
// Для обеспечения обратной совместимости.
Если ПропускатьПустыеСтроки = Неопределено Тогда
ПропускатьПустыеСтроки = ?(Разделитель = " ", Истина, Ложь);
Если ПустаяСтрока(Строка) Тогда
Если Разделитель = " " Тогда
Результат.Добавить("");
КонецЕсли;
Возврат Результат;
КонецЕсли;
КонецЕсли;
Позиция = СтрНайти(Строка, Разделитель);
Пока Позиция > 0 Цикл
Подстрока = Лев(Строка, Позиция - 1);
Если Не ПропускатьПустыеСтроки Или Не ПустаяСтрока(Подстрока) Тогда
Если СокращатьНепечатаемыеСимволы Тогда
Результат.Добавить(СокрЛП(Подстрока));
Иначе
Результат.Добавить(Подстрока);
КонецЕсли;
КонецЕсли;
Строка = Сред(Строка, Позиция + СтрДлина(Разделитель));
Позиция = СтрНайти(Строка, Разделитель);
КонецЦикла;
Если Не ПропускатьПустыеСтроки Или Не ПустаяСтрока(Строка) Тогда
Если СокращатьНепечатаемыеСимволы Тогда
Результат.Добавить(СокрЛП(Строка));
Иначе
Результат.Добавить(Строка);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции // РазложитьСтрокуВМассивПодстрок
Функция ПутьЕстьВИсключениях(Знач Путь, Знач Исключения)
Для каждого Маска Из Исключения Цикл
Если СтрЧислоВхождений(НРег(Путь), НРег(Маска)) > 0 Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции // ПутьЕстьВИсключениях
Функция ЭтоWindows()
СИ = Новый СистемнаяИнформация;
Возврат Найти(СИ.ВерсияОС, "Windows") > 0;
КонецФункции // ЭтоWindows
Функция ПривестиСлэшиПодОС(Знач Путь)
Если ЭтоWindows Тогда
Возврат СтрЗаменить(Путь, "/", "\");
Иначе
Возврат СтрЗаменить(Путь, "\", "/");
КонецЕсли;
КонецФункции // ПривестиСлэшиПодОС
///////////////////////////////////////////////////////////////////////////////////////////////////
Лог = Логирование.ПолучитьЛог("ibmgmt.find-ib");
Лог.УстановитьУровень(УровниЛога.Отладка);
НайтиБазы("c:\");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment