//ирПортативный Перем ирПлатформа Экспорт; // Эта переменная нужна только здесь

//ирПортативный Перем ирПортативный Экспорт;
//ирПортативный Перем ирОбщий Экспорт;
//ирПортативный Перем ирСервер Экспорт;
//ирПортативный Перем ирКэш Экспорт;
//ирПортативный Перем ирКлиент Экспорт;

#Если Не ТонкийКлиент И Не ВебКлиент И Не МобильныйКлиент Тогда

Функция Получить() Экспорт 
	
	Если Истина
//ирПортативный 		И Ложь // Для ускорения работы в портативном варианте
	Тогда 
		// Не следует использовать для хранения таких данных, переинициализация которых автоматически невозможна или приведет к ошибкам
		Попытка
			ирПлатформа = Вычислить("ирПлатформа");
		Исключение
		КонецПопытки;
	КонецЕсли;
	Если ирПлатформа = Неопределено Тогда
		//ирСервер.СтрокаСоединенияСервераЛкс(); // http://www.hostedredmine.com/issues/851201
		ирПлатформа = ирОбщий.СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирПлатформа");
		#Если Сервер И Не Сервер Тогда
		    ирПлатформа = Обработки.ирПлатформа.Создать();  
		#КонецЕсли
	КонецЕсли; 
	Возврат ирПлатформа;
	
КонецФункции

Функция ИмяПродукта() Экспорт 
	
	Возврат "ИнструментыРазработчикаTormozit";
	
КонецФункции

Функция КомпоновщикТаблицыМетаданныхЛкс(Знач ПолноеИмяМД, ВызыватьИсключениеПриОтсутствииПрав = Истина, ИндексПараметраПериодичность = Неопределено,
	ВыражениеПараметраПериодичность = "", ИменаВместоПредставлений = Ложь) Экспорт
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("КомпоновщикТаблицыМетаданныхЛкс");
		КлючНаборПараметров = "" + ПолноеИмяМД + ";" + ВызыватьИсключениеПриОтсутствииПрав + ";" + ИндексПараметраПериодичность + ";" + ВыражениеПараметраПериодичность
			+ ";" + ИменаВместоПредставлений;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	КомпоновщикНастроек = ирОбщий.КомпоновщикТаблицыМетаданныхЛкс(ПолноеИмяМД, ВызыватьИсключениеПриОтсутствииПрав, ИндексПараметраПериодичность, ВыражениеПараметраПериодичность, ИменаВместоПредставлений);
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = КомпоновщикНастроек;
	КонецЕсли; 
	Возврат КомпоновщикНастроек;
	
КонецФункции

Функция ПоляТаблицыБДЛкс(ПолноеИмяТаблицыБД, НужныТолькоТипы = Ложь, ИндексПараметраПериодичность = Неопределено, ВыражениеПараметраПериодичность = "") Экспорт 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ПоляТаблицыБДЛкс");
		КлючНаборПараметров = "" + ПолноеИмяТаблицыБД + ";" + НужныТолькоТипы + ";" + ИндексПараметраПериодичность + ";" + ВыражениеПараметраПериодичность;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	Результат = ирОбщий.ПоляТаблицыБДЛкс(ПолноеИмяТаблицыБД, НужныТолькоТипы, ИндексПараметраПериодичность, ВыражениеПараметраПериодичность);
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

Функция ПараметрыСеансаЛкс() Экспорт 
	
	Результат = Новый Структура("ПереданныйКэш");
	Возврат Результат;
	
КонецФункции

Функция ТаблицаВсехТаблицБДЛкс() Экспорт 
	
	мПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
		мПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	ТаблицаВсехТаблицБД = мПлатформа.ТаблицаВсехТаблицБД();
	Возврат ТаблицаВсехТаблицБД;
	
КонецФункции

Функция ДеревоОбъектовМДЛкс() Экспорт 
	
	мПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
		мПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	ТаблицаВсехТаблицБД = мПлатформа.ДеревоОбъектовМД();
	Возврат ТаблицаВсехТаблицБД;
	
КонецФункции

Функция ЛиЭтоРасширениеКонфигурацииЛкс() Экспорт
	
	Расширение = ирКэш.ЭтотРасширениеКонфигурацииЛкс();
	#Если Сервер И Не Сервер Тогда
		Расширение = РасширенияКонфигурации.Создать();
	#КонецЕсли
	Результат = Истина
		И Расширение <> Неопределено
		И (Ложь
			Или ирКэш.НомерВерсииПлатформыЛкс() < 803012
			Или Расширение.Активно);
	Возврат Результат;
	
КонецФункции

Функция ЭтотРасширениеКонфигурацииЛкс() Экспорт
	
	Результат = ирОбщий.ЭтотРасширениеКонфигурацииЛкс();
	Возврат Результат;
	
КонецФункции

Функция СтруктураХраненияБДЛкс(ЛиИменаБД = Ложь, АдресЧужойСхемыБД = "") Экспорт

	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("СтруктураХраненияБДЛкс");
		КлючНаборПараметров = "" + ЛиИменаБД + ";" + АдресЧужойСхемыБД;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли;
	КонецЕсли; 
	
	Результат = ирОбщий.СтруктураХраненияБДЛкс(, ЛиИменаБД, АдресЧужойСхемыБД);
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;

КонецФункции

// Получить словарь метаданных состоящий из шаблонов имен таблиц
//
// Параметры:
//  ЛиИменаБД - Булево
//
// Возвращаемое значение:
//  Соответствие - словарь шаблонов имен метаданных. Ключ - наименование объекта
//                 метаданных, где его номер заменен на номер позиции этого
//                 числа в строке; Значение - количество чисел в строке
//
Функция СловарьШаблоновХраненияБДЛкс(ЛиИменаБД = Ложь, АдресЧужойСхемыБД = "") Экспорт

	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("СловарьШаблоновХраненияБДЛкс");
		КлючНаборПараметров = "" + ЛиИменаБД + ";" + АдресЧужойСхемыБД;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 

	СтруктураХраненияБД = ирКэш.СтруктураХраненияБДЛкс(ЛиИменаБД, АдресЧужойСхемыБД);
	Результат = Новый ТаблицаЗначений;
	Результат.Колонки.Добавить("РегулярныйШаблон");
	Результат.Колонки.Добавить("ПозиционныйШаблон");
	Результат.Колонки.Добавить("КоличествоПараметров");
	КоличествоСимволов = 0;
	ПозицияЧисла = 0;
	Для Каждого СтрокаСтруктурыБазы Из СтруктураХраненияБД Цикл
		ИмяТаблицыХранения = НРег(Лев(СтрокаСтруктурыБазы.ИмяТаблицыХранения, СтрДлина(СтрокаСтруктурыБазы.ИмяТаблицыХранения)));
		РегулярныйШаблон = "";
		ПозиционныйШаблон = "";
		КоличествоЧисел = 0;
		ПоследнееИмяШаблона = "";
		Пока ирОбщий.НайтиЧислоВСтрокеЛкс(ИмяТаблицыХранения, ПозицияЧисла, КоличествоСимволов) Цикл
			КоличествоЧисел = КоличествоЧисел + 1;
			ПоследнееИмяШаблона = Лев(ИмяТаблицыХранения, ПозицияЧисла - 1);
			РегулярныйШаблон = РегулярныйШаблон + ПоследнееИмяШаблона + "(\d+)";
			ПозиционныйШаблон = ПозиционныйШаблон + ПоследнееИмяШаблона + XMLСтрока(КоличествоЧисел);
			ИмяТаблицыХранения = Прав(ИмяТаблицыХранения, СтрДлина(ИмяТаблицыХранения) - ПозицияЧисла - КоличествоСимволов + 1);
		КонецЦикла;
		РегулярныйШаблон = РегулярныйШаблон + ИмяТаблицыХранения;
		ПозиционныйШаблон = ПозиционныйШаблон + ИмяТаблицыХранения;
		СтрокаРезультата = Результат.Добавить();
		СтрокаРезультата.РегулярныйШаблон = НРег(РегулярныйШаблон);
		СтрокаРезультата.ПозиционныйШаблон = ПозиционныйШаблон;
		СтрокаРезультата.КоличествоПараметров = КоличествоЧисел;
		Если Не ЛиИменаБД Тогда
			// Сохранить шаблон дочерней таблицы независимо
			Если КоличествоЧисел > 1 Тогда
				Если Лев(ПоследнееИмяШаблона, 1) = "." Тогда
					ПоследнееИмяШаблона = Сред(ПоследнееИмяШаблона, 2);
				КонецЕсли; 
				РегулярныйШаблон = ПоследнееИмяШаблона + "(\d+)";
				ПозиционныйШаблон = ПоследнееИмяШаблона + XMLСтрока(КоличествоЧисел);
				СтрокаРезультата = Результат.Добавить();
				СтрокаРезультата.РегулярныйШаблон = НРег(РегулярныйШаблон);
				СтрокаРезультата.ПозиционныйШаблон = ПозиционныйШаблон;
				СтрокаРезультата.КоличествоПараметров = 1;
			КонецЕсли; 
		КонецЕсли; 
	КонецЦикла;
	Результат.Свернуть("РегулярныйШаблон,ПозиционныйШаблон,КоличествоПараметров");
	Результат.Сортировать("ПозиционныйШаблон");  
	
	// Для ускорения многократного использования
	Результат.Колонки.Добавить("БыстрыйМаркер"); // главное ускорение 
	Результат.Колонки.Добавить("Вычислитель");
	Для Каждого СтрокаРезультата Из Результат Цикл
		СтрокаРезультата.БыстрыйМаркер = ирОбщий.ПервыйФрагментЛкс(СтрокаРезультата.РегулярныйШаблон, "(");
		Вычислитель = ирОбщий.НовоеРегВыражениеЛкс();
		Вычислитель.Global = Истина;
		Вычислитель.Pattern = СтрокаРезультата.РегулярныйШаблон;
		СтрокаРезультата.Вычислитель = Вычислитель;
	КонецЦикла;
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;

КонецФункции

Функция ПолучитьСеансПустойИнфобазы1С8Лкс(Знач ТипCOMОбъекта = "Application", Знач Видимость = Ложь, Знач ОбработатьИсключениеПодключения = Ложь,
	ОписаниеОшибки = "", ИмяСервераПроцессов = "") Экспорт
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ПолучитьСеансПустойИнфобазы1С8Лкс");
		КлючНаборПараметров = "" + ТипCOMОбъекта + ";" + Видимость + ";" + ОбработатьИсключениеПодключения + ";" + ОписаниеОшибки + ";" + ИмяСервераПроцессов;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	СтрокаСоединения = ирОбщий.СтрокаСоединенияПустойИнфобазыЛкс();
	Результат = ирОбщий.СоздатьСеансИнфобазы1С8Лкс(СтрокаСоединения, , , ТипCOMОбъекта, Видимость, ОбработатьИсключениеПодключения,
		ОписаниеОшибки, ИмяСервераПроцессов);
		
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

Функция БуферСравненияЛкс(ТипДанных) Экспорт
	
	ирПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
		ирПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	Результат = ирПлатформа.БуферыСравнения[ТипДанных]; 
	Если Результат = Неопределено Тогда
		Результат = Новый Массив;
		ирПлатформа.БуферыСравнения[ТипДанных] = Результат;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

Функция ФорматБуфераОбмена1СЛкс() Экспорт 
	
	WinAPI = ирКэш.ПолучитьWinAPI();
	Если WinAPI <> Неопределено Тогда
		ФорматБуфераОбмена1С = WinAPI.RegisterClipboardFormat("V8Value");
	КонецЕсли; 
	Возврат ФорматБуфераОбмена1С;
	
КонецФункции

Функция Это64битнаяОСЛкс(Компьютер = Неопределено) Экспорт
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("Это64битнаяОСЛкс");
		КлючНаборПараметров = "" + Компьютер;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	Результат = ирКэш.Это64битныйПроцессЛкс();
	Если Не Результат Тогда
		мWMI =  ирКэш.ПолучитьCOMОбъектWMIЛкс(Компьютер);
		// http://www.forum.mista.ru/topic.php?id=752260
		//ИмяКласса = "Win32_OperatingSystem";
		//КоллекцияОС = мWMI.InstancesOf(ИмяКласса);
		//Для каждого лОС Из КоллекцияОС Цикл
		//	Прервать;
		//КонецЦикла;
		//Результат = Лев(лОС.OSArchitecture, 2) = "64";
		РезультатЗапроса = мWMI.ExecQuery("select AddressWidth from Win32_Processor where DeviceID=""CPU0"" AND AddressWidth=64");
		Результат = РезультатЗапроса.Count > 0;
	КонецЕсли;
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;

КонецФункции

