360 Total Security приветствует Хабрахабр

Команда Qihoo 360, вооружившись флагманским антивирусом 360 Total Security, добралась до портала Хабрахабр и рада знакомству с местными обитателями.

Это наш первый пост, в котором мы расскажем о себе. Возможно, что многие из вас уже знакомы продуктами Qihoo 360 – кто-то уже установил антивирус своим друзьям и коллегам, кто-то только распробовал перспективный софт, а кто-то вообще впервые увидел наш логотип и хочет узнать, как максимально обезопасить компьютер.
Ну что, поехали?

Простой, мощный и… бесплатный?

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

В июне 2015 антивирус 360 Total Security был установлен у 514 000 000 активных пользователей, а его мобильная версия установлена на 800 миллионах смартфонов и планшетов. Имея такую базу, мы ненавязчиво монетизируем её, предлагая платные приложения и продукты наших партнеров – web-игры, онлайн-видео, путешествия и т.д. При этом важно, что баннеры не занимают 60% пространства экрана, раздражая наших клиентов, а все продукты предлагаются в специальном магазине.

Все прозрачно и просто, друзья. Мы делаем качественный продукт, увеличиваем базу пользователей и монетизируем её через продажу приложений и партнерских продуктов. Сомневаетесь? Задавайте вопросы в комментариях, и вы получите на них исчерпывающие ответы.

А пока расскажем, почему так быстро растет количество пользователей антивируса 360 Total Security.

Единое решение компьютерных проблем

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

Естественно, для этого пришлось поработать над начинкой. Мы объединили в одном продукте несколько популярных движков и антивирусных систем, включая 360 Cloud Scan Engine, 360 QVMII AI Engine, Avira и Bitdefender, которые дают полный набор средств для защиты от вирусов.

В результате, вместо обычной защиты мы предлагаем одновременно 5 функций:

  1. Быстро проверяем все параметры работоспособности и безопасности одним кликом.

  2. Находим и устраняем вирусы.

  3. Настраиваем службы, включая автозагрузку, подключаемые модули и оптимизацию соединения с интернетом.

  4. Очищаем жесткие диски от мусорных или устаревших файлов, которые пользователь не использует.

  5. Предлагаем набор дополнительных инструментов – защиту браузера, «песочницу», функцию 360 Connect, брандмауэр и сжатие диска.

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

Теперь и на русском

Начиная с седьмой версии антивируса, пользователям доступен полностью русифицированный интерфейс. Хотя интуитивно понятные иконки помогали без проблем пользоваться 360 Total Security и ранее, теперь число поклонников среди русскоязычного населения резко увеличилось.

Мобильная безопасность

Принимая во внимание количество мобильного трафика, мы не могли обойти стороной и оставить беззащитными планшеты и смартфоны. Разработки в этом сегменте начались еще в ноябре 2009 года, так что мы были одними из первых, кто задумался о гаджетах. К настоящему времени все наработки вылились в полноценный продукт 360 Security, который дружит с Android.

Мобильное приложение дает многослойную защиту:

  • в реальном времени обновляются антивирусные базы, так что даже новейший троян или червь обломает зубы;
  • прекращаются «тормоза» в работе, потому что программа следит за оптимальным распределением оперативной памяти и мгновенно отключает второстепенные задачи;
  • в памяти устройства не скапливается мусор в виде кусков старых программ и бесполезных APK-файлов;
  • под дополнительной защитой оказываются личные данные – логины и аккаунты, номера счетов, списки контактов.

В одном только Китае более 800 миллионов юзеров используют наш продукт, и это число растет с каждым днем!

А вы уже пробовали 360 Total Security?

Мы честно рассказали о нашем продукте. Теперь вы знаете, почему наш антивирус бесплатный и что у него внутри.

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

Приятно было познакомиться и до встречи в комментариях.

ссылка на оригинал статьи https://habrahabr.ru/post/278205/

Персонализация IMGUI и редактора Unity. Часть вторая

С момента выхода новой системы Unity UI прошло больше года, поэтому Ричард Файн решил написать о ее предшественнице – IMGUI. В прошлой части материала мы разобрали как создать MyCustomSlider. У нас получился простой функциональный элемент IMGUI, который можно использовать в пользовательских редакторах, PropertyDrawers, EditorWindows и т. д. Но это еще не всё. Во второй части статьи мы поговорим о том, как можно расширить его функционал, например добавить возможность мультиредактирования.


Управляющие функции

Еще один немаловажный момент – взаимосвязь IMGUI с компонентом Scene View. Вы, должно быть, знакомы со вспомогательными элементами UI, такими как ортогональные стрелки, кольца или линии, которые позволяют перемещать, вращать и масштабировать объекты. Эти элементы называются управляющими функциями. Что интересно, они также поддерживаются в IMGUI.

Стандартные элементы классов GUI и EditorGUI, используемые в Unity Editor / EditorWindows, двухмерны, но основные концепции IMGUI, такие как идентификаторы управляющих элементов и типы событий, не привязаны ни к редактору Unity, ни к 2D. Управляющие функции для трехмерных элементов Scene View представлены классом Handles, который заменяет собой GUI и EditorGUI. Например, вместо функции EditorGUI.IntField, создающей элемент для редактирования одного целого числа, можно использовать функцию, позволяющую редактировать значение Vector3 при помощи интерактивных стрелок в Scene View:

Vector3 PositionHandle(Vector3 position, Quaternion rotation); 

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

Прописав функцию OnSceneGUI в пользовательском классе редактора, вы сможете использовать управляющие функции в редакторах, а функции из GUI – в Scene View. Для этого придется приложить дополнительные усилия: установить GL-матрицы или применить Handles.BeginGUI() и Handles.EndGUI() для установки контекста.

Объекты состояния

В случае с MyCustomSlider нам нужно было отслеживать 2 вещи: плавающее значение ползунка (которое передавалось пользователем и возвращалось к нему) и изменение ползунка в конкретный момент времени (для этого мы использовали элемент hotControl). Но что, если в элементе содержится намного больше информации?

IMGUI предоставляет простую систему хранения так называемых объектов состояния, связанных с элементами интерфейса. Для этого нужно определить новый класс, который будет использоваться для хранения данных, и связать новый объект с идентификатором управляющего элемента. Каждому объекту можно присвоить не более одного идентификатора, причем IMGUI делает это сам – с помощью встроенного конструктора. При загрузке кода редактора такие объекты не сериализуются (даже если поставлена метка [Serializable]), поэтому их нельзя использовать для долговременного хранения данных.

Предположим, нам нужна кнопка, которая возвращает значение TRUE при каждом нажатии, но при этом загорается красным, если удерживать ее дольше двух секунд. Для отслеживания времени нажатия кнопки мы воспользуемся объектом состояния. Объявим класс:

public class FlashingButtonInfo {       private double mouseDownAt;        public void MouseDownNow()       {       		mouseDownAt = EditorApplication.timeSinceStartup;       }        public bool IsFlashing(int controlID)       {             if (GUIUtility.hotControl != controlID)                   return false;              double elapsedTime = EditorApplication.timeSinceStartup - mouseDownAt;             if (elapsedTime < 2f)                   return false;                                      return (int)((elapsedTime - 2f) / 0.1f) % 2 == 0;       } }  

