gifts2017

Веб-сервер многопоточный с обработкой запросов в коде 1С (1C.Net:Предприятие)

Опубликовал Сергей Карташев (Elisy) в раздел Обмен - Интеграция с WEB

Новая идея организации веб-сервера внутри 1С, предложенная в статье, опирается на проверенную временем богатую функциональность .Net Framework. Решение на основе идеи лишены недостатков COM и веб-сервисов 1С. По сравнению с COM http-сервер можно использовать вне локальной сети, поддерживается одновременная обработка нескольких запросов. По сравнению с веб-сервисами 1С решение на базе http-сервера обладает большей гибкостью, так как программист волен сам выбирать формат ответа сервера (в том числе HTML, JSON, графические изображения, RSS и т.д.), а также контролировать при ответе URL-адрес, идентификацию пользователей, коды ошибок, куки, кодировку, осуществлять кеширование. Настройка же http-сервера внутри 1С сводится к простому запуску внешней обработки.

В сентябрьском номере журнала MSDeveloper.ru была опубликована обзорная статья, посвященная технологии 1C.Net:Предприятие и использованию .Net Framework внутри 1С:Предприятие. Данная статья – продолжение, описывающее практическое применение технологии при решении разного рода задач. Метод изначально был разработан для подключения медицинского лабораторного оборудования к 1С:Предприятие 8.2, но может быть использован для подключения любого другого оборудования и организации обменов данными между базами 1С и другими системами. Статья сопровождается готовыми примерами, доступными для работы, расширения и экспериментов.

В процессе автоматизации деятельности предприятия при помощи 1С: Предприятие часто возникают задачи интеграции и обмена с оборудованием и другими сторонними информационными системами, например, банками, веб-сайтами, информационными системами партнеров. Традиционно 1С:Предприятие выступает в качестве потребителя услуг, и реже – в качестве поставщика. До этого момента у разработчиков популярными технологиями при получении информации от 1C были COM и веб-сервисы, которые появились только в версии 8.1.

У обеих технологий (COM и веб-сервисы) есть свои минусы. Главные недостатки заключаются в следующем. COM-технология позволяет в каждый момент времени выполнять только один запрос. Обращение возможно только внутри своей локальной сети. Обработка одновременных запросов для COM возможна, но требует затрат на организацию пула соединений и отладку многопоточного приложения. Веб-сервисы же сложны по настройке и негибкие для программирования: жестко привязаны к SOAP-стандартам. Подключение устройств, обменивающихся простыми пакетами, работающих по http-протоколу, невозможно.

Новая идея организации веб-сервера внутри 1С, предложенная в статье, опирается на проверенную временем богатую функциональность .Net Framework. Решение на основе идеи лишены недостатков COM и веб-сервисов 1С. По сравнению с COM http-сервер можно использовать вне локальной сети, поддерживается одновременная обработка нескольких запросов. По сравнению с веб-сервисами 1С решение на базе http-сервера обладает большей гибкостью, так как программист волен сам выбирать формат ответа сервера (в том числе HTML, JSON, графические изображения, RSS и т.д.), а также контролировать при ответе URL-адрес, идентификацию пользователей, коды ошибок, куки, кодировку, осуществлять кеширование. Настройка же http-сервера внутри 1С сводится к простому запуску внешней обработки.

Описание примера

Пример, приложенный к статье, состоит из двух файлов: http-сервера (внешняя обработка 1С 8.2 HttpServer82) и тестового приложения эмуляции одновременных запросов к серверу (внешняя обработка 1С 8.2 TestHttpServer82). Обе обработки выполнены на основе управляемых форм. По умолчанию оба приложения настроены на работу с портом 8082.

Сервер и тестовое приложение разработаны на 1С:Предприятие 8.2 и используют .Net Framework 4.0 и компонент Elisy .Net Bridge 4. Соответственно, для работы примера требуется установленный .Net Framework 4.0 и версия библиотеки Elisy .Net Bridge v.4.0.2.0 и выше. Elisy .Net Bridge позволяет гармонично использовать классы и технологии .Net Framework на 1С, ведущую роль оставляя 1С.

Для проверки работы достаточно запустить внешнюю обработку HttpServer82.epf из 1С:Предприятие 8.2. Если у вас Windows с включенным UAC, то запустить 1С:Предприятие необходимо под администратором, иначе у приложения не будет достаточно прав на прослушивание запросов.

Внешний вид обработки-примера

Внешняя обработка позволяет задать порт, по которому будет осуществляться прослушивание и число создаваемых потоков для обработки одновременных запросов. По умолчанию установлен порт 8082 и 50 потоков.

После нажатия на кнопку Старт сервер переходит в рабочее состояние и осуществляет обработку запросов на заданный порт. Например, теперь можно обратиться из вашего браузера по адресу http://localhost:8082 и открыть страницу, которую вернет сервер. В запросе же можно передавать параметры, например, так: http://localhost:8082/test?x=1

Результат работы обработки

