Skip to content

Как переименовать элементы в SCSM

Как переименовать элементы в SCSM published on 1 комментарий к записи Как переименовать элементы в SCSM

image

Иногда стандартный текст, используемый для элементов в SCSM, не всегда подходит. И если для объектов, которые хранятся в незапечатанных пакетах, это не проблема – мы можем изменить отображаемое имя как нам угодно, то вот для для объектах, хранящихся в запечатанных пакетах управления всё несколько сложнее. Но, как говориться, нет ничего невозможного.

Для начала давайте определимся, что же мы можем изменить:

  • Отображаемое имя любого компонента SCSM – класса, отношения, свойства и так далее
  • Отображаемое имя папок и представлений
  • Элементы формы

Как вы видите, мы можем менять практически всё, что есть в SCSM.

Как осуществляется перевод в SCSM

Теперь немного теории. Если вы читали мою статью про OpsMgr, то должны знать, что все компоненты в пакете управления (напомню, структура пакетов управления OpsMgr и SCSM родственна) имеют ID – строковый идентификатор. К примеру, ID класса инцидента – System.WorkItem.Incident (надеюсь, что скоро будет закончена статья про пакеты управления в SCSM, где я постараюсь описать это чуть более подробно). Кроме этого, каждый пакет управления содержит специальную секцию LanguagePack, где для каждого поддерживаемого языка содержится отображаемое имя (Display Name) каждого элемента, который содержится в этом пакете управления. К примеру, ниже представлен часть пакета управления, где представлены строки для класса “Инцидент”:

<LanguagePacks>
  <LanguagePack ID="ENU" IsDefault="true">
    <DisplayStrings>
      <DisplayString ElementID="System.WorkItem.Incident">
        <Name>Incident</Name>
        <Description>Defines the basic properties of incidents</Description>
      </DisplayString>
    </DisplayStrings>
  </LanguagePack>
  <LanguagePack ID="RUS" IsDefault="false">
    <DisplayStrings>
      <DisplayString ElementID="System.WorkItem.Incident">
        <Name>Инцидент</Name>
        <Description>Определение основных свойств инцидентов</Description>
      </DisplayString>
    </DisplayStrings>
  </LanguagePack>
</LanguagePacks>

LanguagePack имеет параметр ID, определяющий 3х буквенный код страны по стандарту ISO 639. Далее следует набор элементов DisplayString, в которых атрибут ElementID указывает, для какого элемента предназначена эта строка. Для подкомпонентов (таких как название свойств классов, компонентов type propjection) DispayString будет иметь дополнительный атрибут SubElementID. К примеру, вот описание свойства Источник класса Инцидент:

<DisplayString ElementID="System.WorkItem.Incident" SubElementID="Source">
  <Name>Источник</Name>
  <Description>Источник</Description>
</DisplayString>

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

<Form ID="System.WorkItem.Incident.ConsoleForm" Accessibility="Public" Target="System.WorkItem.Incident.ProjectionType" Assembly="ServiceManager.Incident.Forms" TypeName="Microsoft.EnterpriseManagement.ServiceManager.Incident.Forms.IncidentFormControl">
        <Category>Form</Category>
        <FormStrings>
          <FormString ID="Label_hours">$MPElement[Name="Microsoft.EnterpriseManagement.ServiceManager.Incident.Forms.IncidentFormControl.Label_hours"]$</FormString>
          <FormString ID="Label_minutes">$MPElement[Name="Microsoft.EnterpriseManagement.ServiceManager.Incident.Forms.IncidentFormControl.Label_minutes"]$</FormString>
<!-- обрезано -->

Собственно, значением элемента FormString является ссылка на элемент StringResource в пакете управления, который в свою очередь имеет перевод в секции LanguagePacks:

<!-- обрезано -->
  <StringResources>
      <StringResource ID="Microsoft.EnterpriseManagement.ServiceManager.Incident.Forms.IncidentFormControl.Label_hours" />
      <StringResource ID="Microsoft.EnterpriseManagement.ServiceManager.Incident.Forms.DCMIncidentFormControl.Label_hours" />
<!-- обрезано -->
<LanguagePacks>
  <LanguagePack ID="ENU" IsDefault="true">
    <DisplayStrings>
<!-- обрезано -->
      <DisplayString ElementID="Microsoft.EnterpriseManagement.ServiceManager.Incident.Forms.IncidentFormControl.Label_hours">
        <Name>hours</Name>
        <Description>hours</Description>
      </DisplayString>
<!-- обрезано -->
  <LanguagePack ID="RUS" IsDefault="false">
    <DisplayStrings>
<!-- обрезано -->
        <DisplayString ElementID="Microsoft.EnterpriseManagement.ServiceManager.Incident.Forms.IncidentFormControl.Label_hours">
          <Name>часы</Name>
          <Description>часы</Description>
        </DisplayString>
<!-- обрезано -->

При загрузке пакета управления, все переведенные строки попадают в таблицу LocalizedText, формы (и вообще все компоненты SCSM, т.к. обращение идет через SDK, а он в свою очередь берет данные из таблицы) используют строки именно из этой таблицы.

Меняем отображаемое имя на своё

Итак, как вы знаете, менять значения в запечатанных пакетах управления напрямую мы не можем. Трюк состоит в том, что DisplayString в качестве значения атрибута ElementID может принимать ссылку на ID элемента в другом пакете управления. Ссылки на элементы в других запечатанных пакетах управления выглядят в пакете управления следующим образом:

“alias!id”, где:
alias – имя псевдонима для данного пакета, определенного в секции References текущего пакета управления
id – ID элемента в запечатанном пакете управления.

К примеру, чтобы получить ссылку на класс System.WorkItem.Incident, в своем пакет управления, необходимо в нем создать ссылку на пакет управления “System.WorkItem.Incident.Library” (именно в нем содержится определение класса):

<Reference Alias="CoreIncident">
  <ID>System.WorkItem.Incident.Library</ID>
  <Version>7.0.6555.0</Version>
  <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
</Reference>

Теперь ссылка на класс будет выглядеть следующим образом:
CoreIncident!System.WorkItem.Incident”

Вставьте такую ссылку в атрибут ElementID элемента DisplayString и укажите своё значение в подэлементе Name. После экспортирования своего пакета управления все названия класса будут изменены на ваше значение.

Такой способ имеет один серьезный минус – в большинстве случае вы не сможете вернуть все строки в первоначальное значение, кроме как установив их в своем пакете управления. Связано это с тем, что строки в таблице LocalizedText обновляются только при добавлении пакета управления, но не при удалении. Еще одно важное замечание – прямое редактирование таблицы LocalizedText НЕ ПОДДЕРЖИВАЕТСЯ!

Примеры

Несколько примеров, в которых я не только покажу как переименовать значение, но и как найти его в пакете управления. Самое частое, что просят переименовать – это влияние и приоритет в инцидентах и запросах на изменение, т.к. они как раз таки содержаться в запечатанном пакете управления. Для начала, нам нужно найти в каком пакете управления содержатся эти элементы. Самый простой способ – поиск по базе данных, т.к. все пакеты (даже запечатанные) хранятся в базе данных SCSM. Подробно как производить поиск по базе данных описано здесь.

Для поиска нужный строк очень удобно пользоваться запросом с условием like. Обратите внимание, что все строки находятся внутри элемента <Name>, поэтому чтобы найти к примеру пакет управления, где содержится перечисление с уровнями влияния “Средний”, можно воспользоваться вот таким запросом:

SELECT [MPIsSealed]
      ,[MPName]
      ,[MPFriendlyName]
      ,convert(xml, [MPXML])
  FROM [dbo].[ManagementPack]
  where MPXML like '%<Name>Средний</Name>%'

Обратите внимание на функцию convert – она позволяет преобразовать текст в XML. Тип XML можно просматривать прямо из SQL Server Management Studio (поле открывается в новом окне). В результате выполнения мы получим следующую выборку:
image
Как мы уже знаем, значение хранится в запечатанном пакете управления, так что нам подходит всего один пакет управления — System.WorkItem.Library. Открываем его и находим вхождение в нем:
image
В итоге мы видим ID этого элемента (атрибут ElementID), запишем его, он нам потом потребуется. Не закрывайте окно с этим пакетом управления.

Следующим шагом нам надо создать пустой пакет управления, проще всего это сделать с помощью Authoring Tool. Далее, в этом созданном пакете управления необходимо добавить ссылку на пакет управления, в котором содержится наш элемент. Продублируйте любой элемент Reference в созданном пакете управления, и в качестве значение атрибута ID вставьте ID открытого в SQL Server Management Studio пакета управления (он находится в самом верху). Значение Version оставьте не меньше, чем в запечатанном пакете управления. Значение PublicKeyToken для всех пакетов управления Microsoft равно 31bf3856ad364e35. Alias можете указать любой. Для лучшего понимания ниже дана картинка что и куда копировать (справа запечатанный):
image
Теперь необходимо создать в LanguagePack новый элемент DisplayString, и указать в ElementID ID нужного нам элемента и нужное нам значение, не забыв добавить ссылку на пакет управления (WorkItem!):

<DisplayString ElementID="WorkItem!System.WorkItem.TroubleTicket.ImpactEnum.Medium">
  <Name>2 - Среднее</Name>
</DisplayString>

После импортирования пакета управления значение изменится в консоли SCSM:
image

Следующий пример показывает, как можно переименовать строку на форме, и даже добиться легкого изменения логики. По умолчанию, все комментарии, добавляемые в инцидент из консоли, являются публичными. Что, если хочется сделать их по умолчанию приватными? Если вы настраиваете процесс рассылки писем, вы можете установить условие как вам удобно: отправлять, когда флаг Public равнен False или True, это ваша воля. Но на форме будет висеть “галочка” Личное и сбивать ваших инженеров с толку.
image

Как мы уже знаем, мы можем легко переименовать этот элемент.

  1. Запустим запрос, указав в критерии поиск <Name>личное</Name>
  2. Запрос выдаст два похожих пакета управления — System.WorkItem.Library и ServiceManager.IncidentManagement.Library. Если вы посмотрите первый, то увидите, что в нем идет речь о свойстве, а вот во втором – о чекбоксе, в теории нам нужны оба, чтобы потом не путаться в других формах (н-р при настройке условий отбора). Записываем  пакеты управления и ElementID обоих.
  3. Добавляем в наш пакет управления ссылки на эти ПУ (WorkItem уже был, так что нужна лишь одна ссылка)
  4. Добавляем в секцию LanguagePack элементы DisplayString

В итоге должно получится вот так:

<DisplayString ElementID="IncidentManagement!Microsoft.EnterpriseManagement.ServiceManager.Incident.Forms.IncidentFormControl.CheckBox_Private">
  <Name>Общий</Name>
  <Description>Общий (изменено!)</Description>
</DisplayString>
<DisplayString ElementID="WorkItem!System.WorkItem.TroubleTicket.AnalystCommentLog" SubElementID="IsPrivate">
  <Name>Общий</Name>
  <Description>Общий (изменено!)</Description>
</DisplayString>

И как результат:
image

В качестве заключения

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

  1. Делайте всё сначала на стенде, потом только переносите в боевую среду.
  2. Следите, что бы в вашем пакете не было дублирований в секции Reference (иначе будет ошибка при импортировании пакет)
  3. Не забывайте добавлять ссылку на пакет управления

Поделиться в соц. сетях

Primary Sidebar