Время нажатия кнопки будет храниться в свойстве mouseDownAt при вызове MouseDownNow(), а функция IsFlashing будет определять, должна ли кнопка гореть красным в данный момент. Естественно, если не задействован hotControl или с момента нажатия кнопки прошло менее двух секунд, кнопка не загорится. Но в противном случае ее цвет будет меняться каждые 0,1 секунды.

Теперь напишем код для самой кнопки:

public static bool FlashingButton(Rect rc, GUIContent content, GUIStyle style) {         int controlID = GUIUtility.GetControlID (FocusType.Native);          // Get (or create) the state object         var state = (FlashingButtonInfo)GUIUtility.GetStateObject(                                              typeof(FlashingButtonInfo),                                               controlID);          switch (Event.current.GetTypeForControl(controlID)) {                 case EventType.Repaint:                 {                         GUI.color = state.IsFlashing (controlID)                              ? Color.red                              : Color.white;                         style.Draw (rc, content, controlID);                         break;                 }                 case EventType.MouseDown:                 {                         if (rc.Contains (Event.current.mousePosition)                           && Event.current.button == 0                          && GUIUtility.hotControl == 0)                          {                                 GUIUtility.hotControl = controlID;                                 state.MouseDownNow();                         }                         break;                 }                 case EventType.MouseUp:                 {                         if (GUIUtility.hotControl == controlID)                                 GUIUtility.hotControl = 0;                         break;                 }         }          return GUIUtility.hotControl == controlID; } 

Всё предельно просто. Обратите внимание, что фрагменты кода для ответа на mouseDown и mouseUp очень похожи на те, которые мы использовали ранее для обработки захвата ползунка в полосе прокрутки. Единственные различия – вызов state.MouseDownNow() при нажатии кнопки мыши, а также изменение значения GUI.color при перерисовке кнопки.

Возможно, вы заметили еще одно различие, связанное с событием перерисовки, а именно вызов style.Draw(). Об этом стоит поговорить подробнее.

Стили графического интерфейса

При создании нашего первого элемента мы использовали GUI.DrawTexture для отрисовки самого слайдера. Но с элементом FlashingButton всё не так просто – кнопка должна включать в себя не только изображение в виде закругленного прямоугольника, но и надпись. Мы могли бы попытаться нарисовать кнопку с помощью GUI.DrawTexture и поместить поверх нее GUI.Label, но есть способ получше. Попробуем воспользоваться техникой отрисовки изображения GUI.Label, не используя сам GUI.Label.

Класс GUIStyle содержит данные о визуальных свойствах элемента интерфейса: от шрифта и цвета текста до интервалов между элементами. Кроме того, в GUIStyle хранятся функции, используемые для определения ширины и высоты объектов с помощью стиля, а также для непосредственной отрисовки элементов на экране.

GUIStyle может включать в себя разные стили отрисовки элемента: когда на него наведен курсор, когда он получил фокус ввода с клавиатуры, когда он отключен или когда активен (при зажатой кнопке мыши). Для любого состояния можно определить цвет и фоновое изображение, и GUIStyle подставит их при отрисовке элемента, исходя из его control ID.

Существует 4 способа применения GUIStyles для отрисовки элементов интерфейса:

• Написать новый стиль (new GUIStyle()), задав необходимые значения.
• Использовать один из встроенных стилей класса EditorStyles (если вы хотите, чтобы ваши пользовательские элементы выглядели как стандартные).
• Если вам нужно слегка изменить существующий стиль, например выровнять текст кнопки по правому краю. Вы можете скопировать нужный стиль класса EditorStyles и изменить нужное свойство вручную.
• Извлечь стиль из GUISkin.

GUISkin – это большая коллекция объектов GUIStyle, которую можно создать в самом проекте в виде отдельного ресурса и редактировать с помощью Unity Inspector. Создав новый GUISkin и открыв его, вы увидите слоты для всех стандартных элементов интерфейса: кнопок, текстовых окон, переключателей и т. д. Но особенный интерес представляет раздел пользовательских стилей. Сюда можно поместить любое количество объектов GUIStyle с уникальными именами, которые можно будет извлекать с помощью метода GUISkin.GetStyle(“имя_стиля”). Осталось выяснить, как загружать объекты GUISkin из кода. Для этого есть несколько способов. Если объект лежит в папке Editor Default Resources, используйте функцию EditorGUIUtility.LoadRequired(); для загрузки из другой директории используйте AssetDatabase.LoadAssetAtPath(). Главное – ни в коем случае не помещайте ресурсы, предназначенные только для редактора, в пакеты ресурсов или в папку Resources.

Теперь, когда у нас есть GUIStyle, можно отрисовать GUIContent, содержащий нужный текст, изображение и подсказку, с помощью GUIStyle.Draw(). В качестве аргументов используются координаты прямоугольника, в котором выполняется отрисовка, сам GUIContent и идентификатор управляющего элемента.

Разметка IMGUI

Возможно, вы заметили, что каждый из рассмотренных нами элементов интерфейса имел параметр Rect, определяющий его положение на экране. Вместе с тем, мы только что говорили о том, что GUIStyle включает в себя свойства разметки. Напрашивается вопрос: неужели нужно вручную высчитывать все значения Rect с учетом особенностей разметки? В принципе, можно. Но IMGUI предлагает более простое решение – механизм разметки, который делает это автоматически.

Для этого существует особый тип событий – EventType.Layout. После того, как IMGUI посылает такое событие интерфейсу, его элементы вызывают функции разметки: GUILayoutUtility.GetRect(), GUILayout.BeginHorizontal / Vertical, и GUILayout.EndHorizontal / Vertical и другие. IMGUI запоминает результаты этих вызовов в виде дерева, которое содержит все элементы интерфейса и необходимое для них пространство. После построения дерева проводится его рекурсивный обход, во время которого вычисляются размеры элементов и их положение относительно друг друга.

При запуске любого другого события, например EventType.Repaint, элементы снова вызывают функции разметки. Но на этот раз IMGUI повторяет «записанные» вызовы и возвращает готовые прямоугольники. Другими словами, если во время события Layout параметры прямоугольников уже были вычислены с помощью функции GUILayoutUtility.GetRect(), при запуске другого события она просто подставит сохраненный ранее результат.

По аналогии с идентификаторами управляющих элементов при выполнении события Layout и других событий важно соблюдать порядок вызовов функций разметки, чтобы элементы не получили данные чужих прямоугольников. Также стоит учитывать, что значения, возвращаемые вызовом GUILayoutUtility.GetRect() во время события Layout, бесполезны, так как IMGUI не будет знать, какому элементу соответствует каждый прямоугольник вплоть до окончания события и обработки дерева.

Итак, давайте добавим разметку для нашей полосы с ползунком. Это несложно: получив квадрат от IMGUI, мы можем вызвать уже готовый код:

public static float MyCustomSlider(float value, GUIStyle style) { 	Rect position = GUILayoutUtility.GetRect(GUIContent.none, style); 	return MyCustomSlider(position, value, style); } 

В случае вызова GUILayoutUtility.GetRect во время события Layout IMGUI запоминает, что определенный стиль нужен для пустого контента (пустого, потому что для него не указаны изображение или текст). Во время других событий GetRect возвращает существующий прямоугольник. Получается, что во время события Layout наш элемент MyCustomSlider будет вызываться с неправильным прямоугольником, но это неважно, поскольку без него мы все равно не сможем вызывать GetControlID().

Все данные, на основе которых IMGUI определяет размер прямоугольника, содержатся в стиле. Но что если пользователь захочет задать один или несколько параметров вручную?

Для этого используется класс GUILayoutOption. Объекты этого класса – своего рода инструкции для системы разметок, указывающие, как именно должен рассчитываться прямоугольник (например, иметь определенное значение высоты/ширины или заполнять доступное пространство по вертикали/горизонтали). Для создания такого объекта нужно вызвать фабричные функции класса GUILayout, такие как GUILayout.ExpandWidth() или GUILayout.MinHeight(), и передать их в GUILayoutUtility.GetRect() в виде массива. Затем они сохраняются в дереве разметок и учитываются при его обработке.

Вместо того чтобы создавать собственные массивы из объектов GUILayoutOption, мы воспользуемся ключевым словом C# params, которое позволяет вызвать метод c любым количеством параметров, из которых автоматически составляется массив. Вот так выглядит новая функция нашей полосы:

public static float MyCustomSlider(float value, GUIStyle style, params GUILayoutOption[] opts) { 	Rect position = GUILayoutUtility.GetRect(GUIContent.none, style, opts); 	return MyCustomSlider(position, value, style); } 

Как вы видите, все данные, введенные пользователем, передаются прямиком к GetRect.

Подобный метод совмещения функции элемента IMGUI с версией этой же функции, использующей автоматическое размещение по разметке, применим для любого элемента IMGUI, включая встроенные в класс GUI. Получается, что класс GUILayout предоставляет размещенные версии элементов из класса GUI (а мы используем класс EditorGUILayout, соответствующий EditorGUI).

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

Обратите внимание, что при написании PropertyDrawers не рекомендуется использовать разметку, вместо этого лучше использовать прямоугольник, передаваемый перегрузке PropertyDrawer.OnGUI(). Дело в том, что сам класс Editor не использует разметку, а вычисляет простой прямоугольник, который сдвигается вниз для каждого следующего свойства. Поэтому, если для PropertyDrawer используется разметка, Editor не будет знать о предыдущих свойствах и, следовательно, разместит прямоугольник неправильно.

Использование сериализованных свойств

Итак, вы уже можете создать собственный элемент IMGUI. Осталось обсудить пару моментов, которые помогут привести его к стандарту качества Unity.

Во-первых, это использование SerializedProperty. Мы поговорим о системе сериализации более подробно в следующей статье, а пока обобщим: интерфейс SerializedProperty позволяет получить доступ к любому свойству, к которому подключена система сериализации (загрузки и сохранения) Unity. Таким образом, мы можем использовать любую переменную из скриптов или объектов, отображаемых в Unity Inspector.
SerializedProperty предоставляет доступ не только к значению переменной, но и к разного рода информации, например, сравнение текущего и изначального значения переменной или состояние переменной с дочерними полями в окне Inspector (свернута/развернута). Кроме того, интерфейс интегрирует любые пользовательские изменения значения переменной в системы Undo и scene-dirtying. При этом не используется управляемая версия объекта, что положительно сказывается на производительности. Поэтому использование SerializedProperty необходимо для полноценного функционирования любых сложных элементов интерфейса.

Сигнатура методов класса EditorGUI, получающих объекты SerializedProperty в качестве аргументов, несколько отличается от обычной. Такие методы ничего не возвращают, потому что изменения вносятся напрямую в SerializedProperty. Улучшенная версия нашей полосы будет выглядеть так:

public static void MyCustomSlider(Rect controlRect, SerializedProperty prop, GUIStyle style) 

Теперь у нас нет параметра value, вместо него в SerializedProperty передается параметр prop. С помощью prop.floatValue мы можем извлекать значение плавающего числа при отрисовке полосы и изменять его при перетаскивании ползунка.

Существуют и другие преимущества использования SerializedProperty в коде IMGUI. Допустим, значение prefabOverride показывает изменения значения свойства в шаблонном объекте. По умолчанию измененные свойства выделяются жирным шрифтом, но мы можем установить другой стиль отображения с помощью GUIStyle.

Еще одна немаловажная возможность – редактирование множественных объектов, то есть отображение сразу нескольких значений с помощью одного элемента. Если для значения EditorGUI.showMixedValue установлено TRUE, элемент используется для отображения нескольких значений.
Использование механизмов prefabOverride и showMixedValue требует установки контекста для свойства с помощью EditorGUI.BeginProperty() и EditorGUI.EndProperty(). Как правило, если метод элемента принимает аргумент класса SerializedProperty, он должен сам вызывать BeginProperty и EndProperty. Если же он принимает «чистые» значения (например, метод EditorGUI.IntField, который принимает int и не работает со свойствами), вызовы BeginProperty и EndProperty должны содержаться в коде, вызывающем этот метод.

public class MySliderDrawer : PropertyDrawer {     public override float GetPropertyHeight (SerializedProperty property, GUIContent label)     {         return EditorGUIUtility.singleLineHeight;     }      private GUISkin _sliderSkin;      public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)     {         if (_sliderSkin == null)             _sliderSkin = (GUISkin)EditorGUIUtility.LoadRequired ("MyCustomSlider Skin");          MyCustomSlider (position, property, _sliderSkin.GetStyle ("MyCustomSlider"), label);              } }  // Then, the updated definition of MyCustomSlider: public static void MyCustomSlider(Rect controlRect, SerializedProperty prop, GUIStyle style, GUIContent label) {     label = EditorGUI.BeginProperty (controlRect, label, prop);     controlRect = EditorGUI.PrefixLabel (controlRect, label);      // Use our previous definition of MyCustomSlider, which we’ve updated to do something     // sensible if EditorGUI.showMixedValue is true     EditorGUI.BeginChangeCheck();     float newValue = MyCustomSlider(controlRect, prop.floatValue, style);     if(EditorGUI.EndChangeCheck())         prop.floatValue = newValue;      EditorGUI.EndProperty (); } 

Заключение

Надеюсь, эта статья поможет вам разобраться в основах IMGUI. Чтобы стать настоящим профессионалом, вам предстоит освоить много других аспектов: систему SerializedObject/SerializedProperty, особенности работы с CustomEditor/EditorWindow/PropertyDrawer, использование класса Undo и т. д. Так или иначе, IMGUI позволяет раскрыть широчайший потенциал Unity по созданию пользовательских инструментов для продажи на Asset Store или личного использования.

ссылка на оригинал статьи https://habrahabr.ru/post/278213/

Alljoyn: взгляд embedded разработчика. Часть 1: знакомство

Не сочтите за расовые предрассудки, но в сегодняшней статье понятие «embedded разработка» будет означать разработку и программирование устройств на микроконтроллерах с использованием языка Си, безо всяких процессоров, Linux’ов, Windows’ов, Pyton’ов и прочего «не хардкора». Я намеренно сделал эту оговорку в самом начале, чтобы не пришлось постоянно акцентировать внимание на этом в дальнейшем.

Alljoyn — это протокол взаимодействия между устройствами разрабатываемый альянсом Allseen. В отличии от распространенных ныне протоколов промавтоматики (ModBus, KNX, BacNET и пр.) Alljoyn изначально рассчитан на применение в бытовых устройствах, т.е. тот самый пресловутый Интернет вещей. Причем Alljoyn претендует на статус глобального мирового стандарта и если взглянуть на список комнаний-участников альянса, вполне можно допустить, что его амбиции не безосновательны.
Сегодня мы попытаемся заглянуть за ширму маркетинговых заявлений об «универсальности, кросплатформенности и простоте использования» и понять что же за зверя пытается изобрести группа самых известных IT компаний со всего мира.

Итак, Alljoyn — это фреймворк с открытыми исходными кодами и документацией. Его идея изначально зародилась в компании Qualcomm и со временем переросла в крупный альянс. Физическим транспортом, в теории может служить любая среда передачи данных, при условии, что в качестве транспорта используется стек TCP/IPv4 или TCP/IPv6. Но в реальности, на данный момент используются только локальные сети (ethernet и Wi-Fi). Заявлена поддержка всех основных платформ: Linux, Windows, IOS, Android, а так же возможность портирования на микроконтроллеры.

Разработчиков железа такой подход привлекает тем, что в теории им не нужно заниматься написанием приложений под телефоны и компьютеры для управления исполнительными устройствами — железячник делает устройство и пишет для него прошивку, а различные красивые приложения для айфончика рисуют специально обученные люди. Многие скажут, что подобные попытки создать стандартизированный протокол уже принимались неоднократно, мне лично тут же вспоминается непростая судьба ZigBee. Тут можно только ждать и надеяться, что на этот раз всё удастся.

Топология


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

  • APP — блок, реализующий бизнес-логику. Это может быть физическое устройство (такое как лампочка, кондиционер или телевизор), предоставляющее свои интерфейсы управления в Alljoyn шину. Так же это может быть приложение на смартфоне или компьютерная программа, которая преобразовывает Alljoyn-интерфейсы в визуальные интерфейсы пользователя (проще говоря, это приложение на телефоне, с помощью которого мы управляем Alljoyn-устройствами). Причем, APP никогда не взаимодействуют друг с другом напрямую, это взаимодействие всегда происходит через Router.
  • Router — блок, реализующий взаимодействие между APPs и шиной Alljoyn. Может находиться как одном физическом устройстве с APP, так и на различных.

Теперь постепенно подбираемся к Embedded части. Есть 2 варианта исполнения фреймворка:

  • Standard Core — вариант предназначенный для использования в устройствах с операционными системами (смартфоны, компьютеры, телевизоры и пр.)
  • Thin Core — версия фреймворка на «чистом» Си для применения во встраиваемых приложениях (а именно в микроконтроллерах).

В рамках данного цикла нас в основном будет интересовать облегченная версия Thin. Так вот в состав Thin-устройства никогда не входит Router. Самым простым примером такого Thin-устройства является «умная лампочка» с Wi-Fi. и реализованным в ней протоколом AllJoyn.
Таким образом, для того чтобы управлять нашей «лампочкой» в сети должен быть хотя бы один роутер, а так как в «лампочке», в соответствии с идеологией AllJoyn, он находиться не может, выходит, что должно существовать отдельное физическое устройство, в котором реализован блок Router. Внимательный читатель, возразит: пусть Router (раз уж это просто отдельный процесс в операционке) будет находиться в телефоне, с которого мы запускаем приложение для управления «лампочкой». Да, в частном случае такой вариант будет работать. Но только в частном.
Во-первых, в телефоне может оказаться «неправильный» Router, который делает «неправильный мёд» и предоставляет услуги роутинга только для APP, находящихся внутри телефона.

На рисунке слева «правильный» Router получает презентационные данные от всех APP вокруг, включая 2 «лампочки» и начинает их презентовать в окружающую сеть и внутрь себя. В результате получаем возможность управлять «лампочками».
На рисунке справа, Router отказывается презентовать «лампочки», он, по задумке разработчика, служит лишь для вывода «наружу» своих блоков APP. Подчеркну, что термин «неправильный» не подразумевает неверное функционирование (разработчик намеренно не наделяет Router подобными функциями), а лишь показывает невозможность непосредственной работы с «лампочками».

Про Windows 10 и AllJoyn

Microsoft является одним из главных членов Альянса и судя по всему делает определенную ставку на AllJoyn. Так, тут на хабре уже была статья по этому поводу. Цитата из указанной статьи:

в Windows 10 включена полная поддержка данного протокола, а именно:
Во-первых, вам не нужно заботиться об AllJoyn-роутере, описанном выше, так как Windows 10 включает специальный сервис AllJoyn Router Service, который может использоваться как вашими приложениями, так и другими устройствами в сети.


К сожалению, в Windows как раз тот самый «неправильный» Router. Он решает главную поставленную перед ним задачу — убрать необходимость написания блока Router в своих приложениях, но не выполняет маршрутизацию сторонних Thin устройств.

Теперь мы можем представить структуру сети, при которой мы получим работающую систему в любом случае, следующим образом:

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

Общие принципы взаимодействия в сети

Каждое AllJoyn устройство обладает некоторым набором интерфейсов. Это может быть один из базовых наборов, несколько базовых наборов, это может быть фиксированный набор одного из профилей или собственные интерфейсы, которые необходимы именно этому устройству.
Каждое устройство умеет объявлять о своих интерфейсах в сети (это происходит автоматически). Если другое устройство «заинтересовалось» одним из объявленных интерфейсов, то оно «спрашивает подробности».
Кроме интерфейсов каждое устройство может генерировать события и выполнять действия, инициированные другими устройствами по сети.
Технически самое первое объявление о себе в сеть выполняется одним из трех способов:

  • Broadcast сообщения в порт 9956 (устаревший способ, использовавшийся в ранних версиях)
  • Multicast сообщения AllJoyn (адрес 224.0.0.113, порт 9956)
  • Multicast сообщения mDNS (адрес 224.0.0.251, порт 5353)

Допускается использовать как одного из способов, так и сразу несколько.
Внутри этих посылок запаковывается информация о TCP-соединении (IP-адрес и порт) по которому необходимо будет подключиться для последующего взаимодействия. Таким образом, UDP используется только для знакомства и обмена первичной информацией, а в последствии работа идет через TCP-сокет. Объявление «своих» интерфейсов происходит уже по TCP. Официально за AllJoyn зарегистрирован порт 9955 для TCP соединения, но данное правило не является обязательным, так как информация о реальном порте передается при «знакомстве». Однако, я рекомендую использовать именно 9955, так как в WireShark именно этот порт зарезервирован для AllJoyn, и WireShark парсит пакет и разбивает его на отдельные поля в очень удобной форме, что существенно упрощает жизнь на этапе отладки.

События и действия

События и действия – это базовый механизм, который облегчает взаимодействие между приложениями и устройствами alljoyn. Этот механизм позволяет приложениям и устройствам посылать события в сеть, которые будут видеть все остальные устройства сети. Похожим образом приложения и устройства могут «рассказывать» о действиях, которые они могут осуществлять по команде других устройств. Например, датчик движения может посылать событие, если кто-то проходит мимо, а лампочка выполнять по команде извне действие включения. Возможность обнаружения этих событий и действий, позволяет создавать приложение, которое включает свет при срабатывании датчика. Этот простой механизм обнаружения действий и событий позволяет приложениям создавать динамические реакции на события.
Самый простой пример этого механизма — обратная связь: у нас есть 1 лампочка и 2 телефона, которые ей управляют. С первого телефона выключаем лампочку, и на экране второго тут же видим что лампочка выключена.

Проект «Освещение»

Allseen альянс поддерживает и развивает свой протокол. Одним из способов развития являются «рабочие группы», в которых реализуются различные проекты, например, по профилям устройств.
Проект Освещение разрабатывает библиотеку сервисов освещения Lighting Service Framework (LSF), которая реализует открытый и общедоступный способ взаимодействия с устройствами освещения на базе AllJoyn вне зависимости от производителя. Этот проект позволяет производителям устройств освещения создавать устройства, которые могут взаимодействовать друг с другом и с другими устройствами сети AllJoyn, а разработчикам приложений предоставляется API для общения с устройствами освещения от любого производителя.

Особенности LSF включают в себя реализацию в виде открытого кода следующих возможностей:

  • Управление состоянием отдельной лампы: включение/выключение, оттенком, насыщенностью, яркостью и температурой цвета
  • Управление группами ламп, включая создание, присвоение имен, удаление групп и управление группой как будто это одна лампа
  • Сохранение настроек освещения, называемое пресет, позволяя конкретному состоянию лампы быть сохраненным для будущего использования
  • Применение эффектов, например, пульсации или перехода из одного состояния в другое в течение некоторого времени
  • Создание сцен освещения, включающих в себя отдельные лампы или группы ламп, и необходимые пресеты и эффекты, которые могут быть установлены для создания настроения и атмосферы

Именно на этот профиль мы обратим свой взор в следующей части цикла, когда займемся практической реализацией «умной» лампочки на связке микроконтроллера SAMD21 (Cortex M0) и Wi-Fi модуля WINC1500.

Что есть на данный момент

На сайте альянса есть страница Product Showcase, на которой публикуется список существующего оборудования. Насколько этот список полон и актуален можно только догадываться. Для глобального мирового стандарта, список весьма скромен, но все-таки альянс находится лишь в начале своего пути. Присутствуют тут и различные «умные» лампочки, розетки и т.п. Но если присмотреться к ним на сайтах производителей, то увидим, что AllJoyn реализован как альтернативный протокол в дополнение к своему проприетарному. Одна из причин этого — практически полное отсутствие реальных мобильных приложений для AllJoyn.

DashBoard 14.12. На момент написания данной статьи, по неведомым мне причинам, это приложение было удалено Play Маркета для Android. Приложение представляет собой панель управления для различных AllJoyn устройств.

LSF Sample App. Приложение для Android, реализующее панель управления для лампочек, поддерживающих профиль LSF. На данный момент его можно скачать только в виде apk-файла или исходных кодов с сайта альянса.

Luminaire. Приложение, имитирующее на экране телефона AllJoyn «умную» лампочку. Использует Thin вариант библиотеки. Отличная вещь для отладки, эта лампочка определяется предыдущим приложение (LSF) как реальная лампочка. К тому же в состав Luminaire включен «Правильный» Router, чьими услугами мы воспользуемся в последствии, когда будем делать «умную лампочку в железе».

ссылка на оригинал статьи https://habrahabr.ru/post/273859/

Польза от девальвации? Российские компании переносят сборку электроники из Азии в Россию

Многие могли заметить, что в последнее время курс рубля к доллару несколько изменился в сторону обвала. Обесценивание собственной валюты — одна из эффективных мер стимулирования экономики во время рецессии. Уменьшается импорт, что стимулирует отечественных производителей. Снижаются зарплаты у населения (в долларовом выражении), это уменьшает себестоимость отечественной продукции и делает её более конкурентоспособной.

Пользу из девальвации рубля извлекли российские производители электроники, пишут «Ведомости».

Например, компания «Датакам» (производит автомобильные видеорегистраторы, рации и др.) перенесла часть сборочного производства с Тайваня в Москву. За счёт экономии на ввозных таможенных пошлинах, сокращения логистических расходов и более низких зарплат работников в целом себестоимость собранных в России регистраторов для «Датакама» на 20% ниже, чем на Тайване, сказал владелец компании Владислав Механцев. Он добавил, что затраты на оплату труда в расчёте на одного работника здесь втрое ниже, чем на Тайване.

Гибкость ассортимента и выпуск товаров малыми партиями — ещё одно преимущество местной сборки. Локализация производства позволила расширить модельный ряд устройств и разработать новые модели раций. Менее чем за год после переноса сборки в Россию уровень брака снизился с 3 до 0,5%, а производительность труда российских сборщиков оказалась в 2,5 раза выше, сказал владелец компании. Печатные платы для раций «Датакама» теперь делают в Екатеринбурге, полимерные аккумуляторы – в Липецке.

Ещё один производитель, который извлёк выгоду из девальвации, — компания «Вокорд», разработчик систем видеонаблюдения и распознавания лиц, пишут «Ведомости». Гендиректор компании Тимур Векилов уверяет, что по качеству продукция российских сборщиков не уступает зарубежным аналогам, но заметно дешевле: «Конечно, есть комплектующие, которые в России не производятся, и мы вынуждены заказывать их за рубежом. Но их доля в себестоимости нашей продукции всегда была незначительна и, судя по всему, будет сокращаться». Он говорит, что раньше затраты на производство оборудования в России и за рубежом были примерно одинаковы, а сейчас собирать в России зачастую оказывается дешевле.

Для компании GS Group (владеет предприятиями по производству электроники в Калининградской области) пару лет назад сборка электроники в Китае обходилась гораздо дешевле, чем в России. Но из-за падения рубля подготовка пресс-форм и смежные процессы для сборки электроники в Азии подорожали для российских B-брендов почти в два раза. Поэтому размещение сборочного производства в России для них стало гораздо привлекательнее.

Президент группы компаний «Аквариус» Александр Калинин считает, что благодаря девальвации доходы российских сборщиков вырастут до 15%.

GS Nanotech (в составе «Технополиса GS») начинала со сборки микросхем оперативной памяти, а теперь разработала и производит собственный процессор SiP Amber S2. Kraftway выпускает на заводе в Обнинске материнские платы собственной разработки, планшеты, серверы, оборудование связи и другое оборудование на своих материнских платах.

Получается, благодаря кризису в России наконец-то начали выпускать современную электронику.

ссылка на оригинал статьи https://geektimes.ru/post/271830/

Kaspersky Security Center — борьба за автоматизацию

Как это ни странно, я нашёл на Хабре всего одну статью по данной тематике — и ту в песочнице и сильно незаконченную фактически содержащую в себе маленький кусочек чуть переделанной справки по продукту. Да и Google по запросу klakaut молчит.

Я не собираюсь рассказывать, как администрировать иерархию Kaspersky Security Center (далее по тексту KSC) из командной строки — мне это пока не понадобилось ни разу. Просто хочу поделиться некоторыми соображениями по поводу средств автоматизации с теми, кому это может понадобиться, и разберу один кейс, с которым мне пришлось столкнуться. Если тебе, %habrauser%, эта тема будет интересной — добро пожаловать под кат.

Исторически сложилось так, что в качестве средства антивирусной защиты на работе я предпочитаю продукты Лаборатории Касперского (далее ЛК). Причины и прочие священные войны личных мнений, пожалуй, оставим за кадром.

Естественно, хотелось бы централизованно развернуть, защитить, оградить и не пущать рисовать красивые графики, интегрироваться в существующие системы мониторинга и заниматься прочим перекладыванием работы с больной головы на здоровый сервер. И если с развёртыванием и защитой тут всё более или менее в порядке (у ЛК даже есть какие-то онлайн-курсы по продуктам), то с интеграцией уже сильно грустнее: в последней на текущий момент версии KSC 10.2.434 появилась интеграция аж с двумя SIEM: Arcsight и Qradar. На этом всё.

Для интеграции в что-то своё KSC предоставляет аж 2 интерфейса:

  • klakdb: в БД KSC есть ряд представлений с именами, начинающимися на «v_akpub_», из которых можно достать какую-то информацию о состоянии антивирусной защиты.
  • klakaut: DCOM-объект, позволяющий скриптовать работу с KSC.

По обоим пунктам есть документация в составе KSC, как это и указано в статьях, на которые я дал ссылки. Правда, документация эта вызывает ряд вопросов, которые можно задать в службу поддержки корпоративных продуктов CompanyAccount и получить ответ вида «Уточнили информацию. К сожалению, поддержка по скриптам для klakaut не оказывается.».

Минусы klakdb очевидны: чтобы напрямую обратиться к БД, нужно иметь к этой БД доступ, что приводит к необходимости лишних телодвижений по созданию правил доступа в межсетевых экранах, настройке прав доступа на серверах СУБД и прочему крайне неувлекательному времяпрепровождению. Ну и плюс мониторинг актуальности всех этих правил, естественно. Особенно интересно становится, когда имеется 20+ серверов — и все в разных филиалах, в каждом из которых свои администраторы.

Ну и вишенки на этом торте: доступ исключительно Read Only и, мягко говоря, неполная информация о среде. Плюсы не столь очевидны, но тоже есть: можно очень быстро выгрузить по одному серверу статистическую информацию по количеству хостов, используемым версиям антивирусов и антивирусных баз, а главное — можно весьма удобно (удобство зависит от знания SQL) работать с зарегистрированными на KSC событиями антивирусной инфраструктуры.

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

Минусы тоже есть, естественно: долго и сложно. Если нужно собрать какую-то статистику — нужно будет сначала долго писать скрипт, а потом долго ловить баги ждать, когда он отработает.

Естественно, никто не запрещает (по крайней мере, мне про это неизвестно) использовать оба механизма вместе: например, пройтись по иерархии серверов с помощью klakaut, получить полный список серверов KSC с информацией об используемых БД, а потом уже передать эту информацию в более другие средства автоматизации, которые удалят устаревшие правила из сетевых экранов, создадут новые, дадут разрешения на доступ и принесут кофе в постель отредактируют список источников данных в вашей системе мониторинга, которая, в свою очередь, опросит список и, обнаружив какие-нибудь девиации, с помощью klakaut сделает что-нибудь хорошее. Ну, или просто зарегистрирует инцидент в трекере. Тогда что-нибудь хорошее сделают администраторы в ручном режиме.

Воодушевлённый всеми этими соображениями, я написал свой первый скрипт:

Вот он

 $Params = New-Object -ComObject 'klakaut.KlAkParams'; $Params.Add('Address', 'localhost:13000'); $Params.Add('UseSSL', $true);  $Proxy = New-Object -ComObject 'klakaut.KlAkProxy'; try {     $Proxy.Connect($Params);     $Proxy.Disconnect(); } catch {     $_; }  Remove-Variable -Name 'Params'; Remove-Variable -Name 'Proxy'; 

И запустил его на сервере:

 Exception calling "Connect" with "1" argument(s): "Transport level error while connecting to http://localhost:13000: authentication failure" At line:7 char:5 +     $Proxy.Connect($Params); +     ~~~~~~~~~~~~~~~~~~~~~~~     + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException     + FullyQualifiedErrorId : ComMethodTargetInvocation 


Начало хорошее.

Хозяйке на заметку

Если использовать js, эта ошибка не возникает. Интересно, почему.

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

К сожалению, KSC не логирует неудачные попытки входа. Переписка с вендором показала, что логирование неудачных попыток входа можно включить (это была отдельная увлекательная история, которая, кстати, ещё не закончилась), однако данная конкретная попытка в логи всё равно попадать отказалась.

Казалось бы, можно сделать вот так:

Неправильный скрипт

 $Params = New-Object -ComObject 'klakaut.KlAkParams'; $Params.Add('Address', 'localhost:13000'); $Params.Add('UseSSL', $true);  #------------ Зададим в явном виде данные для входа -------------------------------- $Params.Add('User', 'kavadmin'); $Params.Add('Password', 'P@ssw0rd'); $Params.Add('Domain', 'test'); #-----------------------------------------------------------------------------------  $Proxy = New-Object -ComObject 'klakaut.KlAkProxy'; try {     $Proxy.Connect($Params);     $Proxy.Disconnect(); }  Remove-Variable -Name 'Params'; Remove-Variable -Name 'Proxy'; 

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

Необходимо выставить в настройках COM, на вкладке Default Properties:
Default Authentication Level: Packet
Default Impersonation Level: Delegate

Эта инструкция заставила работать исходный скрипт, но показалась мне сомнительной в плане безопасности, поэтому я решил покопать чуть глубже. После некоторого времени поисков нашёлся добрый человек, который подсказал мне, как задать указанные уровни проверки подлинности и олицетворения для конкретного объекта, а не разрешать всем и всё сразу:

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

 $Params = New-Object -ComObject 'klakaut.KlAkParams'; $Params.Add('Address', 'localhost:13000'); $Params.Add('UseSSL', $true);  $Proxy = New-Object -ComObject 'klakaut.KlAkProxy';  $code =  @" using System; using System.Runtime.InteropServices;  public class PowershellComSecurity {    [DllImport("Ole32.dll", CharSet = CharSet.Auto)]    public static extern int CoSetProxyBlanket(IntPtr p0, uint p1, uint p2, uint p3, uint p4, uint p5, IntPtr p6, uint p7);     public static int EnableImpersonation(object objDCOM) { return CoSetProxyBlanket(Marshal.GetIDispatchForObject(objDCOM), 10, 0, 0, 0, 3, IntPtr.Zero, 0); } } "@ Add-Type -TypeDefinition $code; Remove-Variable -Name 'code';  [PowershellComSecurity]::EnableImpersonation($Proxy) | Out-Null;  try {     $Proxy.Connect($Params);     # <-- Вот сюда мы будем вставлять код     $Proxy.Disconnect(); } catch {     $_; }  Remove-Variable -Name 'Params'; Remove-Variable -Name 'Proxy'; 

Вот так скрипт никаких ошибок выдавать не стал. Первый квест пройден.

Хозяйке на заметку

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

Следующая задача: получить от KSC данные об используемой БД.

А вот тут всё сложно: документация о том, как это сделать, молчит. Исследование класса KlAkProxy ничего интересного не выявило, кроме параметра KLADMSRV_SERVER_HOSTNAME, который оказался идентификатором компьютера, на котором установлен KSC.

Перейдём тогда к компьютеру, для этого есть специальный класс KlAkHosts2. Для сокращения количества кода приведу только содержимое блока try:

блок try

 try {     $Proxy.Connect($Params);     $KSCHost = New-Object -ComObject 'klakaut.KlAkHosts2';     $KSCHost.AdmServer = $Proxy;     $HostParams = New-Object -ComObject 'klakaut.KlAkCollection';     $HostParams.SetSize(1);     $HostParams.SetAt(0, 'KLHST_WKS_DN');     ($KSCHost.GetHostInfo($Proxy.GetProp('KLADMSRV_SERVER_HOSTNAME'), $HostParams)).Item('KLHST_WKS_DN');     Remove-Variable -Name 'HostParams';     Remove-Variable -Name 'KSCHost';     $Proxy.Disconnect(); } 

Обратите внимание: переменная $Params, которую я использовал при подключении к KSC — экземпляр класса KlAkParams. А переменная $HostParams при, на мой взгляд, аналогичной функциональности, является экземпляром класса KlAkCollection. Почему используются разные классы — боюсь даже представить. Видимо, то, что SetAt принимает первым аргументом только целочисленные значения — очень принципиальный момент.

Данный код вернул значение «KSC», а значит, я на верном пути.

Метод GetHostInfo класса KlAkHosts2 достаточно хорошо задокументирован, но — не содержит нужной мне информации. Увы и ах. Зато есть метод GetHostSettings. Всё описание для которого сводится к следующему:

Returns host’s settings as setting storage.

Давайте, заглянем внутрь:

try

 try {     $Proxy.Connect($Params);     $KSCHost = New-Object -ComObject 'klakaut.KlAkHosts2';     $KSCHost.AdmServer = $Proxy;     $KSCSettings = $KSCHost.GetHostSettings($Proxy.GetProp('KLADMSRV_SERVER_HOSTNAME'), 'SS_SETTINGS');     $KSCSettings.Enum() | % {         '------------------------';         $tmp = $_;         $tmp | % {"$_ = $($tmp.Item($_))";};         Remove-Variable -Name 'tmp';     };     Remove-Variable -Name 'KSCSettings';     Remove-Variable -Name 'KSCHost';     $Proxy.Disconnect(); } 

Результат

 ------------------------ PRODUCT = .core SECTION = SubscriptionData VERSION = .independent ------------------------ PRODUCT = 1093 SECTION = 85 VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = 87 VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KLEVP_NF_SECTION VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KLNAG_SECTION_DPNS VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KLSRV_CONSRVINIT VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KLSRV_CONSRVUPGRADE VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KLSRV_DEF_NAGENT_PACKAGE VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KLSRV_MASTER_SRV VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KLSRV_NETSIZE_SECTION VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KLSRV_PKG_ANDROID_CERT_SECTION VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KLSRV_PROXY_SECTION VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KLSRV_SRVLIC_SECTION VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KLSRV_USER_ACCOUNTS_SECTION VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KSNPROXY_KEY_STORAGE VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = KSNPROXY_SETTINGS VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = Packages VERSION = 1.0.0.0 ------------------------ PRODUCT = 1093 SECTION = Updater VERSION = 1.0.0.0 ------------------------ PRODUCT = 1103 SECTION = 85 VERSION = 1.0.0.0 ------------------------ PRODUCT = 1103 SECTION = 86 VERSION = 1.0.0.0 ------------------------ PRODUCT = 1103 SECTION = FileTransfer VERSION = 1.0.0.0 ------------------------ PRODUCT = 1103 SECTION = KLEVP_NF_SECTION VERSION = 1.0.0.0 ------------------------ PRODUCT = 1103 SECTION = KLNAG_KLNLA_DATA VERSION = 1.0.0.0 ------------------------ PRODUCT = 1103 SECTION = KLNAG_SECTION_NETSCAN VERSION = 1.0.0.0 ------------------------ PRODUCT = 1103 SECTION = KLNAG_SECTION_SERVERDATA VERSION = 1.0.0.0 ------------------------ PRODUCT = 1103 SECTION = Updater VERSION = 1.0.0.0 ------------------------ PRODUCT = KAVFSEE SECTION = .KLNAG_SECTION_REBOOT_REQUEST VERSION = 8.0.0.0 ------------------------ PRODUCT = KAVFSEE SECTION = 85 VERSION = 8.0.0.0 ------------------------ PRODUCT = KAVFSEE SECTION = Backup section VERSION = 8.0.0.0 ------------------------ PRODUCT = KAVFSEE SECTION = Business logic section VERSION = 8.0.0.0 ------------------------ PRODUCT = KAVFSEE SECTION = HSM system section VERSION = 8.0.0.0 ------------------------ PRODUCT = KAVFSEE SECTION = Internal product info VERSION = 8.0.0.0 ------------------------ PRODUCT = KAVFSEE SECTION = KLEVP_NF_SECTION VERSION = 8.0.0.0 ------------------------ PRODUCT = KAVFSEE SECTION = Notification section VERSION = 8.0.0.0 ------------------------ PRODUCT = KAVFSEE SECTION = Predefined tasks section VERSION = 8.0.0.0 ------------------------ PRODUCT = KAVFSEE SECTION = Quarantine section VERSION = 8.0.0.0 ------------------------ PRODUCT = KAVFSEE SECTION = Reporting section VERSION = 8.0.0.0 ------------------------ PRODUCT = KAVFSEE SECTION = Trusted processes section VERSION = 8.0.0.0 

В klakaut.chm есть раздел «List of KLHST_WKS_PRODUCT_NAME and KLHST_WKS_PRODUCT_VERSION values for products», где можно подсмотреть, что поле PRODUCT для KSC должно быть 1093, соответственно, всё остальное можно смело проигнорировать. Пока что, по крайней мере.

Пробежавшись глазами по названиям секций, я решил просмотреть 85 и 87, поскольку остальные на нужное мне были не очень похожи.

try

 try {     $Proxy.Connect($Params);     $KSCHost = New-Object -ComObject 'klakaut.KlAkHosts2';     $KSCHost.AdmServer = $Proxy;     $KSCSettings = $KSCHost.GetHostSettings($Proxy.GetProp('KLADMSRV_SERVER_HOSTNAME'), 'SS_SETTINGS');     $KSCSettings.Read('1093', '1.0.0.0', '85');     '-----------------';     $KSCSettings.Read('1093', '1.0.0.0', '87');     Remove-Variable -Name 'KSCSettings';     Remove-Variable -Name 'KSCHost';     $Proxy.Disconnect(); } 

Результат

 EventFolder EventStoragePath KLAG_WAIT_SCHED_FOR_START_EVENT TaskStoragePath ----------------- KLSRV_AD_SCAN_ENABLED KLSRV_CONNECTION_DATA KLSRV_DATABASENAME KLSRV_NET_SCAN_ENABLED KLSRV_SERVERINSTANCENAME KLSRV_SP_DPNS_ENABLE KLSRV_SP_FASTUPDATENET_PERIOD KLSRV_SP_FULLUPDATENET_PERIOD KLSRV_SP_INSTANCE_ID KLSRV_SP_MAX_EVENTS_IN_DB KLSRV_SP_OPEN_AKLWNGT_PORT KLSRV_SP_SCAN_AD KLSRV_SP_SERVERID KLSRV_SP_SERVERID_DPE KLSRV_SP_SERVER_AKLWNGT_PORTS_ARRAY KLSRV_SP_SERVER_PORTS_ARRAY KLSRV_SP_SERVER_SSL_PORTS_ARRAY KLSRV_SP_SERVER_SSL_PORTS_ARRAY_GUI KLSRV_SP_SYNC_LIFETIME KLSRV_SP_SYNC_LOCKTIME KLSRV_SP_SYNC_SEC_PACKET_SIZE KLSRV_SSL_CERT_RSA_BIT_NUMBER 

Секция 85, судя по всему, отвечает за события и ныне нам неинтересна. А вот в 87 есть что-то, на что стоит обратить внимание:

try

 try {     $Proxy.Connect($Params);     $KSCHost = New-Object -ComObject 'klakaut.KlAkHosts2';     $KSCHost.AdmServer = $Proxy;     $KSCSettings = $KSCHost.GetHostSettings($Proxy.GetProp('KLADMSRV_SERVER_HOSTNAME'), 'SS_SETTINGS');     $87 = $KSCSettings.Read('1093', '1.0.0.0', '87');     "KLSRV_SERVERINSTANCENAME = $($87.Item('KLSRV_SERVERINSTANCENAME'))";     "KLSRV_DATABASENAME = $($87.Item('KLSRV_DATABASENAME'))";     "KLSRV_CONNECTION_DATA =`r`n$($87.Item('KLSRV_CONNECTION_DATA') | % {"`t$_ = $($87.Item('KLSRV_CONNECTION_DATA').Item($_))`r`n";})";     Remove-Variable -Name '87';     Remove-Variable -Name 'KSCSettings';     Remove-Variable -Name 'KSCHost';     $Proxy.Disconnect(); } 

Результат

 KLSRV_SERVERINSTANCENAME = . KLSRV_DATABASENAME = KAV KLSRV_CONNECTION_DATA = 	KLDBCON_DB = KAV  	KLDBCON_DBTYPE = MSSQLSRV  	KLDBCON_HOST = . 

Тут я воспользовался одним из предыдущих кейсов, где упоминалось, что нужные данные следует брать именно из KLSRV_CONNECTION_DATA (тогда я ещё не знал, что это вообще такое, просто отложилось).

Ну, вот, в общем-то, и всё. Данные об используемой БД получены. Квест пройден.

Наверное, ещё неплохо бы набросать скрипт для прохождения по иерархии серверов. Здесь ничего загадочного не оказалось, всё было вполне по документации. Я написал скрипт, который выбирает UID родителя, UID самого сервера, экземпляр СУБД и имя БД и выводит их в stdout через разделитель.

Скрипт

 $SrvAddr = 'localhost:13291'  function EnumSrv(     $Pxy,     [bool]$IsAlive = $true,     [string]$ParentPxyId = 'Root' ) {     [string]$result = "$ParentPxyId";     if ($IsAlive) {         $result += "|$($Pxy.GetProp('KLADMSRV_SERVER_HOSTNAME'))";                  $Hosts = New-Object -ComObject 'klakaut.KlAkHosts2';         $Hosts.AdmServer = $Pxy;                  $Settings = $Hosts.GetHostSettings($Pxy.GetProp('KLADMSRV_SERVER_HOSTNAME'), 'SS_SETTINGS').Read('1093', '1.0.0.0', '87').Item('KLSRV_CONNECTION_DATA');         Remove-Variable -Name 'Hosts';              #'-------->   DB  Info <--------';         $result += "|$($Settings.Item('KLDBCON_HOST'))";         $result += "|$($Settings.Item('KLDBCON_DB'))";         #'-----------------------------';                  Remove-Variable -Name 'Settings';                  $SlaveSrvEnum = New-Object -ComObject 'klakaut.KlAkSlaveServers';         $SlaveSrvEnum.AdmServer = $Pxy;         $SlaveServers = $SlaveSrvEnum.GetServers(-1);                  $SlaveServers | % {             $Child = $_;             $TmpSrvId = $Child.Item('KLSRVH_SRV_ID');             $HostActive = $true;             try             {                 $TmpSrv = $SlaveSrvEnum.Connect($TmpSrvId, -1);             }             catch             {                 $HostActive = $false;             };             if ($HostActive) {$HostActive = ($TmpSrv.GetProp('IsAlive') -eq 1);};             $result += "`r`n$(EnumSrv -Pxy $TmpSrv -IsAlive $HostActive -ParentPxyId $Pxy.GetProp('KLADMSRV_SERVER_HOSTNAME'))";         };         Remove-Variable -Name 'SlaveServers';         Remove-Variable -Name 'SlaveSrvEnum';     };     return ("$result`r`n"); }  Clear-Host  $Params = New-Object -ComObject 'klakaut.KlAkParams' $Params.Add('Address', $SrvAddr) $Params.Add('UseSSL', $true)  $code =  @" using System; using System.Runtime.InteropServices;  public class PowershellComSecurity {    [DllImport("Ole32.dll", CharSet = CharSet.Auto)]    public static extern int CoSetProxyBlanket(IntPtr p0, uint p1, uint p2, uint p3, uint p4, uint p5, IntPtr p6, uint p7);     public static int EnableImpersonation(object objDCOM) { return CoSetProxyBlanket(Marshal.GetIDispatchForObject(objDCOM), 10, 0, 0, 0, 3, IntPtr.Zero, 0); } } "@ Add-Type -TypeDefinition $code  $Srv = New-Object -ComObject 'klakaut.KlAkProxy' [PowershellComSecurity]::EnableImpersonation($Srv) | Out-Null $Srv.Connect($Params)  "ParentPxyId|KLADMSRV_SERVER_HOSTNAME|KLDBCON_HOST|KLDBCON_DB`r`n" + (EnumSrv -Pxy $Srv); Remove-Variable -Name 'Srv'; Remove-Variable -Name 'Params'; 

Стенд маленький, поэтому результат оказался не очень впечатляющим:

Результат

 ParentPxyId|KLADMSRV_SERVER_HOSTNAME|KLDBCON_HOST|KLDBCON_DB Root|9d476a75-1e36-4c0e-8145-56e5b888df67|.|KAV 9d476a75-1e36-4c0e-8145-56e5b888df67|ef4fc3be-3abd-4322-ae35-2c50afdce780|.\KAV_CS_ADMIN_KIT|KAV 

Естественно, чтобы превратить точку в актуальное имя сервера, придётся поколдовать с KlAkHosts2.GetHostInfo(), но это уже не столь страшно, просто ещё сколько-то кода.

Техподдержка ЛК, естественно, пугала меня тем, что структура SS_SETTINGS в следующих релизах KSC может поменяться, поэтому так лучше не делать. К сожалению, даже мой внутренний перфекционист считает, что скрипт нельзя просто написать и забыть: при смене версии используемого ПО его по-любому придётся тестировать и отлаживать. Так что пока пользуемся тем, что есть, а проблемы будем решать по мере поступления, благо, техника уже отработана.

ссылка на оригинал статьи https://habrahabr.ru/post/278209/