Часто, при использовании динамического обновления конфигурации, у пользователей забивается кэш и программма не работает так, как надо. Проблема устраняется путем чистки пользовательского кэша. Но основновная загвоздка в том, что не возможно определить у какого пользователя (особенно если их больше 100) кэшированные модули соотвествуют текущей версии конфигурации, а у какого нет. Программист понимает это только тогда, когда у пользователя возникла ошибка и он присылает в отдел 1С письмо с руганью, принт-скринами и матами.
Подумав, как можно очищать кэш автоматом, было решено вызывать всем известный скрипт очистки кэша непосредственно из 1С.
В типовых конфигурациях уже предусмотрен обработчик оповещения, который проверяет не изменена ли конфигурация динамически. Если изменена, то пользователю предлагается перезапустить 1С, для того чтобы изменения вступли в силу.
Суть метода в том, чтобы при завершении работы проверить изменена ли конфигурация динамически еще раз, собрать скрипт, записать его и вызвать в момент закрытия программы. Скрипт сначала засыпает на 5 секунд, ожидая, пока закроется процесс 1С. После этого, смотрит есть ли запущенные процессы 1С, если есть, то убивает их. Затем, удаляет папки кэша и, в случае, если пользователь выбрал перезапуск сеанса, перезапускает 1С.
Т.к. мы пока не написали ничего на управляемом приложении, все описанное ниже, предназначено только для обычного.
В модуле обычного приложения есть процедура ОбработчикОповещения(), в ней периодически вызывается еще одна процедура ОбработчикОжиданияПроверкиДинамическогоИзмененияИБ ()
// Проверяет в конфигурации ИБ наличие изменений появившихся после старта сеанса
//
Процедура ОбработчикОжиданияПроверкиДинамическогоИзмененияИБ() Экспорт
// Если в конфигурации после старта текущего сеанса что-то изменилось
Если КонфигурацияБазыДанныхИзмененаДинамически() Тогда
// Завершим проверку обновления
ЗавершитьПроверкуДинамическогоОбновленияИБ();
// Спросим пользователя о его желании перезапустить сеанс
ТекстВопроса = "В конфигурацию ИБ внесены изменения." + Символы.ПС +
"Для работы с ними рекомендуется перезапустить программу." + Символы.ПС +
"Перезапустить?";
РезультатВопроса = Вопрос(ТекстВопроса, РежимДиалогаВопрос.ДаНет);
// Если пользователь не хочет перезапускать сеанс
Если РезультатВопроса = КодВозвратаДиалога.Нет Тогда
// Запустим проверку обновления опять
НачатьПроверкуДинамическогоОбновленияИБ();
Возврат;
КонецЕсли;
глЗначениеПеременнойУстановить("глПерезапускатьСеансРаботыСПрограммой", Истина);
// Попробуем перезапустить
ПерезапуститьСеансРаботыСПрограммой();
КонецЕсли;
КонецПроцедуры
// Процедура перезапуска сеанса работы с программой
Процедура ПерезапуститьСеансРаботыСПрограммой() Экспорт
глЗначениеПеременнойУстановить("глЗапрашиватьПодтверждениеПриЗакрытии", Ложь);
ЗавершитьРаботуСистемы(Истина);
КонецПроцедуры
Процедура ПриЗавершенииРаботыСистемы()
//...
Если КонфигурацияБазыДанныхИзмененаДинамически() Тогда
// у всех кроме программистов, т.к. у нас слишком часто открыты как рабочие базы так и конфигуратор.
Если НЕ РольДоступна("Администрирование") Тогда
ОчиститьКэшИПерезапуститьПрограмму();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Процедура создает и запускает vbs файл, который производит очистку кэша.
// 1С и презапускает программу
//
Процедура ОчиститьКэшИПерезапуститьПрограмму() Экспорт
СкриптФайл = Новый ТекстовыйДокумент;
СтрокаСоединенияСБД = СтрокаСоединенияИнформационнойБазы();
СтрокаЗапускаПрограммы = КаталогПрограммы();
ПутьКФайлуСкрипта = КаталогВременныхФайлов() + "CacheCleaning.vbs";
ПутьКФайлу1С = СтрокаЗапускаПрограммы + "1cv8.exe";
ИмяСервера = "";
ИмяБазы = "";
Путь = "";
КомандаЗапуска = "";
Один = """";
Два = """""";
Три = """""""";
Если (Найти(СтрокаСоединенияСБД, "File=") <> 0) Тогда
Путь = СтрЗаменить(СтрокаСоединенияСБД, "File=", "");
Путь = Лев(Путь, СтрДлина(Путь)-1);
КомандаЗапуска = "WshShell.Run " + Три + ПутьКФайлу1С + Два + " ENTERPRISE /F" + Путь + Один + ", 1, true";
Иначе
МассивПараметровСоединения = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(СтрокаСоединенияИнформационнойБазы(), ";");
МассивПараметровСервера = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(МассивПараметровСоединения[0], """");
ИмяСервера = СокрЛП(МассивПараметровСервера[1]);
МассивПараметровБазы = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(МассивПараметровСоединения[1], """");
ИмяБазы = СокрЛП(МассивПараметровБазы[1]);
КомандаЗапуска = "WshShell.Run " + Три + ПутьКФайлу1С + Два + " ENTERPRISE /S" + ИмяСервера + "\" + ИмяБазы + Один + ", 1, true";
КонецЕсли;
// Если пользователь не хочет перезапускать сеанс 1С, то после выполнения скрипта ничего не делаем.
Если Не глЗначениеПеременной("глПерезапускатьСеансРаботыСПрограммой") Тогда
КомандаЗапуска = "";
КонецЕсли;
СкриптФайл.УстановитьТекст("WScript.Sleep(5000)
|
|Dim FSO
|Set FSO = WScript.CreateObject(""Scripting.FileSystemObject"")
|Set WshShell = WScript.CreateObject(""WScript.Shell"")
|Set colEnvVars = WshShell.Environment(""Process"")
|
|strComputer = "".""
|Set objWMIService = GetObject(""winmgmts:"" _
|& ""{impersonationLevel=impersonate}!\\"" _
|& strComputer & ""\root\cimv2"")
|
|Set colProcesses = objWMIService.ExecQuery( _
|""Select * From Win32_Process "" _
|& ""Where Name = '1cv8.exe'"")
|
|For Each objProcess In colProcesses
| objProcess.Terminate
|Next
|
|WScript.Sleep(1000)
|
|FolderName1 = ""\Local Settings\Application Data\1C\1Cv82""
|FolderName2 = ""\Local Settings\Application Data\1C\1Cv81""
|FolderName3 = ""\appdata\Local\1C\1Cv82""
|FolderName4 = ""\appdata\Local\1C\1Cv81""
|
|If FSO.FolderExists(colEnvVars(""userprofile"") & FolderName1) Then
| GoSubFolders colEnvVars(""userprofile"") & FolderName1
|End If
|If FSO.FolderExists(colEnvVars(""userprofile"") & FolderName2) Then
|GoSubFolders colEnvVars(""userprofile"") & FolderName2
| End If
|If FSO.FolderExists(colEnvVars(""userprofile"") & FolderName3) Then
| GoSubFolders colEnvVars(""userprofile"") & FolderName3
|End If
|If FSO.FolderExists(colEnvVars(""userprofile"") & FolderName4) Then
| GoSubFolders colEnvVars(""userprofile"") & FolderName4
|End If
|
|" + КомандаЗапуска + "
|Set WshShell = Nothing
|
|Sub DelFile(sFILE)
| On Error Resume Next
| FSO.DeleteFile sFILE, True
| If Err.Number <> 0 Then
| Wscript.Echo ""Error deleting file: "" & sFILE
| End If
|End sub
|
|Function GetFolder(sFOLDER)
| On Error Resume Next
| Set GetFolder = FSO.GetFolder(sFOLDER)
| If Err.Number <> 0 Then
| Wscript.Echo ""Error connecting to folder:"" & sFOLDER & VBlf & ""["" & Err.Number & ""]"" & Err.Description
| Wscript.Quit Err.Number
| End If
|End Function
|
|Sub GoSubFolders (objDIR)
| ProcessFilesInFolder objDIR
| Set sFolder = GetFolder(objDIR)
| For Each eFolder in sFolder.SubFolders
| GoSubFolders eFolder
| Next
| FSO.DeleteFolder sFolder, True
|End Sub
|
|Sub ProcessFilesInFolder (objDIR)
|Set sFolder = GetFolder(objDIR)
|For Each objFile in sFolder.Files
| DelFile objFile
|Next
|End Sub");
Попытка
СкриптФайл.Записать(ПутьКФайлуСкрипта, КодировкаТекста.Системная);
ЗапуститьПриложение(ПутьКФайлуСкрипта);
Исключение
КонецПопытки;
КонецПроцедуры
Vofka @ 19.07.13, 15:55
,
Добавлю от себя еще проще.
Процедура Кнопка1Нажатие(Элемент)
файл = Новый ТекстовыйДокумент;
scr = КаталогВременныхФайлов()+"clear1c.ps1";
файл.УстановитьТекст("echo 'Подготовка к запуску, дождитесь окончания работы этого скрипта.'
|timeout.exe /T 4 /NOBREAK
|echo 'Не запускайте 1С.'
|Get-childitem -Path $ENV:Userprofile\appdata\Roaming\1c\1cv8*\* -Exclude *.pfl,def.usr,tmplts | Remove-item -recurse
|Get-childitem -Path $ENV:Userprofile\appdata\Local\1c\1cv8*\* -Exclude *.pfl,tmplts | Remove-item -recurse
|echo 'КОНЕЦ!'
|echo 'Если не пробегало красное, значит все нормально. Можно запускать 1С.'
|timeout.exe /T 5 /NOBREAK");
файл.Записать(scr,КодировкаТекста.Системная);
Сообщить(scr);
ЗапуститьПриложение("powershell -executionpolicy unrestricted -command "+scr,,Ложь);
ПрекратитьРаботуСистемы(Ложь, "/ClearCache");
КонецПроцедуры
Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7
https://pro1c.org.ua