Архив за месяц: Апрель 2016

XslCompiledTransform и OutOfMemoryException

Столкнулся с проблемой, что при использовании xslt преобразований возникает Out Of Memory, если входной XML файл имеет достаточно большой объем, а приложение в ресурсах ограниченно, например по тому, что работает в 32-х разрядной системе. Под катом способы, как с этим можно бороться.

1. Отключение отладки

Если вызвать конструктор по умолчанию для XslCompiledTransform, то он автоматически включает режим записи отладочной информации. Во время отладки это может быть и полезно, но вот в работающем приложении это лишняя память. Поэтому надо пользоваться конструктором с булевым параметром и в явном виде ее отключать:

XslCompiledTransform xslt = new XslCompiledTransform(false);

2. Предварительная компиляция XSLT

Как это не странно звучит, но для того чтобы применить XSLT преобразование к XML файлу, файл содержащий это преобразование надо скомпилировать. Можно сэкономить память, если сделать это предварительно ручками.
Для этого, необходимо по пути вида:
C:Program Files (x86)Microsoft SDKsWindowsv8.1AbinNETFX 4.5.1 Tools
найти утилиту: xsltc.exe
и запустить ее указав какой файл с xslt преобразовать, в какую сборку и с каким именем класса записать получившийся код.
Получится что-то вида:
xsltc.exe /class:ClassName /out:OutputXSLT.dll input.xslt
Дальше все просто, подключаем сборку в проект, ну или загружаем ее во время выполнения через Reflection.
Все, теперь вместо пути к файлу, можем указать тип из нашей dll:

XslCompiledTransform xslt = new XslCompiledTransform(false);
xslt.Load(typeof(ClassName));

3. Если приходится преобразовывать много файлов одним XSLT

Во-первых, один раз создав XslCompiledTransform держим его в памяти и не пересоздаем.
Во-вторых, незабываем чистить память под поток записи результатов. Например, так:

using (XmlWriterxmlWriter = XmlWriter.Create(outputFileName))
{
    xslt.Transform(InputXmlFileName, xmlWriter);
}

4. Общее

Ну и последнее, можно попробовать собрать проект в Release конфигурации, может и на этом что-то полуситься выграть по памяти.

И снова о хостинге WCF-сервисов в 2016-м accoreconsole.exe…

Подумал тут... Вполне возможно, что Autodesk умышленно прикрыла возможность хостинга сервисов в 2016-м accoreconsole.exe, дабы если не полностью пресечь (т.к. это не возможно), то хотя бы максимально усложнить возможность использования инструмента в системе распределённых приложений взаимодействующих через сервисы...

Наличие возможности хостинга WCF-сервисов в accoreconsole.exe для ряда случаев может существенно сократить потребность в количестве приобретаемых лицензий AutoCAD на предприятиях, где выполнение некоторого (если даже не всего) объёма работ можно автоматизировать (т.е. сделать программно). Одним сервисом или набором сервисов (читать как "одной лицензией AutoCAD") в таком случае сможет пользоваться неограниченное количество сотрудников компании одновременно. Для компании клиента это, безусловно, экономия... Но вот для компании Autodesk - это потеря денег... Т.е. налицо явный конфликт интересов и вполне очевидно, кто в данной ситуации имеет на руках "все козыри".

Кроме того, не стоит забывать, что теперь в Autodesk хотят одних и тех же овец стричь каждый год (новая ценовая политика) в виду чего даже сама по себе потенциальная возможность  сокращения лицензий вряд ли будет воспринята ими положительно. Т.о., как я уже писал выше: не исключено, что в 2016-м AutoCAD "кислород" сервисам был перекрыт преднамеренно...

Резюме
Я не удивлюсь, если в более новых версиях AutoCAD приложение accoreconsole.exe будет вовсе тихо изъято, мол "за ненадобностью"...

И снова о хостинге WCF-сервисов в 2016-м accoreconsole.exe…

Подумал тут... Вполне возможно, что Autodesk умышленно прикрыла возможность хостинга сервисов в 2016-м accoreconsole.exe, дабы если не полностью пресечь (т.к. это не возможно), то хотя бы максимально усложнить возможность использования инструмента в системе распределённых приложений взаимодействующих через сервисы...

Наличие возможности хостинга WCF-сервисов в accoreconsole.exe для ряда случаев может существенно сократить потребность в количестве приобретаемых лицензий AutoCAD на предприятиях, где выполнение некоторого (если даже не всего) объёма работ можно автоматизировать (т.е. сделать программно). Одним сервисом или набором сервисов (читать как "одной лицензией AutoCAD") в таком случае сможет пользоваться неограниченное количество сотрудников компании одновременно. Для компании клиента это, безусловно, экономия... Но вот для компании Autodesk - это потеря денег... Т.е. налицо явный конфликт интересов и вполне очевидно, кто в данной ситуации имеет на руках "все козыри".

