Версионирование объектов

В модуле формы, в процедуре «ПриСозданииНаСервере», добавить:
ВерсионированиеОбъектов.ПриСозданииНаСервере(ЭтаФорма);
ВерсионированиеОбъектов.ВключитьВерсионированиеОбъекта("Документ|Справочник.Имя", Перечисления.ВариантыВерсионированияОбъектов.ВерсионироватьПриЗаписи);
В модуле формы, в процедуре «ПриЗаписиНаСервере», добавить:
ВерсионированиеОбъектовСобытия.ЗаписатьВерсиюДокумента(ТекущийОбъект, Отказ, РежимЗаписиДокумента, РежимПроведенияДокумента)
Добавить команду в ПанельНавигации.См также
	Если ПараметрКоманды = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Если ТипЗнч(ПараметрКоманды) = Тип("Массив") Тогда
		Если ПараметрКоманды.Количество() = 0 Тогда
			Возврат;
		КонецЕсли;
		СсылкаНаОбъект = ПараметрКоманды[0];
	Иначе
		СсылкаНаОбъект = ПараметрКоманды;
	КонецЕсли;
	
	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("Ссылка", СсылкаНаОбъект);
	ПараметрыФормы.Вставить("ТолькоПросмотр", ПараметрыВыполненияКоманды.Источник.ТолькоПросмотр);
	
	ОткрытьФорму("РегистрСведений.ВерсииОбъектов.Форма.ВыборХранимыхВерсий",
								ПараметрыФормы,
								ПараметрыВыполненияКоманды.Источник,
							ПараметрыВыполненияКоманды.Уникальность,
							ПараметрыВыполненияКоманды.Окно);
	

Результат работы СКД в запросе

В модуле объекта Внешний отчет
 
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
	
	Настройки = КомпоновщикНастроек.ПолучитьНастройки();
	
	КомпоновщикМакета 		= Новый КомпоновщикМакетаКомпоновкиДанных;
	МакетКомпоновкиДанных 	= КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки);
	
	Если МакетКомпоновкиДанных.НаборыДанных.Количество() > 0 Тогда
		Сообщить(МакетКомпоновкиДанных.НаборыДанных[0].Запрос);      // Итиоговый текст запроса
	КонецЕсли;
	
КонецПроцедуры // ПриКомпоновкеРезультата()

Блокировка повторного запуска процессов в 1С: Документооборот

Все что нужно, добавить подписку на событие ПередЗаписью для БизнесПроцессСсылка.

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

Exception Details: System.Web.HttpException: A potentially dangerous Request.Path value was detected from the client (:)

Ошибка:
«Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Web.HttpException: A potentially dangerous Request.Path value was detected from the client (:).

Решение:

1. Добавить параметр в раздел system.webServer:

<security>
<requestFiltering allowDoubleEscaping="true" />
</security>

2. Добавить параметр в раздел configuration

<system.web>
<pages validateRequest="false" />
<httpRuntime requestPathInvalidCharacters="" />
</system.web>

Обратите внимание, что если вы переопубликуете базу, изменения нужно будет вносить заново.

Источник: http://www.koderline.ru/expert/programming/article-problemy-bezopasnosti-pri-rabote-s-1s-cherez-iis/

APDEX: Замеры производительности

Встала задача замерить производительность открытия документов, отчетов и пр.

Стандартный ADPEX вполне походил для задачи, однако, серверный вариант замера производительности не удобен для управляемых форм. Пришлось немного допилить его.

Добавляем в серверный модуль

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

Дальше, добавляем новое расширение конфигурации. В расширение добавляем требуемые формы документов и на форме:

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

Главное, не забыть снять флаг “Безопасный режим” с расширения. Замеры производительности в безопасном режиме не работают.

Custom segue

Промучился вечер с настраиваемыми Segue. На новое окно переходило, а обратно – никак. Возвращаешь стандартный Segue – все работает. Фишка оказалась в порядке вызова функции present.

Изначальный вариант выглядел так:

class FlipSegue: UIStoryboardSegue {
 
    override func perform() {
        let fromViewController = self.source
        let toViewController = self.destination
 
        UIView.transition(from: fromViewController.view, to: toViewController.view, duration: 0.5, options: .transitionFlipFromLeft ) {
            fromViewController.present(toViewController, animated: false, completion: nil)
        }
    }
}

а правильный так:

class FlipSegue: UIStoryboardSegue {
 
