PowerShell - Loop through all SharePoint Website & continue when an error occurred - sharepoint

$ErrorActionPreference = "Continue"
Add-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction "SilentlyContinue"
$webApp = "Https://SharePointSite.com"
$wa = Get-SPWebApplication -identity $webApp
foreach ($site in $wa.Sites) {
foreach ($web in $site.AllWebs) {
$siteURL = $web.Url
Write-Host $siteURL
}
}
The problem is that when it hits the statement foreach ($site in $wa.Sites), and it cannot get the site due to access denied or any error, it would stop. I would like to continue. I tried to TRY CATCH FINALLY, and it still stops when it encounters an error.
I tried to put in -ErrorAction Continue, but it gives me an error message as
you must provide a value expression on the right-hand side of the '-' operator
How do I get around it so it would continue to the site?
I really appreciate your help.
Thanks

If you want to use try..catch, then you must throw terminating errors. Non-terminating errors are not handles by a try..catch block.
try {
Add-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction Stop;
$webApp = "Https://SharePointSite.com"
$wa = Get-SPWebApplication -identity $webApp -ErrorAction Stop;
foreach ($site in $wa.Sites) {
foreach ($web in $site.AllWebs) {
$siteURL = $web.Url
Write-Host $siteURL
}
}
}
catch {
Write-Host -Object ('Error occurred: {0}' -f $_);
}

Related

i am trying to add exception handling in powershell script for azure cloud but try block is not responding when error occurs

#adding wrong parameters for checking the try block
$RGName = "RG1"
$VMName="VM1"
$VMSize="standard_B1ls"
$VirtualMachine = Get-AzVm | Where-Object {$_.ResourceGroupName -eq $RGName } | Where-Object {$_.Name -eq $VMName}
$virtualMachine.HardwareProfile.VmSize = $VMSize
#try block
try{
Update-AzVM -VM $VirtualMachine -ResourceGroupName $RGname
write-host "you are in try block "
}
catch{
write-host "you are in catch block "
}
catch block is not working I need to not print try block write-host is exception occurred instead of print catch write-host

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 delete the ADFPipeline which is having the references Forcefully

I'm actually some automation for my ADF. As a part of that, I'm trying to delete all the ADF V2 pipelines. The problem is my pipelines having many references with different pipelines itself.
$ADFPipeline = Get-AzDataFactoryV2Pipeline -DataFactoryName $(datafactory-name) -ResourceGroupName $(rg)
$ADFPipeline | ForEach-Object { Remove-AzDataFactoryV2Pipeline -ResourceGroupName $(rg) -DataFactoryName $(datafactory-name) -Name $_.name -Force }
And most of the time I get the error like
The document cannot be deleted since it is referenced by "blabla"
I understand the error that it saying some references and cannot be deleted. However, when I tried the same deletion in the azure portal, irrespective of the reference I can able to delete. So I want to find a way that whether it possible to tell that Powershell even though it's having a reference delete it forcefully
Any other inputs much appreciated!
I run into the same issue, found out that it's rather complicated to build the whole dependency graph out of the pipeline's Activities property.
As a working solution (powershell):
function Remove-Pipelines {
param (
[Parameter(Mandatory=$true)]
[AllowEmptyCollection()]
[AllowNull()]
[System.Collections.ArrayList]$pipelines
)
if($pipelines.Count -gt 0) {
[System.Collections.ArrayList]$plsToProcess = New-Object System.Collections.ArrayList($null)
foreach ($pipeline in $pipelines) {
try {
$removeAzDFCommand = "Remove-AzDataFactoryV2Pipeline -dataFactoryName '$DataFactoryName' -resourceGroupName '$ResourceGroupName' -Name '$($pipeline.Name)' -Force -ErrorAction Stop"
Write-Host $removeAzDFCommand
Invoke-Expression $removeAzDFCommand
}
catch {
if ($_ -match '.*The document cannot be deleted since it is referenced by.*') {
Write-Host $_
$plsToProcess.Add($pipeline)
} else {
throw $_
}
}
}
Remove-Pipelines $plsToProcess
}
}
Here is the complete solution for clearing the whole DF: "trigger","pipeline","dataflow","dataset","linkedService"
Param(
[Parameter(Mandatory=$true)][string] $ResourceGroupName,
[Parameter(Mandatory=$true)][string] $DataFactoryName
)
$artfTypes = "trigger","pipeline","dataflow","dataset","linkedService"
function Remove-Artifacts {
param (
[Parameter(Mandatory=$true)][AllowEmptyCollection()][AllowNull()][System.Collections.ArrayList]$artifacts,
[Parameter(Mandatory=$true)][string]$artfType
)
if($artifacts.Count -gt 0) {
[System.Collections.ArrayList]$artToProcess = New-Object System.Collections.ArrayList($null)
foreach ($artifact in $artifacts) {
try {
$removeAzDFCommand = "Remove-AzDataFactoryV2$($artfType) -dataFactoryName '$DataFactoryName' -resourceGroupName '$ResourceGroupName' -Name '$($artifact.Name)' -Force -ErrorAction Stop"
Write-Host $removeAzDFCommand
Invoke-Expression $removeAzDFCommand
}
catch {
if ($_ -match '.*The document cannot be deleted since it is referenced by.*') {
Write-Host $_
$artToProcess.Add($artifact)
} else {
throw $_
}
}
}
Remove-Artifacts $artToProcess $artfType
}
}
foreach ($artfType in $artfTypes) {
$getAzDFCommand = "Get-AzDataFactoryV2$($artfType) -dataFactoryName '$DataFactoryName' -resourceGroupName '$ResourceGroupName'"
Write-Output $getAzDFCommand
$artifacts = Invoke-Expression $getAzDFCommand
Write-Output $artifacts.Name
Remove-Artifacts $artifacts $artfType
}
The same approach can be adapted for "Set-AzDataFactoryV2Pipeline" command as well.
It worth to mention that along with dependencies tracking, Remove/Set artifact's sequence should be right (because of cross artifacts' dependencies).
For Set - "linkedService","dataset","dataflow","pipeline","trigger"
For Remove - "trigger","pipeline","dataflow","dataset","linkedService"
Hello and thank you for the question. According to the Remove-AzDataFactoryV2Pipeline doc, the -Force flag simply skips the confirmation prompt. It does not actually 'Force' the deletion in spite of errors.
Since you are already doing automation, might I suggest leveraging the error message to recursively attempt to delete the referencing pipeline. $error[0] gets the most recent error.
(Pseudocode)
try_recurse_delete( pipeline_name )
do_delete(pipeline_name)
if not $error[0].contains("referenced by " + pipeline_name)
then return true
else
try_recurse_delete( get_refrencer_name($error[0]) )
Given that pipeline dependencies can be a many-to-many relationship, subsequent pipelines in your for-each loop might already be deleted by the recursion. You will have to adapt your code to react to 'pipeline not found' type errors.