Для проверки сервера в многопоточном режиме придумана внешняя обработка TestHttpServer82.epf, которая осуществляет одновременный запуск запросов в цикле. В основу обработки для организации параллельной работы положена замечательная технология PLINQ (Parallel LINQ) из .Net framework 4.

Обработка для тестирования работы

Запускать тестовую обработку TestHttpServer82.epf следует из отдельного от сервера сеанса 1С:Предприятие, иначе одновременный запуск в одном сеансе двух обработок приведет к зависанию. В качестве параметров тестового примера выступают адрес запроса, число одновременных запросов и число циклов. По умолчанию запуск алгоритма приведет к 3 циклам обращений по адресу http://localhost:8082 с 20 одновременными запросами (надо отметить, что число одновременных запросов ограничено числом ядер процессора).

Принцип работы

.Net framework предлагает своим разработчикам класс HttpListener, отвечающий за прослушивание http-протокола. Используя HttpListener, вы можете создать прослушивание http-трафика, которое отвечает на http-запросы. Вы можете использовать этот класс только на операционных системах Windows XP SP2 или Windows Server 2003 и выше. Попытка использования класса на более ранних системах вызовет исключение.

Ниже приведен пример кода для 1С, который инициализирует объект типа HttpListener, настраивая его на прослушивание всех URL по порту 8082. При запуске в 1С работа программы приостанавливается, пока не последует запрос на порт, например, из браузера. Как только вы пошлете из браузера запрос, например, http://127.0.0.1:8082/ 1С вернет описанную в программе html-строку.

За что ответственен каждый участок кода, можно понять из комментариев, приведенных внутри исходного кода.

ПодключитьВнешнююКомпоненту("Elisy.NetBridge4");
AddIn = New("AddIn.ElisyNetBridge4");
net = AddIn.GetNet();

Если НЕ net.GetStatic("System.Net.HttpListener","IsSupported") Тогда
    Сообщить("Для класса HttpListener нужна ОС Windows XP SP2/2003 и выше");
    Возврат;
КонецЕсли;

listener = net.New("System.Net.HttpListener");
listener.Prefixes.Add("http://*:8082/");
listener.Start();

Сообщить("Прослушивание...");

//Метод GetContext блокирует выполнение программы пока ждет запрос. 
context = listener.GetContext();
request = context.Request;
// Получить объект ответа
response = context.Response;
// Создать ответ - HTML-строку
responseString = "Ответ от HttpListener";
buffer = net.GetStatic("System.Text.Encoding", "UTF8").GetBytes(responseString);
// Получить поток ответа и записать ответ в него.
response.ContentLength64 = buffer.Length;
output = response.OutputStream;
output.Write(buffer,0,buffer.Length);
// Необходимо закрыть выходной поток и остановить прослушивание
output.Close();
listener.Stop();

Это самый простой пример. Главный смысл простейшего примера в том, что 1С превращается в полнофункциональный http-сервер, а 1С-программист получает инструмент для гибкой настройки ответа с сервера. Он может вернуть его в любом формате (html, рисунок или JSON), затребовать идентификацию пользователя или вообще вернуть ошибку. Но вместе с тем есть недостатки: блокирование всего приложения, обработка только одного запроса. Пример к статье содержит более сложный код, за счет чего устранены недостатки простейшего примера из листинга.

От простого к сложному

В готовый пример вошел видоизмененный код работы с HttpListener, в котором вызов метода listener.GetContext() заменен вызовом асинхронных аналогов listener.BeginGetContext() и listener.EndGetContext(). Кроме этого создаются N отдельных потоков и заложена синхронизация между потоками с вызовом кода-обработки запроса на стороне 1С:Предприятие.