Кроме того, не стоит забывать, что теперь в Autodesk хотят одних и тех же овец стричь каждый год (новая ценовая политика) в виду чего даже сама по себе потенциальная возможность  сокращения лицензий вряд ли будет воспринята ими положительно. Т.о., как я уже писал выше: не исключено, что в 2016-м AutoCAD "кислород" сервисам был перекрыт преднамеренно...

Резюме
Я не удивлюсь, если в более новых версиях AutoCAD приложение accoreconsole.exe будет вовсе тихо изъято, мол "за ненадобностью"...

Уильям Чемберс. История ландшафтного искусства

Уильям Чемберс

Предоставленный материал с сайта — http://tatufoto.ru/.

Уильям Чемберс, о теоретических работах которого упомянуто выше, был сыном йоркширского торговца, который жил в Стокгольме. В ранней молодости он поступил на службу в Шведско-Ост-Индскую компанию и имел случай побывать в Ост-Индии и Китае. Там в свободное время он зарисовывал постройки и сады, материал для будущих своих диссертаций, многого, кажется, не видел, потому что считает, что китайские сады малы, а в диссертации упоминает название только одного. По возвращении Чемберс бросил торговлю, занимался в Париже у Клериссо, где встретился с братьями Адамами и, может быть, Камероном, пробыл несколько лет в Италии. Первой его работой было устройство садов Кью около Лондона и постройка там целого ряда сооружений. Потом он заканчивал устройство садов Вильтона, Тэнфилд-холла, Марино около Дублина, где соорудил великолепный дворец, строил колоссальный Соммерсет-хауз в Лондоне и т. д.

Сады Кью несколько изменены сооружением громадных стеклянных оранжерей и разбивкой чудных цветочных клумб, но в некоторых участках творение Чемберса почти неприкосновенно.

Местность около ручья была красива благодаря отдельным красиво разросшимся деревьям и виду на храмики Эола и Беллоны. Теперь этого пейзажа не существует, так как деревья сильно разрослись, и сочетание пышных крон их с группами кустарников есть главное украшение садов. Маленькие храмики Чемберса красивы по форме, но поражают своей ненужностью и слишком малы, чтобы быть существенным дополнением пейзажа. Один из них, в виде ротонды с круглым куполом, доставлен на невысоком холме на берегу пруда; он красив в сочетании с окружающими рощами и красиво отражается в воде пруда.

О садах Кью можно судить не только потому, что они целы и мы видим, что природа добавила к творению человека, но и потому, что Чемберс сам издал гравюры с изображением их. Рассматривая эти гравюры, мы замечаем прежде всего, что Чемберс не особо стремился воспроизвести свои мечты о китайских садах.

Никакого разнообразия в этих изображениях нет, и самые знаменитые из гравюр (с храмом Эола, пагодой и, главное, ручьем) далеко не столь красивы, как случайные эффекты действительности.

Никакого намека на желание красиво расположить деревья не видно у Чемберса, а поразительная красота нынешних садов зависит от того, что за растениями в них ухаживают чрезвычайно тщательно.

Чемберс поместил в Кью и излюбленное, но мало удачное украшение пейзажных садов — искусственные развалины. И по форме плохо верится в подлинность этой полуразрушенной арки, и помещена она неудачно, не в укромном углу под зеленой листвой деревьев, а на хорошо содержимой аллее вблизи от каменной стены сада. Вообще, ввиду небольшого размера сада, Чемберсу пришлось все главные украшения отодвинуть к краям. В настоящее время сад Кью является наибольшим по размеру ботаническим садом Европы.

Профессиональные грузчики в Киеве – компетентность и универсальность от Артал Грузчик

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

Если Вы желаете заказать услугу профессиональных грузчиков введите в строке поиска — перевозка мебели в киеве http://artal-gruzchik.com.ua/perevozka_mebeli, перевозка мебели в киеве.

Специалист-такелажник широкого профиля без проблем управится с любой поставленной задачей – будь то погрузка имущества, либо демонтированные промышленного оборудования. Так или иначе, приличные компании, предлагающие перевозки грузов по Украине и за границей, могут дать вам весь спектр услуг по транспортировке грузов.

Проф грузчики обязаны уметь создавать инженерные расчеты, раз того требуют обстоятельства. Например, в случае если доставка оборудования к транспорту является неосуществимой в отсутствии постройки подъемных устройств и дополнительных систем, то потребуются как раз навыки инженерных расчетов.

В большинстве случаев грузчиков заказывают для переездов (офисные, загородные, квартирные). Пореже необходимы их услуги для передвижения больших объектов, к примеру, магазинов либо даже заводов. Услуги грузчиков бывают необходимы при закупке оборудования некими компаниями.

Услуги проф грузчиков необходимы при транспортировке оборудования, мебели и остального имущества, требующего щепетильной погрузки и предстоящей транспортировки. Сохранность возимого имущества всегда считается основным требованием любого клиента к фирмам, специализирующимся на перевозках грузов. Когда исполняются такелажные и погрузочно-разгрузочные работы, бригада должна применять такие конструкции, технологии, приспособления и оборудование, которые оптимально подходят в любом определенном случае. В итоге, конкретно от мастерства профессионалов, их искусства работать в команде зависит успех такелажного сервиса.

О хостинге WCF-сервисов в accoreconsole.exe (продолжение)

В продолжение предыдущей записи по обозначенной теме...

Экспериментальным путём выяснил, что проблема хостинга WCF сервисов в accoreconsole.exe присутствует в AutoCAD 2016, но отсутствует во всех более ранних версиях (2013-2015). Проверялось на AutoCAD 2016 x64 SP1 English с установленным Hotfix 3. Проверить наличие обозначенной проблемы в AutoCAD 2017 нет возможности за неимением оного, но очень даже не исключено, что обозначенный баг будет теперь и в нём и во всех последующих версиях...

Примечание:
Во всех без исключениях версиях accoreconsole.exe наблюдал ещё и такую проблему: то, что программно отправляется в консоль AutoCAD через Editor.WriteLine(...) по факту в консоли не появляется... Можно вместо этого воспользоваться Application.ShowAlertDialog(...) - в этом случае текст попадает в консоль, но это очень похоже на выдёргивание зубов плоскогубцами через зад...

О хостинге WCF-сервисов в accoreconsole.exe (продолжение)

В продолжение предыдущей записи по обозначенной теме...

Экспериментальным путём выяснил, что проблема хостинга WCF сервисов в accoreconsole.exe присутствует в AutoCAD 2016, но отсутствует во всех более ранних версиях (2013-2015). Проверялось на AutoCAD 2016 x64 SP1 English с установленным Hotfix 3. Проверить наличие обозначенной проблемы в AutoCAD 2017 нет возможности за неимением оного, но очень даже не исключено, что обозначенный баг будет теперь и в нём и во всех последующих версиях...

Примечание:
Во всех без исключениях версиях accoreconsole.exe наблюдал ещё и такую проблему: то, что программно отправляется в консоль AutoCAD через Editor.WriteLine(...) по факту в консоли не появляется... Можно вместо этого воспользоваться Application.ShowAlertDialog(...) - в этом случае текст попадает в консоль, но это очень похоже на выдёргивание зубов плоскогубцами через зад...

Модель принятия решений Врума-Йеттона

Нет такого человека, который был бы достаточно хорош, чтобы управлять другим человеком без его согласия
  -- Авраам Линкольн

