Edit:
12/11/2014 Updated the script to version 1.1 and provided a download link (see end of this blog post for more details).
PowerShell is a great automation language. What is nice about it, is that it is present in (almost) all of Microsoft palette. As a powerShell developer (Did some one said Devops?) we can technically work on anything as long as it has Powershell underlying on it. And that is really one of our strength! In today’s topic, we will discuss Powershell in Sharepoint.
Knowing the PowerShell language and syntax pretty well is really a strong asset. We can easily go from one (infrastructure) field to another. This implies that we often need to adapt to new technologies and learn their basic architecture components in order to be able to write a script that will not blow up the complete production environment.
Sharepoint is one these Microsoft technologies that is present EVERYWHERE. A lot of the huge companies out there use it for various different business scenarios. It really must be a great collaboration tool (I cannot give a strong opinion for my self, but that will come soon I guess). Yet every body seem to hate it. If you google “Why sharepoint sucks”, you will receive huge amount of results back. Anyways, ignoring all of this, I just start my day, with the task of adding a Specific AD group to several all of our Web site collections.
Ok, seems easy right?
I know that the architecture for a site is (in a very basic shape) like this:
- Web Application
- Site Collection
- Site
- Site Collection
It is pretty much comparable to standard file system hierarchy, so nothing to complicate there!
But when you take a look in the powershell cmdlets, it seems like they haven’t really respected the same naming convention (or at least, It is not as clear as I am used to with other products).
The three main cmdlets that will be used here are :
- Get-SPWebApplication
- Get-SPSite
- Get-SPWeb
But, when I looked at their parameters I got confused. I created the following small mind map which helped to link which cmdlet was actually needed for what part of sharepoint.
Why is that important ? Well, what I actually needed to do, is to set read and write rights to all of the child sites of a specefic site collection.
The logic and the technicity behind this script is really not that high. But I simply want to share it with the community since I have had a small learning curve here.
Writing about it actually helps me to actually better understand what and why I have done things. So why not give it out to everybody and see what will come back out of this? 🙂
PowerShell and Sharepoint:
Big learning points:
- Sharepoint architecture.
- PowerShell cmdlets
The sharepoint cmdlets are not based on a module, but on PsSnapin. (yep, a PSSnapin).
A PSSnaping work just like a regular PowerShell module. We first have to load the cmdlets into memory, and only then we can start really work in the sharepoint automation activites.
If we look at the cmdlets available for “PSSnaping” we will have the following results back.
We can use the following line to see what PSSnapins are available on the system:
1
|
Get-PSSnapin -Registerd
|
To see the ones that are currently loaded use Get-PSSnapin
1
|
Get-PSSnapin
|
Now to be able to load the sharepoint PSSnapin, the following will need to be called prior to any Sharpeoint code execution:
1
|
Add-PSSnapin ‘Microsoft.SharePoint.PowerShell’
|
[/stextbox]
EDIT:
As mentionned by
-
The most import of all “EnsureUser”
The most significant change I did between version 1.0 and 1.1 is located at line 102 (and has been showed to me by our sharepoint specialist):
1
|
$targetUser = $SPWeb.EnsureUser($Account)
|
In version 1.0, I would use the following logic in order to first verify if the account is already created in Sharepoint, and if not, create it.
1
2
3
4
5
|
$Accounts = Get-SPUser -Web $site.url
write-host “Verifying if Group $($Account) is present…”
if (!($Accounts.userlogin -contains $Account)){...}
|
-
-match is not -contains
For some reason, the -contains I used didn’t worked as expected. The link that was present in the exlusionlist file was never skipped. This mostly came because of the fact that the if condition was always false. (So testing in a test environment is really not done only for peanuts!).Changing the -contains to -match fix that issue and allowed us to be able to filter out some specific sites that we didn’t want to be affected by the script.
-
ValidateScript parameter for $fileexlusionlist parameter
If a FileExlusionList is specified we want to be sure that it actually exists and is present. I have added this validateScript parameter to “test-path $_” simply to be sure that the file actually really exists.
Of course, we could have added more validation, but this script was a one-shot script, and the public that was going to use it had sufficient knowledge in order to make these checks enough.
-
Comment based help update
I have also updated the comment based help, just to be sure that I remember what this script actually was about when I will take a look into it again in 6 months.
Do you add comment based help to your scripts also? No time for that you say ? Sure, nobody does. But you might rewrite a script that you already had somewhere (or a function), or will need some time to search in your logic and try to understand what exactly happens in there. And who has time for that?
[/stextbox]
Download final Script:
Script listing:
Version 1.1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
<#
.Synopsis
Propagate an Active directory account (Group or User) on one or several Sharepoint Sites.
.DESCRIPTION
Propagate an Active directory account (Group or User) on one or several Sharepoint Sites.
.PARAMETER Account
Specify the group that should be added to the different sites.
.PARAMETER WebAppURL
The Web Application URL where it should connect to.
.PARAMETER ExclusionListFile
Specify a text file that contains sites (in link format) that you would like to skip during this process.
The text file have a link per line, without comas etc.
Example of of content that C:tempExlusionList.txt could have:
Https://Sp.lab.District.com/Projects/Client1“
Https://Sp.Lab.district.com/Projects/Client4″
.EXAMPLE
Set-SharepointSecurityGroupOnSites -Account ‘labG_AllSharepointSites_RW’ -WebAppURL ‘Https://Sp.lab.district.com’ -ExclusionFile
.EXAMPLE
Another example of how to use this cmdlet
#>
[/fusion_builder_column][fusion_builder_column type=“1_1” background_position=“left top” background_color=“” border_size=“” border_color=“” border_style=“solid” spacing=“yes” background_image=“” background_repeat=“no-repeat” padding=“” margin_top=“0px” margin_bottom=“0px” class=“” id=“” animation_type=“” animation_speed=“0.3” animation_direction=“left” hide_on_mobile=“no” center_content=“no” min_height=“none”][cmdletbinding()]
Param(
[Parameter(Mandatory=$true)]
[string]$Account = ‘labG_AllSharepointSites_RW’,
[Parameter(Mandatory=$true)]
[string]$WebAppUrl = ‘Https://Sp.lab.district.com’,
[Parameter(Mandatory=$true)]
[ValidateScript({
Test-Path $_
})]
[string]$exclusionlistFile
)
write-host ‘Starting operations.’
write-host ‘Loading module and gathering core information’
Add-PSSnapin ‘Microsoft.SharePoint.PowerShell’
$WebApplication = Get-SPWebApplication -Identity $WebAppUrl
$Sites = Get-SPSite -WebApplication $WebApplication
write-host ‘Starting site operations’
try {
$ExclusionList = Get-content -Path $exclusionlistFile -ErrorAction Stop
if (!($ExclusionList.gettype().basetype.name -eq “Array” )){
write-host “The exclusion list is not an array. Be sure to put each link on a new line of the text file $($exclusionlistFile).”
}
else{
if ($ExclusionList){
write-host “Exlusion list file $($ExclusionListFile) has been loaded with the following content:”
write-host “$($exclusionlist)”
}
}
}
catch{
write-host “Could not load the exclusion list. Quiting…”
}
$SPWebApp = Get-SPWebApplication $WebApplicationLink
foreach ($SPSite in $SPWebApp.Sites)
{
if ($ExclusionList -match $SPSite.URL){
write-host “The site $($SPSite) is in the exclusion list. Skipping site…”
continue
}
else{
write-host “The site $($SPSite) is not in the exclusion list. Continuing operations.”
}
if ($SPSite -ne $null)
{
foreach($SPWeb in $SPSite.AllWebs)
{
write-host $SPWeb.URL
if($SPWeb.URL -ne $SPSite.URL)
{
if($SPWeb.HasUniqueRoleAssignments -eq $true)
{
write-host “Working on $($SPWeb.URL)”
#Get Groups
write-host “Getting Groups…”
$memberGroup = $SPWeb.AssociatedMemberGroup
if ($memberGroup -ne $null){
#add user to membergroup
$targetUser = $SPWeb.EnsureUser($Account)
if ($targetUser -eq $null -or “”){
write-host “The target group could not be located”
exit
}
if( !(($memberGroup.Users | Select -ExpandProperty UserLogin) -contains $targetUser.LoginName))
{
$memberGroup.AddUser($targetUser)
write-host “Adding User $user to $($memberGroup)…”
}
if( ($SPWeb.AssociatedMemberGroup.Users | Select -ExpandProperty UserLogin) -contains $targetUser.LoginName)
{
foreach($user in $SPWeb.AssociatedMemberGroup.Users)
{
If (!($user.loginname -eq $targetUser.loginname)){
write-host “Removing user $($user)”
$memberGroup.RemoveUser($user)
Write-Host “User $($user) removed” -ForegroundColor Green
}
}
}
$SPWeb.Update()
$SPWeb.Dispose()
}else{
write-host “The associated groups could not be found for site $($SPWeb).”
}
}
}
else{
write-host “Root site. skipping site.”
}
}
}
else
{
write-host “Site is empty”
}
}
write-host ‘End of Script.’
|
Version 1.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
<#
.Synopsis
Propagate an Active directory account (Group or User) on one or several Sharepoint Sites.
.DESCRIPTION
Propagate an Active directory account (Group or User) on one or several Sharepoint Sites.
.EXAMPLE
Set-SharepointSecurityGroupOnSites -Account ‘labG_AllSharepointSites_RW’ -WebAppURL ‘Https://Sh.lab.district.com’
.EXAMPLE
Another example of how to use this cmdlet
#>
[cmdletbinding()]
Param(
[Parameter(Mandatory=$true)][string]$Account = ‘labG_AllSharepointSites_RW’,
[Parameter(Mandatory=$true)][string]$WebAppUrl = ‘Https://Sh.lab.district.com’,
[Parameter(Mandatory=$false)][string[]]$ExlusionList
)
write-host ‘Starting operations.’
write-host ‘Loading module and gathering core information’
Add-PSSnapin ‘Microsoft.SharePoint.PowerShell’
$WebApplication = Get-SPWebApplication -Identity $WebAppUrl
$Sites = Get-SPSite -WebApplication $WebApplication
write-host ‘Starting site operations’
foreach ($site in $Sites){
#Excluding specefic sites
If ($site.url -contains $NotToTreat ){
write-host “The site $($site.url) will be skipped.”
continue
}
write-host “Working on $($site.url)”
#If Group is present,
$Accounts = Get-SPUser -Web $site.url
write-host “Verifying if Group $($Account) is present…”
if (!($Accounts.userlogin -contains $Account)){
write-host “The group $($Account) Is currently not on to the site $($site.url) and will be added.”
$SpGroup = Get-SPUser -Identity ‘$group’ -web $site.url -ErrorAction SilentlyContinue
if (!($SpGroup)){
write-host “The group $($Account) is not on this site yet. Adding Group.”
try{
New-SPUser -UserAlias $Account -Web $site.Url -PermissionLevel ‘Contribute’ -ErrorAction stop
}
catch{
write-error $_
}
}else {
try{
Set-SPUser -Identity ‘$group’ -Web $site.url -AddPermissionLevel ‘Contributor’ -erroraction STOP
write-host “Sucessfully added the group $($Account) to $($site.url) with Contributor rights.”
}catch{
write-host $_
}
}
}else{
write-host “The account $($Account) is already present on $($site.url)”
}
}
write-host ‘End of Script.’
|
Dig more deeper into it!
Technet Powershell references –> http://technet.microsoft.com/en-us/library/ff678226(v=office.15).aspx
http://manasbhardwaj.net/add-users-sharepoint-group-using-powershell/
Leave A Comment