Достоинством предлагаемой реализации http-сервера является возможность одновременной обработки N запросов в разных потоках с передачей логики обработки в метод формы 1С:Предприятие. Пример при каждом запросе возвращает html с описанием источника и URL запроса. Решение очень гибкое, так как все доработки можно делать прямо из конфигуратора 1С. Никакие дополнительные проекты (например, C# или VB.Net) не задействованы.

Пример условно можно разделить на 2 части: код, который выполняется на стороне 1С:Предприятие и код, который выполняется на стороне .Net framework. При этом .Net framework взял на себя все, что нельзя реализовать средствами 1С:Предприятие, например, создание и синхронизацию потоков.

Http-сервер оформлен в виде управляемой формы. При нажатии на кнопку Старт происходит создание объектов классов HttpServer и Helper. Оба класса описываются на C# в макете обработки ИсходныйКод и компилируются «на лету» в обработчике ПриОткрытии формы. Класс Helper отвечает за перенаправление .Net-события в функцию ОбработатьЗапрос на форме 1С и формирование сообщение об ошибке.

Опустив не относящиеся к теме задачи по инициализации формы и вспомогательных классов, следует остановиться на методе ОбработатьЗапрос, который отвечает за возврат результата http-клиенту. Вызывается обработчик из класса Helper, в качестве параметра принимает объект контекста, может возвратить сообщение об ошибке, которое будет возвращено клиенту.

Объект контекста типа HttpListenerContext, передаваемый в метод ОбработатьЗапрос содержит два важных свойства: Request и Response, отвечающие за информацию о запросе и ответе соответственно.

Значение свойств Context.Request в отладчике

Свойство Request позволяет получить параметры и содержимое, переданные клиентом при запросе. Информация о запросе, помещенная в свойство Request содержит такие основные свойства как:

  • AcceptTypes – MIME-типы, поддерживаемые клиентом
  • ContentEncoding – информация о кодировке при ответе
  • Headers – набор заголовков
  • HttpMethod – метод HTTP, определенный клиентом
  • InputStream – поток, содержащий данные тела, пришедшие от клиента
  • IsAuthenticated – булево значение, показывающее идентифицирован ли пользователь
  • IsLocal – значение, показывающее локальный ли запрос (через localhost)
  • QueryString – строка запроса из запроса
  • RawUrl – информация об URL без хоста и порта
  • UrlReferrer – URL ресурса-источник данного перехода
  • UserAgent – информация о агенте-браузере пользователя

Значение свойств Context.Response в отладчике

Через свойство Response осуществляется возврат контента клиенту, передача информации об ошибке или перенаправление. Сопровождаться все может выставлением необходимых заголовков. Многие свойства ответа (Response) схожи со свойствами запроса. Значимые среди них следующие:

  • ContentEncoding – информация о кодировке при ответе
  • Headers – набор заголовков
  • OutputStream – поток, в который будет записан ответ (например, текст Html, XML или байтовый массив изображения)
  • RedirectLocation – свойство отвечает за HTTP-заголовок Location и позволяет перенаправить вызов
  • StatusCode – код статсуса при возврате клиенту,например: 200 (OK), 404 (ресурс не найден)
  • StatusDescription – описание статуса при возврате клиенту

Следующий код метода ОбработатьЗапрос преобразует сформированную строку РезультатHTML с HTML-кодом в набор байт и записывает этот набор байт в выходной поток, который будет возвращен клиенту. Ссылка на выходной поток получена через параметр метода.

ОтветСервера = context.Response; 
МассивБайт = net.GetStatic("System.Text.Encoding", "UTF8").GetBytes(РезультатHTML);
ОтветСервера.ContentLength64 = МассивБайт.Length;
ВыходнойПоток = ОтветСервера.OutputStream;
ВыходнойПоток.Write(МассивБайт, 0, МассивБайт.Length);
ВыходнойПоток.Close();

Основой обработки является класс HttpServer, который создает объект HttpListener и нужное число потоков для обработки. При вызове метода Start происходит запуск всех потоков-обработчиков и отдельного потока для работы HttpListener. Благодаря этому, можно продолжать работать с 1С во время работы http-сервера. При поступлении запроса HttpListener помещает запрос в очередь, где каждый запрос последовательно обрабатывает первый свободный поток. При обработке потока срабатывает цепочка вызовов: событие HttpServer.ProcessRequest, обработчик события Helper. HttpServer_ProcessRequest, 1С-функция Форма. ОбработатьЗапрос. Код C# класса HttpServer при запуске 1C из макета ИсходныйКод компилируется «на лету».

_listener.AuthenticationSchemes = authenticationScheme;
_listener.Prefixes.Add(String.Format(@"http://+:{0}/", port));
_listener.Start();
_listenerThread.Start();

for (int i = 0; i < _workers.Length; i++)
{
    _workers[i] = new Thread(Worker);
    _workers[i].Start();
 }

Начало получения запросов происходит в методе HandleRequests до тех пор, пока обработка не прекратится пользователем. При поступлении запроса, запрос передается в метод ContextReady и работа процесса прослушивания продолжается.

private void HandleRequests()
{
    while (_listener.IsListening)
    {
         var context = _listener.BeginGetContext(ContextReady, null);

         if (0 == WaitHandle.WaitAny(new[] { _stop, context.AsyncWaitHandle }))
         return;
    }
}
        
private void Worker()
{
    WaitHandle[] wait = new[] { _ready, _stop };
    while (0 == WaitHandle.WaitAny(wait))
    {
        HttpListenerContext context;
        lock (_queue)
        {
            if (_queue.Count > 0)
                context = _queue.Dequeue();
            else
            {
               _ready.Reset();
                continue;
            }
        }

        try { ProcessRequest(context); }
        catch (Exception e) { Console.Error.WriteLine(e); }
    }
}

Заключение

Многопоточный сервер, описанный в статье, по простоте настройки и функциональности превосходит традиционные методы доступа извне к информационным базам 1С:Предприятие 8.х. Это простой по запуску метод, позволяющий одновременно обрабатывать несколько запросов. При этом приложение 1С не блокируется, и пользователь может продолжать работу после запуска сервера.

Основное преимущество предложенного подхода – полная подконтрольность программисту процесса от получения запроса до формирования ответа. Например, на этапе получения запроса может быть выполнен парсинг URL, получена информация о том, как себя идентифицировал пользователь, а также полная информация о клиенте (поддерживаемые языки, записанные куки, заголовки, метод доступа). Ответ же можно вернуть практически любой, начиная от ошибки 404 Not found, заканчивая разными графическими форматами, форматами Word, Excel и популярными форматами на основе XML (JSON, HTML, RSS).

Пример, приложенный к статье, спроектирован так, что его функциональность можно легко расширить. Например, для организации кеша применить System.Web.Caching.Cache класс из .Net framework. А при парсинге URL попробовать поработать с классом RouteCollection из Asp.Net MVC. При создании RSS-ленты вам поможет класс System.ServiceModel.Syndication .SyndicationFeed. А при Json-сериализации обратите внимание на класс System.Runtime.Serialization.Json.DataContractJsonSerializer.

Конкретно для предложенного подхода на данный момент не выявлено явных недостатков. Есть вероятность того, что 1С:Предприятие в силу своих ограничений не сможет обеспечить на своей стороне должного распараллеливания и значительного увеличения производительности. Тем не менее опыты проведенные ранее для 1С:Предприятие 8.2 показали, что в схожем применении 1С достигается увеличение производительности, и 1С работает при этом стабильно.

Необходимо обратить внимание разработчиков еще на несколько моментов. Любая публикация информации в Интернете связана с риском взлома вне зависимости от способа публикации. Но в предложенном способе благодаря гибкости есть больше возможностей противостоять угрозам извне. Например, в запросе теперь доступен IP-адрес клиента, который можно блокировать по каким-то правилам (осуществляя поиск в черном списке локально или в специализированных сервисах). Параметры запроса доступны в виде строк и их можно анализировать на стороне 1С или .Net framework и блокировать опасное содержимое. Кроме этого есть несколько специализированных .Net-библиотек, доступных для решения данной проблемы, которые можно привлечь в 1С, например AntiXSS.

Второй момент заключается в том, что известные методы, в том числе и этот, предоставления услуг со стороны 1С не предназначены для массовых обращений и будут всегда уступать с этой точки зрения профессиональным серверам, например, IIS. При решении таких задач для массового доступа к информационным базам 1С рекомендуется обратить внимание на технологию прямого доступа к данным Elisy Open InfoBase. Более подробно о ней можно узнать в октябрьском выпуске журнала MSDeveloper.ru, ознакомившись со статьей «Elisy Open Infobase - необычно-экономное использование 1С:Предприятие 8 на Asp.Net-хостинге».

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
Пример организации многопоточного веб-сервера
.epf 11,50Kb
18.01.12
114
.epf 11,50Kb 114 Скачать
Обработка для тестирования примера
.epf 8,30Kb
18.01.12
52
.epf 8,30Kb 52 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Serg Kondrasgov (SergDi) 19.01.12 11:36
очень интересно, но придумать практическое применение не могу...
2. Сергей Карташев (Elisy) 19.01.12 12:45
(1) Изначально писался для подключения медицинского лабораторного оборудования, работающего пакетами http. Но, показалось, что применений можно больше найти, например, опубликовать в Интернет как 8.2 )))))
3. Сергей Сытько (8SiriuS8) 20.01.12 01:10
Надо более приближенный пример "для народа". Например какой нибудь приемщик заявок от клиентов
4. Олег (oleg_km) 25.01.12 08:27
делаем тоже самое но на ActiveX. Планирум применять как личный кабинет клиента или сотрудника: промотр сообщений, электронной почты, остатки, прайсы, наиболее важные отчеты.
5. Александр Щемелёв (zavyzka) 07.03.12 15:53
Должно быть очень специфическое использование.
6. Константин Канделла (kandellaster) 27.04.12 04:19
а можете ткнуть носом по теме обработки параметров пришедших на сервер в POST запросе?
7. Сергей Карташев (Elisy) 27.04.12 07:32
(6) kandellaster,
Судя по обсуждениям в Интернете нужно использовать Request.InputStream
В простейшем случае так (код на C#):
var requestBody = new StreamReader(context.Request.InputStream).ReadToEnd();

еще предлагается воспользоваться готовым методом HttpUtility.ParseQueryString:
var nameValuePairs = HttpUtility.ParseQueryString(requestBody, context.Request.ContentEncoding);


Здесь пример на C# как получить все значения из POST-запроса руками:
http://blog.mikehacker.net/2006/11/13/httplistener-and-forms/
kandellaster; +1 Ответить
8. Константин Канделла (kandellaster) 27.04.12 08:29
9. Константин Канделла (kandellaster) 22.06.12 06:23
и еще созрел такой вопрос немного не по теме но все же)
в каталоге откуда запускается сервер лежит папка CSS с файлами, в шаблоне прописано их подключение но не подключаются, пробовал копировать их в корень с шаблоном но результат тот же, в какую сторону копнуть?
10. Константин Канделла (kandellaster) 22.06.12 07:36
нашел приблизительное решение http://www.dreamincode.net/forums/topic/215467-c%23-httplistener-and-threading/
но как то статично все кажется
11. Сергей Карташев (Elisy) 22.06.12 07:39
(9) kandellaster,
и еще созрел такой вопрос немного не по теме но все же)
в каталоге откуда запускается сервер лежит папка CSS с файлами, в шаблоне прописано их подключение но не подключаются, пробовал копировать их в корень с шаблоном но результат тот же, в какую сторону копнуть?

