1: param(
2: [string]$siteUrl,
3: [string]$login,
4: [string]$password
5: )
6:
7: $currentDir = Convert-Path(Get-Location)
8: $dllsDir = resolve-path($currentDir +
9: "\Microsoft.SharePointOnline.CSOM.16.1.6420.1200\lib\net45")
10:
11: [System.Reflection.Assembly]::LoadFile([System.IO.Path]::Combine($dllsDir,
12: "Microsoft.SharePoint.Client.dll"))
13: [System.Reflection.Assembly]::LoadFile([System.IO.Path]::Combine($dllsDir,
14: "Microsoft.SharePoint.Client.Runtime.dll"))
15:
16: if (-not $siteUrl)
17: {
18: Write-Host "Specify site url in siteUrl parameter" -foregroundcolor red
19: return
20: }
21:
22: if (-not $login)
23: {
24: Write-Host "Specify user name in login parameter" -foregroundcolor red
25: return
26: }
27:
28: if (-not $password)
29: {
30: Write-Host "Specify user password in password parameter" -foregroundcolor red
31: return
32: }
33:
34: <#
35: .Synopsis
36: Facilitates the loading of specific properties of a Microsoft.SharePoint.Client.ClientObject object or Microsoft.SharePoint.Client.ClientObjectCollection object.
37: .DESCRIPTION
38: Replicates what you would do with a lambda expression in C#.
39: For example, "ctx.Load(list, l => list.Title, l => list.Id)" becomes
40: "Load-CSOMProperties -object $list -propertyNames @('Title', 'Id')".
41: .EXAMPLE
42: Load-CSOMProperties -parentObject $web -collectionObject $web.Fields -propertyNames @("InternalName", "Id") -parentPropertyName "Fields" -executeQuery
43: $web.Fields | select InternalName, Id
44: .EXAMPLE
45: Load-CSOMProperties -object $web -propertyNames @("Title", "Url", "AllProperties") -executeQuery
46: $web | select Title, Url, AllProperties
47: #>
48: function Load-CSOMProperties {
49: [CmdletBinding(DefaultParameterSetName='ClientObject')]
50: param (
51: # The Microsoft.SharePoint.Client.ClientObject to populate.
52: [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0, ParameterSetName = "ClientObject")]
53: [Microsoft.SharePoint.Client.ClientObject]
54: $object,
55:
56: # The Microsoft.SharePoint.Client.ClientObject that contains the collection object.
57: [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0, ParameterSetName = "ClientObjectCollection")]
58: [Microsoft.SharePoint.Client.ClientObject]
59: $parentObject,
60:
61: # The Microsoft.SharePoint.Client.ClientObjectCollection to populate.
62: [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 1, ParameterSetName = "ClientObjectCollection")]
63: [Microsoft.SharePoint.Client.ClientObjectCollection]
64: $collectionObject,
65:
66: # The object properties to populate
67: [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "ClientObject")]
68: [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "ClientObjectCollection")]
69: [string[]]
70: $propertyNames,
71:
72: # The parent object's property name corresponding to the collection object to retrieve (this is required to build the correct lamda expression).
73: [Parameter(Mandatory = $true, Position = 3, ParameterSetName = "ClientObjectCollection")]
74: [string]
75: $parentPropertyName,
76:
77: # If specified, execute the ClientContext.ExecuteQuery() method.
78: [Parameter(Mandatory = $false, Position = 4)]
79: [switch]
80: $executeQuery
81: )
82:
83: begin { }
84: process {
85: if ($PsCmdlet.ParameterSetName -eq "ClientObject") {
86: $type = $object.GetType()
87: } else {
88: $type = $collectionObject.GetType()
89: if ($collectionObject -is [Microsoft.SharePoint.Client.ClientObjectCollection]) {
90: $type = $collectionObject.GetType().BaseType.GenericTypeArguments[0]
91: }
92: }
93:
94: $exprType = [System.Linq.Expressions.Expression]
95: $parameterExprType = [System.Linq.Expressions.ParameterExpression].MakeArrayType()
96: $lambdaMethod = $exprType.GetMethods() | ? { $_.Name -eq "Lambda" -and $_.IsGenericMethod -and $_.GetParameters().Length -eq 2 -and $_.GetParameters()[1].ParameterType -eq $parameterExprType }
97: $lambdaMethodGeneric = Invoke-Expression "`$lambdaMethod.MakeGenericMethod([System.Func``2[$($type.FullName),System.Object]])"
98: $expressions = @()
99:
100: foreach ($propertyName in $propertyNames) {
101: $param1 = [System.Linq.Expressions.Expression]::Parameter($type, "p")
102: try {
103: $name1 = [System.Linq.Expressions.Expression]::Property($param1, $propertyName)
104: } catch {
105: Write-Error "Instance property '$propertyName' is not defined for type $type"
106: return
107: }
108: $body1 = [System.Linq.Expressions.Expression]::Convert($name1, [System.Object])
109: $expression1 = $lambdaMethodGeneric.Invoke($null, [System.Object[]] @($body1, [System.Linq.Expressions.ParameterExpression[]] @($param1)))
110:
111: if ($collectionObject -ne $null) {
112: $expression1 = [System.Linq.Expressions.Expression]::Quote($expression1)
113: }
114: $expressions += @($expression1)
115: }
116:
117:
118: if ($PsCmdlet.ParameterSetName -eq "ClientObject") {
119: $object.Context.Load($object, $expressions)
120: if ($executeQuery) { $object.Context.ExecuteQuery() }
121: } else {
122: $newArrayInitParam1 = Invoke-Expression "[System.Linq.Expressions.Expression``1[System.Func````2[$($type.FullName),System.Object]]]"
123: $newArrayInit = [System.Linq.Expressions.Expression]::NewArrayInit($newArrayInitParam1, $expressions)
124:
125: $collectionParam = [System.Linq.Expressions.Expression]::Parameter($parentObject.GetType(), "cp")
126: $collectionProperty = [System.Linq.Expressions.Expression]::Property($collectionParam, $parentPropertyName)
127:
128: $expressionArray = @($collectionProperty, $newArrayInit)
129: $includeMethod = [Microsoft.SharePoint.Client.ClientObjectQueryableExtension].GetMethod("Include")
130: $includeMethodGeneric = Invoke-Expression "`$includeMethod.MakeGenericMethod([$($type.FullName)])"
131:
132: $lambdaMethodGeneric2 = Invoke-Expression "`$lambdaMethod.MakeGenericMethod([System.Func``2[$($parentObject.GetType().FullName),System.Object]])"
133: $callMethod = [System.Linq.Expressions.Expression]::Call($null, $includeMethodGeneric, $expressionArray)
134:
135: $expression2 = $lambdaMethodGeneric2.Invoke($null, @($callMethod, [System.Linq.Expressions.ParameterExpression[]] @($collectionParam)))
136:
137: $parentObject.Context.Load($parentObject, $expression2)
138: if ($executeQuery) { $parentObject.Context.ExecuteQuery() }
139: }
140: }
141: end { }
142: }
143:
144: function CheckMasterPage($ctx, $web)
145: {
146: Load-CSOMProperties -object $web -propertyNames @("MasterUrl", "CustomMasterUrl",
147: "Webs", "AllProperties")
148: $ctx.ExecuteQuery()
149:
150: ($web.Url) | Out-File "log.txt" -Append
151: (" " + $web.MasterUrl) | Out-File "log.txt" -Append
152: (" " + $web.AllProperties["__InheritsMasterUrl"]) | Out-File "log.txt" -Append
153: (" " + $web.CustomMasterUrl) | Out-File "log.txt" -Append
154: (" " + $web.AllProperties["__InheritsCustomMasterUrl"]) | Out-File "log.txt" -Append
155:
156: foreach ($w in $web.Webs)
157: {
158: CheckMasterPage $ctx $w
159: }
160: }
161:
162: $securePassword = ConvertTo-SecureString $password -AsPlainText -Force
163: $credentials =
164: New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($login,
165: $securePassword)
166: $ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
167: $ctx.AuthenticationMode =
168: [Microsoft.SharePoint.Client.ClientAuthenticationMode]::Default
169: $ctx.Credentials = $credentials
170: $ctx.Load($ctx.Site)
171: $ctx.Load($ctx.Web)
172: $ctx.ExecuteQuery()
173:
174: CheckMasterPage $ctx $ctx.Web