В 2002 году у меня появились первые подчиненные. Само-собой, была куча ошибок, не очень удачных решений, но что-то и получалось. Часть на уровне интуиции, часть подсмотрев поведение других руководителей.
Если пользоваться классификацией психотипов предложенной Адизесом, то я "производитель". И видимо этим объясняется, что самым сложным в освоении навыком управления для меня было отдать принятие решений другим людям. Под катом упоминаемая в предыдущей статье модель, позволяющая на основе если-то понять, какой вид лидерства наиболее применим в текущей ситуации.
Как я уже написал выше, делегировать было для меня очень тяжело, ведь мне нравиться делать самому, а еще и психотип бубнит в уголочке, что я один знаю как правильно. И здесь очень важно без перегибов в ту или иную сторону. В каких-то случаях принятие решение должно остаться прерогативой руководителя, в других решения могут и должны приниматься командой или ее членами. Модель Врума-Йеттона как раз про это. Начнем с описания какие варианты поведения предлагает модель. Их всего пять:
Стиль AI. Вы сами решаете проблему или принимаете решение, используя имеющуюся у вас на данный момент информацию.
Стиль АII. Вы получаете необходимую информацию от своих подчиненных, и затем сами решаете проблему. Получая информацию, вы можете сказать или не сказать своим подчиненным, в чем состоит проблема. Роль ваших подчиненных в принятии решений - представление необходимой информации, а не поиск и оценка альтернативных решений.
Стиль CI. Вы излагаете проблему индивидуально тем подчиненным, кого это касается, и выслушиваете их идеи и предложения, но не собираете их вместе в одну группу. Затем вы принимаете решение, которое отражает или не отражает мнение ваших подчиненных.
Стиль СII. Вы излагаете проблему группе ваших подчиненных, и весь коллектив выслушивает все идеи и предложения. Затем вы принимаете решение, которое отражает или не отражает мнение ваших подчиненных.
Стиль GII. Вы излагаете проблему группе ваших подчиненных. Все вместе вы находите и оцениваете альтернативы и пытаетесь достичь согласия касательно выбора альтернативы. Ваша роль фасилитатора. Вы не пытаетесь влиять на группу, чтобы она приняла «ваше» решение, а хотите принять и выполнить любое решение, которое вся группа сочтет наиболее приемлемым.
Как видно, весь спектр, от авторитарного решения в одиночку, до передачи принятия решения группе. Для определения какой из этих стилей поведения применять, служат восемь вопросов:
1) Требование к качеству (QR): Насколько важно техническое качество решения?
2) Требование к приверженности (CR): Насколько важна приверженность подчинённых принятому решению?
3) Информация, доступная лидеру (LI): Имеешь ли ты информацию, достаточную для принятия самостоятельного решения?
4) Структура проблемы (ST): Является ли проблема хорошо структурированной (т.е. она ясно определена, ясна, ограничена во времени и так далее)?
5) Вероятность приверженности (CP): Если бы ты принял решение самостоятельно, достаточно ли очевидно, что твои подчинённые будут поддерживать это решение?
6) Конгруэнтность цели (GC): Разделяют ли подчинённые цели организации, которые должны быть достигнуты решением этой проблемы?
7) Конфликт подчинённых (CO): Вероятен ли конфликт между подчинёнными по вопросу предпочтённого решения?
8) Информация подчинённых (SI): Имеют ли подчинённые достаточно информации для принятия высококачественного решения?
Ну и смотрим на картинку которая описывает модель Врума-Йеттона (взята здесь):
Как этим пользоваться. Начинаем с первого вопроса и дальше, в зависимости от ответа, идем по стрелкам пока не дойдем до стиля поведения. Например, стоит вопрос, куда выбраться всей командой на выходные, чтобы поесть шашлыку на природе в хорошей компании. Поехали:
Первый вопрос: насколько важно техническое качество решения? Здесь сразу очевидный ответ, что техническое качество как таковое отсутствует и поэтому требования к нему низкие. Переходим по нижней стрелке ко второму вопросу: Насколько важна приверженность подчинённых принятому решению? Здесь тоже ситуация очевидна, если подчиненные не будут привержены принятому решению, то вместо приятного отдыха, будет обязаловка которая не принесет абсолютно никакой пользы. Значит выбираем ветку высокой важности.
По нижней стрелке переходим к пятому вопросу: Если бы ты принял решение самостоятельно, достаточно ли очевидно, что твои подчинённые будут поддерживать это решение? Нет, не очевидно что подчиненные будут привержены моему решению с выбором места и формата, может будут другие предложения, которые всех привлекут, например, съездить пострелять в пейнтбол или еще что-то. Перейдя по нижней ветке "Нет" мы приходим к модели поведения GII. Собираем мнения, помогаем договориться, но решение оставляем целиком на команде.
Ну а теперь о печальном.
Во-первых, если вопрос тривиален, то вместо принятия одного решения, может выясниться что надо принять от трех до восьми решений, а в конце может выясниться что и первоначальное решение надо принимать самостоятельно.
Во-вторых, кто сказал, что качество технической организации пикника имеет низкую важность? А что если мясо будет порезано неудачными кусками? А что если уголь будет некачественный? А что если шампуры не будут нормально держаться и будут прокручиваться на один бок и мясо прожариться не равномерно? И это пикник. В серьезном вопросе таких вопросов будет возникать еще больше и есть очень большой риск постоянно скатываться к авторитарному решению.
В общем, модель интересная, но больше как способ подумать над проблемой. Когда проблема достаточно серьезна чтобы потратить на ее обдумывание 10-15 минут (а может и больше), то почему бы не отдать ей должное и не подумать в рамках ее вопросов о том, кто будет принимать решение о том, как разбираться с проблемой.

О хостинге WCF-сервисов в accoreconsole.exe (AutoCAD 2016)

Как известно, WCF-сервисы могут в качестве хостинга использовать не только IIS и WAS, но так же и произвольные приложения (консольные или GUI). Как показывает практика, в качестве хоста можно использовать acad.exe. В идеале хотелось бы иметь возможность хостить службы в accoreconsole.exe, но не забываем, что это Autodesk, а это означает, что скучать не придётся...


Когда это может оказаться интересным?

