Enabling Sharepoint Features With Powershell - sharepoint

I am new to PowerShell and have been asked to modify a script that is used to activate features on a site. The script has some latency issues between the two feature activations, so I decided to make a new function that will enable the feature and sleep or delay until the feature is finished enabling. Will this work? And if so, how can I tell that the feature is finished activating?
# This is a function that enable's a Sharepoint Feature and Sleeps Until Its Finished Enabling
function Feature-Enable
{param ([string]$ID, [string]$URL)
#Enable Feature
Enable-SPFeature -Identity $ID -url $URL -Confirm:$false
#Sleep Until Feature is Done Enabling
}
#Set parameters/variables for script
$serverName = "someServerName"
$rootwebUrl = "someRootUrl"
$currentpath=Split-Path -Path $MyInvocation.MyCommand.Path -Parent
$siteURL = "http://" + $servername + $rootwebURL
$start = Get-Date -DisplayHint Time
# check to ensure Microsoft.SharePoint.PowerShell is loaded
$snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
if ($snapin -eq $null) {
Write-Host "Loading SharePoint Powershell Snapin"
Add-PSSnapin "Microsoft.SharePoint.Powershell"
}
# Active Site Collection Features (in order)
write-host ""
write-host "----------------------------------------"
write-host "Begin activation of site collection features"
write-host "----------------------------------------"
write-host ""
Feature-Enable –identity "3cbf5d1e-ff2e-48d2-82a4-99b060381268" -URL $siteUrl
#NOTE: POTENTIAL LATENCY ISSUES. MAY NEED TO INSERT DELAY TIMER!
Feature-Enable –identity "bbde524e-9293-468e-84f7-fdb763ffa309" -URL $siteUrl
write-host ""
write-host "----------------------------------------"
write-host "Activation of site collection features - DONE!"
write-host "----------------------------------------"
write-host ""
$end= Get-Date -DisplayHint Time
Write-Host "Started at: " $start " Ended at: " $end;

function WaitForJobToFinish([string]$SolutionFileName)
{
$JobName = "*solution-deployment*$SolutionFileName*"
$job = Get-SPTimerJob | ?{ $_.Name -like $JobName }
if ($job -eq $null)
{
Write-Host 'Timer job not found'
}
else
{
$JobFullName = $job.Name
Write-Host -NoNewLine "Waiting to finish job $JobFullName"
while ((Get-SPTimerJob $JobFullName) -ne $null)
{
Write-Host -NoNewLine .
Start-Sleep -Seconds 2
}
Write-Host "Finished waiting for job.."
}
}

Related

Issues having a retry count work in powershell

I have a Powershell script that checks on a set of VM status before starting them. If the VM'S are in deallocating mode there should be a sleep and retry on 30 seconds. The code does not do a a retry. The code does a vm start in batches on 2 for vm's with wilcards as mentioned below in an order.
Need help if possible
$ResName= "resvmtest"
$action="start"
if($action -eq "start"){
$vnames=#('*dom*','*DBs*','*')
foreach($vname in $vnames) {
Write-Host "Starting VM with "$vname
$vmList = Get-AzVM -ResourceGroupName $ResName -Name $vname -Status | Select-Object Name, PowerState, ResourceGroupName
do{
$batch = #{
Skip = 0
First = 2
}
do{
foreach($vm in ($vmList | Select-Object #batch)){
$Stoploop = $false
[int]$Retrycount = "0"
do {
try {
if($vm.PowerState -eq "VM Deallocated"){
Write-Host "Job completed"
$Stoploop = $true
}
}
catch {
if ($vm.PowerState -eq "VM Deallocatting") {
Write-Host "VM Still not Deallocated"
Start-Sleep -Seconds 10
$Retrycount = $Retrycount + 1
}
}
}
While ($Stoploop -eq $false)
$params = #($vm.Name, $vm.ResourceGroupName,$vm.PowerState)
$job = Start-Job -ScriptBlock {
param($ComputerName,$serviceName,$statuses)
Start-AzVM -Name $ComputerName -ResourceGroupName $serviceName
} -ArgumentList $params
}
Wait-Job -Job $job
Get-Job | Receive-Job
$batch.Skip += 2
}
until($batch.skip -ge $vmList.count)
}
while($job.state -ne "Completed")
}
}
If you just want to wait for a VM's PowerState turns to VM Deallocated from VM Deallocatting, try the code below:
$vms = Get-AzVm -Status| Select-Object Name, PowerState,ResourceGroupName
#pick certain vm for demo here.
$vm = $vms[1]
$retryCount = 0
while($vm.PowerState -eq 'VM deallocating'){
Write-Host "waiting for VM deallocated..."
Start-Sleep -Seconds 5
$retryCount +=1
Write-Host "check count:$retryCount"
#get latest vm status
$vm.PowerState = (Get-AzVM -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -Status).Statuses[1].DisplayStatus
Write-Host "vm current state:"$vm.PowerState
}
Write-Host "vm new state:" + $vm.PowerState
Result:

Error: Cannot find an overload for "restore" and the argument count: "1"

I am getting this error from the following code. It's coming from $Context.Load($RecycleBinItems). Any idea what's wrong with the code? I am attempting to restore all recyclebin items.
Add-Type -Path "C:\Program Files\WindowsPowerShell\Modules\SharePointPnPPowerShellOnline\3.17.2001.2\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\WindowsPowerShell\Modules\SharePointPnPPowerShellOnline\3.17.2001.2\Microsoft.SharePoint.Client.Runtime.dll"
Import-Module 'Microsoft.PowerShell.Security'
#Get the Site Owners Credentials to connect the SharePoint
$SiteUrl = "https://phaselinknet.sharepoint.com"
$UserName = Read-host "Enter the Email ID"
$Password = Read-host - assecurestring "Enter Password for $AdminUserName"
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $Password)
# Once Connected, get the Site information using current Context objects
Try {
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)
$Context.Credentials = $Credentials
$Site = $Context.Site
$RecycleBinItems = $Site.RecycleBin
$Context.Load($Site)
$Context.Load($RecycleBinItems)
$Context.ExecuteQuery()
Write-Host "Total Number of Files found in Recycle Bin:" $RecycleBinItems.Count
}
catch {
write - host "Error: $($_.Exception.Message)" - foregroundcolor Red
}
# using for loop to restore the item one by one
Try {
if($RecycleBinItems)
{
foreach($Item in $RecycleBinItems)
{
$Site.RecycleBin.restore($Item.ID)
#Write-Host "Item restored:"$Item.Title
}
}
}
catch {
write-host "Error: $($_.Exception.Message)" -foregroundcolor Red
}
The error message is giving you you answer. There is not a version of the method Restore that takes 1 parameter.
You need to load up a list of items simular to this
$Item = $RecycleBin | Where{$_.Title -eq $ItemName}
Then call restore for the items.
if($Item -ne $null)
{
$Item.Restore()
}
Thanks for the tip. So I load up the first 10 items in the recyclebin, and Write-Host does write out the correct files, but the $Item.Restore() does noting as the files are still not restored:
$itemsToRestore = #()
for ($i = 0; $i -lt 10; $i++)
{
$Item = $RecycleBinItems[$i]
$itemsToRestore += $Item
}
Write-Host "Total Number of Files to Restore:" $itemsToRestore.Count
foreach($item in $itemsToRestore)
{
Write-Host "Item:" $Item.Title
$item.Restore()
}
I found the problem. I missed $Context.ExecuteQuery() after $Item.Restore(). It works now.

How to do a full site collecion level re-index in sharepoint online?

