При частом динамическом обновлении конфигурации ИБ иногда возникают неожиданные глюки 1С у различных пользователей, связанные с ошибкой кэша 1С.
Предлагается решение, позволяющее автоматически очищать этот проблемный кэш без помощи сисадмина.
Алгоритм:
1) создаем регистр сведений "НеобходимостьОчисткиКэша" с одним строковым измерением "Пользователь" . Сюда будет добавляться пользователи, для которых будет необходима процедура очистки кэша при завершении работы 1С.
2) В глобальном модуле обычного приложения (для управляемых форм модуль управляемого приложения) в процедуре ПриНачалеРаботыСистемы() прописываем обработчик ожидания "ПодключитьОбработчикОжидания("ПроверкаДинОбновления",60);"
Процедура ПроверкаДинОбновления() Экспорт
Если КонфигурацияБазыДанныхИзмененаДинамически() Тогда //добавляем в очередь обновления кэша - когда будет выходить - очистится кэш конфигурации
Наб1 = РегистрыСведений.НеобходимостьОчисткиКэша.СоздатьНаборЗаписей();
Наб1.Отбор.Пользователь.Установить(ПользователиИнформационнойБазы.ТекущийПользователь().Имя);
наб1.Прочитать();
Если Наб1.Количество()<>0 Тогда
Возврат;
КонецЕсли;
зап1 = наб1.Добавить();
зап1.Пользователь = ПользователиИнформационнойБазы.ТекущийПользователь().Имя;
наб1.Записать();
КонецЕсли;
КонецПроцедуры
3) При завершении работы в глобальном модуле прописываем вызов функции очистки кэша:
Процедура ПриЗавершенииРаботыСистемы()
ОчиститьКэш1С();
КонецПроцедуры
Собственно сама функция очистки кэша:
Процедура ОчиститьКэш1С()
//определяем нужно ли текущему пользователю очистка кэша
запр1 = Новый Запрос;
запр1.УстановитьПараметр("Пользователь", ПользователиИнформационнойБазы.ТекущийПользователь().Имя);
запр1.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1
| НеобходимостьОчисткиКэша.Пользователь
|ИЗ
| РегистрСведений.НеобходимостьОчисткиКэша КАК НеобходимостьОчисткиКэша
|ГДЕ
| НеобходимостьОчисткиКэша.Пользователь = &Пользователь";
тз1 = запр1.Выполнить().Выгрузить();
Если тз1.Количество() = 0 Тогда
Возврат;
КонецЕсли;
СтрокаПоиска = "Connect="+СтрокаСоединенияИнформационнойБазы();
Ф1 = Новый ТекстовыйДокумент;
ф1.ТолькоПросмотр = Истина;
Шелл = Новый COMОбъект("WScript.Shell");
АППДата = Шелл.ExpandEnvironmentStrings("%APPDATA%");
АППДата2 = Шелл.ExpandEnvironmentStrings("%LOCALAPPDATA%");
ИмяФайла = АППДата+"\1C\1CEStart\ibases.v8i";
//сообщить(ИмяФайла);
ф1.Прочитать(ИмяФайла);
Для сч1 = 1 по ф1.КоличествоСтрок() Цикл
стр1 = СокрЛП(ф1.ПолучитьСтроку(сч1));
Если стр1 <> СтрокаПоиска Тогда
Продолжить;
КонецЕсли;
ИДБазы = стрЗаменить(СокрЛП(ф1.ПолучитьСтроку(сч1 + 1)), "ID=", "");
//сообщить(ИДБазы);
прервать;
КонецЦикла;
Путь1 = АППДата + "\1C\1Cv82\"+ИДБазы+"\"; //пользовательские настройки - ничего не трогаем
Путь2 = АППДата2 + "\1C\1Cv82\"+ИДБазы+"\*"; //кэш конфигурации - удаляем только его
ИмяСкрипта1 = ПолучитьИмяВременногоФайла("cmd");
ф2 = Новый ТекстовыйДокумент;
//Удал1 = "del /f /s /q """+Путь1+""""; //пользовательские настройки
Удал2 = "del /f /s /q """+Путь2+""""; //кеш конфигурации
ф2.ДобавитьСтроку("ping -n 11 127.0.0.1 & "+Удал2); //пауза 10 сек + удаление кеша конфигурации - В нескольких строках не срабатывает!!!
ф2.Записать(ИмяСкрипта1, КодировкаТекста.ANSI);
Шелл.Run(""""+ИмяСкрипта1+"""",0);
//удаляем из очереди очистки кэша текущего пользователя
Наб1 = РегистрыСведений.НеобходимостьОчисткиКэша.СоздатьНаборЗаписей();
Наб1.Отбор.Пользователь.Установить(ПользователиИнформационнойБазы.ТекущийПользователь().Имя);
наб1.Прочитать();
наб1.Очистить();
наб1.Записать();
КонецПроцедуры
Можно также в интерфейс пользователя добавить следующую команду - очистить кэш конфигурации вручную (если есть непонятные глюки с программой):
Процедура Вызов_ОчиститьКэш1С() Экспорт //пользователь сам решает почистить кэш
ТекстВопроса = "Программа 1С будет завершена. Повторно зайти в 1С можно будет через 1 минуту. Продолжить?";
Ответ = Вопрос(ТекстВопроса, РежимДиалогаВопрос.ДаНет, , КодВозвратаДиалога.Да,);
Если Ответ <> КодВозвратаДиалога.Да Тогда
Возврат;
КонецЕсли;
Наб1 = РегистрыСведений.НеобходимостьОчисткиКэша.СоздатьНаборЗаписей();
Наб1.Отбор.Пользователь.Установить(ПользователиИнформационнойБазы.ТекущийПользователь().Имя);
наб1.Прочитать();
Если Наб1.Количество() = 0 Тогда
зап1 = наб1.Добавить();
зап1.Пользователь = ПользователиИнформационнойБазы.ТекущийПользователь().Имя;
наб1.Записать();
КонецЕсли;
ЗавершитьРаботуСистемы(Ложь, Ложь);
КонецПроцедуры
Примечание: процедура очистки корректно отрабатывает при локальном подключении и терминальном подключении. При подключении на ферму с несколькими терминальными серверами - процедура работает некорректно, из-за того что очищает кэш только для текущего терминального сервера, не затрагивая остальные сервера фермы.