В одной из своих предыдущих статей я рассмотрел вопросы, связанные с использованием PowerShell для инвентаризации объектов SharePoint высшего уровня. Я показал, как создаются списки компонентов ферм, веб-приложения, коллекции сайтов и сайты. Вы узнали о том, как из системы SharePoint извлекается информация о списках, библиотеках, файлах и страницах. Одна из статей («Инвентаризация учетных записей пользователей и групп SharePoint с помощью PowerShell», опубликована в Windows IT Pro/RE № 3 за 2015 год) была посвящена запросам — пользовательским и связанным с обеспечением безопасности. На этот раз мы займемся углубленным изучением более сложных запросов с целью выявления и перезагрузки отключенных от шаблонов или индивидуализированных страниц.
Для ознакомления с базовыми требованиями по безопасности при работе с PowerShell обратитесь к предыдущим статьям серии (см. Windows IT Pro/RE № 8 за 2013 год). При выполнении сценариев, публикуемых в этой статье, нагрузки на сервер могут существенно возрастать, что в свою очередь может отразиться на работе пользователей. Возможно, запускать эти сценарии целесообразно только в нерабочее время. Они предназначены для версий SharePoint, устанавливаемых на локальном оборудовании, и не функционируют на платформе Office 365 или SharePoint Online.
Страницы, подключенные к шаблонам и отключенные от шаблонов
Во времена преобладания SharePoint 2007 в ходу были два странных термина, с помощью которых мы описывали изменения, вносимые в страницы SharePoint в процессе их индивидуализации с помощью конструктора SharePoint Designer. И несмотря на попытки представителей Microsoft подкорректировать эти термины, мы до сих пор говорим о Ghosted (подключенных к шаблону) и Unghosted (отключенных от шаблона) страницах. Сегодня страницы Un-ghosted следует называть Customized («индивидуализированными»), а Ghosted страницы — Un-customized («неиндивидуализированными»).
Индивидуализированные или настраиваемые?
Когда владелец сайта редактирует страницу в браузере с помощью меню Settings или с использованием параметров ленты, он осуществляет «безопасную индивидуализацию» с помощью процесса, который можно просто назвать настройкой. Все внесенные в браузере изменения можно отменить в том же браузере. А что делать, если возникнет необходимость в изменениях, которые нельзя внести внутри браузера? Мы открываем сайт в SharePoint Designer. И хотя многие изменения, реализуемые в этом конструкторе, подобны изменениям, которые вносятся в браузере, в нашем распоряжении имеется возможность выполнения дополнительных операций, изменяющих процесс сохранения и извлечения страницы внутри SharePoint.
Неиндивидуализированные (подключенные к шаблону) страницы:
- Определение страницы хранится на дисковых накопителях сервера SharePoint или в файловой системе.
- Страницы, извлекаемые из файловой системы, могут быть быстро визуализированы и сохранены в кэше.
- Эти страницы часто допускают редактирование в браузере с помощью меню Settings, Edit Page или лент PAGE. Такого рода изменения меняют настройки страницы, но не базовое определение. При работе со страницами веб-частей мы можем добавлять, настраивать или удалять веб-части, но не изменять компоновку зон веб-частей. Если же речь идет о страницах Wiki, мы можем настраивать текст, веб-части и число столбцов, но не можем изменять язык HTML основного макета страницы.
Индивидуализированные (отключенные от шаблона) страницы:
- Когда страница индивидуализируется, или отсоединяется от шаблона, она копируется из файловой системы в базу данных SQL Server.
- Для выполнения запроса на индивидуализированную страницу необходимо выполнить запрос к таблице SQL, что повышает непроизводительные затраты при каждой загрузке страницы.
- Возможно, индивидуализированные страницы будут непригодны к использованию в следующей версии SharePoint.
- Применение индивидуализированных страниц может снижать производительность сайта и сервера.
- Изменения, индивидуализирующие страницы, редко документируются владельцами сайтов и потому создают для следующего владельца, наследующего этот сайт, трудности в организации поддержки.
- Индивидуализирующие страницу изменения могут даже препятствовать загрузке страницы. Таким образом, вы можете дробить страницы.
Что можно индивидуализировать?
Существует обстоятельство, которое в наибольшей степени осложняет окончательный сценарий PowerShell. Речь идет о числе мест, где имеются файлы, которые можно индивидуализировать с помощью конструктора SharePoint Designer:
- Файлы в коллекции SPWeb.Files (пример: /Training/default.aspx);
- Файлы страниц в библиотеках, таких как Site Pages и Pages (пример: /Training/SitePages/Home.aspx; /EnterpriseSearch/Pages/videoresults.aspx);
- Файлы. ASPX и. MASTER, размещающиеся по маршруту _catalogs (пример: /_catalogs/masterpage/seattle.master; /Search/_catalogs/masterpage/Display Templates/Search/Item_PowerPoint.html);
- Формы списков и библиотек, такие как newform.aspx и editform.aspx (пример: /Lists/Announcements/NewForm.aspx).
Как индивидуализировать страницу
Обычно страницы индивидуализируются с помощью SharePoint Designer. Это делается следующим образом.
- Загрузите и установите SharePoint Designer, он распространяется бесплатно. Загружать можно версию 2010 или 2013 — в зависимости от того, с какой версией SharePoint вы работаете. Пользователям Office 365 и SharePoint 2016 потребуется версия SPD 2013.
- Запустите конструктор и откройте свой сайт.
- Откройте страницу для редактирования и нажмите кнопку Advanced Mode на ленте HOME.
- Добавьте пробел, пустую строку или внесите другую редакторскую правку (то есть внесение реальных изменений не требуется).
- Нажмите кнопку Save.
Итак, ваша страница индивидуализирована или отключена от шаблона. Теперь она будет загружаться чуть медленнее (как правило, разница слишком мала, чтобы ее можно было заметить); возможно, она не будет обновляться до уровня следующей версии SharePoint, а может быть, и вообще не будет загружаться.
Обратный процесс
Страницу нельзя вновь подсоединить к шаблону или «деиндивидуализировать» путем простого удаления с нее внесенных индивидуализирующих изменений. Страницу нужно привести в исходное состояние, что можно сделать с помощью браузера, конструктора SharePoint Designer или оболочки PowerShell.
Перезагрузка страницы с помощью браузера выполняется так:
- Перейдите на сайт и выберите пункты Settings (gear), Site Settings.
- В разделе Site Actions выберите пункт Reset to Site Definition. Вместо этого можете изменить указатель URL и перейти по адресу: _layouts/15/reghost.aspx (смотрите, опять появилось знакомое «привидение» — ghost!).
- Введите URL перезагружаемой страницы и нажмите кнопку Reset.
- Нажмите кнопку OK. Файл будет перезагружен, а все индивидуализирующие изменения в нем отменены.
Имейте в виду, что вы можете также привести в исходное состояние все индивидуализированные страницы сайта с этой страницы.
Перезагрузка страницы с помощью SharePoint Designer производится следующим образом:
- Откройте сайт в окне SharePoint Designer.
- В области Navigation выберите пункт All Files.
- Пройдя через все промежуточные уровни, выйдите на интересующую вас страницу и обратите внимание на символ «i», обозначающий, что данная страница была индивидуализирована.
- Щелкните на файле страницы правой кнопкой мыши и в открывшемся меню выберите пункт Reset to Site Definition.
Файл будет перезагружен и с индивидуализированного файла будет снята резервная копия.
Перезагрузка страницы с помощью PowerShell или с использованием кода
Если вы хотите за один раз привести в исходное состояние все страницы сайта, можете воспользоваться методом RevertAllDocumentContentStreams объекта SPWeb (см. листинг 1).
Чтобы перезагрузить отдельную страницу, можно использовать метод RevertContentStream объекта SPFile. Пример для формы списка приведен в листинге 2.
Обратите внимание: чтобы реализовать это изменение, вам не потребуется вызывать. Update () по каждому объекту; в этом отношении данное обновление отличается от большинства других обновлений объектов SharePoint (см. листинг 3).
Обнаружение всех индивидуализированных или отключенных от шаблона страниц
Теперь мы переходим к сценариям. Первый сценарий относится к категории «безопасных» (см. листинг 4). Он не предусматривает внесения каких-либо изменений. Но при всей его безопасности не забывайте, что при выполнении сценария в рабочей сети может снизиться ее производительность.
Примечания к сценарию:
- С помощью данного сценария вы можете обрабатывать всю ферму, одну коллекцию сайтов или отдельный сайт.
- В каждом разделе сценария тестируется свойство файла. CustomizedPageStatus.
- В некоторых разделах тестируется расширение файла (.Name.EndsWith («.aspx»)).
- Доступ к каталогу главной страницы осуществляется с помощью команды $web.GetCatalog (116).
- В каждом разделе определяются пользовательские столбцы, так чтобы мы могли объединять результаты в единый выходной файл, который может быть перенаправлен в Out-GridView, Select *, Export-CSV и т. д.
- При извлечении форм списков необходимо выполнить дополнительную операцию с целью получения объекта файла.
Перезагрузка всех индивидуализированных или отсоединенных от шаблона страниц
А теперь мы переходим к опасному сценарию. При выполнении приведенного сценария результаты труда специалистов компьютерной графики и консультантов, оплаченные тысячами долларов, могут обратиться в ничто. Перед запуском этого сценария тщательно взвесьте все обстоятельства и, если возможно, выполняйте его на резервной копии фермы. Из соображений безопасности я закомментировал те строки, выполнение которых приводит к изменениям.
Приведенный в листинге 5 сценарий отличается от сценария в листинге 4 только тем, что в каждом его разделе имеется одна дополнительная строка. Эта строка вызывает метод RevertContentStream для каждого найденного индивидуализированного файла.
Примечания к сценарию:
- НЕ ЗАПУСКАЙТЕ ДАННЫЙ СЦЕНАРИЙ, ЕСЛИ ПРЕДВАРИТЕЛЬНО НЕ СНЯЛИ РЕЗЕРВНЫЕ КОПИИ СО ВСЕХ ИМЕЮЩИХСЯ ДАННЫХ!
- Проявляйте исключительную осторожность при возвращении к исходному состоянию файлов из Master Page Gallery ($_.GetCatalog (116)), ведь вы, вероятно, заплатили тысячи долларов создавшему их специалисту. Большая часть вашей работы по формированию фирменной символики выполняется на основе файлов из этой галереи.
- В приведенном в листинге 5 сценарии строки, вносящие изменения, закомментированы. Удаляйте из них символы комментирования только после выполнения сценария из листинга 4. Это поможет вам определить, что именно будет изменено.
- ВЫ ВЫПОЛНЯЕТЕ ЭТОТ СЦЕНАРИЙ НА СВОЙ СТРАХ И РИСК!
Итак, в этой статье речь шла об индивидуализированных страницах. Я рассказал о том, как обнаруживать их и возвращать в исходное состояние. В следующей статье мы продолжим поиск веб-частей.
$web = Get-SPWeb "http://yourServer/sites/yourSite/yourSubsite" $web.RevertAllDocumentContentStreams()
$web = Get-SPWeb "http://yourServer/sites/yourSite/yourSubsite" $file = $web.GetFile("http://yourServer/sites/yourSite/yourSubsite/Lists/yourList/newform.aspx") $file.RevertContentStream()
$file = $web.GetFile("http:// yourServer/sites/yourSite/yourSubsite /SitePages/home.aspx") $file.RevertContentStream()
***## Выберите источник... Уберите символы комментария перед одним (!) из следующих источников: ## Для всех сайтов: #Get-SPSite -Limit All | Get-SPWeb -Limit All | ## или для одной коллекции сайтов #Get-SPSite http://yourServer/sites/yourSite | Get-SPWeb -Limit All | ## или для одного веба Get-SPWeb http://yourServer/sites/yourSite | ## обрабатываем вебы по одному... ForEach { # # Находим все файлы уровня SPWeb # $_ | Select -ExpandProperty Files | Where { $_.Name.EndsWith(".aspx") -AND $_.CustomizedPageStatus -eq "Customized" } | Select @{l='Location'; e={'WebFile'}}, ServerRelativeUrl, TimeCreated, TimeLastModified, ModifiedBy # # Находим все файлы Catalog (116 = Master Page Gallery) # $_.GetCatalog(116).Items | Select -ExpandProperty File | Where { $_.CustomizedPageStatus -eq "Customized" } | Select @{l='Location'; e={'MP Gallery'}}, ServerRelativeUrl, TimeCreated, TimeLastModified, ModifiedBy # # Находим все библиотечные файлы # $LibrariesToCheck = "Site Pages", "Pages" $_ | Select -ExpandProperty Lists | where {$LibrariesToCheck -contains $_.Title} | Select -ExpandProperty Items | Select -ExpandProperty File | Where { $_.Name.EndsWith(".aspx") -AND $_.CustomizedPageStatus -eq "Customized" } | Select @{l='Location'; e={'Library'}}, ServerRelativeUrl, TimeCreated, TimeLastModified, ModifiedBy # # Преобразуем в файлы все формы списков # $w = $_; #сохраняем веб-объект для использования в следующем конвейере $_.Lists.forms | foreach {$w.getfile($_.url)} | Where { $_.CustomizedPageStatus -eq "Customized" } | Select @{l='Location'; e={'List Form'}}, ServerRelativeUrl, TimeCreated, TimeLastModified, ModifiedBy } | # Выбираем объект назначения Select * | Format-Table -AutoSize #Out-GridView #Export-Csv C:\test\ListOfCustomizedPages.CSV
## Выберите источник... Раскомментируйте один и только один из следующих источников ## Для всех сайтов: #Get-SPSite -Limit All | Get-SPWeb -Limit All | ## или для одной коллекции сайтов #Get-SPSite http://yourServer/sites/yourSite | Get-SPWeb -Limit All | ## или для одного веба #Get-SPSite http://maxsp2013wfe/sites/training | Get-SPWeb -Limit All | ## или для одного веба Get-SPWeb http://maxsp2013wfe/sites/training | ## обрабатываем вебы по одному... ForEach { # # Находим все файлы уровня SPWeb # $_ | Select -ExpandProperty Files | Where { $_.Name.EndsWith(".aspx") -AND $_.CustomizedPageStatus -eq "Customized" } | ####### Следующая строка выполняет операцию Reset to Site Definition! ###foreach {$_.RevertContentStream(); $_} | ###foreach {$_.RevertContentStream(); $_} | Select @{l='Location'; e={'WebFile'}}, ServerRelativeUrl, TimeCreated, TimeLastModified, ModifiedBy # # Находим все файлы Catalog (116 = Master Page Gallery) # $_.GetCatalog(116).Items | Select -ExpandProperty File | Where { $_.CustomizedPageStatus -eq "Customized" } | ####### Следующая строка выполняет операцию Reset to Site Definition! ###foreach {$_.RevertContentStream(); $_} | Select @{l='Location'; e={'MP Gallery'}}, ServerRelativeUrl, TimeCreated, TimeLastModified, ModifiedBy # # Находим все библиотечные файлы # $LibrariesToCheck = "Site Pages", "Pages" $_ | Select -ExpandProperty Lists | where {$LibrariesToCheck -contains $_.Title} | Select -ExpandProperty Items | Select -ExpandProperty File | Where { $_.Name.EndsWith(".aspx") - AND $_.CustomizedPageStatus -eq "Customized" } | ####### Следующая строка выполняет операцию Reset to Site Definition! ###foreach {$_.RevertContentStream(); $_} | Sel ect @{l='Location'; e={'Library'}}, ServerRelativeUrl, TimeCreated, TimeLastModified, ModifiedBy # # Преобразуем в файлы все формы списков # $w = $_; $_.Lists.forms | foreach {$w.getfile($_.url)} | Where { $_.CustomizedPageStatus -eq "Customized" } | ####### Следующая строка выполняет операцию Reset to Site Definition! ###foreach {$_.RevertContentStream(); $_} | Select @{l='Location'; e={'List Form'}}, ServerRelativeUrl, TimeCreated, TimeLastModified, ModifiedBy } | # Выбираем объект назначения Select * | Format-Table -AutoSize #Out-GridView #Export-Csv C:\test\ListOfCustomizedPages.CSV