// Возвращает смещение времени из-за некорректной функции ПолучитьВремяИзменения()
// Часть примечание из описания функции:
//  В режиме совместимости выдает местное время последней модификации файла с ошибкой NTFS.
//  Если файл изменен летом, а просматривается зимой, то полученное время отстает на 1 час.
//  Если файл изменен зимой, а просматривается летом, то полученное время опережает на 1 час.
//
// Источник - http://infostart.ru/public/323233/
// Автор - OtTech http://infostart.ru/profile/492011/
//
// Возвращаемое значение:
// Число - Количество секунд смещения.
//
Функция ПолучитьСмещениеВремениЛкс() Экспорт 
	
	ИмяФайла = ПолучитьИмяВременногоФайла();
	ТекстовыйДокумент = Новый ТекстовыйДокумент;
	ТекстовыйДокумент.Записать(ИмяФайла);
	Файл = Новый Файл(ИмяФайла);
	Разница = ОКР((ТекущаяДата() - Файл.ПолучитьВремяИзменения()) / 3600);
	УдалитьФайлы(ИмяФайла);
	Возврат Разница * 3600;
	
КонецФункции

Функция РазницаВремениКлиентСерверЛкс() Экспорт 
	
	Результат = ирОбщий.РазницаВремениКлиентСерверЛкс();
	Возврат Результат;

КонецФункции

Функция АнализТехножурналаЛкс() Экспорт
	
	Результат = ирОбщий.СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирАнализТехножурнала");
	Возврат Результат;
	
КонецФункции

Функция КоличествоОшибокВЖурналеЛкс(Знач Начало, Знач Конец, Знач СтруктураОтбора, Знач МаксимальныйРазмерВыгрузки = Неопределено) Экспорт 
	
	КоличествоОшибокВЖурнале = ирОбщий.КоличествоОшибокВЖурналеЛкс(Начало, Конец, СтруктураОтбора, МаксимальныйРазмерВыгрузки);
	Возврат КоличествоОшибокВЖурнале;

КонецФункции

