Troubleshooting

Display PowerShell Full Exception Message with (Out-String)

Posted on Updated on

I was requested to write a detailed PowerShell Script that can log the Caught exception as string.

Actually it wasn’t easy as it looks like at first.

I tried to use write-host with a lot of Exception properties, as below, and all didn’t work as expected, I never found the error location as the Out-of-the-box PowerShell exception.

This is what I expected to see, detailed Exception with location error

then I came across one article mentioned that I need to use Out-String during the catch { }, this gives me exactly the details for the  exception I’m looking for

try
{
$v= 9/0
}
catch
{
write-host ($_ | Out-String) -ForegroundColor Red
}

Now the Exception looks really detailed and meaningful.

Advertisements

Create Test Microsoft O365 Group and Delete it

Posted on Updated on

If you are involved in rolling-out of Microsoft Teams or groups recently, then you may need a test script to create temporary O365 Groups
Using the below PowerShell script, you will be able to do so

Pre-requisites:
——————
You should have :

  1. Client Id
  2. Client Secret
  3. tenant admin Url & Credentials

function Test-Group {
##Get Access Token
$body = @{
scope="https://graph.microsoft.com/.default";
client_id=$AppID;
client_secret=$AppSecret;
grant_type="client_credentials";
}
$accessToken = (Invoke-RestMethod `
-Uri https://login.microsoftonline.com/$AADDomain/oauth2/v2.0/token `
-Method POST `
-Body $body `
-Headers @{"Accept" ="application/json"; "Content-Type"="application/x-www-form-urlencoded"}).access_token
##Create Group
$body = @{
displayName="$prefix$suffix";
description="$prefix$suffix";
groupTypes= @("Unified");
mailEnabled="true";
mailNickname="$prefix$suffix";
securityEnabled="false";
visibility="Private";
#"owners@odata.bind"=@("https://graph.microsoft.com/v1.0/users/5a97df74-a0c9-4fb9-8f9f-26bd29d4bf06");
}| ConvertTo-Json
$NewGroup = (Invoke-WebRequest `
-Uri https://graph.microsoft.com/v1.0/groups `
-Method POST `
-Body $body `
-Headers @{"Authorization" = "Bearer $accessToken"; "Accept" ="application/json"; "Content-Type"="application/json"} )
$NewGroupId = ($NewGroup.Content | ConvertFrom-Json).Id
##Check if group was provisioned
$success = $false
$time = [System.Diagnostics.Stopwatch]::StartNew()
for ($i=0; $i -lt 60; $i+=5) {
Start-Sleep -s 5
try{
Invoke-WebRequest `
-Uri https://graph.microsoft.com/v1.0/groups/$NewGroupId/drive `
-Headers @{"Authorization" = "Bearer $accessToken"; "Accept" ="application/json";} | Out-Null
$success = $true
break
}catch [System.Net.WebException]{
If ($_.Exception.Response.StatusCode.Value__ -ne 404){
throw
}
}
}
if($success){
##Delete Group, you can leave it or keep it based on your needs
# Invoke-RestMethod `
# -Uri https://graph.microsoft.com/v1.0/groups/$NewGroupId `
# -Method Delete `
# -Headers @{"Authorization" = "Bearer $accessToken"; "Accept" ="application/json";} | Out-Null
} else {
Write-Host ModernGroup failed to provision in ([Math]::floor($time.Elapsed.TotalSeconds)) seconds -ForegroundColor Red
Write-Host GroupId: $NewGroupId -ForegroundColor Red
Write-Host CorrelationId: $NewGroup.Headers.'request-id' -ForegroundColor Red
Write-Host Date: $NewGroup.Headers.'Date' -ForegroundColor Red
}
}
$AppID = 'xxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxxxxxx' #Put your AppId
$AppSecret = '**********************************' #Put your Secret
$AADDomain = 'yourtenant.onmicrosoft.com'
for ($i=0; $i -lt 1; $i++) {
$suffix = (Get-Date).Ticks
$prefix = "MSFT_Test_"
Test-Group
}

At the End you will have a test group created

How to get useful Nintex Workflows Analytics from SharePoint?

Posted on Updated on

Nintex is still one of the most effective Workflow platforms, and it have complete suite with SharePoint.

Nintex with SharePoint On-Prem is still hard to be managed and maintained, this before it reaches its threshold very quickly, Nintex stated that its threshold is 30 Million WorkflowProgress items per Nintex Database. To understand what does this means I will quickly describe How Nintex data is stored in Databases, and this is for SharePoint 2016, SharePoint 2013, SharePoint 2010, & also SharePoint 2007.

Every Nintex worklflow is broken down to something named Workflow Instances, and each workflow instances is break down to workflow Progress.
Assume we have a Vacation Approval workflow, every time this workflow runs it generate a workflow instance,  if you re-run it on a single item 100 times, it will generates 100 workflow instances in the Nintex database. depends on the number of components it consist, workflow progress will be generated, so if this Workflow consists of 3 controls (Pause, Query list, Send Mail) then it will generate 3 WF progress records per run.

To get some useful info from the NinteDatabase, run the below commands:


create PROC [dbo].[WorkflowProgressProc] @db nvarchar(50)
AS
IF DB_ID(@db) IS NULL /*Validate the database name exists*/
BEGIN
RAISERROR('Invalid Database Name passed',16,1)
RETURN
END<
BEGIN
CREATE TABLE #tmpBus
(
WorkflowProgress INT,
WorkflowInstance INT,
size int,
NumOfSites int
)
declare @WorkflowProgress int,
@WorkflowInstance int,
@size int,
@NumOfSites int
select @WorkflowProgress= COUNT(*) from dbo.WorkflowProgress (nolock)
select @WorkflowInstance=COUNT(*) from dbo.WorkflowInstance (nolock)
select @size=size * 8.0 / 1024 from sys.master_files where name like @db
select @NumOfSites= count(*) from ( Select SiteID
From WorkflowProgress P inner join WorkflowInstance I
on (P.InstanceID = I.InstanceId)
group by I.SiteID) x
INSERT INTO #tmpBus values(@WorkflowProgress,@WorkflowInstance,@size,@NumOfSites)
END
select * from #tmpBus

After that, run the stored procedure and give the database name as a parameter

exec [WorkflowProgressProc] [NintexWF2013DB]

The result will be as follow:

From experience in Nintex, the threshold can be much more, even till 50 millions item if you have powerful servers. but other than this, you will face alot of delays and Nintex workflow errors.

Also, to get more details about SharePoint Sites vs WorkflowProgress numbers.


Select I.SiteID, Count(P.WorkflowProgressID) NoWFProgress,Count(distinct I.InstanceID) NoWFInstance , MAX(p.TimeStamp) Last_Activity
From WorkflowProgress P inner join WorkflowInstance I (nolock)
on (P.InstanceID = I.InstanceId)
group by I.SiteID
order by I.SiteID

This will give you a good figures about Nintex Analytics in your SharePoint environment.

“Access Denied” to Access Requests list or “Request approval failed” when you process a pending request in SharePoint Online

Posted on Updated on

I have run through a problem today during my work on one of the clients, and this sometimes happened mainly with sites that is migrated to SharePoint Online

 

 

 

This works perfectly fine !