    override func perform() {
        let fromViewController = self.source
        let toViewController = self.destination
 
        fromViewController.present(toViewController, animated: false, completion: nil)
        UIView.transition(from: fromViewController.view, to: toViewController.view, duration: 0.5, options: .transitionFlipFromLeft )
    }
}

притом unwind segue должно быть таким:

class UnFlipSegue: UIStoryboardSegue {
    override func perform() {
        let fromViewController = self.source
        let toViewController = self.destination
 
 
        UIView.transition(from: fromViewController.view, to: toViewController.view, duration: 0.5, options: .transitionFlipFromRight) { _ in
            fromViewController.dismiss(animated: false, completion: nil )
        }
    }
 
}

32-х битные isapi на 64-х битном IIS

Перейти в настройки IIS, выбрать “Пулы приложений”, “DefaultAppPool”, “Дополнительные параметры”.

изменить “Разрешены 32-х разрядные приложения” на True.

Получить целые числа языком запросов 1С

Интересная задачка с собеседования – получить средствами языка запросов числа от -500 до 500. Само решение тривиально, но для него нужно получить перечень чисел от 0 до… ну хотя бы до 500. А это уже интереснее. Одно из возможных решений приведено ниже. Продолжая подставляя степени двойки можно получить очень длинную последовательность целых чисел.

ВЫБРАТЬ
0 КАК Числа
ПОМЕСТИТЬ Шаг0
 
ОБЪЕДИНИТЬ ВСЕ
 
ВЫБРАТЬ
1
;
 
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Лево.Числа * 2 + Право.Числа КАК Числа
ПОМЕСТИТЬ Шаг2
ИЗ
Шаг0 КАК Лево,
Шаг0 КАК Право
;
 
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Лево.Числа * 4 + Право.Числа КАК Числа
ПОМЕСТИТЬ Шаг4
ИЗ
Шаг2 КАК Лево,
Шаг2 КАК Право
;
 
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Лево.Числа * 8 + Право.Числа КАК Числа
ПОМЕСТИТЬ Шаг8
ИЗ
Шаг4 КАК Лево,
Шаг4 КАК Право
;
 
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Лево.Числа * 16 + Право.Числа КАК Числа
ПОМЕСТИТЬ Шаг16
ИЗ
Шаг8 КАК Лево,
Шаг8 КАК Право
;
 
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Лево.Числа * 32 + Право.Числа КАК Числа
ИЗ
Шаг16 КАК Лево,
Шаг16 КАК Право

IIS & 1C

Если веб-интерфейс у 1С не работает, не отображает элементы,  выходят ошибки  и т.п. можно попробовать отредактировать web.config на сервере IIS:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
   <system.webServer>
      <handlers>
         <remove name="ISAPI-dll" />
         <add name="1C Web-service Extension" path="*" verb="*" modules="IsapiModule" scriptProcessor="C:\Program Files\1cv8\8.3.5.1443\bin\wsisapi.dll" resourceType="Unspecified" requireAccess="None" />
         <add name="ISAPI-dll" path="*" verb="*" modules="IsapiModule" scriptProcessor="C:\Program Files\1cv8\8.3.5.1443\bin\wsisapi.dll" resourceType="File" requireAccess="Execute" allowPathInfo="true" preCondition="bitness64" />
      </handlers>
   </system.webServer>
</configuration>

Подключение приложений*32 к серверу*64

v83.ComConnector на x64

Объект V83.Application выполняется в рамках нового процесса 1cv8.exe.
Объект V83.COMConnector является внутрипроцессным сервером. На удаленном компьютере нет процесса, в котором он может быть создан.
Чтобы объект V83.COMConnector можно было создать на удаленном компьютере, регистрации компоненты comcntr.dll в COM утилитой regsvr32.exe недостаточно. Требуется выполнить регистрацию на удаленном компьютере компоненты comcntr.dll в качестве приложения COM+.

Для этого:
запустите утилиту Component Services;
создайте пустое COM+ приложение с:
Activation type – Server application;
именем, например, V83_COMConnector;
укажите имя пользователя Windows, от имени которого компонента будет запускаться специальный процесс dllhost.exe;
в ветке Components добавьте новую компоненту comcntr.dll из каталога загрузочных модулей 1С:Предприятия.
В результате при создании объекта V83.COMConnector на удаленном компьютере будет запущен специальный системный процесс dllhost.exe, и в нем будет создан объект V83.COMConnector.