Creating "mysite" through powershell throws error

I'm trying to create a "mysite" though powershell but I run into an error that I have a really hard time find the answer.
This is the error i get:
New-Object : Exception calling ".ctor" with "1" argument(s): "UserProfileApplicationNotAvailableException_Logging :: UserProfileApplicationProxy.ApplicationProperties ProfilePropertyCache does not have c05da7c0-d405-4655-a7fa-08e271f4174d"
This is my PS Code:
param
(
[Parameter(Mandatory=$true)]
[string]$username
)
asnp *sh*
$mysite = Get-SPSite "http://mysite.dev.loc"
$context = Get-SPServiceContext $mysite
$upm = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)
#Create user profile
$profile = $upm.ResolveProfile($username)
if(!$profile)
{
Write-Host "$profile does not have a profile. Can't create personal site"
}
elseif($profile)
{
if($profile.PersonalSite -eq $Null)
{
$profile.CreatePersonalSite()
Write-Host "Personal site created"
}
else
{
Write-Warning "$username already has a personal site"
}
}
looking at this https://social.technet.microsoft.com/Forums/office/en-US/d8ee4f32-c380-4d1d-9f26-59765aae4a7f/getting-errors-when-i-try-to-create-newobject-for-userprofile-manager-powershell-sharepoint-2010?forum=sharepointadminprevious
it looks like a permissions issue. try running it as administrator and running the program itself with admin powers.

Powershell runspaces won't execute

I'm at a bit of a loss with the script I am trying to pull.
In short: I want to scan my domain-computers for WinRM connectivity - and I can do that just fine. The problem is, that it takes up to 5 minutes to finish - thats why I want to multithread the task.
Working NON MULTITHREAD code:
# this is normaly a textfile with lots of machine hostnames
$computers = "PC100","PC106","PC124","PC115","PC21"
function checkMachine($computers){
$ErrorActionPreference = "Stop"
foreach ($item in $computers){
#the function contest only performs a ping and returne $true or $false
$connection = ConTest($item)
if($connection){
try{
$winRM = test-wsman -ComputerName $item
if($winRM){
write-host "winRM"
[void] $objListboxLeft.Items.Add($item)
}
}catch{
write-host "NO winRM"
[void] $objListboxCenter.Items.Add($item)
}
}else{
write-host "offline"
[void] $objListboxRight.Items.Add($item)
}
}
}
this is basically just a small portion of what my skript does/will do but it's the part that takes ages.
My failing runspace test - I basically fail to get ANY results at all. Nothing in textboxes, no output on my commandline and I basically have no idea what I am doing wrong.
Multithread code:
function MulticheckMachine($computers){
$ErrorActionPreference = "Stop"
$runspaceCollection = #()
$runspacePool = [RunspaceFactory]::CreateRunspacePool(1,5)
$runspacePool.open()
$scriptBlock = {
Param($item)
$connection = ConTest($item)
if($connection){
try{
test-wsman -ComputerName $item
$winRM = test-wsman -ComputerName $item
if($winRM){
write-host "winRM"
[void] $objListboxLeft.Items.Add($item)
}
}catch{
write-host "NO winRM"
[void] $objListboxCenter.Items.Add($item)
}
}else{
write-host "offline"
[void] $objListboxRight.Items.Add($item)
}
}
Foreach($item in $computers){
$powershell = [PowerShell]::Create().AddScript($scriptBlock).AddArgument($item)
$powershell.runspacePool = $runspacePool
[Collections.Arraylist]$runspaceCollection += New-Object -TypeName PSObject -Property #{
Runspace = $powershell.BeginInvoke()
PowerShell = $powershell
}
$runspaceCollection
}
While($runspaceCollection){
Foreach($runspace in $runspaceCollection.ToArray()){
If($runspace.Runspace.IsCompleted){
$runspace.PowerShell.EndInvoke($runspace.Runspace)
$runspace.PowerShell.Dispose()
$runspaceCollection.Remove($runspace)
}
}
}
}
the runspace code comes from a mix of these guides:
http://blogs.technet.com/b/heyscriptingguy/archive/2013/09/29/weekend-scripter-max-out-powershell-in-a-little-bit-of-time-part-2.aspx
http://newsqlblog.com/2012/05/22/concurrency-in-powershell-multi-threading-with-runspaces/
I hope someone can help me out and tell me where/why I fail. Thanks!
Well, thanks for the hints but the problem was far more basic.
I was trying to get my data at the wrong position. Also, I simplified my script a bit. I don't call functions in functions anymore.
Note1: I did not realize I can/need to work with return values within my scriptblock for the runspace.
Note2: I am now collecting my data and inserting it into my listboxes (or where-ever else I wanted to) at the end of my function within the while loop - where I basically build-back my runspaces.
Note3: All "GUI parts" I reference to are located in a different file and do exist!
I got the duration down to roughly 20 seconds (from almost 5 minutes before)
The number of threads I use is a bit random, it's one of the combinations that works fastest.
Code:
function multiCheckMachine($computers){
$ErrorActionPreference = "Stop"
$runspaceCollection = #()
$runspacePool = [RunspaceFactory]::CreateRunspacePool(1,50)
$runspacePool.open()
$scriptBlock = {
Param($item)
$FQDNitem = "$item.domain.com"
$address = nslookup $FQDNitem
if($address -like "addresses*"){
$address = $address[5] -replace ".* ",""
}else{
$address = $address[4] -replace ".* ",""
}
$con = ping -n 1 $address
if($con[2] -like "*Bytes*"){
$winRM = test-wsman -ComputerName $item
if($winRM){
return "$item.winRM"
}else{
return "$item.NOremote"
}
}else{
return "$item.offline"
}
}
Foreach($item in $computers){
$powershell = [PowerShell]::Create().AddScript($scriptBlock).AddArgument($item)
$powershell.runspacePool = $runspacePool
[Collections.Arraylist]$runspaceCollection += New-Object -TypeName PSObject -Property #{
Runspace = $powershell.BeginInvoke()
PowerShell = $powershell
}
}
While($runspaceCollection){
Foreach($runspace in $runspaceCollection.ToArray()){
If($runspace.Runspace.IsCompleted){
if($runspace.PowerShell.EndInvoke($runspace.Runspace) -like "*winrm"){
[void] $objListboxOnline.Items.Add($runspace.PowerShell.EndInvoke($runspace.Runspace).split(".")[0])
}elseif($runspace.PowerShell.EndInvoke($runspace.Runspace) -like "*NOremote"){
[void] $objListboxNoWinRM.Items.Add($runspace.PowerShell.EndInvoke($runspace.Runspace).split(".")[0])
}elseif($runspace.PowerShell.EndInvoke($runspace.Runspace) -like "*offline"){
[void] $objListboxOffline.Items.Add($runspace.PowerShell.EndInvoke($runspace.Runspace).split(".")[0])
}
$runspace.PowerShell.Dispose()
$runspaceCollection.Remove($runspace)
}
}
}
}

Resources