Функция ПолучитьСеансТонкогоКлиентаЛкс() Экспорт
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ПолучитьСеансТонкогоКлиентаЛкс");
		КлючНаборПараметров = "";
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	СвязанныйСеансТонкогоКлиента = ирОбщий.ЗапуститьСеансПодПользователемЛкс(ИмяПользователя(),, "c.Application",,,, Ложь, Ложь); 
	Попытка
		СвязанныйСеансТонкогоКлиента.Visible = Истина;
	Исключение
		ирОбщий.СообщитьЛкс("Не удалось подключить тонкий клиент через COM. Пробуйте под пользователем без пароля https://www.hostedredmine.com/issues/917837.
		|Для диагностики используйте инструмент ""Управление COM классами 1С""", СтатусСообщения.Внимание);
		#Если Клиент Тогда
		Форма = ирКлиент.ПолучитьФормуЛкс("Обработка.ирУправлениеCOMКлассами1С.Форма");
		Форма.ПараметрТипКласса = "CApplication";
		Форма.Открыть();
		#КонецЕсли
		Возврат Неопределено;
	КонецПопытки; 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = СвязанныйСеансТонкогоКлиента;
	КонецЕсли; 
	Возврат СвязанныйСеансТонкогоКлиента;
	
КонецФункции

Функция ОбъектыМетаданныхСРегистрациейИзменений() Экспорт 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ОбъектыМетаданныхСРегистрациейИзменений");
		КлючНаборПараметров = "";
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	Результат = Новый Соответствие;
	Для Каждого МетаПланОбмена Из Метаданные.ПланыОбмена Цикл
		Для Каждого ЭлементСостава Из МетаПланОбмена.Состав Цикл
			Если ЭлементСостава.Метаданные = Неопределено Тогда
				// Битая ссылка
				Продолжить;
			КонецЕсли; 
			Результат[ЭлементСостава.Метаданные.ПолноеИмя()] = 1;
		КонецЦикла;
	КонецЦикла;
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

Функция ВКОбщаяЛкс() Экспорт 

	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ВКОбщаяЛкс");
		КлючНаборПараметров = "";
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	// Все способы помещения ВК в кэш приводят к ошибке плафтормы https://github.com/tormozit/RDT1C/issues/29
	//Результат = ирОбщий.НоваяВКОбщаяЛкс(Секунда(ТекущаяДата()));
	Результат = ирОбщий.НоваяВКОбщаяЛкс();
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

Функция КорневыеТипыСсылочныеЛкс() Экспорт 
	
	Результат = Новый Массив;
	мПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
		мПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	СтрокиМетаОбъектов = мПлатформа.ТаблицаТиповМетаОбъектов.НайтиСтроки(Новый Структура("Категория", 0));
	Для Каждого СтрокаТаблицыМетаОбъектов Из СтрокиМетаОбъектов Цикл
		Единственное = СтрокаТаблицыМетаОбъектов.Единственное;
		Если ирОбщий.ЛиКорневойТипСсылочногоОбъектаБДЛкс(Единственное) Тогда
			Результат.Добавить(СтрокаТаблицыМетаОбъектов);
		КонецЕсли;
	КонецЦикла;
	Возврат Результат;

КонецФункции

Функция ЭтоФоновоеЗаданиеЛкс() Экспорт 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		Возврат Ложь;
	КонецЕсли; 
	ТекущийСеанс = ирКэш.ТекущийСеансЛкс();
	Если ТекущийСеанс = Неопределено Тогда
		Результат = Ложь;
	Иначе
		Результат = ирОбщий.СтрокиРавныЛкс(ТекущийСеанс.ИмяПриложения, "BackgroundJob");
	КонецЕсли; 
	Возврат Результат;

КонецФункции

Функция ТекущийСеансЛкс() Экспорт 

	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ТекущийСеансЛкс");
		КлючНаборПараметров = "";
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли;
	Если ирКэш.НомерРежимаСовместимостиЛкс() >= 803007 Тогда
		Результат = Вычислить("ПолучитьТекущийСеансИнформационнойБазы()");
	Иначе
		Результат = ирСервер.ТекущийСеансЛкс();
	КонецЕсли; 
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;

КонецФункции

Функция РежимОтладкиЛкс() Экспорт 

	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("РежимОтладкиЛкс");
		КлючНаборПараметров = "";
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	Результат = ирКэш.Получить().РежимОтладки;
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

// 8.3.5+
Функция ДоступныВидыСравненияПодобноШаблонЛкс() Экспорт 
	
	Результат = ирКэш.НомерВерсииПлатформыЛкс() >= 803005;
	Возврат Результат;
	
КонецФункции

// 8.3.8+
Функция ДоступныТаблицыМенеджераВременныхТаблицЛкс() Экспорт 
	
	Менеджер = Новый МенеджерВременныхТаблиц;
	Попытка
		Результат = Менеджер.Таблицы;
	Исключение
		Результат = Неопределено;
	КонецПопытки;
	Возврат Результат <> Неопределено;
	
КонецФункции

// 8.3.9+
Функция ДоступнаЗащитаОтОпасныхДействийЛкс() Экспорт 
	
	ЗащитаОтОпасныхДействийЛ = Неопределено;
	Попытка
		ТекущийПользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
		ЗащитаОтОпасныхДействийЛ = ТекущийПользователь.ЗащитаОтОпасныхДействий;
	Исключение
	КонецПопытки;
	Возврат ЗащитаОтОпасныхДействийЛ <> Неопределено;
	
КонецФункции

// 8.2.14+
Функция ДоступныВнешниеИсточникДанныхЛкс() Экспорт 
	
	Результат = ирКэш.НомерВерсииПлатформыЛкс() >= 802014;
	Возврат Результат;
	
КонецФункции

// 8.2.14+
Функция ДоступныОбщиеРеквизитыЛкс() Экспорт 
	
	Результат = ирКэш.НомерВерсииПлатформыЛкс() >= 802014;
	Возврат Результат;
	
КонецФункции

// 8.3.18+
Функция ДоступноВосстановлениеПароляПользователямЛкс() Экспорт 
	
	Результат = Неопределено;
	Попытка
		ТекущийПользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
		Результат = ТекущийПользователь.ЗапрещеноВосстанавливатьПароль;
	Исключение
	КонецПопытки;
	Возврат Результат <> Неопределено;
	
КонецФункции

Функция ДоступноИсторияДанныхЛкс() Экспорт 
	
	Возврат ирКэш.НомерРежимаСовместимостиЛкс() >= 803011;

КонецФункции

Функция ДоступныПодключемыеКомандыЛкс() Экспорт 
	
	Результат = Истина
		И ирКэш.НомерВерсииБСПЛкс() >= 204
		И Метаданные.ОбщиеМодули.Найти("ПодключаемыеКоманды") <> Неопределено
		И Не ирКэш.ЛиПортативныйРежимЛкс(); 
	Возврат Результат;

КонецФункции

// 8.3.6+
// https://www.hostedredmine.com/issues/964302
Функция ЛиДоступнаКомпоновкаТаблицыЗначенийКлс() Экспорт 
	
	Возврат ирКэш.НомерРежимаСовместимостиЛкс() > 803005;

КонецФункции

// совместим 8.3.7+
Функция ЛиДоступнаСтрогаяСвязьСеансаСФоновымЗаданиемЛкс() Экспорт
	Возврат ирКэш.НомерРежимаСовместимостиЛкс() >= 803007;
КонецФункции

// Результат: Число . Например 801000-8.1, 803019-8.3.19
Функция НомерРежимаСовместимостиЛкс() Экспорт 
	
	ТекущийРежимСовместимости = Метаданные.РежимСовместимости;
	Если ТекущийРежимСовместимости = Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Тогда
		СисИнфо = Новый СистемнаяИнформация;
		Фрагменты = ирОбщий.СтрРазделитьЛкс(СисИнфо.ВерсияПриложения,,, Ложь); // Защита от рекурсии! 
	Иначе
		// Пример значения СтрокаВерсии = Версия8_3_1
		ТекущийРежимСовместимости = СтрЗаменить(ТекущийРежимСовместимости, "Версия", "");
		ТекущийРежимСовместимости = СтрЗаменить(ТекущийРежимСовместимости, "Version", ""); // Вариант встроенного языка Английский
		Фрагменты = ирОбщий.СтрРазделитьЛкс(ТекущийРежимСовместимости, "_",, Ложь); // Защита от рекурсии!
	КонецЕсли; 
	Результат = Число(Фрагменты[0]) * 100 * 1000 + Число(Фрагменты[1]) * 1000;
	Если Фрагменты.Количество() > 2 Тогда
		Результат = Результат + Число(Фрагменты[2]);
	КонецЕсли;
	Возврат Результат;
	
КонецФункции

// Например "82", "83"
// Результат: Строка
Функция НомерИзданияПлатформыЛкс() Экспорт 
	
	СисИнфо = Новый СистемнаяИнформация;
	Фрагменты = ирОбщий.СтрРазделитьЛкс(СисИнфо.ВерсияПриложения);
	Результат = Фрагменты[0] + Фрагменты[1];
	Возврат Результат;
	
КонецФункции

// Результат: Число
Функция НомерВерсииПлатформыЛкс(ВключаяНомерСборки = Ложь) Экспорт 
	
	СисИнфо = Новый СистемнаяИнформация;
	СтрокаВерсии = СисИнфо.ВерсияПриложения;
	Результат = ирОбщий.НомерВерсииПлатформыЛкс(СтрокаВерсии, ВключаяНомерСборки);
	Возврат Результат;
	
КонецФункции 

Функция НомерВерсииПодсистемыИРЛкс() Экспорт 
	
	ИспользуемаяВерсия = ИспользуемаяВерсияИРЛкс();
	Фрагменты = ирОбщий.СтрРазделитьЛкс(ИспользуемаяВерсия);
	#Если Сервер И Не Сервер Тогда
		Фрагменты = Новый Массив;
	#КонецЕсли
	Для Счетчик = Фрагменты.Количество() По 2 Цикл
		Фрагменты.Добавить("0");
	КонецЦикла;
	Результат = Число(Фрагменты[0]) * 100 + Число(Фрагменты[1]);
	Возврат Результат;
	
КонецФункции

Функция ИспользуемаяВерсияИРЛкс() Экспорт
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		ИспользуемаяВерсия = ирПортативный.мВерсия;
	Иначе 
		ИспользуемаяВерсия = Метаданные.Подсистемы.ИнструментыРазработчикаTormozit.Комментарий;
	КонецЕсли;
	Возврат ИспользуемаяВерсия;
КонецФункции

Функция НомерВерсииPowerShellЛкс() Экспорт 
	
	ТекстСкрипта = Новый ТекстовыйДокумент;
	ТекстСкрипта.УстановитьТекст("$PSVersionTable.PSVersion.major");
	ФайлСкрипта = Новый Файл(ПолучитьИмяВременногоФайла("ps1"));
	ТекстСкрипта.Записать(ФайлСкрипта.ПолноеИмя);
	СтрокаЗапуска = ирОбщий.КомандаСистемыЗапускаСкриптаPowerShellЛкс(ФайлСкрипта.Имя);
	РезультатКоманды = ирОбщий.ВыполнитьКомандуОСЛкс(СтрокаЗапуска);
	Результат = Число(РезультатКоманды);
	Возврат Результат;
	
КонецФункции

Функция ВерсияБСПЛкс() Экспорт 
	УстановитьПривилегированныйРежим(Истина);
	Если Истина
		И Метаданные.РегистрыСведений.Найти("ВерсииПодсистем") <> Неопределено 
		И ПравоДоступа("Чтение", Метаданные.РегистрыСведений.ВерсииПодсистем)
	Тогда
		Запрос = Новый Запрос;
		Запрос.Текст = "
		|ВЫБРАТЬ
		|	ВерсииПодсистем.Версия КАК Версия
		|ИЗ
		|	РегистрСведений.ВерсииПодсистем КАК ВерсииПодсистем
		|ГДЕ
		|	ВерсииПодсистем.ИмяПодсистемы = &ИмяПодсистемы
		|";
		Запрос.УстановитьПараметр("ИмяПодсистемы", "СтандартныеПодсистемы");
		Таблица = Запрос.Выполнить().Выгрузить();
		Если Таблица.Количество() > 0 Тогда
			ВерсияБСП = Таблица[0].Версия;
		КонецЕсли; 
	КонецЕсли;
	Возврат ВерсияБСП;
КонецФункции

Функция НомерВерсииБСПЛкс() Экспорт 
	
	ВерсияБСП = ирКэш.ВерсияБСПЛкс();
	Если ЗначениеЗаполнено(ВерсияБСП) Тогда
		Фрагменты = ирОбщий.СтрРазделитьЛкс(ВерсияБСП);
		Результат = Число(Фрагменты[0]) * 100 + Число(Фрагменты[1]);
	Иначе
		Результат = 0;
	КонецЕсли; 
	Возврат Результат;

КонецФункции

Функция ЭталонныйНаборЗаписейЛкс(Знач ПолноеИмяТаблицыБД) Экспорт 
	
	#Если Сервер Тогда 
		// Будет всегда работать в файловой базе. Поэтому там объект будет всегда на клиенте создаваться
		ОбъектыНаСервере = Ложь; 
	#Иначе
		ОбъектыНаСервере = "Обязательно";
	#КонецЕсли 
	НаборЗаписей = ирОбщий.СоздатьНаборЗаписейПоИмениТаблицыБДЛкс(ПолноеИмяТаблицыБД, ОбъектыНаСервере).Методы;   
	Возврат НаборЗаписей;

КонецФункции

// Каталог издания платформы в профиле пользователя ОС
//
// Параметры:
//  Локальный        - Булево - при Истина будет Local, иначе Roaming
//  ИзданиеПлатформы - Строка - например "82", "83"
// 
// Возвращаемое значение:
//   - 
//
Функция КаталогИзданияПлатформыВПрофилеЛкс(Локальный = Истина, Знач ИзданиеПлатформы = "") Экспорт

	КаталогДанныхПриложения = КаталогПлатформыВПрофилеЛкс(Локальный);
	Если Не ЗначениеЗаполнено(ИзданиеПлатформы) Тогда
		ИзданиеПлатформы = ирКэш.НомерИзданияПлатформыЛкс();
	КонецЕсли; 
	Если ИзданиеПлатформы > "82" Тогда
		Суффикс = Лев(ИзданиеПлатформы, 1);
	Иначе
		Суффикс = ИзданиеПлатформы;
	КонецЕсли; 
	Разделитель = ирОбщий.РазделительПутиКФайлуЛкс();
	КаталогДанныхПриложения = КаталогДанныхПриложения + Разделитель + "1cv" + Суффикс;
	ФайлПеренаправления = Новый Файл(КаталогДанныхПриложения + Разделитель + "location.cfg");
	Если ФайлПеренаправления.Существует() Тогда
		ЧтениеТекста = Новый ЧтениеТекста;
		ЧтениеТекста.Открыть(ФайлПеренаправления.ПолноеИмя);
		СтрокаФайла = ЧтениеТекста.ПрочитатьСтроку();
		НовыйКаталог = НСтр(СтрокаФайла, "location");
		Если ЗначениеЗаполнено(НовыйКаталог) Тогда
			Если Разделитель = "\" Тогда
				КаталогДанныхПриложения = СтрЗаменить(НовыйКаталог, "/", Разделитель);
			Иначе
				КаталогДанныхПриложения = СтрЗаменить(НовыйКаталог, "\", Разделитель);
			КонецЕсли;
		КонецЕсли; 
	КонецЕсли; 
	Возврат КаталогДанныхПриложения;

КонецФункции

Функция КаталогПлатформыВПрофилеЛкс(Знач Локальный = Ложь) Экспорт 
	
	Если Не ирКэш.ЛиПлатформаWindowsЛкс() Тогда 
		//КаталогДанныхПриложения = "~/.1cv8"; // Похоже так можно только в bash.  Ошибка доступа к файлу '~'. 13(0x0000000D): Permission denied
		#Если Клиент Тогда
			Если Локальный Тогда
				Подкаталог = ".1cv8" + ирОбщий.РазделительПутиКФайлуЛкс() + "1C";
			Иначе
				Подкаталог = ".1C";
			КонецЕсли; 
			ПеременныеОкружения = ирОбщий.ВыполнитьКомандуОСЛкс("env");
			КаталогПользователя = ирОбщий.ЗначениеПеременнойОкруженияЛкс(ПеременныеОкружения, "HOME=");
			Если Не ЗначениеЗаполнено(КаталогПользователя) Тогда
				КаталогДанныхПриложения = "/home/" + ирКэш.ТекущийПользовательОСЛкс(Ложь) + ирОбщий.РазделительПутиКФайлуЛкс() + Подкаталог;
			Иначе    
				КаталогДанныхПриложения = КаталогПользователя + ирОбщий.РазделительПутиКФайлуЛкс() + Подкаталог;
			КонецЕсли;
		#Иначе
			КаталогДанныхПриложения = КаталогВременныхФайлов();
		#КонецЕсли
	Иначе
		Если Локальный Тогда
			Подкаталог = 28;
		Иначе
			Подкаталог = 26;
		КонецЕсли; 
		ПриложениеОболочкиОС = Новый COMobject("Shell.Application");
		КаталогДанныхПриложения = ПриложениеОболочкиОС.NameSpace(Подкаталог);
		Если КаталогДанныхПриложения = Неопределено Тогда
			// https://www.hostedredmine.com/issues/954427
			КаталогДанныхПриложения = КаталогВременныхФайлов();
		Иначе
			КаталогДанныхПриложения = КаталогДанныхПриложения.Self.Path;
			КаталогДанныхПриложения = КаталогДанныхПриложения + ирОбщий.РазделительПутиКФайлуЛкс() + "1C";
		КонецЕсли;
	КонецЕсли;
	Возврат КаталогДанныхПриложения;

КонецФункции

Функция ВычислительРегВыраженийЛкс(Ключ = "") Экспорт 
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ВычислительРегВыраженийЛкс");
		КлючНаборПараметров = "" + Ключ;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли;
	Результат = ирОбщий.НовоеРегВыражениеЛкс();
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;
КонецФункции

Функция ПолучитьCOMОбъектWMIЛкс(Знач ИмяСервера = Неопределено, Знач ИмяСервераИсполнителя = Неопределено, Знач ТочкаПодключения = Неопределено) Экспорт
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ПолучитьCOMОбъектWMIЛкс");
		КлючНаборПараметров = "" + ИмяСервера + ";" + ИмяСервераИсполнителя + ";" + ТочкаПодключения;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	Если Не ирОбщий.ЭтоИмяЛокальногоКомпьютераЛкс(ИмяСервера) Тогда
		// Обходим проблему с большим таймаутом метода WbemScripting.SWbemLocator.ConnectServer http://www.forum.mista.ru/topic.php?id=752526
		// https://www.hostedredmine.com/issues/907854
		ДопустимоеОжиданиеОтвета = 1;
		ФайлРезультата = ирОбщий.ВыполнитьКомандуОСЛкс("rpcping -s " + ИмяСервера, Ложь);
		#Если Сервер И Не Сервер Тогда
			ФайлРезультата = Новый Файл;
		#КонецЕсли
		ТекстовыйДокумент = Новый ТекстовыйДокумент;
		ТекстРезультата = "";
		НачальнаяДата = ТекущаяДата();
		Пока Истина Цикл
			Попытка
				ТекстовыйДокумент.Прочитать(ФайлРезультата.ПолноеИмя);
				ТекстРезультата = ТекстовыйДокумент.ПолучитьТекст();
				УдалитьФайлы(ФайлРезультата.ПолноеИмя);
			Исключение
				// Файл недоступен, значит процесс все еще запускается
			КонецПопытки; 
			Если Ложь
				Или ФайлРезультата = Неопределено
				Или ТекущаяДата() - НачальнаяДата >= ДопустимоеОжиданиеОтвета 
				Или Найти(ТекстРезультата, "0x000006BA") > 0
			Тогда
				ирОбщий.СообщитьЛкс(ирОбщий.СтрШаблонИменЛкс("The RPC server %1 is unavailable",, ИмяСервера), СтатусСообщения.Внимание);
				Возврат Неопределено;
			КонецЕсли;
			Если ЗначениеЗаполнено(ТекстРезультата) Тогда
				Прервать;
			КонецЕсли; 
			ирОбщий.ПаузаЛкс(1);
		КонецЦикла; 
	КонецЕсли; 

	//http://msdn.microsoft.com/en-us/library/windows/desktop/aa389763(v=vs.85).aspx
	Если Не ЗначениеЗаполнено(ИмяСервераИсполнителя) Тогда 
		Locator = Новый COMОбъект("WbemScripting.SWbemLocator");
	Иначе
		Locator = Новый COMОбъект("WbemScripting.SWbemLocator", ИмяСервераИсполнителя);
	КонецЕсли;
	Если Не ЗначениеЗаполнено(ИмяСервера) Тогда 
		ИмяСервера = ".";
	КонецЕсли;
	Если Не ЗначениеЗаполнено(ТочкаПодключения) Тогда 
		ТочкаПодключения = "root\cimv2";
	КонецЕсли;
	Попытка
		Результат = Locator.ConnectServer(ИмяСервера, ТочкаПодключения, , , );
	Исключение
		Результат = Неопределено;
		ирОбщий.СообщитьЛкс(ОписаниеОшибки(), СтатусСообщения.Внимание);
	КонецПопытки;
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

Функция ТекущийПользовательОСЛкс(СИменемДомена = Истина) Экспорт  
	
	#Если ВебКлиент Тогда
		ПользовательОС = "";
	#Иначе
		Если Не ирКэш.ЛиПлатформаWindowsЛкс() Тогда 
			// https://wiki.merionet.ru/servernye-resheniya/43/peremennye-okruzheniya-v-linux-kak-posmotret-ustanovit-i-sbrosit/
			ПеременныеОкружения = ирОбщий.ВыполнитьКомандуОСЛкс("env");
			ПользовательОС = ирОбщий.ТекстМеждуМаркерамиЛкс(ПеременныеОкружения, "USER=", Символы.ПС, Ложь);
			Если Не ЗначениеЗаполнено(ПользовательОС) Тогда
				ПользовательОС = ирОбщий.ПоследнийФрагментЛкс(ирОбщий.ТекстМеждуМаркерамиЛкс(ПеременныеОкружения, "HOME=", Символы.ПС, Ложь), "/");
			КонецЕсли; 
			// Переделать на ирОбщий.ВыполнитьКомандуОСЛкс("whoami")
		Иначе
			Network = Новый COMОбъект("WScript.Network");
			ПользовательОС = Network.UserName;
			Если СИменемДомена Тогда
				ПользовательОС = Network.UserDomain + "\" + ПользовательОС;
			КонецЕсли; 
		КонецЕсли; 
	#КонецЕсли
	Возврат ПользовательОС;
	
КонецФункции

Функция ПеременныеОкруженияПроцессаЛкс() Экспорт 
	
	// https://ab57.ru/cmdlist/set.html
	Shell = Новый COMОбъект("WScript.Shell");
	ПеременныеОкружения = Shell.Environment("PROCESS");
	Возврат ПеременныеОкружения;

КонецФункции

Функция ПараметрыЗаписиОбъектовЛкс() Экспорт 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ПараметрыЗаписиОбъектовЛкс");
		КлючНаборПараметров = "";
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	Результат = Новый Структура("БезАвторегистрацииИзменений, ОбъектыНаСервере, ДополнительныеСвойства, ОтключатьКонтрольЗаписи, НеИспользоватьИмитаторыОбъектовДанных, ПривилегированныйРежим,
		|ОтключатьЗаписьВерсии, ПроверятьЗаполнение");
	Результат.БезАвторегистрацииИзменений = ирОбщий.ВосстановитьЗначениеЛкс("ирПараметрыЗаписиОбъектов.БезАвторегистрацииИзменений");
	Результат.ОбъектыНаСервере = ирОбщий.ВосстановитьЗначениеЛкс("ирПараметрыЗаписиОбъектов.ОбъектыНаСервере");
	Если Результат.ОбъектыНаСервере = Неопределено Тогда
		Результат.ОбъектыНаСервере = ирОбщий.РежимОбъектыНаСервереПоУмолчаниюЛкс();
	КонецЕсли; 
	Результат.НеИспользоватьИмитаторыОбъектовДанных = ирОбщий.ВосстановитьЗначениеЛкс("ирПараметрыЗаписиОбъектов.НеИспользоватьИмитаторыОбъектовДанных");
	Если Результат.НеИспользоватьИмитаторыОбъектовДанных = Неопределено Тогда
		Результат.НеИспользоватьИмитаторыОбъектовДанных = ирОбщий.ВосстановитьЗначениеЛкс("НеИспользоватьИмитаторыОбъектовДанных");
		Если Результат.НеИспользоватьИмитаторыОбъектовДанных = Неопределено Тогда
			Результат.НеИспользоватьИмитаторыОбъектовДанных = Ложь;
		КонецЕсли; 
	КонецЕсли; 
	Результат.ДополнительныеСвойства = ирОбщий.ВосстановитьЗначениеЛкс("ирПараметрыЗаписиОбъектов.ДополнительныеСвойства");
	Если Результат.ДополнительныеСвойства = Неопределено Тогда
		Результат.ДополнительныеСвойства = Новый ТаблицаЗначений; // см. Обработка.ирПлатформа.Форма.ПараметрыЗаписиОбъектов.ДополнительныеСвойства                
	КонецЕсли;
	Если Результат.ДополнительныеСвойства.Колонки.Найти("Пометка") = Неопределено Тогда
		Результат.ДополнительныеСвойства.Колонки.Добавить("Пометка");
	КонецЕсли;
	Результат.ОтключатьКонтрольЗаписи = ирОбщий.ВосстановитьЗначениеЛкс("ирПараметрыЗаписиОбъектов.ОтключатьКонтрольЗаписи");
	Если Результат.ОтключатьКонтрольЗаписи = Неопределено Тогда
		Результат.ОтключатьКонтрольЗаписи = Ложь;
	КонецЕсли; 
	Результат.ПроверятьЗаполнение = ирОбщий.ВосстановитьЗначениеЛкс("ирПараметрыЗаписиОбъектов.ПроверятьЗаполнение");
	Если Результат.ПроверятьЗаполнение = Неопределено Тогда
		Результат.ПроверятьЗаполнение = Ложь;
	КонецЕсли; 
	Результат.ОтключатьЗаписьВерсии = ирОбщий.ВосстановитьЗначениеЛкс("ирПараметрыЗаписиОбъектов.ОтключатьЗаписьВерсии");
	Если Результат.ОтключатьЗаписьВерсии = Неопределено Тогда
		Результат.ОтключатьЗаписьВерсии = Ложь;
	КонецЕсли; 
	Результат.ПривилегированныйРежим = ирОбщий.ВосстановитьЗначениеЛкс("ирПараметрыЗаписиОбъектов.ПривилегированныйРежим");
	Если Результат.ПривилегированныйРежим = Неопределено Тогда
		Результат.ПривилегированныйРежим = Ложь;
	КонецЕсли; 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	//Возврат Новый ФиксированнаяСтруктура(Результат); // Нельзя т.к. мы кэш эту структуру обновляем сами в форме настроек
	Возврат Результат;

КонецФункции

Функция ЛюбойТипРегистраЛкс(Знач ПодтипРус) Экспорт 
	
	ПодтипРус = ирОбщий.ПеревестиСтроку(ПодтипРус);
	ТипОбразец = Неопределено;
	КоллекцииМетаданных = Новый Массив;
	КоллекцииМетаданных.Добавить(Метаданные.РегистрыСведений);
	КоллекцииМетаданных.Добавить(Метаданные.РегистрыНакопления);
	КоллекцииМетаданных.Добавить(Метаданные.РегистрыБухгалтерии);
	КоллекцииМетаданных.Добавить(Метаданные.РегистрыРасчета);
	КоллекцииМетаданных.Добавить(Метаданные.Последовательности);
	Для Каждого КоллекцияМетаданных Из КоллекцииМетаданных Цикл
		Для Каждого МетаРегистр Из КоллекцияМетаданных Цикл
			ИмяТипа = СтрЗаменить(МетаРегистр.ПолноеИмя(), ".", ПодтипРус + ".");
			Попытка
				ТипОбразец = Тип(ИмяТипа);
			Исключение
				Продолжить;
			КонецПопытки; 
			Прервать;
		КонецЦикла;
		Если ТипОбразец <> Неопределено Тогда
			Прервать;
		КонецЕсли; 
	КонецЦикла; 
	Возврат ТипОбразец;

КонецФункции

Функция ЛюбойТипТабличнойЧастиЛкс() Экспорт 
	Результат = ТипЗнч(ирКэш.Получить().КолонкиТабличногоПоля);
	Возврат Результат;
КонецФункции

Функция ЛюбойТипСтрокиТабличнойЧастиЛкс() Экспорт 
	Результат = ТипЗнч(ирКэш.Получить().КолонкиТабличногоПоля.Добавить());
	Возврат Результат;
КонецФункции

Функция МаркерПодтипаИзТипаЛкс(Знач ПредставлениеТипа, Знач КоличествоСлов) Экспорт 
	
	ПредставлениеОбразца = ирОбщий.ПервыйФрагментЛкс(ПредставлениеТипа, ":");
	ФрагментыОбразца = ирОбщий.СтрРазделитьЛкс(ПредставлениеОбразца, " ");
	#Если Сервер И Не Сервер Тогда
		ФрагментыОбразца = Новый Массив;
	#КонецЕсли
	МаркерТипа = "";
	Для Счетчик = 1 По КоличествоСлов Цикл
		Если МаркерТипа <> "" Тогда
			МаркерТипа = МаркерТипа + " ";
		КонецЕсли; 
		МаркерТипа = МаркерТипа + ФрагментыОбразца[ФрагментыОбразца.ВГраница() - (КоличествоСлов - Счетчик)];
	КонецЦикла;
	Возврат МаркерТипа;

КонецФункции

Функция КлючБазыВСпискеПользователяИзКоманднойСтрокиЛкс() Экспорт 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("КлючБазыВСпискеПользователяИзКоманднойСтрокиЛкс");
		КлючНаборПараметров = "";
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	Если ирОбщий.ЛиИдентификацияБазыВСпискеПоНаименованиюЛкс() Тогда
		Если Не ирКэш.ДоступныРегВыраженияЛкс() Тогда
			Результат = Неопределено;
		Иначе
			КоманднаяСтрокаПроцесса = ирКэш.КоманднаяСтрокаТекущегоПроцессаОСЛкс();
			РегВыражение = ирОбщий.НовоеРегВыражениеЛкс();
			РегВыражение.IgnoreCase = Истина;
			РегВыражение.Global = Истина;
			РегВыражение.Pattern = "(?:/IBName\s*(""((.|"""")+?)""|(((.)+?))))(\s|$)";
			Вхождения = РегВыражение.НайтиВхождения(КоманднаяСтрокаПроцесса);
			Если Вхождения.Количество() > 0 Тогда
				Результат = Вхождения[0].SubMatches(0);
				Если Лев(Результат, 1) = """" Тогда
					Результат = ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(Результат);
				КонецЕсли;
			КонецЕсли;
		КонецЕсли; 
	Иначе
		Результат = СтрокаСоединенияИнформационнойБазы();
	КонецЕсли; 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

Функция НастройкиБазыНаКлиентеЛкс() Экспорт 
	
	ТаблицаБазКлиента = ирОбщий.СписокБазПользователяОСЛкс();
	#Если Сервер И Не Сервер Тогда
		ТаблицаБазКлиента = Обработки.ирПлатформа.Создать().СписокБазПользователя;
	#КонецЕсли
	КлючомЯвляетсяСтрокаСоединения = Ложь;
	КлючБазыВСпискеПользователя = ирОбщий.КлючБазыВСпискеПользователяЛкс(КлючомЯвляетсяСтрокаСоединения);
	Если КлючомЯвляетсяСтрокаСоединения Тогда
		ИмяКлюча = "НСтрокаСоединения";
	Иначе
		ИмяКлюча = "КлючСтроки";
	КонецЕсли; 
	СтрокаТекущейБазы = ТаблицаБазКлиента.Найти(НРег(КлючБазыВСпискеПользователя), ИмяКлюча);
	Возврат СтрокаТекущейБазы;
	
КонецФункции

Функция АбсолютныйЦветЛкс(Знач ИсходныйЦвет) Экспорт
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("АбсолютныйЦветЛкс");
		КлючНаборПараметров = "" + ИсходныйЦвет;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	#Если Сервер И Не Сервер Тогда
		ИсходныйЦвет = Новый Цвет;
	#КонецЕсли
	ИсходныйЦвет = ЗначениеИзСтрокиВнутр(ИсходныйЦвет);
	Если ИсходныйЦвет.Вид = ВидЦвета.Абсолютный Тогда
		Возврат ИсходныйЦвет;
	КонецЕсли;
	
	Если ирКэш.НомерВерсииПлатформыЛкс() >= 803001 Тогда
		// Способ без операций вывода https://infostart.ru/public/1278131/
		ФорматДок = Новый ФорматированныйДокумент;
		ФорматДок.УстановитьФорматированнуюСтроку(Вычислить("Новый ФорматированнаяСтрока("" "", , ИсходныйЦвет)")); // На 8.2 нет типа ФорматированнаяСтрока
		ТекстHTML = "";
		ФорматДок.ПолучитьHTML(ТекстHTML, Неопределено);
		ПозицияЧислаHEX = Найти(ТекстHTML, "#") + 1;
		ЧислоHEX = Сред(ТекстHTML, ПозицияЧислаHEX, 6);
		Результат = ирОбщий.ЧислоHEXВЦветЛкс(ЧислоHEX);
	Иначе
		Если ирКэш.ЭтоУчебнаяПлатформаЛкс() Тогда
			Результат = ИсходныйЦвет;
		Иначе
			ВременныйФайл = ПолучитьИмяВременногоФайла("mxl");
			ТабДок = Новый ТабличныйДокумент;
			ТабДок.Область("R1C1").ЦветФона = ИсходныйЦвет;
			ТабДок.Записать(ВременныйФайл, ТипФайлаТабличногоДокумента.MXL7); // В учебной версии платформы это запрещено https://www.hostedredmine.com/issues/923942
			ТабДок.Прочитать(ВременныйФайл);
			Результат = ТабДок.Область("R1C1").ЦветФона;
		КонецЕсли; 
	КонецЕсли; 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции 

Функция КартинкаИнструментаЛкс(ПолноеИмя) Экспорт 
	
	мПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
		мПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	мПлатформа.ЗаполнитьСписокИнструментов();
	СтрокаИнструмента = мПлатформа.СписокИнструментов.Найти(ПолноеИмя, "ПолноеИмя");
	Если СтрокаИнструмента <> Неопределено Тогда
		Результат = ирКэш.КартинкаПоИмениЛкс(СтрокаИнструмента.ИмяКартинки);
	ИначеЕсли ПолноеИмя = "Обработка.ирДинамическийСписок" Тогда 
		Результат = ирКэш.КартинкаПоИмениЛкс("ирДинамическийСписок");
	Иначе
		Результат = Новый Картинка;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

Функция ТипыРасширенийКонфигурацииЛкс(Знач ИмяКлассаМетаданных = Неопределено) Экспорт 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ТипыРасширенийКонфигурацииЛкс");
		КлючНаборПараметров = "" + ИмяКлассаМетаданных;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	РасширенияКонфигурацииЛ = Вычислить("РасширенияКонфигурации");
	#Если Сервер И Не Сервер Тогда
		РасширенияКонфигурацииЛ = РасширенияКонфигурации;
	#КонецЕсли
	ВсеРасширения = РасширенияКонфигурацииЛ.Получить();
	Если Ложь
		Или ВсеРасширения.Количество() > 1
		Или (Не ирКэш.ЛиЭтоРасширениеКонфигурацииЛкс() И ВсеРасширения.Количество() > 0)
	Тогда
		//// Медленный способ. Необходимость обусловлена отсутствием типов расширений конфигурации в супертипе ЛюбаяСсылка https://partners.v8.1c.ru/forum/t/1823711/m/1823711
		//ТаблицаВсехТаблицБД = ирКэш.ТаблицаВсехТаблицБДЛкс();
		//#Если Сервер И Не Сервер Тогда
		//	РасширенияКонфигурацииЛ = РасширенияКонфигурации;
		//	ТаблицаВсехТаблицБД = Новый ТаблицаЗначений;
		//#КонецЕсли
		//ВсеТипыСсылок = ТаблицаВсехТаблицБД.ВыгрузитьКолонку("ТипСсылки");
		//Результат = Новый ОписаниеТипов(ВсеТипыСсылок);
		
		Результат = Новый Массив;
		ТаблицаТиповМетаОбъектов = ирКэш.ТипыМетаОбъектов(Ложь, Ложь, Ложь);
		Для Каждого СтрокаМетаТипа Из ТаблицаТиповМетаОбъектов Цикл
			Если Ложь
				Или (Истина
					И ЗначениеЗаполнено(ИмяКлассаМетаданных)
					И СтрокаМетаТипа.Единственное <> ИмяКлассаМетаданных)
				Или Не ирОбщий.ЛиКорневойТипСсылкиЛкс(СтрокаМетаТипа.Единственное)
			Тогда
				Продолжить;
			КонецЕсли; 
			Для Каждого МетаОбъект Из Метаданные[СтрокаМетаТипа.Множественное] Цикл
				Если ирОбщий.РасширениеКонфигурацииОбъектаМДЛкс(МетаОбъект) <> Неопределено Тогда
					Результат.Добавить(Тип(ирОбщий.ИмяТипаИзПолногоИмениМДЛкс(МетаОбъект)));
				КонецЕсли;
			КонецЦикла;
		КонецЦикла;
	КонецЕсли;
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;

КонецФункции

Функция СостояниеПодготовкиКэшМДСеансаЛкс() Экспорт 
	Если Ложь
		#Если Не Клиент И Сервер Тогда
		Или Истина
		#КонецЕсли
		Или ЭтоФоновоеЗаданиеЛкс() 
		
		//Или Не ирОбщий.ЛиАсинхронностьДоступнаЛкс() // Этот способ более жесткий, а в этом фоновом задании права на объекты подсистемы пока не нужны. Поэтому пока не будет его применять
		//
		Или ирКэш.ЛиПортативныйРежимЛкс() 
		Или ирКэш.ЛиФайловаяБазаЛкс()
	Тогда
		Возврат Неопределено;
	КонецЕсли; 
	#Если Клиент Тогда
	// Антибаг 8.3.16-  В обычном приложении в клиент-серверном режиме из временного хранилища иногда возвращается Неопределено https://partners.v8.1c.ru/forum/t/1768363/m/1768363, http://www.hostedredmine.com/issues/884756
	ФормаРезультата = ирКлиент.НоваяФормаРезультатаФоновогоЗаданияЛкс();
	АдресРезультата = ПоместитьВоВременноеХранилище(Неопределено, ФормаРезультата.УникальныйИдентификатор);
	ПараметраЗадания = Новый Массив(1);
	ПараметраЗадания[0] = АдресРезультата;
	ирОбщий.ДобавитьТекущемуПользователюРолиИРЛкс();
	#Если Сервер И Не Сервер Тогда
		ирОбщий.КэшМДСеансаВФонеЛкс();
	#КонецЕсли
	ФоновоеЗадание = ФоновыеЗадания.Выполнить("ирОбщий.КэшМДСеансаВФонеЛкс", ПараметраЗадания,, "Подготовка кэша метаданных сеанса (ИР)");
	Результат = Новый Структура;
	Результат.Вставить("ИдентификаторЗадания", ФоновоеЗадание.УникальныйИдентификатор);
	Результат.Вставить("АдресРезультата", АдресРезультата);
	Результат.Вставить("ФормаРезультата", ФормаРезультата);
	Возврат Новый ФиксированнаяСтруктура(Результат);
	#КонецЕсли
КонецФункции

Функция ВсеПодсистемыЛкс(Подсистема = Неопределено, Результат = Неопределено) Экспорт 
	Если Подсистема = Неопределено Тогда
		Подсистема = Метаданные;
	КонецЕсли; 
	Если Результат = Неопределено Тогда
		Результат = Новый СписокЗначений;
	КонецЕсли; 
	Для Каждого ДочерняяПодсистема Из Подсистема.Подсистемы Цикл
		Результат.Добавить(ДочерняяПодсистема, ирОбщий.ПолноеИмяПодсистемыЛкс(ДочерняяПодсистема));
		ВсеПодсистемыЛкс(ДочерняяПодсистема, Результат); 
	КонецЦикла;
	Возврат Результат;
КонецФункции

// Кэширование в 100 раз ускоряет повторный поиск
Функция ОбъектМДПоПолномуИмениЛкс(ПолноеИмяМД) Экспорт 
	Если Найти(ПолноеИмяМД, ".") = 0 Тогда
		// https://www.hostedredmine.com/issues/890489
		Возврат Неопределено;
	КонецЕсли; 
	Возврат Метаданные.НайтиПоПолномуИмени(ПолноеИмяМД);
КонецФункции

Функция ИмяТаблицыИзМетаданныхЛкс(Знач ПолноеИмяМД, Знач ЛиТаблицаИзменений = Ложь, Знач ЛиДвиженияССубконтоДляРегистраБухгалтерии = Истина, Знач ТолькоРазрешенные = Ложь) Экспорт 
	Фрагменты = ирОбщий.СтрРазделитьЛкс(ПолноеИмяМД);
	Если ТолькоРазрешенные Тогда 
		//Если ТипЗнч(ОбъектИлиИмяМД) = Тип("Строка") Тогда
			Если Фрагменты[0] = "ВнешнийИсточникДанных" Тогда 
				ОбъектМД = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяМД);
			ИначеЕсли Фрагменты.Количество() > 1 Тогда
				ОбъектМД = ирКэш.ОбъектМДПоПолномуИмениЛкс(Фрагменты[0] + "." + Фрагменты[1]); // очень долгая операция, поэтому лучше не устанавливать флаг ТолькоРазрешенные
			Иначе
				//ОбъектМД = Метаданные[Фрагменты[0]];
				ОбъектМД = Неопределено;
			КонецЕсли;
		//Иначе
		//	ОбъектМД = ОбъектИлиИмяМД;
		//КонецЕсли;  
		Если Истина
			И ОбъектМД <> Неопределено
			И Не ПравоДоступа("Чтение", ОбъектМД)
		Тогда
			Возврат Неопределено;
		КонецЕсли;
	КонецЕсли;
	Если ЛиТаблицаИзменений Тогда 
		ДублиТаблицыБД = ирКэш.ТаблицаВсехТаблицБДЛкс().НайтиСтроки(Новый Структура("НПолноеИмя", Нрег(ПолноеИмяМД + ".Изменения")));
		Если ДублиТаблицыБД.Количество() > 1 Тогда 
			// Конфликтная ситуация в платформе - ТЧ имеет имя совпадающее с именем общей таблицы "Изменения" - побеждает ТЧ
			ирОбщий.СообщитьЛкс(ирОбщий.СтрШаблонИменЛкс("Таблица изменений %1 перекрыта табличной частью ""Изменения"". Поэтому невозможно получить количество изменений в ней.",, ПолноеИмяМД),
				СтатусСообщения.Внимание);
			Возврат Неопределено;
		КонецЕсли; 
	КонецЕсли; 
	Если Истина
		И Фрагменты.Количество() = 2
		И Не ЛиТаблицаИзменений
		И Фрагменты[0] = ирОбщий.ПеревестиСтроку("Константа")
	Тогда
		Если Не ирКэш.ДоступныТаблицыКонстантЛкс() Тогда
			Фрагменты = ирОбщий.СтрРазделитьЛкс("Константы");
		КонецЕсли; 
	КонецЕсли; 
	Если Фрагменты.Количество() = 4 Тогда
		Если Ложь
			Или ирОбщий.СтрокиРавныЛкс(Фрагменты[2], ирОбщий.ПеревестиСтроку("ТабличнаяЧасть"))
			Или ирОбщий.СтрокиРавныЛкс(Фрагменты[2], ирОбщий.ПеревестиСтроку("Перерасчет"))
			//Или СтрокиРавныЛкс(Фрагменты[2], "Таблица") // Неправильная строка!
		Тогда
			Фрагменты.Удалить(2);
		КонецЕсли; 
	КонецЕсли; 
	ИмяТаблицы = ирОбщий.СтрСоединитьЛкс(Фрагменты, ".");
	Если Истина
		И ЛиДвиженияССубконтоДляРегистраБухгалтерии
		И Не ЛиТаблицаИзменений
		И ирОбщий.ЛиПолноеИмяРегистраБухгалтерииЛкс(ПолноеИмяМД, Фрагменты)
	Тогда
		ИмяТаблицы = ИмяТаблицы + "." + ирОбщий.ПеревестиСтроку("ДвиженияССубконто");
	КонецЕсли; 
	Если ЛиТаблицаИзменений Тогда
		ИмяТаблицы = ИмяТаблицы + "." + ирОбщий.ПеревестиСтроку("Изменения");
	КонецЕсли; 
	Возврат ИмяТаблицы;
КонецФункции

// Функция - Доступные общие модули лкс
//
// Параметры:
//  Сервер				 - Булево -
//  КлиентОбычный		 - Булево, Неопределено - Неопределено означает текущий тип клиента
//  КлиентУправляемый	 - Булево, Неопределено - Неопределено означает текущий тип клиента 
// 
// Возвращаемое значение:
//   ФиксированнаяСтруктура - 
//
Функция ДоступныеОбщиеМодулиЛкс(Знач Сервер = Истина, Знач КлиентОбычный = Неопределено, Знач КлиентУправляемый = Неопределено) Экспорт 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ДоступныеОбщиеМодулиЛкс");
		КлючНаборПараметров = "" + Сервер + ";" + КлиентОбычный + ";" + КлиентУправляемый;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	Результат = Новый Структура;
	Для Каждого МетаОбщийМодуль Из Метаданные.ОбщиеМодули Цикл
		#Если Сервер И Не Сервер Тогда
			МетаОбщийМодуль = Метаданные.ОбщиеМодули.ирОбщий;       
		#КонецЕсли
		Если МетаОбщийМодуль.Глобальный Тогда
			Продолжить;
		КонецЕсли;
		Добавлять = Ложь;
		Если МетаОбщийМодуль.ВызовСервера Тогда
			Добавлять = Истина;
		КонецЕсли; 
		Если Сервер = Истина И МетаОбщийМодуль.Сервер Тогда
			Добавлять = Истина;
		КонецЕсли; 
		Если КлиентУправляемый = Истина И МетаОбщийМодуль.КлиентУправляемоеПриложение Тогда 
			Добавлять = Истина;
		КонецЕсли; 
		Если КлиентОбычный = Истина И МетаОбщийМодуль.КлиентОбычноеПриложение Тогда 
			Добавлять = Истина;
		КонецЕсли;
		Если КлиентОбычный = Неопределено Тогда 
			// В больших или содержащих ошибки конфигурациях компиляция неглобальных общих модулей неудобна
			//Попытка
			//	ОбщийМодульЛ = Вычислить(МетаОбщийМодуль.Имя);
			//Исключение
			//КонецПопытки; 
			//КоллекцияЗначений.Вставить(МетаОбщийМодуль.Имя, ОбщийМодульЛ);
			//
			Попытка
				Выполнить("Если Ложь Тогда "  + МетаОбщийМодуль.Имя + ".Й() КонецЕсли");
				Добавлять = Истина;
			Исключение
			КонецПопытки; 
		КонецЕсли;
		Если Добавлять Тогда
			Результат.Вставить(МетаОбщийМодуль.Имя, МетаОбщийМодуль);
		КонецЕсли;
	КонецЦикла;
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Новый ФиксированнаяСтруктура(Результат);

КонецФункции

// Добавляет новую строку в таблицу корневых объектов.
//
// Параметры:
//  Таблица      - ТаблицаЗначений;
//  *Категория   - Число, *0;
//  Единственное - Строка;
//  ИндексКартинкиЕдинственное - Число;
//  Множественное - Строка;
//  ИндексКартинкиМножественное - Число;
//
Процедура ДобавитьВТаблицуТиповМетаОбъектов(Таблица, Категория = 0, Единственное, ИндексКартинкиЕдинственное, Множественное, ИндексКартинкиМножественное)

	НовыйКорневойОбъект = Таблица.Добавить();
	НовыйКорневойОбъект.Категория = Категория;
	НовыйКорневойОбъект.Единственное = Единственное;
	НовыйКорневойОбъект.НЕдинственное = НРег(Единственное);
	НовыйКорневойОбъект.ИндексКартинкиЕдинственное = ИндексКартинкиЕдинственное;
	НовыйКорневойОбъект.Множественное = Множественное;
	НовыйКорневойОбъект.НМножественное = НРег(Множественное);
	НовыйКорневойОбъект.ИндексКартинкиМножественное = ИндексКартинкиМножественное;

КонецПроцедуры

// Получает таблицу единственных и множественных чисел корневых типов.
//
// Параметры:
//  *ЛиВключатьНехранимые - Булево, *Истина - включать ли нехранимые корневые типы;
//  *ЛиВключатьДочерние - Булево, *Истина - включать ли дочерние корневые типы;
//  *ЛиВключатьВнешние - Булево, *Истина - включать ли внешние корневые типы (внешние отчеты и обработки).
//
Функция ТипыМетаОбъектов(ЛиВключатьНехранимые = Истина, ЛиВключатьДочерние = Истина, ЛиВключатьВнешние = Истина) Экспорт

	Таблица = Новый ТаблицаЗначений;
	Таблица.Колонки.Добавить("Категория", Новый ОписаниеТипов("Число")); // 0 - корневой, 1 - нехранимый, 2 - дочерний, 3 - внешний
	Таблица.Колонки.Добавить("Единственное", Новый ОписаниеТипов("Строка"));
	Таблица.Колонки.Добавить("НЕдинственное", Новый ОписаниеТипов("Строка"));
	Таблица.Колонки.Добавить("ИндексКартинкиЕдинственное", Новый ОписаниеТипов("Число"));
	Таблица.Колонки.Добавить("Множественное", Новый ОписаниеТипов("Строка")); // Имя свойства, содержащего коллекцию этих объектов
	Таблица.Колонки.Добавить("НМножественное", Новый ОписаниеТипов("Строка"));
	Таблица.Колонки.Добавить("ИндексКартинкиМножественное", Новый ОписаниеТипов("Число"));
	
	// Корневые типы
	Если ЛиВключатьНехранимые Тогда
		// Главным образом эти строки нужны для связи с пиктограммами этих коллекций
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "WebСервис", ,          "WebСервисы", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "WSСсылка", ,           "WSСсылки", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ГруппаКоманд", ,       "ГруппыКоманд", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "Интерфейс", ,          "Интерфейсы", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "Нумератор", ,          "НумераторыДокументов", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "Обработка", 19,        "Обработки", 18);
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ОбщаяКартинка", ,      "ОбщиеКартинки", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ОбщаяКоманда", ,       "ОбщиеКоманды", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ОбщаяФорма", ,         "ОбщиеФормы", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ОбщийМакет", ,         "ОбщиеМакеты", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ОбщийМодуль", ,        "ОбщиеМодули", );
		Если ирКэш.НомерВерсииПлатформыЛкс() >= 802014 Тогда
			ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ОбщийРеквизит", , "ОбщиеРеквизиты", );
		КонецЕсли; 
		Если ирКэш.НомерВерсииПлатформыЛкс() >= 803003 Тогда
			ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ОпределяемыйТип", , "ОпределяемыеТипы", );
			ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "HTTPСервис", , "HTTPСервисы", );
		КонецЕсли; 
		Если ирКэш.НомерВерсииПлатформыЛкс() >= 803017 Тогда
			ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "СервисИнтеграции", , "СервисыИнтеграции", );
		КонецЕсли; 
		Если ирКэш.НомерВерсииПлатформыЛкс() >= 803018 Тогда
			ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "Бот", , "Боты", );
		КонецЕсли; 
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "Отчет", 24,            "Отчеты", 23);
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ПараметрСеанса", ,     "ПараметрыСеанса", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ПараметрФункциональныхОпций", , "ПараметрыФункциональныхОпций", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ПакетXDTO", ,          "ПакетыXDTO", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ПодпискаНаСобытие", ,  "ПодпискиНаСобытия", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "Подсистема", 61,         "Подсистемы", 61);
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "РегламентноеЗадание", , "РегламентныеЗадания", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "Роль", 60,               "Роли", 60);
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "Стиль", ,              "Стили", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ФункциональнаяОпция", ,"ФункциональныеОпции", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ХранилищеНастроек", ,  "ХранилищаНастроек", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "ЭлементСтиля", ,       "ЭлементыСтиля", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 1, "Язык", ,               "Языки", );
	КонецЕсли;
	// Порядок влияет на отображение пользователю
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "Константа", 0,             "Константы", 1);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "Справочник", 3,            "Справочники", 2);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "Документ", 13,             "Документы", 12);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "ЖурналДокументов", 16,     "ЖурналыДокументов", 15); 
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "ПланВидовХарактеристик", 38, "ПланыВидовХарактеристик", 37);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "ПланСчетов", 40,           "ПланыСчетов",39 );
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "ПланВидовРасчета", 48,     "ПланыВидовРасчета", 47);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "РегистрСведений", 34,      "РегистрыСведений", 33);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "РегистрНакопления", 32,    "РегистрыНакопления", 31);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "РегистрБухгалтерии", 42,   "РегистрыБухгалтерии", 41);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "РегистрРасчета", 50,       "РегистрыРасчета", 49);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "Перерасчет", 57,           "Перерасчеты", 57);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "Последовательность", 30,   "Последовательности", 29);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "БизнесПроцесс", 44,        "БизнесПроцессы", 43);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "Задача", 46,               "Задачи", 45);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "ПланОбмена", 52,           "ПланыОбмена", 51);
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "Перечисление", 10,         "Перечисления", 9);
	
	ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "КритерийОтбора", ,         "КритерииОтбора", );
	
	Если ирКэш.ДоступныВнешниеИсточникДанныхЛкс() Тогда
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 0, "ВнешнийИсточникДанных", 59,  "ВнешниеИсточникиДанных", 58);
	КонецЕсли; 
	
	// Дочерние типы
	Если ЛиВключатьДочерние Тогда
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "Графа", ,                 "Графы", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "ЗначениеПеречисления", ,  "ЗначенияПеречисления", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "Измерение", ,             "Измерения", );
		Если ирКэш.НомерВерсииПлатформыЛкс() >= 803017 Тогда
			ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "КаналСервисаИнтеграции", , "Каналы", );
		КонецЕсли; 
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "Команда", ,               "Команды", );
		Если ирКэш.НомерВерсииПлатформыЛкс() >= 803003 Тогда
			ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "Куб", , "Кубы", );
		КонецЕсли; 
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "Макет", ,                 "Макеты", );
		Если ирКэш.НомерВерсииПлатформыЛкс() >= 803005 Тогда
			ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "МетодHTTPСервиса", , "Методы", );
		КонецЕсли; 
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "ОперацияWebСервиса", , "Операции", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "ПараметрWebСервиса", , "Параметры", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "Поле", , "Поля", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "ПризнакУчетаПланаСчетов", ,  "ПризнакиУчета", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "ПризнакУчетаСубконтоПланаСчетов", ,  "ПризнакиУчетаСубконто", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "Реквизит", ,              "Реквизиты", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "РеквизитАдресации", ,     "РеквизитыАдресации", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "Ресурс", ,                "Ресурсы", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "Таблица", ,               "Таблицы", );
		Если ирКэш.НомерВерсииПлатформыЛкс() >= 803003 Тогда
			ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "ТаблицаИзмерения", ,   "ТаблицыИзмерений", );
		КонецЕсли; 
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "ТабличнаяЧасть", 55,      "ТабличныеЧасти", 54);
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "Форма", ,                 "Формы", );
		Если ирКэш.НомерВерсииПлатформыЛкс() >= 803004 Тогда
			ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "Функция", , "Функции", );
		КонецЕсли; 
		Если ирКэш.НомерВерсииПлатформыЛкс() >= 803005 Тогда
			ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 2, "ШаблонURLHTTPСервиса", , "ШаблоныURL", );
		КонецЕсли; 
	КонецЕсли;
	
	// Внешние типы
	Если ЛиВключатьВнешние Тогда
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 3, "ВнешняяОбработка", ,      "ВнешниеОбработки", );
		ДобавитьВТаблицуТиповМетаОбъектов(Таблица, 3, "ВнешнийОтчет", ,          "ВнешниеОтчеты", );
	КонецЕсли;
	Таблица.Индексы.Добавить("Единственное,  Категория");
	Таблица.Индексы.Добавить("НЕдинственное");
	Таблица.Индексы.Добавить("Множественное, Категория");
	Таблица.Индексы.Добавить("НМножественное");
	Возврат Таблица;

КонецФункции

Функция ФормаПустышкаЛкс() Экспорт 
	
	ирПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
		ирПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	Форма = ирПлатформа.ФормаПустышка;
	Если Форма = Неопределено Тогда
		ирПлатформа.ФормаПустышка = ирПлатформа.ПолучитьФорму("Пустышка");
		Форма = ирПлатформа.ФормаПустышка;
	КонецЕсли; 
	Возврат Форма;

КонецФункции

Функция ЗначенияДляПроверкиИзмененияЛкс() Экспорт 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ЗначенияДляПроверкиИзмененияЛкс");
		КлючНаборПараметров = "";
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли;
	Результат = Новый Структура;
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;

КонецФункции

Функция ФункциональныеОпцииОбъектовМДЛкс() Экспорт 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ФункциональныеОпцииОбъектовМДЛкс");
		КлючНаборПараметров = "";
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли;
	Результат = Новый ТаблицаЗначений;
	Результат.Колонки.Добавить("ИмяОбъектаМД");
	Результат.Колонки.Добавить("ИмяОпции");
	Для Каждого ФункциональнаяОпция Из Метаданные.ФункциональныеОпции Цикл
		Для Каждого ЭлементСостава Из ФункциональнаяОпция.Состав Цикл
			Если ЭлементСостава.Объект = Неопределено Тогда
				// Битая ссылка
				Продолжить;
			КонецЕсли; 
			СтрокаТЗ = Результат.Добавить();
			СтрокаТЗ.ИмяОбъектаМД = ЭлементСостава.Объект.ПолноеИмя();
			СтрокаТЗ.ИмяОпции = ФункциональнаяОпция.Имя;
		КонецЦикла;
	КонецЦикла;
	Результат.Индексы.Добавить("ИмяОбъектаМД");
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;

КонецФункции

Функция СкриптМенеджерЛкс() Экспорт
	
	СкриптМенеджер = Новый COMОбъект("MSScriptControl.ScriptControl");
	Возврат СкриптМенеджер;  
	
КонецФункции

Функция ИдентификаторПроцессаОСЛкс() Экспорт

	Если Не ирКэш.ЛиПлатформаWindowsЛкс() Тогда
		Результат = ирОбщий.ВыполнитьКомандуОСЛкс("echo $PPID");
		Попытка
			ИдентификаторПроцессаОС = Число(Результат);
		Исключение
			ИдентификаторПроцессаОС = 0;
			Сообщить(ОписаниеОшибки(), СтатусСообщения.Внимание);
		КонецПопытки; 
	Иначе 
		#Если ТонкийКлиент Тогда
			// Первый вариант иногда не оставлял процесс работать (он сразу завершался) и приводил ниже к ошибкам "Произошла исключительная ситуация (SWbemServicesEx): Not found"
			Оболочка = Новый COMОбъект("WScript.Shell");
			ДочернийПроцесс = Оболочка.Exec("rundll32.exe kernel32,Sleep");
			ИдентификаторПроцессаОС = ПолучитьCOMОбъект("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2:Win32_Process.Handle='" + Формат(ДочернийПроцесс.ProcessID, "ЧГ=") + "'").ParentProcessID;
			ДочернийПроцесс.Terminate(); // Может выполняться долго!
		#Иначе
			Попытка
				ВК = ирОбщий.ВКОбщаяЛкс();
			Исключение
				// Например - Не найден файл внешней компоненты
				ИдентификаторПроцессаОС = 0;
				Сообщить(ОписаниеОшибки(), СтатусСообщения.Внимание);
			КонецПопытки;
			Если ВК <> Неопределено Тогда
				ИдентификаторПроцессаОС = ВК.PID();
			КонецЕсли;
		#КонецЕсли
	КонецЕсли; 
	Возврат ИдентификаторПроцессаОС;

КонецФункции

Функция КоманднаяСтрокаТекущегоПроцессаОСЛкс() Экспорт 
	Если Не ирКэш.ЛиПлатформаWindowsЛкс() Тогда 
		КомандаЗапуска = Новый Массив;
		КомандаЗапуска.Добавить("cat");
		КомандаЗапуска.Добавить("/proc/$PPID/cmdline");
		Результат = ирОбщий.ВыполнитьКомандуОСЛкс(КомандаЗапуска);
		// Пример результата
		// /opt/1cv8/x86_64/8.3.18.1363/rphost -range 1560:1591 -reghost ИмяХоста -regport 1541 -pid 466a359c-54bd-4d6c-9198-ea9f92a74fa2 -debug -tcp
	Иначе
		ИдентификаторПроцессаОС = ирКэш.ИдентификаторПроцессаОСЛкс();
		ТекущийПроцесс = ПолучитьCOMОбъект("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2:Win32_Process.Handle='" + XMLСтрока(ИдентификаторПроцессаОС) + "'");
		Результат = ТекущийПроцесс.CommandLine;
	КонецЕсли; 
	Возврат Результат;
КонецФункции

Функция ЭтоУчебнаяПлатформаЛкс() Экспорт 

	Если Не ирКэш.ЛиФайловаяБазаЛкс() Тогда
		Возврат Ложь;
	КонецЕсли; 
	ВременныйФайл = ПолучитьИмяВременногоФайла("mxl");
	ТабДок = Новый ТабличныйДокумент;
	Попытка
		ТабДок.Записать(ВременныйФайл, ТипФайлаТабличногоДокумента.MXL7); // В учебной версии платформы это запрещено https://www.hostedredmine.com/issues/923942
	Исключение
		// Сработает при отсутствии права "Вывод" (портативный вариант) и в учебной платформе ("Ограничение используемой лицензии")
		ОписаниеОшибки = ОписаниеОшибки();
		Возврат Истина;
	КонецПопытки; 
	УдалитьФайлы(ВременныйФайл);
	Возврат Ложь;

КонецФункции

Функция СоставОбщегоРеквизитаЛкс(Знач Имя) Экспорт 
	
	Состав = Новый Соответствие;
	Для Каждого ЭлементСостава Из Метаданные.ОбщиеРеквизиты[Имя].Состав Цикл
		Состав.Вставить(ЭлементСостава.Метаданные.ПолноеИмя(), ЭлементСостава);
	КонецЦикла;
	Возврат Состав;

КонецФункции

Функция ЛиДоступноДопРеквизитыБСПЛкс() Экспорт 
	Результат = Истина
		И Не ирКэш.ЛиПортативныйРежимЛкс()
		И Метаданные.ОбщиеМодули.Найти("УправлениеСвойствами") <> Неопределено
		И ирКэш.НомерВерсииБСПЛкс() >= 204;
	Возврат Результат;
КонецФункции    

Функция ЛиДоступноФорматированнаяСтрокаЛкс() Экспорт 
	Результат = ирКэш.НомерВерсииПлатформыЛкс() > 803001;
	Возврат Результат;
КонецФункции

Функция СобытияПоИмениОбщегоТипаЛкс(Знач ИмяОбщегоТипа, Знач ИмяТипаРасширения = Неопределено) Экспорт 
	
	мПлатформа = ирКэш.Получить();
	мПлатформа.ИнициацияОписанияМетодовИСвойств();
	СобытияЭлементаФормы = мПлатформа.ТаблицаКонтекстов.НайтиСтроки(Новый Структура("ТипКонтекста, ЯзыкПрограммы, ТипЯзыка, ТипСлова", ИмяОбщегоТипа, 0, "", "Событие"));
	Если ИмяТипаРасширения <> Неопределено Тогда
		СобытияРасширения = ирКэш.СобытияПоИмениОбщегоТипаЛкс(ИмяТипаРасширения);
		ирОбщий.ДополнитьМассивЛкс(СобытияЭлементаФормы, СобытияРасширения);
	КонецЕсли;
	// Сделать учет ПриАктивизацииОбласти->ПриАктивизации в совместимости 8.3.14+ 
	Возврат СобытияЭлементаФормы;

КонецФункции

Функция ДоступныеСборкиПлатформыЛкс() Экспорт
	СборкиПлатформы = ирОбщий.ЗаполнитьДоступныеСборкиПлатформыЛкс();
	Возврат СборкиПлатформы;
КонецФункции

Функция ВсеВидыПравДоступаЛкс() Экспорт 
	
	мПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
		мПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	ВсеВидыПравДоступа = ирОбщий.ТаблицаЗначенийИзТабличногоДокументаЛкс(мПлатформа.ПолучитьМакет("ВидыПравДоступа"));
	ирОбщий.ЗаполнитьКолонкуПорядкаТаблицыЛкс(ВсеВидыПравДоступа);
	Возврат ВсеВидыПравДоступа;

КонецФункции

Функция ЛиСквознаяФайловаяСистемаКлиентаИСервера() Экспорт 
	#Если Не Клиент Тогда
		ВызватьИсключение "Запрещнный вызов на сервере"; 
	#КонецЕсли
	Результат = ирСервер.ИмяКомпьютераЛкс() = ИмяКомпьютера();
	Возврат Результат;
КонецФункции

//.
// Параметры:
//    ПолноеИмяОтчета - Строка - 
// Возвращаемое значение:
//    СхемаКомпоновкиДанных 
Функция ОсновнаяСхемаКомпоновкиОтчетаЛкс(Знач ПолноеИмяОтчета) Экспорт 
	Возврат ирОбщий.ОсновнаяСхемаКомпоновкиОтчетаЛкс(ПолноеИмяОтчета);
КонецФункции

#Если Клиент Тогда

// Постоянный список открытых форм подсистемы
Функция ОткрытыеФормыПодсистемыЛкс() Экспорт 
	
	ирПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
		ирПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	Результат = ирПлатформа.ОткрытыеФормыПодсистемы;
	Если Результат = Неопределено Тогда
		Результат = Новый Массив;
		ирПлатформа.ОткрытыеФормыПодсистемы = Результат;
	КонецЕсли; 
	#Если Сервер И Не Сервер Тогда
		Результат.Добавить(ПолучитьФорму());
	#КонецЕсли
	Возврат Результат;
	
КонецФункции  

// Временный список открытых форм. Они помещаются сюда обычно на несколько секунд - для определения, нужно ли добавлять их в историю.
// 
// Возвращаемое значение:
//   Соответствие - 
//
Функция ОтслеживаемыеФормыЛкс() Экспорт 
	
	ирПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
		ирПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	Результат = ирПлатформа.ОтслеживаемыеФормы;
	Если Результат = Неопределено Тогда
		Результат = Новый Соответствие;
		ирПлатформа.ОтслеживаемыеФормы = Результат;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

Функция ПерехватКлавиатурыЛкс() Экспорт 
	
	Если Не ирКэш.ЛиПортативныйРежимЛкс() Тогда
		Попытка
			Результат = Вычислить("ирПерехватКлавиатуры");
		Исключение
		КонецПопытки;
	КонецЕсли; 
	Если Результат = Неопределено Тогда
		Результат = ирКэш.Получить().ПодключитьПерехватКлавиатуры(); // Тут будет обращение к ирОбщий
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

Функция ЛиМодальностьЗапрещенаЛкс() Экспорт 
	
	Результат = Ложь;
	Список = Новый СписокЗначений;
	Попытка
		Список.ВыбратьЭлемент();
	Исключение
		Результат = Истина;
	КонецПопытки;
	Возврат Результат;

КонецФункции

// Кэшируем форму, т.к. иначе при повторных вызовах в одном потоке кода каждый раз будет возвращаться новый экземпляр
Функция ОкноСообщенийЛкс(МодальнаяГруппа = 0) Экспорт 
	
	Если МодальнаяГруппа = 0 Тогда
		#Если ТолстыйКлиентУправляемоеПриложение Тогда
			//Форма = ПолучитьФорму("Обработка.ирПлатформа.Форма.ВременноеОкноСообщенийУпр",,, МодальнаяГруппа); // Так будет ошибка компиляции в портативном варианте в файловой базе
			Форма = ирКлиент.ПолучитьФормуЛкс("Обработка.ирПлатформа.Форма.ВременноеОкноСообщенийУпр",,, МодальнаяГруппа);
		#КонецЕсли
	Иначе
		мПлатформа = ирКэш.Получить();
		#Если Сервер И Не Сервер Тогда
			мПлатформа = Обработки.ирПлатформа.Создать();
		#КонецЕсли
		Форма = мПлатформа.ПолучитьФорму("СообщенияМодальнойГруппы",, МодальнаяГруппа);
	КонецЕсли; 
	Возврат Форма;

КонецФункции

Функция ФормаСравнителяТекстовЛкс() Экспорт 
	Результат = ирКлиент.НоваяФормаСравнителяТекстовЛкс();
	Возврат Результат;
КонецФункции

Функция ФормаОбщихКомандЛкс() Экспорт 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ФормаОбщихКомандЛкс");
		КлючНаборПараметров = "";
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли;
	мПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
		мПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	Результат = мПлатформа.ПолучитьФорму("ОбщиеКоманды");
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;

КонецФункции

Функция ИмяШрифтаРедактораМодуляКонфигуратораЛкс()  Экспорт 
	
	НастройкиКонфигуратора = ирОбщий.ПрочитатьТекстИзФайлаЛкс(ирКэш.КаталогИзданияПлатформыВПрофилеЛкс(Ложь) + ирОбщий.РазделительПутиКФайлуЛкс() + "1Cv8cmn.pfl");
	ИмяШрифта = ирОбщий.ТекстМеждуМаркерамиЛкс(НастройкиКонфигуратора, "9cd510c8-abfc-11d4-9434-004095e12fc7", """SearchResultBackground""", Ложь);
	ИмяШрифта = ирОбщий.ТекстМеждуМаркерамиЛкс(ИмяШрифта, """", """", Ложь);
	Возврат ИмяШрифта;

КонецФункции

Функция ДоступенРедакторМонакоЛкс() Экспорт 
	
	Возврат Истина
		И ирКэш.ЛиПлатформаWindowsЛкс()
		И (Ложь
			Или ирКэш.НомерВерсииПлатформыЛкс() >= 803018 
			Или (Истина
				И ирКэш.НомерВерсииПлатформыЛкс() >= 803015
				И ирКлиент.ЛиПерехватКлавиатурногоВводаЛкс()))
		;

КонецФункции  

Функция КоличествоСтрокВТаблицеБДЛкс(ПолноеИмяТаблицы) Экспорт 
	Результат = ирОбщий.КоличествоСтрокВТаблицеБДЛкс(ПолноеИмяТаблицы);
	Возврат Результат;
КонецФункции

Функция ЛиДоступноВыполнениеКомандныхФайловЛкс(Знач ВыброситьИсключение = Ложь) Экспорт 
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ЛиДоступноВыполнениеКомандныхФайловЛкс");
		КлючНаборПараметров = "" + ВыброситьИсключение;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли;
	Если Не ирКэш.ЛиПлатформаWindowsЛкс() Тогда
		Результат = Истина;
	Иначе 
		Файл = ПолучитьИмяВременногоФайла("bat");
		Маркер = Новый УникальныйИдентификатор;
		Текст = Новый ТекстовыйДокумент;
		Текст.УстановитьТекст("echo " + Маркер);
		Текст.Записать(Файл, КодировкаТекста.ANSI);
		Результат = ирОбщий.ВыполнитьКомандуОСЛкс(Файл);
		Результат = Найти(Результат, Маркер) > 0;
		Если Не Результат Тогда
			ирОбщий.СообщитьЛкс("Пользователю ОС недоступно выполнение командных файлов (bat). Выполнение некоторых операций будет замедлено или невозможно!", СтатусСообщения.Внимание,, Истина);
		КонецЕсли;
	КонецЕсли;
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;
КонецФункции

// Нельзя звать напрямую, т.к. текст модуля может быть неактуален!
// Вместо этого надо звать ирПлатформа.ПолеТекстаМодуля()
// Параметры:
//    ИмяМодуля - Строка -
//    ТекстФайла - Строка - 
// Возвращаемое значение:
//    ОбработкаОбъект.ирКлсПолеТекстаПрограммы - 
Функция ПолеТекстаМодуляЛкс(ИмяМодуля) Экспорт
	ПолеТекстаМодуля = ирКэш.ПолеТекстаМодуляБезСтруктурыТипаЛкс(ИмяМодуля);
	ПолеТекстаМодуля.УстановитьТекст(,,,,, СтрЗаменить(ИмяМодуля, "\", " "));
	Возврат ПолеТекстаМодуля;
КонецФункции 

// Нельзя звать напрямую, т.к. текст модуля может быть неактуален!
// Параметры:
//    ИмяМодуля - Строка -
//    ТекстФайла - Строка - 
// Возвращаемое значение:
//    ОбработкаОбъект.ирКлсПолеТекстаПрограммы - 
Функция ПолеТекстаМодуляБезСтруктурыТипаЛкс(ИмяМодуля) Экспорт
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("ПолеТекстаМодуляБезСтруктурыТипаЛкс");
		КлючНаборПараметров = ИмяМодуля;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли;
	ПолеТекстаМодуля = ирОбщий.НовыйАнализаторКодаЛкс();
	#Если Сервер И Не Сервер Тогда
		ПолеТекстаМодуля = Обработки.ирКлсПолеТекстаПрограммы.Создать();
	#КонецЕсли
	ПолеТекстаМодуля.ИнициироватьНеинтерактивно();
	ПолеТекстаМодуля.СлужебноеПолеТекстаДолгое = ПолеТекстаМодуля.ПолеТекста.ЭлементФормы;
	ФайлМодуля = Получить().ФайлМодуляИзИмениМодуля(ИмяМодуля);
	Если ФайлМодуля.Существует() Тогда
		ПолеТекстаМодуля.ПрочитатьТекстИзФайлаБезМетаданных(ФайлМодуля.ПолноеИмя);
	КонецЕсли;
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат ПолеТекстаМодуля;
КонецФункции

Функция КодыКлавишЛкс() Экспорт 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("КодыКлавишЛкс");
		КлючНаборПараметров = "";
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	Таблица = ирОбщий.ТаблицаЗначенийИзТабличногоДокументаЛкс(ирКэш.Получить().ПолучитьМакет("КодыКлавиш"));
	Результат = Новый Соответствие();
	Для Каждого Строка Из Таблица Цикл
		Результат.Вставить(Строка.Ключ, Строка.Значение);
	КонецЦикла;
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

Функция ПолеТекстаПрограммы(Знач ЯзыкПрограммы = 0) Экспорт
	Результат = ирКэш.Получить().ПолеТекстаПрограммы(ЯзыкПрограммы);
	Возврат Результат;
КонецФункции

// Первым элементом всегда идет Неопределено, обозначающий саму конфигурацию.
Функция РасширенияКонфигурацииЛкс(ТолькоАктивные = Истина) Экспорт
	Результат = Новый Соответствие;
	Если ирКэш.НомерРежимаСовместимостиЛкс() >= 803010 Тогда
		РасширенияКонфигурацииМои = Вычислить("РасширенияКонфигурации");
		#Если Сервер И Не Сервер Тогда
			РасширенияКонфигурацииМои = РасширенияКонфигурации;
		#КонецЕсли
		Для Каждого РасширениеКонфигурации Из РасширенияКонфигурацииМои.Получить() Цикл
			#Если Сервер И Не Сервер Тогда
				РасширениеКонфигурации = РасширенияКонфигурации.Создать();
			#КонецЕсли
			Активность = Истина;
			Если ТолькоАктивные И ирКэш.НомерРежимаСовместимостиЛкс() >= 803012 Тогда
				Активность = РасширениеКонфигурации.Активно;
			КонецЕсли;
			Результат.Вставить(РасширениеКонфигурации, Активность);
		КонецЦикла;
	КонецЕсли;
	Возврат Результат;
КонецФункции

Функция ЛиВКонфигурацииЕстьМеханизмЗаменыЗапросовПустышекЛкс() Экспорт 
	
	Результат = ирСервер.ЛиВКонфигурацииЕстьМеханизмЗаменыЗапросовПустышекЛкс();
	Возврат Результат;

КонецФункции

//.
// Параметры:
//    НаСервере - ? - 
//    КлиентОбычноеПриложение - ? - 
//    КлиентУправляемоеПриложение - ? - 
// Возвращаемое значение:
//    Массив[ОбъектМетаданныхОбщийМодуль] - 
Функция ГлобальныеОбщиеМодулиЛкс(Знач НаСервере, Знач КлиентОбычноеПриложение = Истина, Знач КлиентУправляемоеПриложение = Истина) Экспорт
	ГлобальныеОбщиеМодули = Новый Массив;
	Для Каждого ОбщийМодульМД Из Метаданные.ОбщиеМодули Цикл
		#Если Сервер И Не Сервер Тогда
		ОбщийМодульМД = Метаданные.ОбщиеМодули.ирОбщий;
		#КонецЕсли
		Если Ложь 
			Или Не ОбщийМодульМД.Глобальный 
			Или (Истина
				И НаСервере
				И Не ОбщийМодульМД.Сервер)
			Или (Истина
				И КлиентОбычноеПриложение
				И Не ОбщийМодульМД.КлиентОбычноеПриложение)
			Или (Истина
				И КлиентУправляемоеПриложение
				И Не ОбщийМодульМД.КлиентУправляемоеПриложение)
			Или (Истина
				И Не НаСервере
				И Не ОбщийМодульМД.ВызовСервера
				И Не (Ложь
					Или (Истина
						И КлиентОбычноеПриложение
						И ОбщийМодульМД.КлиентОбычноеПриложение)
					Или (Истина
						И КлиентУправляемоеПриложение
						И ОбщийМодульМД.КлиентУправляемоеПриложение)
					)
				)
		Тогда
			Продолжить;
		КонецЕсли;
		ГлобальныеОбщиеМодули.Добавить(ОбщийМодульМД);
	КонецЦикла;
	Возврат ГлобальныеОбщиеМодули;
КонецФункции

Функция ЛиВариантИнтерфейсаТаксиЛкс() Экспорт
	Настройки = ХранилищеСистемныхНастроек.Загрузить("Общее/НастройкиКлиентскогоПриложения"); // НастройкиКлиентскогоПриложения
	Возврат Настройки.ВариантИнтерфейсаКлиентскогоПриложения = Вычислить("ВариантИнтерфейсаКлиентскогоПриложения").Такси; // В 8.2 нет
КонецФункции


#КонецЕсли 

#КонецЕсли

Функция СоединениеЭтойСУБД() Экспорт 
	Результат = ирОбщий.СоединениеЭтойСУБД();
	Если Результат = Неопределено Тогда
		ВызватьИсключение "Ошибка соединения с СУБД";
	КонецЕсли;
	Возврат Результат;
КонецФункции

Функция ЛиПортативныйРежимЛкс() Экспорт
	
	//Попытка
	//	Пустышка = ирПортативный.мВнешниеМодули;
	//	Результат = Истина;
	//Исключение
	//	Результат = Ложь;
	//КонецПопытки; 
	Результат = ТипЗнч(ирПортативный) <> Тип("ОбщийМодуль");
	Возврат Результат;
	
КонецФункции

Функция ЛиСеансТолстогоКлиентаЛкс() Экспорт 
	
	#Если ТолстыйКлиентОбычноеПриложение Или ТолстыйКлиентУправляемоеПриложение Тогда
		Результат = Истина;
	#ИначеЕсли Сервер Тогда 
		ТекущийСеанс = ирКэш.ТекущийСеансЛкс();
		Результат = ирОбщий.СтрокиРавныЛкс(ТекущийСеанс.ИмяПриложения, "1CV8");
	#Иначе
		Результат = Ложь;
	#КонецЕсли 
	Возврат Результат;
	
КонецФункции

Функция ЛиСеансТонкогоКлиентаЛкс() Экспорт 
	#Если ТонкийКлиент Тогда
		Результат = Истина;
	#ИначеЕсли Сервер Тогда 
		ТекущийСеанс = ирКэш.ТекущийСеансЛкс();
		Результат = ирОбщий.СтрокиРавныЛкс(ТекущийСеанс.ИмяПриложения, "1CV8C");
	#Иначе
		Результат = Ложь;
	#КонецЕсли 
	Возврат Результат;
	
КонецФункции

// В параметрах конфигуратора "Модули/Проверка" отсутствует флажок "Толстый клиент (УП)". Поэтому проверка компиляции не выполняется. 
// Поэтому вместо инструкций препроцессора по возможности надо использовать это проверку.
// https://partners.v8.1c.ru/forum/topic/1996623
Функция ЛиСеансТолстогоКлиентаУПЛкс() Экспорт 
	#Если ТолстыйКлиентУправляемоеПриложение Тогда
		Результат = Истина;
	#Иначе
		Результат = Ложь;
	#КонецЕсли 
	Возврат Результат;
	
КонецФункции

Функция ЛиПлатформаLinuxЛкс() Экспорт
	
	//Возврат Истина; // Для отладки
	СисИнфо = Новый СистемнаяИнформация;
	Результат = Ложь
		Или СисИнфо.ТипПлатформы = ТипПлатформы.Linux_x86
		Или СисИнфо.ТипПлатформы = ТипПлатформы.Linux_x86_64;
	Возврат Результат;

КонецФункции

Функция ЛиПлатформаWindowsЛкс() Экспорт
	
	//Возврат Ложь; // Для отладки
	СисИнфо = Новый СистемнаяИнформация;
	Результат = Ложь
		Или СисИнфо.ТипПлатформы = ТипПлатформы.Windows_x86
		Или СисИнфо.ТипПлатформы = ТипПлатформы.Windows_x86_64;
	Возврат Результат;

КонецФункции

Функция ДоступныРегВыраженияЛкс() Экспорт
	
	Результат = Ложь
		Или ирКэш.НомерВерсииПлатформыЛкс() >= 803006
		#Если Клиент Тогда
		Или ирКэш.ЛиПлатформаWindowsЛкс()
		#КонецЕсли
		;
	Возврат Результат;

КонецФункции

Функция ДоступенJSONЛкс() Экспорт
	
	Результат = ирКэш.НомерВерсииПлатформыЛкс() >= 803006;
	Возврат Результат;

КонецФункции
	
Функция ДоступноСхемаЗапросаЛкс(Знач РасширенныеФункции = Ложь) Экспорт 
	
	Результат = Истина
		И ирКэш.НомерВерсииПлатформыЛкс() >= 803005
		И (Ложь
			Или Не РасширенныеФункции
			Или ирКэш.НомерРежимаСовместимостиЛкс() > 803010 // Антибаг схемы запроса https://www.hostedredmine.com/issues/959039
			);
	Возврат Результат;

КонецФункции

Функция ДоступныТаблицыКонстантЛкс() Экспорт 
	
	мПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
		мПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	Результат = ирКэш.НомерРежимаСовместимостиЛкс() >= 802016; // Здесь точно минимальная версия уже. Не трогать!
	Возврат Результат;

КонецФункции

// Метка_9в6676вап6438о
Функция Это64битныйПроцессЛкс() Экспорт
	
	СисИнфо = Новый СистемнаяИнформация;
	Результат = Ложь
		Или СисИнфо.ТипПлатформы = ТипПлатформы.Windows_x86_64
		Или СисИнфо.ТипПлатформы = ТипПлатформы.Linux_x86_64
		Или ирКэш.НомерВерсииПлатформыЛкс() > 803001 И СисИнфо.ТипПлатформы = ТипПлатформы.MacOS_x86_64; // Появилось в 8.3
	Возврат Результат;

КонецФункции

Функция ИмяКолонкиНомерСтрокиЛкс() Экспорт 
	
	ИмяКолонкиНомерСтроки = "НомерСтроки" + ирОбщий.СуффиксСлужебногоСвойстваЛкс();
	Возврат ИмяКолонкиНомерСтроки;

КонецФункции

Функция ЛиФайловаяБазаЛкс(СтрокаСоединенияБазы = "") Экспорт 

	Если Не ЗначениеЗаполнено(СтрокаСоединенияБазы) Тогда
		СтрокаСоединенияБазы = СтрокаСоединенияИнформационнойБазы();
	КонецЕсли;
	ФайловыйКаталог = НСтр(СтрокаСоединенияБазы, "File");
	ЭтоФайловаяБаза = Не ПустаяСтрока(ФайловыйКаталог);
	Возврат ЭтоФайловаяБаза;

КонецФункции

Функция СтрокаСоединенияСервераЛкс() Экспорт
	
	Результат = ирСервер.СтрокаСоединенияСервераЛкс();
	Возврат Результат;
	
КонецФункции

Функция КартинкаПоИмениЛкс(Имя) Экспорт
	
	#Если Сервер И Не Сервер Тогда
	    ирПортативный = Обработки.ирПортативный.Создать();
	#КонецЕсли
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции = ирПортативный.КэшФункцииЛкс("КартинкаПоИмениЛкс");
		КлючНаборПараметров = "" + Имя;
		Результат = КэшФункции[КлючНаборПараметров];
		Если Результат <> Неопределено Тогда
			Возврат Результат;
		КонецЕсли; 
	КонецЕсли; 
	
	Результат = Новый Картинка;
	Если Не ЗначениеЗаполнено(Имя) Тогда
		// Антибаг платформы 8.3.21 https://www.hostedredmine.com/issues/947012
	Иначе
		Попытка
			Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
				Результат = ирПортативный.КартинкаПоИмениЛкс(Имя);
			Иначе
				Результат = БиблиотекаКартинок[Имя];
			КонецЕсли; 
		Исключение
			ОписаниеОшибки = ОписаниеОшибки(); // Для отладки
		КонецПопытки;
	КонецЕсли; 
	
	Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
		КэшФункции[КлючНаборПараметров] = Результат;
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции

Функция ЭтоТолстыйКлиентЛкс() Экспорт 
	
	#Если ТонкийКлиент Или ВебКлиент Или МобильныйКлиент Тогда
		Результат = Ложь;
	#Иначе
		Результат = Истина;
	#КонецЕсли
	Возврат Результат;
	
КонецФункции

Функция ДоступенБраузерWebKitЛкс() Экспорт 
	
	Возврат ирКэш.НомерВерсииПлатформыЛкс() >= 803014;

КонецФункции

Функция ДоступенРежимИспользованияСинхронныхВызововЛкс() Экспорт 
	
	Возврат ирКэш.НомерВерсииПлатформыЛкс() >= 803008;

КонецФункции

Функция ЛиОтладкаРазрешенаЛкс() Экспорт 
	
	мПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
		мПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	#Если Клиент Тогда
		//ОтладкаРазрешена = мПлатформа.ИдентификаторыПроцессовОтладчиков().Количество() > 0;
		ОтладкаРазрешена = ЗначениеЗаполнено(мПлатформа.ПортДляПодключенияОтладчика());
	#Иначе
		ОтладкаРазрешена = Не ирОбщий.СтрокиРавныЛкс(ирОбщий.РежимОтладкиСервераИзКоманднойСтрокиЛкс(), "нет");
	#КонецЕсли
	Возврат ОтладкаРазрешена;

КонецФункции

#Если Сервер И Не Сервер Тогда
	ирПортативный = Обработки.ирПортативный.Создать();
#КонецЕсли