After adding a new managed property I need to do a full site collection level or tenant level re-indexing to get the search crawler run. But I could not find a way to do this in SharePoint online.Is there a way to do this?
There is a script to re-index a SharePoint online site collection via CSOM. I think this will help you to re-index your 100+ subsites.
#Grab the tenant information
$username = Read-Host "Enter the tenant admin account login"
$password = Read-host -AsSecureString "Enter the admin account password"
$siteUrl = Read-Host "Please enter the site collection URL to re-index"
Write-Host "Would you like to populate the managed properties on all lists post re-crawl (ex. Cross Site Publishing)?" -ForegroundColor Green
Write-Host "1. Yes - enable managed properties on all lists in this site!" -ForegroundColor Cyan
Write-Host "2. No - Turn off managed properties in all lists in the site!" -ForegroundColor Blue
Write-Host "3. No - Just re-index the site!" -ForegroundColor Red
$enableAllManagedProperties = Read-Host "Choice [1-3]?"
$date = (Get-Date).ToString("yyyyMMdd")
#Load the assemblies
$load1 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
$load2 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
$load3 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.UserProfiles")
if (!$load1) {
$script_folder = (Split-Path -Parent $MyInvocation.MyCommand.Path)
$load1 = [System.Reflection.Assembly]::LoadFile($script_folder + "\Microsoft.SharePoint.Client.dll")
if (!$load1) {
Write-Host "Failed to load Microsoft.SharePoint.Client.dll - please ensure it is in the same location as the PS1." -ForegroundColor Red
write-host "Alternatively, install the SPO Client Components SDK from http://www.microsoft.com/en-us/download/details.aspx?id=42038" -ForegroundColor Red
exit;
}
}
if (!$load2) {
$script_folder = (Split-Path -Parent $MyInvocation.MyCommand.Path)
$load2 = [System.Reflection.Assembly]::LoadFile($script_folder + "\Microsoft.SharePoint.Client.Runtime.dll")
if (!$load2) {
Write-Host "Failed to load Microsoft.SharePoint.Client.Runtime.dll - please ensure it is in the same location as the PS1." -ForegroundColor Red
write-host "Alternatively, install the SPO Client Components SDK from http://www.microsoft.com/en-us/download/details.aspx?id=42038" -ForegroundColor Red
exit;
}
}
if (!$load3) {
$script_folder = (Split-Path -Parent $MyInvocation.MyCommand.Path)
$load3 = [System.Reflection.Assembly]::LoadFile($script_folder + "\Microsoft.SharePoint.Client.UserProfiles.dll")
if (!$load3) {
Write-Host "Failed to load Microsoft.SharePoint.Client.UserProfiles.dll - please ensure it is in the same location as the PS1." -ForegroundColor Red
write-host "Alternatively, install the SPO Client Components SDK from http://www.microsoft.com/en-us/download/details.aspx?id=42038" -ForegroundColor Red
exit;
}
}
function Connect-SPO($siteUrl) {
$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
$clientContext.Credentials = $credentials
if (!$clientContext.ServerObjectIsNull.Value) {
Write-Host "Connected to SharePoint Online site: '$siteUrl'" -ForegroundColor Green
}
$rootWeb = $clientContext.Web
processWeb($rootweb)
}
function processWeb($web) {
$subWebs = $web.Webs
$clientContext.Load($web)
$clientContext.Load($web.AllProperties)
$clientContext.Load($subWebs)
try
{
$clientContext.ExecuteQuery()
}
catch
{
write-host "Error on $($clientContext) - $($_)" -ForegroundColor Red
Write-Host "It's possible you are not an administrator on the site collection - Exiting the script" -ForegroundColor Red
Sleep 10
Exit
}
Write-Host "Web URL:" $web.Url -ForegroundColor White
if ( $enableAllManagedProperties -ne "3" ) {
Set-AllManagedProperties -web $web -clientContext $clientContext -enableAllManagedProps $enableAllManagedProperties
}
[int]$version = 0
$allProperties = $web.AllProperties
if ( $allProperties.FieldValues.ContainsKey("vti_searchversion") -eq $true ) {
$version = $allProperties["vti_searchversion"]
}
$version++
$allProperties["vti_searchversion"] = $version
Write-Host "-- Updated search version: " $version -ForegroundColor Green
$web.Update()
$clientContext.ExecuteQuery()
# No need to process subwebs if we only mark site collection for indexing
if ($enableAllManagedProperties -ne "3") {
foreach ($subWeb in $subWebs) {
processWeb($subWeb)
}
}
}
function Set-AllManagedProperties( $web, $clientContext, $enableAllManagedProps ) {
$lists = $web.Lists
$clientContext.Load($lists)
$clientContext.ExecuteQuery()
foreach ($list in $lists) {
Write-Host "--" $list.Title
if ( $list.NoCrawl ) {
Write-Host "-- Skipping list due to not being crawled" -ForegroundColor Yellow
continue
}
$skip = $false;
$eventReceivers = $list.EventReceivers
$clientContext.Load($eventReceivers)
$clientContext.ExecuteQuery()
foreach ( $eventReceiver in $eventReceivers ) {
if ( $eventReceiver.ReceiverClass -eq "Microsoft.SharePoint.Publishing.CatalogEventReceiver" ) {
$skip = $true
Write-Host "-- Skipping list as it's published as a catalog" -ForegroundColor Yellow
break
}
}
if ( $skip ) {continue}
$folder = $list.RootFolder
$props = $folder.Properties
$clientContext.Load($folder)
$clientContext.Load($props)
$clientContext.ExecuteQuery()
if ( $enableAllManagedProps -eq "1" ) {
Write-Host "-- Enabling all managed properties" -ForegroundColor Green
$props["vti_indexedpropertykeys"] = "UAB1AGIAbABpAHMAaABpAG4AZwBDAGEAdABhAGwAbwBnAFMAZQB0AHQAaQBuAGcAcwA=|SQBzAFAAdQBiAGwAaQBzAGgAaQBuAGcAQwBhAHQAYQBsAG8AZwA=|"
$props["IsPublishingCatalog"] = "True"
}
if ( $enableAllManagedProps -eq "2" ) {
Write-Host "-- Disabling all managed properties" -ForegroundColor Green
$props["vti_indexedpropertykeys"] = $null
$props["IsPublishingCatalog"] = $null
}
$folder.Update()
$clientContext.ExecuteQuery()
}
}
#SPO Credentials
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $Password)
Connect-SPO -siteUrl $siteurl
if ($version -ne "$null" ) {
Write-Host "Re-index has should now have been succesfully triggered for $siteurl - Please remember that this can take some time before the crawl picks up the index." -ForegroundColor Cyan
}
https://gallery.technet.microsoft.com/office/Re-index-a-Sharepoint-e70d285b
Note: This will not improve crawl time, merely ensure items are re-indexed.
You need to go to the Site Settings > Search and Offline Availability link and then press the reindex option as in below image.
You need to be site collection admin or owner to view these settings:
Updated as per comments:
To trigger a full site collections reindex, you need to make use of PS script as in this link.

Thread does not create multiple VMs (session issue)

Data is taken from *.CSV file. Script should create in my test case 2 VM on the same vcenter but in different thread. Need guidance how to solve this.
cls
Add-PSSnapin VMware.VimAutomation.Core | Out-Null
#import VM settings
$VMs = Import-CSV '...\Data.csv' -UseCulture
#array for connections
$server = #()
#threads
$Throttle = 2
# Create session state
$sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
# Create runspace pool consisting of runspaces
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $Throttle, $sessionState, $Host)
$RunspacePool.Open()
#array for jobs
$Jobs = #()
$global:DefaultVIServer
$ScriptBlocky = {
Param ($VM, $ses)
Add-PSSnapin VMware.VimAutomation.Core | Out-Null
Write-Host $VM.vm_name "Father session: " $ses.SessionSecret
$sessionf = Connect-VIServer $VM.vs_xstream__vc_host -Session $ses.SessionSecret -wa 0
Write-Host $VM.vm_name "Child session: " $sessionf.SessionId
$domain_name = $VM.FQDN.split('.')
Write-Host $domain_name
#Random for testing purposes
$OSspec = ("BasicLinuxSpec_rand{0}" -f (Get-Random))
# Create new OS Customization Specification template for further usage
New-OSCustomizationSpec –Name $OSspec –Domain ("{0}.{1}" -f $domain_name[1],$domain_name[2]) –DnsServer $VM.DNS,$VM.DNS2 –NamingScheme VM –OSType Linux
Get-OSCustomizationSpec $OSspec -Server $VM.vs_xstream__vc_host | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping -IpMode UseStaticIp -IpAddress $VM.Ipaddress -SubnetMask $VM.NetMask -DefaultGateway $VM.Gateway
Write-Host $VM.vm_name "OSspec: "$OSspec
Write-Host $VM.vm_name "Cluster: "$VM.Cluster
Write-Host $VM.vm_name "Host: "$VM.vs_xstream__vc_host
# Selecting random Cluster for VMs deployment
$ClusterHost = Get-Cluster $VM.Cluster -server $VM.vs_xstream__vc_host | Get-VMHost | Get-Random
Write-Host "================="
Write-Host $VM.vm_name "ClusterHost " $ClusterHost
Write-Host "================="
New-Vm -VMhost $ClusterHost -Name $VM.vm_name -Server $VM.vs_xstream__vc_host -Datastore $VM.Datastore -Template $VM.Template -Description $VM.Description -DiskStorageFormat "Thin" -OScustomizationSpec $OSspec
Remove-OSCustomizationSpec $OSspec -Server $VM.vs_xstream__vc_host -confirm:$false
}
Write-Host ("Starting script: {0}" -f (Get-Date))
$startTime = Get-Date
$count = 0
ForEach($VM in $VMs)
{
$count = $count + 1
Write-Host $VM.vs_xstream__vc_host
Write-Host "Current connections:"
$Global:DefaultVIServers.count
$ses = Connect-VIServer $VM.vs_xstream__vc_host -User $VM.vs_xstream__vc_admin -Password $VM.vs_xstream__vc_password -wa 0
$Job = [powershell]::create()
$Job.RunspacePool = $RunspacePool
$Job.AddScript($ScriptBlocky).AddParameter("VM", $VM).AddParameter("ses", $ses)
Write-Host "Adding job to jobs list"
$Jobs += New-Object PSObject -Property #{
RunNum = $count
Job = $Job
Result = $Job.BeginInvoke()
}
#Disconnect-VIServer $VM.vs_xstream__vc_host -Confirm:$false -Force
}
Write-Host "Waiting.." -NoNewline
Do {
Write-Host "." -NoNewline
Start-Sleep -Seconds 1
} While ( $Jobs.Result.IsCompleted -contains $false)
$endTime = Get-Date
$totalSeconds = "{0:N4}" -f ($endTime-$startTime).TotalSeconds
Write-Host "All jobs finished in $totalSeconds seconds"
Results:
Name Port User
---- ---- ----
10.xxx.xx.10 443 VSPHERE.LOCAL\do1xstream
Starting script: 2/29/2016 2:48:20 PM
10.xxx.xx.10
Current connections:
1
Adding job to jobs list
10.xxx.xx.10
Current connections:
1
The specified mount name 'vmstores' is already in use.
The specified mount name 'vis' is already in use.
virtual38 Father session: f8bafd42e6b7c85aa313e2896eba11c0f9f876cf
Adding job to jobs list
virtual38 Child session: f8bafd42e6b7c85aa313e2896eba11c0f9f876cf
virtual38 domain com
Waiting...virtual39 Father session: f8bafd42e6b7c85aa313e2896eba11c0f9f876cf
virtual39 Child session:
virtual39 domain com
virtual39 OSspec: BasicLinuxSpec_rand618798101
virtual39 Cluster: do1mgmt
virtual39 Host: 10.xxx.xx.10
=================
virtual39 ClusterHost
=================
virtual38 OSspec: BasicLinuxSpec_rand581276505
virtual38 Cluster: do1mgmt
virtual38 Host: 10.xxx.xx.10
.=================
virtual38 ClusterHost 10.xxx.xx.2
=================
..............
As result shows because virtual38 was first in line it has session information and can perform actions.
maybe i am wrong about this I think session isssue is preventing to create second VM (virtual39 )
Update/notice: I realized that when threads $Throttle = 1 then both VM is created, when I set $Throttle = 2 or more then only one of them (first one) is created.
Any suggestions?
Believe me or not but I found what was wrong. Script is working, but when connecting to new session or existing one (or even different vCenter, when is need to create VM in more then one vCenter environment) DefaultVIServers variable is modified and session drops.
Solution:
* Create all connection to vCenter's before all other actions so connection would be stable. for example:
# Iterate and connect to all vCenters so connections to them will be stable and read only
ForEach($VM in $VMs)
{
If ($VM.Use -eq 1)
{
If($server.Contains($VM.vs_xstream__vc_host) -eq $FALSE)
{
$server += $VM.vs_xstream__vc_host
$AllSessions += Connect-VIServer $VM.vs_xstream__vc_host -User $VM.vs_xstream__vc_admin -Password $VM.vs_xstream__vc_password -NotDefault
Write-Host "Connected to: " $VM.vs_xstream__vc_host
}
}
}
After all work is done i simply disconnect from all sessions
# Disconnect all created sessions
ForEach($item in $server)
{
Write-Host ("Disconnecting from {0}...." -f ($item))
Disconnect-VIServer $item -Confirm:$false
}
Now script works perfectly and creates VM in different or the same vCenter. if anyone will experience any problems with it let me know.