Файловая система автоматически с веб-сервером никак не связана. В коде обработки ОбработатьЗапрос нужно отлавливать обращения к ресурсам вида "/mycssfile.css", самостоятельно загружать содержимое из файла и возвращать в ответ.
12. Константин Канделла (kandellaster) 22.06.12 07:42
тобиш это можно сделать средствами 1С ? не прибегая к изменению исходника сервера?
13. Сергей Карташев (Elisy) 22.06.12 08:21
(12) kandellaster,
тобиш это можно сделать средствами 1С ? не прибегая к изменению исходника сервера?

Да, можно сделать средствами 1С. Гибкость решения это позволяет. Таким же образом можно возвращать рисунки, js-скрипты - всю статику.
14. Константин Канделла (kandellaster) 22.06.12 09:07
действительно все оказалось просто)) спасибо
15. Александр Кузин (sashocq) 23.07.12 11:11
Все-таки непонятна многопоточность. 1С не поддерживает многопоточность внутри одного процесса. И если код с локальными переменными и будет так работать, то запросы к БД - вряд ли.
16. Сергей Карташев (Elisy) 23.07.12 11:32
(15) sashocq,
Все-таки непонятна многопоточность. 1С не поддерживает многопоточность внутри одного процесса. И если код с локальными переменными и будет так работать, то запросы к БД - вряд ли.