Как известно, в параметрах запуска accoreconsole.exe можно указывать набор ключей, в т.ч. и ключ /s, при помощи которого разрешено передавать имя файла скрипта (SCR-файла). По завершению работы скрипта приложение так же автоматически завершит свою работу. Однако порой может возникнуть потребность интерактивного использования функционала, предоставляемого accoreconsole.exe (т.е. само по себе консольное окно при этом не требуется) не закрывая приложение столько времени, сколько потребуется (можно просто скрыть консольное окошко).

Хостинг службы в AutoCAD позволяет другим приложениям (т.н. клиентам) взаимодействовать с ним не прибегая к использованию AutoCAD COM API и при этом получая возможность задействовать возможности AutoCAD .NET API. Кроме того, в любой момент служба может быть перемещена на любой др. компьютер абсолютно прозрачно для клиентов.

В случае необходимости, клиент так же сможет отправлять службе произвольный набор команд, которые будут выполняться в AutoCAD на локальной или удалённо расположенной машине. Например с планшета, работающего под управлением OS Android пользователь сможет отправлять команды пакетной обработки чертежей (очистка, аудит, пересохранение и т.п.).

Это не означает, что на удалённой или локальной машинке обязательно должен быть постоянно запущен AutoCAD. Нет. Клиент может обратиться к службе, которая хостится в IIS или WAS с требованием что-то сделать в AutoCAD. Эта служба запускает AutoCAD (устанавливая видимость его окна в False) и в свою очередь является клиентом для другой службы, хостящейся в AutoCAD, передавая ей ваши запросы, а вам - её ответы. После того, как необходимый вам набор операций в AutoCAD будет выполнен служба, хостящаяся в IIS или WAS завершает работу AutoCAD и ждёт следующих обращений. В случае необходимости, параллельно может быть запущено несколько экземпляров AutoCAD, выполняющих каждый свою задачу, полученную от клиента. Для упрощения в данной теме я не использую промежуточную службу.

Сервис может, к примеру, проверять наличие обновлений (для AutoCAD и его расширений) на сервере компании и в случае их обнаружения сообщать об этом пользователю (или выполнять обновление - это на откуп администраторов CAD).

В идеале, конечно же, лучше всего на роль хоста службы подошёл бы accoreconsole.exe...


Служба

Предположим, что служба, предназначенная для хостинга в AutoCAD, реализует такой интерфейс:

namespace Bushman.CAD.Services {

    [ServiceContract(Namespace = "www.gpsm.ru")]
    interface IMyContract {
        [OperationContract]
        void Write(string msg); // Write message into AutoCAD command console.

        [OperationContract]
        string GetVersion(); // Get AutoCAD version
    }
}

Реализуем обозначенный интерфейс как-то так:

using cad = Autodesk.AutoCAD.ApplicationServices.Core.Application;
using Autodesk.AutoCAD.ApplicationServices;

namespace Bushman.CAD.Services {
    class MyService : IMyContract {
        public string GetVersion() {
            return cad.Version.ToString();
        }

        public void Write(string msg) {
            Document doc = cad.DocumentManager.MdiActiveDocument;
            if (null != doc) {
                doc.Editor.WriteMessage(msg);
            }
        }
    }

Никаких команд определять не будем, а инициализацию расширения выполним следующим образом:

using System;
using System.ServiceModel;
using cad = Autodesk.AutoCAD.ApplicationServices.Core.Application;
usingAutodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;

[assembly: ExtensionApplication(typeof(Bushman.CAD.Services.ExtensionApplication))]

namespace Bushman.CAD.Services {
    public class ExtensionApplication : IExtensionApplication {

        static ServiceHost host = null;

        static ExtensionApplication() {
            try{
                host = new ServiceHost(typeof(MyService));
                host.Open();
                host.UnknownMessageReceived += Host_UnknownMessageReceived;
                AppDomain.CurrentDomain.ProcessExit += ProcessExit;
            }
            catch(System.Exception ex) {
                Document doc = cad.DocumentManager.MdiActiveDocument;
                if (null != doc) doc.Editor.WriteMessage(ex.Message);
            }
        }

        private static void Host_UnknownMessageReceived(object sender,
            UnknownMessageReceivedEventArgs e) {
            Document doc = cad.DocumentManager.MdiActiveDocument;
            if(null != doc) doc.Editor.WriteMessage(e.Message.ToString());
        }

        private static void ProcessExit(object sender, EventArgs e) {
            if(null != host) host.Close();
        }

        public void Initialize() {
            string status = null == host ? "null" : host.State.ToString();
            Document doc = cad.DocumentManager.MdiActiveDocument;
            if(null != doc) doc.Editor.WriteMessage("\nHost status: {0}.\n", status);
        }

        public void Terminate() {
            // Nothing is here.
        }
    }
}


Клиент

Клиента реализуем следующим образом:

using System;
using System.ServiceModel;
usingBushman.MyClient.ServiceReference1;

namespace Bushman.MyClient {
    classProgram {
        static void Main(string[] args) {
            Console.Title = "CAD client";
            try{
                using (MyContractClient client = new MyContractClient("http")) {
                    if (client.InnerChannel.State != CommunicationState.Faulted) {
                        client.Open();
                        string version = client.GetVersion();
                        Console.WriteLine("CAD version: {0}", version);
                        client.Write("Client said: Hello, AutoCAD.\n");
                    }
                }
            }
            catch(Exception ex) {
                Console.WriteLine(ex.Message);
            }

            Console.WriteLine("Press any key for exit...");
            Console.ReadKey();
        }
    }
}


Конфигурационные файлы acad.exe.config и accoreconsole.exe.config настраиваю на работу с обозначенной выше службой:


<configuration>

  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0"/>
  </startup>

  <!--All assemblies in AutoCAD are fully trusted so there's no point generating publisher evidence-->
  <runtime>
    <generatePublisherEvidence enabled="false"/>
  </runtime>

  <system.serviceModel>
    <services>
      <service name="Bushman.CAD.Services.MyService" behaviorConfiguration="MEXGET">
        <host>
          <baseAddresses>
            <add baseAddress="http://win7x64ac2:8001"/>
          </baseAddresses>
        </host>
        <endpoint name="http"
                  binding="wsHttpBinding"
                  address="MyService"
                  bindingConfiguration="MyContract"
                  contract ="Bushman.CAD.Services.IMyContract">
        </endpoint>
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="MyContract"/>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MEXGET">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <diagnostics wmiProviderEnabled="true">
      <messageLogging
           logEntireMessage="true"
           logMalformedMessages="true"
           logMessagesAtServiceLevel="true"
           logMessagesAtTransportLevel="true"
           maxMessagesToLog="3000"
       />
    </diagnostics>

  </system.serviceModel>

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true" >
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
      <source name="myUserTraceSource"
              switchValue="Information, ActivityTracing">
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="xml"
           type="System.Diagnostics.XmlWriterTraceListener"
                 initializeData="\\hyprostroy\dfs\Обмен\Бушман\logs\Service-Traces.svclog" />
    </sharedListeners>
  </system.diagnostics>
</configuration>


Конфигурационный файл клиента выглядит так:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="http" />
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://win7x64ac2:8001/MyService" binding="wsHttpBinding"
          bindingConfiguration="http" contract="ServiceReference1.IMyContract"
          name="http">
        <identity>
          <!-- WARNING: change the value according your user principal name. -->
          <userPrincipalName value="admin@hyprostr" />
        </identity>
      </endpoint>
    </client>

    <diagnostics wmiProviderEnabled="true">
      <messageLogging
           logEntireMessage="true"
           logMalformedMessages="true"
           logMessagesAtServiceLevel="true"
           logMessagesAtTransportLevel="true"
           maxMessagesToLog="3000"
       />
    </diagnostics>

  </system.serviceModel>

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true" >
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
      <source name="myUserTraceSource"
              switchValue="Information, ActivityTracing">
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="xml"
           type="System.Diagnostics.XmlWriterTraceListener"
                 initializeData="\\hyprostroy\dfs\Обмен\Бушман\logs\Client-Traces.svclog" />
    </sharedListeners>
  </system.diagnostics>

</configuration>


Запускаем службу и клиента
Служба и клиент могут находится как на одном компьютере, так и на разных компьютерах в сети (или в Интернет). Если в качестве хоста использовать acad.exe, то всё нормально работает:



Но вот если в качестве хоста использовать accoreconsole.exe, то достучаться до сервиса не удастся даже с локального компьютера, на котором запущен хост сервиса. При этом сервис успешно запускается, но не доступен:




В логах клиента можно посмотреть описание проблемы:



По обозначенной теме мне ответил Августо Гонсалес:
Augusto Goncalves (API Evangelist at Autodesk):
As far as I remember trying, accoreconsole.exe doesn't accept new calls (from automation) after is open (but I haven't tried with WCF). Acad.exe is a little different... I don't believe accoreconsole will remain receiving calls after it was launched, it was designed to launch with a list of commands on the .scr file.
Если Августо прав, то это будет очередной, весьма досадный недостаток accoreconsole.exe...

Продолжение темы - здесь...

О хостинге WCF-сервисов в accoreconsole.exe (AutoCAD 2016)

Как известно, WCF-сервисы могут в качестве хостинга использовать не только IIS и WAS, но так же и произвольные приложения (консольные или GUI). Как показывает практика, в качестве хоста можно использовать acad.exe. В идеале хотелось бы иметь возможность хостить службы в accoreconsole.exe, но не забываем, что это Autodesk, а это означает, что скучать не придётся...


