← Назад в блог

Организация PowerShell-модулей для разработки под SharePoint

Опубликовано
5 мин чтения
--- просмотров

В этом посте я поделюсь своим подходом к организации PowerShell-кода. Основные цели:

  1. Минимизировать дублирование кода
  2. Сохранять структуру простой
  3. Сделать код переиспользуемым
  4. Обеспечить гибкость
  5. Сфокусироваться на разработке для SharePoint

Если ты работаешь с SharePoint и используешь Visual Studio Code для разработки на PowerShell, сначала загляни в этот пост: VisualStudioCode – PowerShell stubs for SharePoint.

Концепции организации кода:

  • Dot-sourcing
  • Модули

Dot-Sourcing:

Эта концепция основана на особом вызове скрипта (шаблон: . .\script.ps1). Благодаря такому выполнению все переменные, использованные в script.ps1, будут существовать в текущем контексте (там, откуда вызывается script1.ps1). Обрати внимание: при обычном запуске скрипт выглядит так: .\script.ps1. **Пример:**Например, у нас есть скрипт:

$answer=42
write-output ultimate answer is $answer

Посмотрим, как это выполнится в обычном режиме:

PS D:\temp> .\script.ps1
ultimate answer is 42

PS D:\temp> $answer

А теперь выполнение как dot-sourced:

PS D:\temp> . .\script.ps1
ultimate answer is 42

PS D:\temp> $answer
42

Как видишь, после обычного выполнения внутренняя переменная $answer не существует в родительском контексте. В dot-sourcing она существует. ## Модули

Эта концепция основана на двух сущностях: манифест модуля и сам модуль. Модуль содержит всю логику PowerShell-скрипта (например, функции, которые нужно экспортировать). Манифест модуля — простой формат для описания этого модуля (какие функции будут экспортироваться, откуда и так далее). Посмотрим на модуль подробнее. Например, у меня есть модуль Web.psm1 в репозитории powershell-sharepoint:

function Get-List-On-Web {
    Param(
        [Microsoft.SharePoint.SPWeb] $web,
        [string] $listUrl
    )

    return $web.GetList($web.Url + '/lists/' + $listUrl)
}

Как видишь, это обычная функция. Файл Web.psm1 находится в отдельной папке Web внутри папки utils. Структура выглядит так:

+---scenarios
\---utils
    \---Web
            Web.psd1
            Web.psm1

Рядом с Web.psm1 также создаётся файл Web.psd1 (файл-манифест). Команда для создания файла манифеста (описана здесь = [ссылка])

New-ModuleManifest -Path C:\ps-test\Test-Module\Test-Module.psd1 -PassThru

Посмотрим, что содержит файл манифеста:

#
# Module manifest for module 'Web'
#
# Generated by: administrator
#
# Generated on: 14.08.2019
#

@{

# Script module or binary module file associated with this manifest.
RootModule = '.\Web.psm1'

# Version number of this module.
ModuleVersion = '1.0'

# Supported PSEditions
# CompatiblePSEditions = @()

# ID used to uniquely identify this module
GUID = 'd187c4b7-7b8e-4285-a750-6e87477e6a33'

# Author of this module
Author = 'administrator'

# Company or vendor of this module
CompanyName = 'Unknown'

# Copyright statement for this module
Copyright = '(c) 2019 administrator. All rights reserved.'

# Description of the functionality provided by this module
# Description = ''

# Minimum version of the Windows PowerShell engine required by this module
# PowerShellVersion = ''

# Name of the Windows PowerShell host required by this module
# PowerShellHostName = ''

# Minimum version of the Windows PowerShell host required by this module
# PowerShellHostVersion = ''

# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = ''

# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# CLRVersion = ''

# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''

# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()

# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()

# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()

# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()

# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()

# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()

# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @('Get-List-On-Web')

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @()

# Variables to export from this module
VariablesToExport = '*'

# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()

# DSC resources to export from this module
# DscResourcesToExport = @()

# List of all modules packaged with this module
# ModuleList = @()

# List of all files packaged with this module
# FileList = @()

# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{

    PSData = @{

        # Tags applied to this module. These help with module discovery in online galleries.
        # Tags = @()

        # A URL to the license for this module.
        # LicenseUri = ''

        # A URL to the main website for this project.
        # ProjectUri = ''

        # A URL to an icon representing this module.
        # IconUri = ''

        # ReleaseNotes of this module
        # ReleaseNotes = ''

    } # End of PSData hashtable

} # End of PrivateData hashtable

# HelpInfo URI of this module
# HelpInfoURI = ''

# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''

}
  • FunctionsToExport — массив имён функций, которые будут экспортироваться из модуля
    • Здесь можно указать wildcard *, но это не рекомендуется

Базовый сценарий, использующий логическую функцию из внешнего модуля, показан ниже:

Add-PSSnapin Microsoft.Sharepoint.Powershell

.\Load-Module.ps1 Web

$siteUrl = http://bot-sp2016/
$webUrl = http://bot-sp2016/SalesManagement/
$list = Sale

$web = Get-SPWeb $webUrl
$list = Get-List-On-Web $web $list

LoadModule.ps1 — вспомогательный скрипт для удобного использования Import-Module из единого центрального хранилища утилит:


Param(
    [string] $moduleName
)

Import-Module $PSScriptRoot\..\utils\$moduleName -Force

Открыт для работы по контракту

Я доступен для работы по контракту. Если у вас есть интересная идея проекта — запишитесь на звонок через Calendly.

Записаться на 30-минутный звонок