Согласен, что в таком решении 1С-слабое звено и требуются дополнительные исследования. Но как альтернатива громоздким веб-сервисам или для простых операций с оборудованием решение вполне подходит.
17. Константин Канделла (kandellaster) 27.07.12 10:42
ну вот таки на основе вашей разработки пишу в целях самообразования веб-фреймворк с роутами, системой шаблонизации, авторизацией и прочими плюшками
18. Константин Канделла (kandellaster) 27.07.12 10:42
19. Сергей Карташев (Elisy) 27.07.12 15:01
(17) Отлично и не только вы заинтересовались. Решение действительно простое и гибкое, подходит для многих применений. Если будут проблемы, пишите здесь. Постараемся подсказать.
20. Михаил ja-maik-a (ja-maik-a) 06.09.12 16:14
Каким образом можно в 1с получить то, что содержится в теле Post запроса?
21. Сергей Карташев (Elisy) 07.09.12 07:56
(20)
Каким образом можно в 1с получить то, что содержится в теле Post запроса?

В посте (7) был уже такой вопрос.
Следующий код в функции ОбработатьЗапрос считает тело POST-запроса в строку телоЗапроса через StreamReader:
запрос = context.Request;
Если запрос.HttpMethod = "POST" тогда
	//Обработка POST-запроса
	входнойПоток = запрос.InputStream;
	считывательПотока = net.New("System.IO.StreamReader", запрос.InputStream); 
	телоЗапроса = считывательПотока.ReadToEnd();
КонецЕсли;
...Показать Скрыть
22. Михаил ja-maik-a (ja-maik-a) 07.09.12 09:57
(21)Да, я прочитал ветку. Просто сначала не понял как вызывать методы классов из 1с.
Спасибо, все сработало
23. Михаил ja-maik-a (ja-maik-a) 11.09.12 15:40
Еще вопрос:
Возможно ли запустить в одном сеансе 1с два и более http сервера на разных портах?
24. Сергей Карташев (Elisy) 11.09.12 16:07
(23) ja-maik-a,
Возможно ли запустить в одном сеансе 1с два и более http сервера на разных портах?

Думаю, что возможно. Возможны подходы при решении задачи:
1. Расположить их на разных формах
2. Доработать исходный код, чтобы в метод
public void AddEvent(HttpServer httpServer, object form)