Get programmatically User Roles and Permissions in SSRS 2008

I use SSRS 2008 on Windows 2008 R2.
How can I get the user list of roles and permissions (Reports Manager Roles such as Browser, Content Manager, etc) using Powershell or C# (programmatically)?
Any suggestions ?
Notes:
"Folder Settings" area where you can specify roles for a user - "Content Manager," "Publisher," "Browser," "Report Builder," and "My Reports"
SSRS has 2 security/role sections available in the web GUI: Folder Settings and Site Settings.
I try with my script powershell.
References: http://www.bi-rootdata.com/2015/03/list-ssrs-items-permissions-using.html by Anup Agrawal comment
Usage:
$ScriptDirectory = Split-Path $MyInvocation.MyCommand.Path
Clear-Host
Write-Host $ScriptDirectory
Write-Host $env:COMPUTERNAME -ForegroundColor Yellow
Write-Host $env:USERNAME -ForegroundColor Yellow
$ReportServerUri = 'http://localhost/ReportServer/ReportService2005.asmx'
$InheritParent = $true
$SourceFolderPath = '/'
$outSSRSSecurity=#()
$Proxy = New-WebServiceProxy -Uri $ReportServerUri -Namespace SSRS.ReportingService2005 -UseDefaultCredential
$items = $Proxy.ListChildren($sourceFolderPath, $true)|Select-Object Type, Path, Name|Where-Object {$_.type -eq "Folder"};
foreach($item in $items)
{
#Write-Host $item
if ($item.Name -ne "TestsCustomCDR")
{
#continue;
}
Write-Host $item.Path -ForegroundColor Yellow
Write-Host $item.Name -ForegroundColor Green
Add-Member -InputObject $item -MemberType NoteProperty -Name PolicyGroupUserName -Value '';
foreach($policy in $Proxy.GetPolicies($item.path, [ref]$InheritParent))
{
Write-Host $policy.GroupUserName
$objtemp=$item.PsObject.Copy();
$objtemp.PolicyGroupUserName=$policy.GroupUserName;
$outSSRSSecurity += $objtemp;
$objtemp.reset;
}
}
$outSSRSSecurity|Export-csv SSRSSecurityOutput.csv -NoTypeInformation;

Resources