Когда это может оказаться интересным?

Как известно, в параметрах запуска accoreconsole.exe можно указывать набор ключей, в т.ч. и ключ /s, при помощи которого разрешено передавать имя файла скрипта (SCR-файла). По завершению работы скрипта приложение так же автоматически завершит свою работу. Однако порой может возникнуть потребность интерактивного использования функционала, предоставляемого accoreconsole.exe (т.е. само по себе консольное окно при этом не требуется) не закрывая приложение столько времени, сколько потребуется (можно просто скрыть консольное окошко).

Хостинг службы в AutoCAD позволяет другим приложениям (т.н. клиентам) взаимодействовать с ним не прибегая к использованию AutoCAD COM API и при этом получая возможность задействовать возможности AutoCAD .NET API. Кроме того, в любой момент служба может быть перемещена на любой др. компьютер абсолютно прозрачно для клиентов.

В случае необходимости, клиент так же сможет отправлять службе произвольный набор команд, которые будут выполняться в AutoCAD на локальной или удалённо расположенной машине. Например с планшета, работающего под управлением OS Android пользователь сможет отправлять команды пакетной обработки чертежей (очистка, аудит, пересохранение и т.п.).

Это не означает, что на удалённой или локальной машинке обязательно должен быть постоянно запущен AutoCAD. Нет. Клиент может обратиться к службе, которая хостится в IIS или WAS с требованием что-то сделать в AutoCAD. Эта служба запускает AutoCAD (устанавливая видимость его окна в False) и в свою очередь является клиентом для другой службы, хостящейся в AutoCAD, передавая ей ваши запросы, а вам - её ответы. После того, как необходимый вам набор операций в AutoCAD будет выполнен служба, хостящаяся в IIS или WAS завершает работу AutoCAD и ждёт следующих обращений. В случае необходимости, параллельно может быть запущено несколько экземпляров AutoCAD, выполняющих каждый свою задачу, полученную от клиента. Для упрощения в данной теме я не использую промежуточную службу.

Сервис может, к примеру, проверять наличие обновлений (для AutoCAD и его расширений) на сервере компании и в случае их обнаружения сообщать об этом пользователю (или выполнять обновление - это на откуп администраторов CAD).

В идеале, конечно же, лучше всего на роль хоста службы подошёл бы accoreconsole.exe...


Служба

Предположим, что служба, предназначенная для хостинга в AutoCAD, реализует такой интерфейс:

namespace Bushman.CAD.Services {

    [ServiceContract(Namespace = "www.gpsm.ru")]
    interface IMyContract {
        [OperationContract]
        void Write(string msg); // Write message into AutoCAD command console.

        [OperationContract]
        string GetVersion(); // Get AutoCAD version
    }
}

Реализуем обозначенный интерфейс как-то так:

using cad = Autodesk.AutoCAD.ApplicationServices.Core.Application;
using Autodesk.AutoCAD.ApplicationServices;

namespace Bushman.CAD.Services {
    class MyService : IMyContract {
        public string GetVersion() {
            return cad.Version.ToString();
        }

        public void Write(string msg) {
            Document doc = cad.DocumentManager.MdiActiveDocument;
            if (null != doc) {
                doc.Editor.WriteMessage(msg);
            }
        }
    }

Никаких команд определять не будем, а инициализацию расширения выполним следующим образом:

using System;
using System.ServiceModel;
using cad = Autodesk.AutoCAD.ApplicationServices.Core.Application;
usingAutodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;

[assembly: ExtensionApplication(typeof(Bushman.CAD.Services.ExtensionApplication))]

namespace Bushman.CAD.Services {
    public class ExtensionApplication : IExtensionApplication {

        static ServiceHost host = null;

        static ExtensionApplication() {
            try{
                host = new ServiceHost(typeof(MyService));
                host.Open();
                host.UnknownMessageReceived += Host_UnknownMessageReceived;
                AppDomain.CurrentDomain.ProcessExit += ProcessExit;
            }
            catch(System.Exception ex) {
                Document doc = cad.DocumentManager.MdiActiveDocument;
                if (null != doc) doc.Editor.WriteMessage(ex.Message);
            }
        }

        private static void Host_UnknownMessageReceived(object sender,
            UnknownMessageReceivedEventArgs e) {
            Document doc = cad.DocumentManager.MdiActiveDocument;
            if(null != doc) doc.Editor.WriteMessage(e.Message.ToString());
        }

        private static void ProcessExit(object sender, EventArgs e) {
            if(null != host) host.Close();
        }

        public void Initialize() {
            string status = null == host ? "null" : host.State.ToString();
            Document doc = cad.DocumentManager.MdiActiveDocument;
            if(null != doc) doc.Editor.WriteMessage("\nHost status: {0}.\n", status);
        }

        public void Terminate() {
            // Nothing is here.
        }
    }
}


Клиент

Клиента реализуем следующим образом:

using System;
using System.ServiceModel;
usingBushman.MyClient.ServiceReference1;

namespace Bushman.MyClient {
    classProgram {
        static void Main(string[] args) {
            Console.Title = "CAD client";
            try{
                using (MyContractClient client = new MyContractClient("http")) {
                    if (client.InnerChannel.State != CommunicationState.Faulted) {
                        client.Open();
                        string version = client.GetVersion();
                        Console.WriteLine("CAD version: {0}", version);
                        client.Write("Client said: Hello, AutoCAD.\n");
                    }
                }
            }
            catch(Exception ex) {
                Console.WriteLine(ex.Message);
            }

            Console.WriteLine("Press any key for exit...");
            Console.ReadKey();
        }
    }
}


Конфигурационные файлы acad.exe.config и accoreconsole.exe.config настраиваю на работу с обозначенной выше службой:


<configuration>

  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0"/>
  </startup>

  <!--All assemblies in AutoCAD are fully trusted so there's no point generating publisher evidence-->
  <runtime>
    <generatePublisherEvidence enabled="false"/>
  </runtime>

  <system.serviceModel>
    <services>
      <service name="Bushman.CAD.Services.MyService" behaviorConfiguration="MEXGET">
        <host>
          <baseAddresses>
            <add baseAddress="http://win7x64ac2:8001"/>
          </baseAddresses>
        </host>
        <endpoint name="http"
                  binding="wsHttpBinding"
                  address="MyService"
                  bindingConfiguration="MyContract"
                  contract ="Bushman.CAD.Services.IMyContract">
        </endpoint>
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="MyContract"/>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MEXGET">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <diagnostics wmiProviderEnabled="true">
      <messageLogging
           logEntireMessage="true"
           logMalformedMessages="true"
           logMessagesAtServiceLevel="true"
           logMessagesAtTransportLevel="true"
           maxMessagesToLog="3000"
       />
    </diagnostics>

  </system.serviceModel>

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true" >
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
      <source name="myUserTraceSource"
              switchValue="Information, ActivityTracing">
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="xml"
           type="System.Diagnostics.XmlWriterTraceListener"
                 initializeData="\\hyprostroy\dfs\Обмен\Бушман\logs\Service-Traces.svclog" />
    </sharedListeners>
  </system.diagnostics>
</configuration>


Конфигурационный файл клиента выглядит так:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="http" />
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://win7x64ac2:8001/MyService" binding="wsHttpBinding"
          bindingConfiguration="http" contract="ServiceReference1.IMyContract"
          name="http">
        <identity>
          <!-- WARNING: change the value according your user principal name. -->
          <userPrincipalName value="admin@hyprostr" />
        </identity>
      </endpoint>
    </client>

    <diagnostics wmiProviderEnabled="true">
      <messageLogging
           logEntireMessage="true"
           logMalformedMessages="true"
           logMessagesAtServiceLevel="true"
           logMessagesAtTransportLevel="true"
           maxMessagesToLog="3000"
       />
    </diagnostics>

  </system.serviceModel>

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true" >
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
      <source name="myUserTraceSource"
              switchValue="Information, ActivityTracing">
        <listeners>
          <add name="xml"/>
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="xml"
           type="System.Diagnostics.XmlWriterTraceListener"
                 initializeData="\\hyprostroy\dfs\Обмен\Бушман\logs\Client-Traces.svclog" />
    </sharedListeners>
  </system.diagnostics>

</configuration>


Запускаем службу и клиента
Служба и клиент могут находится как на одном компьютере, так и на разных компьютерах в сети (или в Интернет). Если в качестве хоста использовать acad.exe, то всё нормально работает:



Но вот если в качестве хоста использовать accoreconsole.exe, то достучаться до сервиса не удастся даже с локального компьютера, на котором запущен хост сервиса. При этом сервис успешно запускается, но не доступен:




В логах клиента можно посмотреть описание проблемы:



По обозначенной теме мне ответил Августо Гонсалес:
Augusto Goncalves (API Evangelist at Autodesk):
As far as I remember trying, accoreconsole.exe doesn't accept new calls (from automation) after is open (but I haven't tried with WCF). Acad.exe is a little different... I don't believe accoreconsole will remain receiving calls after it was launched, it was designed to launch with a list of commands on the .scr file.
Если Августо прав, то это будет очередной, весьма досадный недостаток accoreconsole.exe...

Продолжение темы - здесь...