передавалось также имя функции формы. И на него сослаться в методе HttpServer_ProcessRequest
25. serg Ig (sigum) 17.09.12 10:47
Прошу помочь разобраться с ошибкой.
На windows xp Все работает нормально
если пытаюсь запустить на windows server 2003 где установлен sharepoint server 3.0, соответвенно SQL-server, IIS-server
При команде в 1С82 Net.GetStatic("System.Net.HttpListener", "IsSupported") выдается ошибка:
{Обработка.HttpServer82.Форма.Форма.Форма(353)}: Ошибка при вызове метода контекста (Start)
HttpServer.Start(Объект.Порт, net.New("System.Net.AuthenticationSchemes").Anonymous);
по причине:
Произошла исключительная ситуация (Elisy.NetBridge.dll): System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Net.HttpListenerException: Процесс не может получить доступ к файлу, так как этот файл занят другим процессом
at System.Net.HttpListener.AddAllPrefixes()
at System.Net.HttpListener.Start()
at Elisy.NetBridge.HttpServer.HttpServer.Start(Int32 port, AuthenticationSchemes authenticationScheme)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
at Elisy.ElisyNetBridge.InvokeMethod_Internal(Object instance, String method, Object[] args)
at CDispatchExWrapper.InvokeEx(CDispatchExWrapper* , Int32 id, UInt32 __unnamed001, UInt16 wFlags, tagDISPPARAMS* pdp, tagVARIANT* pVarRes, tagEXCEPINFO* pei, IServiceProvider* __unnamed006)

возможно что объект использует sharepoint, как использовать совместно на одном сервере?
26. Сергей Карташев (Elisy) 17.09.12 12:51
(25) sigum,
Прошу помочь разобраться с ошибкой.
На windows xp Все работает нормально
если пытаюсь запустить на windows server 2003 где установлен sharepoint server 3.0, соответвенно SQL-server, IIS-server


Судя по сообщению об ошибке, ошибка возникает на другой строке:
HttpServer.Start(Объект.Порт, net.New("System.Net.AuthenticationSchemes").Anonymous);
и http-серверу не нравится значение Объект.Порт. Попробуйте изменить порт прослушивания - должно помочь.

Иногда зависший процесс 1С не освобождает порт и не дает запустить прослушивание по этому же порту. Нужно убить процесс через диспетчер задач.

Посмотреть процесс, который занял порт, можно через утилиту: netstat -a -o
и по PID выйти на процесс.
27. serg Ig (sigum) 18.09.12 11:17
Дествительно, используемый порт 8082 был занят Microsoft.offise.server.conversions.launcher.exe.
Смена порта исключила ошибку.
Большое спасибо за помощь.
28. Сергей Карташев (Elisy) 09.10.12 16:33
Еще такой вопрос:
object error = _form.GetType().InvokeMember("ОбработатьЗапрос",
                    System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Public,
                    null, _form, new object[] { context });

Понятно, что первый параметр имя процедуры в 1с, а что значат остальные параметры?
и сколько и каких типов может быть передано параметров в 1с?


Первый параметр - имя процедуры в 1С, значения в new object[] { context } передаются как параметры процедуры 1С. Т.е. передается context. Можно передать N параметров, например new object[] { context, DateTime.Now } передастся 2й параметр дата. В процедуру 1С нужно добавить 2й параметр. Процедура 1С должна быть экспортной.
29. foxbeast 13.10.12 15:46
Тестируя возможность применения компоненты, наткнулся на проблему с получением значений из коллекции Cookies, пришедших в запросе браузера. Они нужны для создания авторизованных сессий.
Cookies = ContextRequest.Cookies;  // здесь все хорошо, Cookies - COM объект System.Net.CookieCollection
Если Cookies.Count > 0 Тогда           // да, больше 0, потому что кука s1 там есть и свойство Count=1
   Если Cookies["s1"] // а вот тут ругается - говорит, что поле s1 у объекта не обнаружено
...
...Показать Скрыть

Пробовал разные варианты:
Cookies[0] - "получение элемента по индексу для значения не определено"
ContextRequest.Cookies("s1") - возражает, что нет такого метода (а без ContextRequest 1С считает, что я пытаюсь вызвать несуществующую процедуру или функцию)
Cookies.Item["s1"] - ошибка при получении значения атрибута контекста
ну и так далее.
Я что-то делаю неправильно, или это какой-то баг?
30. foxbeast 15.10.12 07:53
Сработало Cookies.get_Item("s1"), метод про который MSDN умалчивает, во всяком случае для .NET 4.0.
31. Сергей Карташев (Elisy) 15.10.12 09:09
(30) foxbeast,
Сработало Cookies.get_Item("s1"), метод про который MSDN умалчивает, во всяком случае для .NET 4.0.

Действительно, одной из мало документированных возможностей является доступ к индексным свойствам .Net через get_Item и set_Item. Эта альтернатива используется для доступа к сборкам через COM, где нет индексных свойств. В .Net Bridge методы get_Item/set_Item также доступны.
32. адуырщдв (адуырщдв) 18.04.13 07:59
Интересно, попробуем прикрутить к нашей задаче.
33. diver.sun diver.sun (diver.sun) 05.07.13 18:25
В своё время столкнулся с той же проблемой, обошелся без .net bridge просто сам написал веб сервер в виде внешней компоненты, уже используется для личного кабинета в области продаж авиабилетов. А 1с действительно не многопоточна, обошел эту проблему путем создания внешнего приложения которое уже запускает потоки выполнения 1с. Если есть вопросы в личку.
34. Михаил ja-maik-a (ja-maik-a) 08.07.13 10:16
(33) diver.sun, а каждый поток 1с забирает лицензию при таком использовании?
35. diver.sun diver.sun (diver.sun) 08.07.13 10:55
Ну если они на одной машине крутятся.....
36. Михаил ja-maik-a (ja-maik-a) 08.07.13 12:06
(35) diver.sun, а запрос по таймауту не отвалится, пока будет ждать загрузки 1с?
37. diver.sun diver.sun (diver.sun) 08.07.13 13:07
Не.....приложение запускает 3 потока 1с, и ждет, регулярно контролируя не отвалилась ли 1с....и готов ли поток выполнения, при поступлении запроса он отправляется в один из свободных потоков. по тайм ауту выполнения запроса или тестового запроса поток выполнения перезапускается.....тоесть каждый запрос не ждет пока 1с запустится..
38. diver.sun diver.sun (diver.sun) 08.07.13 13:12
Выглядит так
Прикрепленные файлы:
39. Михаил ja-maik-a (ja-maik-a) 08.07.13 15:02
(38) diver.sun, каким образом передается контекст в 1с (параметры запроса, тип запроса)?
40. diver.sun diver.sun (diver.sun) 08.07.13 15:28
1с запускается как процесс с переопредением потоков ввода вывода. с командной строкой в которой указана обработка которая используя ВК ловит события записи в стандартный поток вводи и может писать в стандартный поток вывода FastCGI
41. Михаил ja-maik-a (ja-maik-a) 08.07.13 16:35
А можно ли ознакомиться как-нибудь с кодом? Посмотреть как происходить вызов с командной строки и прием этого вызова в 1с и получение параметров?
42. Максим Кузнецов (Makushimo) 27.07.16 11:11
Чего-то совсем не понял как это использовать. А хочется.
Проясните такие вопросы:
1. Рабочая база 1С может служить нттр-сервером и принимать запросы из вне, правильно?
2. Из вне в эту базу могут приходить запросы от:
- сайтов
- других баз 1С в локальной сети
- других баз 1С через интернет (при этом публиковать эту базу отдельно не надо)
верно?
3. Количество одновременных запросов, которое может принять сервер внутри базы 1С ограниченно?. Каким количеством?
4. Входящие запросы складываются в очередь. Где эта очередь хранится?
5. Входящие запросы по очереди обрабатываются последовательно? или в 1С можно использовать фоновые задания для одновременного выполнения сразу нескольких входящих запросов из очереди?
6. Теоретически все входящие запросы в базе 1С можно как то самому классифицировать и определить обработку каждому из них. Так?
7. Может ли сама база 1С, которая типо сервер, отправлять несколько параллельных запросов? Сколько?
8. Можно ли эти компоненты как то срастить с сайтом, например, чтобы он выступал приемщиком-обработчиком запросов, а 1С как бы не причем?
9. Можете написать от и до пример работы с несколькими запросами сразу:
- от другой базы 1С из локальной сети
- от другой базы 1С через интернет
- 2-3 запроса от сайта
Именно одновременно. Хочется увидеть как это все разруливать в коде базы 1С, которая типо сервер.
10. не понятно, каким образом оборудование отправляет запросы в базу 1С, которая типо сервер.
43. Ярослав Григорьев (yaroslavch) 08.11.16 21:41
Статья хорошая, интересная, НО! где брать саму компоненту? Приложенные обработки без неё не работают,
44. Сергей Карташев (Elisy) 09.11.16 06:13
(43) yaroslavch,
Отдельная страница есть для компонента, где можно бесплатную демо-версию скачать:
http://infostart.ru/public/20035/
45. Ярослав Григорьев (yaroslavch) 11.11.16 23:22
(44) Elisy, Сергей. До смешного доходит. Но ни как в боевом действии не могу попробовать вашу обработку.

Не взлетают ваши обработки, сначала на длл(Microsoft.СSharp.dll, mscorlib.dll) ругались, переустанавливал фреймворк до 4.6.1

Теперь ваша компонента выдаёт (на нажатие кнопки старт/стоп):

{ВнешняяОбработка.HttpServer82.Форма.Форма.Форма(88)}: Ошибка при вызове метода контекста (Stop)
HttpServer.Stop();
по причине:
Произошла исключительная ситуация (Elisy.NetBridge.dll): System.Reflection.TargetInvocationException: Адресат вызова создал исключение. ---> System.Threading.ThreadStateException: Поток не запущен.
в System.Threading.Thread.JoinInternal(Int32 millisecondsTimeout)
в Elisy.NetBridge.HttpServer.HttpServer.Stop()
--- Конец трассировки внутреннего стека исключений ---
в System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
в System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
в System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
в System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
в Elisy.ElisyNetBridge.InvokeMethod_Internal(Object instance, String method, Object[] args)
в CDispatchExWrapper.InvokeEx(CDispatchExWrapper* , Int32 id, UInt32 __unnamed001, UInt16 wFlags, tagDISPPARAMS* pdp, tagVARIANT* pVarRes, tagEXCEPINFO* pei, IServiceProvider* __unnamed006)
46. Сергей Карташев (Elisy) 12.11.16 07:30
(45) yaroslavch,
Как-будто ошибка происходит при попытке остановки сервера. Значит до этого была попытка запуска и тоже должна быть ошибка. Какая?
Попробуйте запустить 1С с правами Администратора (правый клик на ярлык 1С - Запустить от имени администратора). Возможно, не хватает прав на запуск сервера под обычным пользователем.
47. Ярослав Григорьев (yaroslavch) 13.11.16 07:57
(46) Elisy, спасибо, попробовал запустить с правами администратора - помогло. Но! это не совсем правильно, не могут же все пользователи с Администраторскими правами работать.

Мне программист знакомый на C# сказал что не хватает прав(в винде) для прослушивания порта. По идее обработку нужно настраивать так, или компоненты, чтобы права были. А вот как это сделать, не давая полных администраторских прав? что зарегистрировать, что прописать?

так же в обработке пришлось переписать строку, участок кода реализован не оптимально, т.к. компоненты могут лежать по разному адресу:
Эту:   параметрыКомпилятора.ReferencedAssemblies.Add("C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.CSharp.dll");
на эту:
    параметрыКомпилятора.ReferencedAssemblies.Add("C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.CSharp.dll");
...Показать Скрыть



48. Сергей Карташев (Elisy) 14.11.16 08:34
(47) yaroslavch,
так же в обработке пришлось переписать строку, участок кода реализован не оптимально, т.к. компоненты могут лежать по разному адресу:

Вроде, начиная с .Net 4 ссылки на основные сборки .Net можно указывать без пути. Попробуйте так:
параметрыКомпилятора.ReferencedAssemblies.Add("Microsoft.CSharp");
49. Сергей Карташев (Elisy) 14.11.16 08:40
(47) yaroslavch,
Мне программист знакомый на C# сказал что не хватает прав(в винде) для прослушивания порта. По идее обработку нужно настраивать так, или компоненты, чтобы права были. А вот как это сделать, не давая полных администраторских прав? что зарегистрировать, что прописать?

Есть вопрос/ответ в Интернете по поводу прав:
http://stackoverflow.com/questions/4019466/httplistener-access-denied

Пишут, что права на конкретный адрес можно выставить так:
netsh http add urlacl url=http://+:80/MyUri user=DOMAIN\user
yaroslavch; +1 Ответить
50. Ярослав Григорьев (yaroslavch) 14.11.16 17:12
Сергей. Еще такая проблемка. Пробовали обработку сервера, скрыть. Т.е. сделать невидимой, ну и поставить на автозапуск фоном от пользователя.

Но столкнулись с проблемой. Если сервер "стартануть", и закрыть 1С, не прекращая работу обработки(обработчик при закрытии не срабатывает), то Ваша компонента зависает, до перезагрузки компьютера или принудительного её завершения. Что достаточно не удобно.

Есть ли такой функционал, чтобы компонента проверяла свою связь с вызвавшей её обработкой, и если такая связь прерывается (обработка закрыта), то чтобы компонента сама себя закрывала?

51. Сергей Карташев (Elisy) 15.11.16 10:55
(50) yaroslavch,
Есть ли такой функционал, чтобы компонента проверяла свою связь с вызвавшей её обработкой, и если такая связь прерывается (обработка закрыта), то чтобы компонента сама себя закрывала?

Обработка и компонент внутри 1С живут по правилам COM/OLE. Зависание означает, что на какой-то объект в .Net остались ссылки. По этой причине в форме сделан обработчик ПередЗакрытием, позволяющий корректно освободить ссылки на объекты.
Если закомментировать этот обработчик, то в обычном режиме при закрытии приложения остается 1С в задачах невидимой. Скорее всего, у вас происходит такая же ситуация. Вам нужно каким-то способом добиться "освобождения" объектов.
52. Ярослав Григорьев (yaroslavch) 15.11.16 11:40
(51) Elisy, я это понимаю, в обработчике перед закрытием, есть код завершения. Но есть бага у 1С, которую я уже наблюдаю на нескольких конфигурациях. Суть в том, что когда закрываешь конфу глобально, файл-выход или "по крестику", то обработки "при закрытии" - НЕ СРАБАТЫВАЮТ.

И сделать что-то в условиях, когда конфигурацию запрещено менять, ни чего нельзя. В этом и предыстория появления предыдущего вопроса....

53. Сергей Карташев (Elisy) 16.11.16 07:23
(52) yaroslavch, я так понял речь идет об ошибке в 1С. В этом случае нужно искать обходной путь. Исследовать нужно. Возможно, сработает другое событие, показывающее окончание работы с формой. Может в новой версии платформы исправили поведение и нужно обновиться. Может, исследовать возможность показа скрытых форм в момент завершения работы.
И кардинальный способ - сделать отдельно работающее приложение на C#, которое свяжется с 1С другим способом через Elisy Business Connector или COM.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа