Powershell v2 и Sharepoint: скриптописание или программирование для администраторов. Часть 2.

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

ListItemEventReceivers и ListEventReceivers

Для всех библиотек и списков в Sharepoint предусмотрен ряд обработчиков событий, часть которых отвечают за события непосредственно списка (изменение свойств, добавление столбцов и т.д.), а часть за события элементов (создание, изменение, удалении и т.д.).

В общем случае, для того, чтобы обрабатывать эти события необходимо создать класс, наследованный от SPItemEventProperties, и реализовать в нем нужные методы. После этого класс необходимо зарегистрировать в Sharepoint с помощью Feature или с помощью сторонних инструментов. Но т.к. C#, компиляция и прочие страшные слова – это не то, что нам сейчас нужно, мы посмотрим что же можно сделать с этими событиями с помощью Powershell.

На помощь нам придет замечательная Feature PowerEventReceivers из пакета iLoveSharepoint. Данная Feature добавляет в каждый список или библиотеку документов возможность вставлять обработчики событий на скриптах Powershell.

Тут следует отвлечься, и немного рассказать о некоторых аспектах безопасности, связанных с событиями. Все обработчики событий в списках и элементах списков выполняются от имени того пользователя, который инициировал изменения. В связи с этим и скрипты Powershell будут выполняться от имени этих пользователей, а пользователю необходимы права на выполнения скриптов на сервере, где установлена front-end MOSS\WSS. В противном случае вы получите ошибку “Requested registry access is not allowed”. Решить эту проблему можно, используя метод SPSecurity.RunWithElevatedPrivileges в WSS\Sahrepoint. Благодаря ему все вызовы будут происходить с привелегиями Системной учетной записи (от которой запущен пул приложений IIS). Но при этом нужно понимать, что ВСЕ скрипты в обработчиках будут запускаться от имени этой учетной записи, и с помощью неё можно наделать не мало бед. Подробно аспекты безопасности будут рассмотрены в конце цикла статей.

Какой из методов использовать – решать вам. Я создал PowerEventReceivers, который выполняется с повышенными привилегиями. Вы можете использовать его или оригинальный.

Установка крайне проста – запустите deploy.bat на сервере Sharepoint, затем активируйте эту Feature на нужном узле (и только на нужном, по соображениям безопасности и производительности):

image

После активации будут доступны два новых пункта в свойствах списков и библиотеках документов:

image

Смысл их понятен из названия, первый отвечает на обработку событий элемента, второй – за обработку событий списка (или библиотеки). Приведу полностью доступные обработчики элемента списка:

ItemAdding Во время добавления элемента
ItemUpdating Во время изменения элемента
ItemDeleting Во время удаления элемента
ItemCheckingIn Во время возврата документа
ItemCheckingOut Во время извлечения документа
ItemUncheckingOut Во время отмены извлечения документа
ItemAttachmentAdding Во время добавления вложения
ItemAttachmentDeleting Во время удаления вложения
ItemFileMoving Во время перемещения файла
ItemAdded После добавления элемента
ItemUpdated После изменения элемента
ItemDeleted После удаления элемента
ItemCheckedIn После возврата документа
ItemCheckedOut После извлечения документа
ItemUncheckedOut После отмены извлечения документа
ItemAttachmentAdded После добавления вложения
ItemAttachmentDeleted После удаления вложения
ItemFileMoved После перемещения файла
ItemFileConverted После конвертации файла (MOSS)
ContextEvent “Ручной” вызов события

и события списка (библиотеки):

FieldAdded После добавления столбца
FieldAdding Во время добавления столбца
FieldDeleted После удаления столбца
FieldDeleting Во время удаления столбца
FieldUpdated После изменения столбца
FieldUpdating Во время изменения столбца

Все обработчики с постфиксом –ing являются синхронными, то есть выполняются одновременно с действием, их породивших. Это позволяет влиять на событие вплоть до его отмены.

Для редактирования доступно как обычное текстовое поле прямо на веб-странице, так и специальный ActiveX для интеграции PowerEventreceivers с редактором PowerGUI. ActiveX доступен на официальном сайте.

Давайте посмотрим, что мы можем сделать с помощью этих обработчиков событий и Powershell (также несколько примеров доступно на страничке PowerEventReceivers).

1. Проверка значений перед вставкой элемента:

    1 function ItemAdding

    2 {

    3     [int]$curVal = $properties.AfterProperties["Title"]

    4     if ($curVal -ge 8)

    5     {

    6         $properties.Cancel = $true

    7         $properties.ErrorMessage = "Нельзя указывать значения поля Название больше или равное 8. Вы указали $curVal"

    8     }

    9 }

Обратите внимание на приведения типов в строке 3. Столбец Название (Title) на самом деле имеет тип “строка”, но это Powershell. Тут мы можем делать и вот так.

Если пользователь ввел значение больше или равное 8, то элемент не будет создан, а ему будет выдана вот такая красивая ошибка:

image

2. Оценка поля до изменения и после, вставка разницы в другой столбец. Мы будем использовать ItemUpdating для получения изменений, т.к. только в нем доступны как свойства до изменения, так и после. Кроме этого мы будем использовать ItemUpdated для фиксации изменений в поле, т.к. вызов метода Update в ItemUpdating приведет к конфликту сохранений:

    1 function ItemUpdating

    2 {

    3     $oldVal = $item["Title"]

    4     $newVal = $properties.AfterProperties["Title"]

    5     $val = "Было $oldVal, а стало $newVal"

    6     $this.DisableEventFiring()

    7     $item.Properties["_Temp"]  = $val

    8     $item.SystemUpdate($False)

    9     $this.EnableEventFiring()

   10 

   11 }

   12 

   13 function ItemUpdated

   14 {

   15     $this.DisableEventFiring()

   16     $item["Field2"] = $item.Properties["_Temp"]

   17     $item.SystemUpdate($False)

   18     $this.EnableEventFiring()

   19 }

Обратите внимание на строки 6, 9, 15 и 18. Методы DisableEventFiring и EnableEventFiring позволяют отключить обработчики событий на время, чтобы у нас не было циклического из вызова из-за изменений в коде.

Также интересна конструкция $item.Properties["_Temp"]  = $val. Свойство Properties позволяет нам записывать любые значения в элемент, которые мы затем можем получить. В основном данное свойство применяется в рабочих процессах (Workflow), но как видно может пригодиться и тут.

Вот результат работы скрипта:

image

3. Создание сложных вычисляемых полей. Данный пример – следствие предыдущего. Формулы в Sharepoint хоть и обширны, но им очень далеко до функционала Powershell. Здесь мы можем применять любые функции, доступные нам в Powershell (и .NET соответственно) для создания вычисляемых полей:

    1 function GetListFromLookupField([string]$InternalFieldName)

    2 {

    3 

    4     $typeField = [Microsoft.SharePoint.SPFieldLookup]$list.Fields.GetFieldByInternalName($InternalFieldName)

    5     $typeListGuid = newobject Guid($typeField.LookupList)

    6     $typeList = $web.Lists[$typeListGuid]

    7     return $typeList

    8 }

    9 

   10 function ItemUpdated

   11 {

   12     $lookupList = GetListFromLookupField("LookupField")

   13 

   14     $this.DisableEventFiring()

   15     $item["LinkField"] = $site.Url + $lookupList.DefaultViewUrl+", Ссылка на список"

   16     $item.SystemUpdate($False)

   17     $this.EnableEventFiring()

   18 }

У нас в списке 2 поля. LookupField – поле типа “Подстановка”, LinkField – поле типа “Гиперссылка”. В результате выполнения в поле LinkField будет записана ссылка на представление по умолчанию списка. из которого берутся данные в поле LookupField. Результат выполнения:

image

Думаю из этих примеров понятно, что обработка событий предлагает нам неограниченные средства по работе с Sharepoint – дело только в фантазии.

Отладка.

Хотелось бы сказать пару слов об отладке. Первое, что отмечу – все ошибки выполнения PowerEventReceivers записывают в системный журнал Приложения. Т.е. если у вас что-то не выполнилось – смотрите журнал:

image

Для отладки же и получения значений каких-либо переменных я использую следующую конструкцию:

    1 ($item["Field"] | ConvertTo-XML).Save("d:\FieldValue_"+[datetime]::Now.ToString("HH.mm.ss.FFFFF")+".xml")

Т.е. просто преобразую значение переменной в XML, а затем записываю на диск в виде XML-файла с меткой времени.

Реклама

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: