Tuesday, 21 August 2018

How to change E-mail address of a Guest user in Office 365

Office 365 team extending its supports to add external users in many services like Office 365 groups, SharePoint groups, etc to provide collaboration experience with customers and clients. In Office 365, the guest users are represented by a mail user objects, so if you want to change email address for the existing guest user account, you can use the Exchange powershell cmdlet Set-MailUser.
Set-MailUser <mail_alias_of_guest_user> -WindowsEmailAddress <new email addresss>

Note:

If you don't have enough admin privilege to use this cmdlet, you can just remove the existing guest account and add again with new email address.

Thursday, 2 August 2018

How to find all digitally signed or encrypted emails in Outlook App

In this post, I am going to explain how to search and filter only the digitally signed emails or encrypted messages. By normal Outlook search we can filter emails by subject and message body, but we can't use this normal filter to search signed messages. For this case, we need to use Advanced Filter option and filter mails by its Message Class type.

You can find some of Message Class types in below list.
  • IPM.Note - Normal e-mail message.
  • IPM.Note.SMIME - The message is encrypted and can also be signed
  • IPM.Note.SMIME.MultipartSigned - The message is clear signed.
You can find the entire list here : E-mail message MessageClass types

Steps to filter messages by Message Class in Outlook

  • Go to Inbox (other mail folder), select Filter Email from the group Find in the Ribbon and click More Filters.
How to find all Digitally Signed and Encrypted Mails in Outlook App
  • Now you can see the Search tab open, select Search Tools under the group Options and click Advanced Find.
How to find signed messages or encrypted emails in outlook
  • Now you can see the Advanced Find window, click the tab Advanced -> Field -> All Mail fields -> Message Class as shown in below figure.
How to find signed messages or encrypted emails in outlook
  • Apply the contains condition in Message Class with the value IPM.Note.SMIME to search both signed and encrypted messages. 
Filter messages by Message Class in Outlook 2016
  • You need to apply exactly condition with the value IPM.Note.SMIME to filter only encrypted messages and apply exactly condition with the value IPM.Note.SMIME.MultipartSigned to list only signed messages that are not encrypted.
  • Once you have added the search criteria, then click Find Now button to scan the results.
Filter messages by Message Class in Outlook 2016

Tuesday, 31 July 2018

Export OneDrive for Business Users Storage Report using Powershell

In this post, I am going to share Powershell script to find and export current storage size used by every OneDrive users, maximum storage quota and warning size of all OneDrive sites to CSV file. We can easily find OneDrive for Business (ODFB) sites storage details using SharePoint management powershell cmdlet Get-SPOSite.

Before proceed, Install and Connect SharePoint Online PowerShell Module. Run the below commands after replacing your SPO Admin site url to connect SPO Online service.
$AdminSiteURL="https://<your tenant name>-admin.sharepoint.com"
#Connect to SharePoint Online Admin Site
Connect-SPOService -Url $AdminSiteURL
The below command retrieves all personal sites and how much storage space (in MB) used by OneDrive users.
Get-SPOSite -IncludePersonalSite $true -Limit All -Filter "Url -like '-my.sharepoint.com/personal/'" |
Select Owner, StorageUsageCurrent, Url

Export OneDrive for Business users storage size report to CSV

The below powershell script get and export all personal sites and storage details to csv file.
$Result=@()
#Get all OneDrive for Business sites
$oneDriveSites = Get-SPOSite -IncludePersonalSite $true -Limit All -Filter "Url -like '-my.sharepoint.com/personal/'"
$oneDriveSites | ForEach-Object {
$site = $_
$Result += New-Object PSObject -property @{ 
UserName = $site.Owner
Size_inMB = $site.StorageUsageCurrent
StorageQuota_inGB = $site.StorageQuota/1024
WarningSize_inGB =  $site.StorageQuotaWarningLevel/1024
OneDriveSiteUrl = $site.URL
}
}
$Result | Select UserName, Size_inMB, StorageQuota_inGB, WarningSize_inGB, OneDriveSiteUrl |
Export-CSV "C:\\OneDrive-for-Business-Size-Report.csv" -NoTypeInformation -Encoding UTF8

CSV output of OneDrive for Business (ODFB) users storage report:

Export OneDrive Users Current Storage Size Report using Powershell

Friday, 20 July 2018

How to Reuse a Deleted SharePoint Site Name and Site Url

When you delete a SharePoint Site from Office 365, by default the deleted site will be retained in the Site Collection Recycle Bin for 93 days (Retention Period) and if you have deleted a site collection, then the site collection will be retained in Tenant Recycle Bin.

The deleted sites are automatically emptied from the Site Collection/Tenant Recycle Bin after the retention period. You can restore a deleted site before this retention period time end.

Scenario 1 :

Consider that you have deleted a team site and you want to create another site with same name and site url. In this case, you can create a site with the same name but you can’t reuse the deleted site url until the deleted site exists in Recycle Bin.

If you are creating another site collection from SharePoint Online Admin portal, then you will get the validation error The site collection already exists. Please enter a different address. . Under this error message you can also see the option Permanently delete the site collection from the recycle bin and continue., you can check this option and proceed to remove the deleted site from Recycle Bin and create a site collection with same site url.

Reuse deleted site collection url

Scenario 2:

Consider that you have a Office 365 group that named as TestO365Group and the O365 group should have a associated team site (https://o365domain.sharepoint.com/sites/TestO365Group). If you delete this O365 group, it will also delete its associated site, both the group and site will be moved into Recycle Bin. Now you can create another O365 group with same name and email alias (group email address), but it will not create the associated team site with same url and it will place a numeric number after the site name in the URL (For example: https://o365domain.sharepoint.com/sites/TestO365Group2). So you have to remove the deleted site first from Recycle Bin to have the same group site url.

Manually deleting the sites from Recycle Bin will be a tough task. So you can use the SharePoint Online Management Powerhsell cmdlet Remove-SPODeletedSite to remove the deleted sites from Recycle Bin.

Before proceed Install and Connect SharePoint Online PowerShell Module, then run the below command to remove a deleted site.
Remove-SPODeletedSite -Identity https://o365domain.sharepoint.com/sites/TestO365Group
If you don’t know the deleted site url, you can use the command Get-SPODeletedSite to list all the deleted sites with Url.

Thursday, 19 July 2018

Fix: The Call to GetCustomUI for RibbonID Microsoft.Excel.Workbook failed

Problem :

I have received the error message The Call to GetCustomUI() for RibbonID "Microsoft.Excel.Workbook" failed with the title Custom UI Runtime Error in Visual Studio Tools for Office Design-Time Adaptor for Excel when opening the Excel application. In my environment the below error comes when I open the Excel application that comes with Microsoft Office Professional Plus 2016.

Error - The Call to GetCustomUI for RibbonID Microsoft.Excel.Workbook failed

Solution :

After analyzing some time found that this error is coming due to the COM Add-In Visual Studio Tools for Office Design-Time Adaptor for Excel. So to fix/remove this error, we need to enable Developer tab and turn off the problematic COM Add-In.

Follow the below steps to disable COM Add-In :

  • In Excel, click File menu and select Options.
Step 1 - Fix The Call to GetCustomUI for RibbonID Microsoft.Excel.Workbook failed

  • In the Options menu select Customize Ribbon. In the right-hand side, you can see the Developer tab under Main Tabs, make sure that this tab is selected and click OK to save the changes.
Step 2 - Fix The Call to GetCustomUI for RibbonID Microsoft.Excel.Workbook failed

  • Now you can see the Developer tab menu. Under the Developer tab ribbon, click on COM Add-Ins
Step 3 - Fix The Call to GetCustomUI for RibbonID Microsoft.Excel.Workbook failed

  • In the COM Add-Ins window, look for the add in Visual Studio Tools of Office Design-Time Adaptor for Excel and Uncheck it (If you find multiple entries, uncheck all the entries).
Step 4 - Fix The Call to GetCustomUI for RibbonID Microsoft.Excel.Workbook failed

  • This will fix the issue, now you can close the Excel app and open it again to check the problem is solved or not.

Tuesday, 17 July 2018

Manage SharePoint Item Level Permissions using PowerShell

Occasionally we need to grant read permission for some set of users on certain document item and set edit permission to a particular user or group. To achieve this requirement, we need to add explicit permission for the particular list item. In this post I am going to share powershell scripts to add or remove item level permissions using CSOM (Client Object Model) and delete unique permissions from list item. To use CSOM in Powershell, we need to load the required Microsoft SharePoint Online SDK assembly files.

Summary:

Find a list item or set of list items :

The below powershell commands find a file item by its name, if you want to reset permissions for all list items you can set this caml query : $camlQuery.ViewXml = "<View Scope='RecursiveAll' />" and you can also write your own caml query to get different set of list items.
#Add required references to SharePoint client assembly to use CSOM 
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client") 
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")  

#Proivde your details: SharePoint Site Url, UserName and Password   
$SiteUrl="https://spotenant.sharepoint.com/sites/TestSite" 
$UserName = "admin@spotenant.onmicrosoft.com"
$Password = 'adminpassword'
$SecPwd = $(ConvertTo-SecureString $Password -asplaintext -force)  

#Connecting site web
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)  
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName,$SecPwd)  
$ctx.credentials = $credentials 
$ctx.Load($ctx.Web) 
$ctx.ExecuteQuery()

#Find list by Title
$list=$ctx.Web.Lists.GetByTitle("Documents") 
$ctx.Load($list) 
$ctx.ExecuteQuery()

#Find list item by Name
$itemName = "TestFile.txt"; 
$camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery 
$camlQuery.ViewXml ="<view><query><where><eq><fieldref name='FileLeafRef'><value type='Text'>" + $itemName + "</value></fieldref></eq></where></query></view>" 
# If you want to set permissions for all list items, you can use the below line (caml query to fetch all items) after commenting above line.
# $camlQuery.ViewXml ="<View Scope='RecursiveAll' />"  
$allItems=$list.GetItems($camlQuery) 
$ctx.Load($allItems) 
$ctx.ExecuteQuery()

# You can use the result $allItems in below examples.

Set item level permissions for user and SharePoint group :

By default all list items inherit the permissions from parent list, so to add unique permission for a particular list item, first we need to stop inheriting permissions (break the inheritance) of the particular item.

Add permission for user account :

The below powershell commands remove the unique permissions from the given list item (or list items) and set Contribute permission for the given user account.
# $allItems - You can get the required list items using the commands from above step.
foreach($listItem in $allItems) 
{ 
# Break inherited permissions. By default, the permissions are inherited from the above level.
$listItem.BreakRoleInheritance($false, $false); 
$ctx.Load($listItem)

#Find the given site user account
$editUser = $ctx.Web.EnsureUser("alland@spotenant.onmicrosoft.com") 
$ctx.Load($editUser)
$ctx.ExecuteQuery()

# Providing edit (contribute permission) access to the given site user.
$editAccess = $ctx.Web.RoleDefinitions.GetByName("Contribute")   
$editRole = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)   
$editRole.Add($editAccess)   
$editPermission = $listItem.RoleAssignments.Add($editUser, $editRole)   
$ctx.Load($editPermission) 
$ctx.ExecuteQuery()
Write-Host "Edit permission granted for the user:" $editUser.Title -foregroundcolor Green 
} 

Add permission for group :

You can use the below powershell commands to grant read access for the given sharepoint group.
foreach($listItem in $allItems) 
{ 
$listItem.BreakRoleInheritance($false, $false); 
$ctx.Load($listItem)

#Fecth the SharePoint groups for the site                         
$spGroups=$ctx.Web.SiteGroups 
$ctx.Load($spGroups)         
#Fecth the specific SharePoint group
$readGroup = $spGroups.GetByName("Test Site Visitors"); 
$ctx.Load($readGroup)
$ctx.ExecuteQuery()

# Providing read permission access to the members of the group "Test Site Visitors".    
$readAccess = $ctx.Web.RoleDefinitions.GetByName("Read")   
$readRole = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)   
$readRole.Add($readAccess)           
$readPermission = $listItem.RoleAssignments.Add($readGroup, $readRole)   
$ctx.Load($readPermission)              
$ctx.ExecuteQuery()
Write-Host "Read access granted for the group 'Test Site Visitors'" -foregroundcolor Green 
} 

Remove item level permissions :

You can use the below csom based powershell commands to remove unique permissions from a particular SharePoint/SharePoint Online list item.

Remove user permission from list item :

foreach($listItem in $allItems) 
{ 
#Remove permissions for a given user
$spUser = $ctx.Web.EnsureUser("alland@spotenant.onmicrosoft.com") 
$ctx.Load($spUser)
$ctx.Load($listItem.RoleAssignments)
$listItem.RoleAssignments.GetByPrincipal($spUser).DeleteObject()
$ctx.ExecuteQuery()
Write-Host "Permissions removed for the given user:" $spUser.Title -foregroundcolor Green
}

Delete group permission from list item :

foreach($listItem in $allItems) 
{ 
#Remove permissions for a given site group
$spGroups=$ctx.Web.SiteGroups 
$ctx.Load($spGroups)         
$spGroup = $spGroups.GetByName("Test Site Visitors"); 
$ctx.Load($spGroup)
$ctx.Load($listItem.RoleAssignments)
$listItem.RoleAssignments.GetByPrincipal($spGroup).DeleteObject()
$ctx.ExecuteQuery()
Write-Host "Permissions removed for the given group:" $spGroup.Title -foregroundcolor Green
}

Delete all unique permissions :

You can use the following powershell commands to remove all the explicit permissions from a list item and reset broken inheritance (recover inheritance).
foreach($listItem in $allItems) 
{ 
$listItem.ResetRoleInheritance()
$ctx.ExecuteQuery()
Write-Host "Unique permissions removed successfully and inheritance recovered." -foregroundcolor Green 
}

Friday, 13 July 2018

How to add user into Organization Management role group via PowerShell and GUI

The Organization Management role is one of most important role in Exchange management. You should have added into this role group to do some important mailbox operations like mailbox searches. You can easily add an user to Organization Management role group either using Powershell or Exchange Admin center GUI.

Add user into Organization Management group using PowerShell:

You can use the Exchange powershell cmdlet Add-RoleGroupMember to add members to a management role group. Before proceed you need to connect Exchange On-premises or Online powershell module based on your environment. Run the following command to connect Exchange Online module.
$o365Cred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $o365Cred -Authentication Basic -AllowRedirection
Import-PSSession $Session
Once you have connected the Exchange powershell module, Run the below command to add the required user into the role group "Organization Management":
Add-RoleGroupMember "Organization Management" -Member "user@o365domain.com"

Add member into Organization Management group via Exchange Admin center GUI:

You can also add a member into required role group through Exchange On-premises/Online Admin center.
  • Go to Office 365 Admin center.
  • In the left navigation, expand Admin centers, and then select Exchange.
  • In the Exchange Administration Center (EAC), navigate to Permissions > Admin Roles.
  • Select the group "Organization Management" and then click on Edit icon.
  • In the Members section, click on Add (+) button.
  • Select the required users, click on Add, and then click on OK.
  • Click on Save to save the changes to the role group.
Steps to add member into Organization Management role group via Exchange Admin center GUI

The term 'Get-UnifiedGroup' is not recognized as the name of a cmdlet

When you run the powershell cmdlet Get-UnifiedGroup you might have received the following error.
Get-UnifiedGroup : The term 'Get-UnifiedGroup' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ Get-UnifiedGroup
+ CategoryInfo          : ObjectNotFound: (Get-UnifiedGroup:String) [],CommandNotFoundException+ FullyQualifiedErrorId : CommandNotFoundException
The command Get-UnifiedGroup belongs to Exchange Online powershell module and you can use this cmdlet to view Office 365 groups in your cloud-based organization.

Solution 1:

Before running this cmdlet, first you have to Exchange Online module by running following commands:
$o365Cred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $o365Cred -Authentication Basic -AllowRedirection
Import-PSSession $Session

Solution 2:

You might have received the same error even after loaded the Exchange Online module. In this case, the error might occurs due to the user account that you used to connect Exchange Online may not have required permissions to run this cmdlet.

To run this cmdlet, the user account needs the permissions Mail Recipients (RoleType: MailRecipients) and View-Only Recipients (RoleType: ViewOnlyRecipients).

If you have global admin account (or other high privileged account), then you can find the permissions required to run Get-UnifiedGroup cmdlet by running following command.
PS C:\> Get-ManagementRole -Cmdlet "Get-UnifiedGroup"

Name                 RoleType
----                 --------
Mail Recipients      MailRecipients
View-Only Recipients ViewOnlyRecipients

Add user into required role group:

To grant the required permissions, you need to add the user into a role group which contains "Mail Recipients" or "View-Only Recipients", such as Organization Management / Recipient Management group, etc.

Run the following powershell command to add the user into the role group "Organization Management":
Add-RoleGroupMember "Organization Management" -Member "user@o365domain.com"
You can also add the required role through Exchange Admin center:
  • Go to Office 365 Admin center.
  • In the left navigation, expand Admin centers, and then select Exchange.
  • In the Exchange Administration Center (EAC), navigate to Permissions > Admin Roles.
  • Select the group "Organization Management" and then click on Edit icon.
  • In the Members section, click on Add (+) button.
  • Select the required users, click on Add, and then click on OK.
  • Click on Save to save the changes to the role group.

Monday, 9 July 2018

How to disable Clutter in Office 365 Mailbox using Powershell

Clutter is a new mailbox management feature in Office 365 and it analyzes how you process all your emails and moves the “un-important mails” out of your Inbox folder and places that into the Clutter folder. This feature will be useful to move marketing and news related messages from Inbox, but for the very long time we are using E-mail Rules to move and organize mails and it has been working good, so this feature may not needed for some users.

This Clutter feature can be turned on or off via a setting in Outlook Web App (OWA) and but not from within Outlook Desktop client (not even Outlook 2016). So we can use the Exchange Online powershell cmdlet Set-Clutter to enable or disable clutter feature in mailbox.

Before proceed, first we need to connect Exchange Online powershel module by running below commands:
$o365Cred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $o365Cred -Authentication Basic -AllowRedirection
Import-PSSession $Session
Run the below command to disable the clutter for single mailbox.
Set-Clutter -Identity “alexw@o365domain.com” -Enable $false
You can enable it by just passing $true value to –Enable parameter.
Set-Clutter -Identity “alexw@o365domain.com” -Enable $true
Run the below commands if you want to remove this clutter feature from all the users mailbox.
Get-Mailbox -ResultSize Unlimited | Set-Clutter -Enable $false
Note: After turning off the clutter feature, the clutter folder will still exist but no emails moved into this folder.

Disable Clutter for specific set of users :

You can use the below powershell commands to remove clutter feature for multiple users.
$users = "user1@o365domain.com","user1@o365domain.com"
ForEach ($user in $users) {
Set-Clutter -Identity $user  -Enable $false 
}

Disable Clutter for bulk mailbox users from CSV :

Use the below powershell commands to disable clutter for bulk office 365 users by importing users from CSV file. Consider the CSV file Users.csv which contains set of mailbox users with the csv column header UserPrincipalName.
Import-Csv 'C:\Users.csv' | ForEach-Object {
$user = $_."UserPrincipalName"
Set-Clutter -Identity $user  -Enable $false
}

Wednesday, 4 July 2018

Find and Export all OneDrive for Business users using Powershell

In this post, I am going to explain how to find and export list of Office 365 users with OneDrive for Business site provisioned. We can easily extract OneDrive sites using SharePoint management powershell cmdlet Get-SPOSite.

Before proceed, Install and Connect SharePoint Online PowerShell Module. Run the below commands after replacing your SPO Admin site url to connect SPO Online service. You can refer this post to know more about how to get SPO Admin Site Url.
$AdminSiteURL="https://<your tenant name>-admin.sharepoint.com"
#Connect to SharePoint Online Admin Site
Connect-SPOService -Url $AdminSiteURL
When you simply run the cmdlet Get-SPOSite, it will list all sites in your SPO tenant but it will not list OneDrive users personal sites by default. So to retrieve personal sites along with normal spo sites , we have to run the Get-SPOSite cmdlet with the parameter -IncludePersonalSite as True.
Get-SPOSite -IncludePersonalSite $true -Limit All
The above command returns personal sites and it also includes normal sites, so we have to filter sites by url to get only personal sites. The below powershell script lists all personal sites in office 365 and its owner detail.
#Get OneDrive for Business Sites alone
Get-SPOSite -IncludePersonalSite $true -Limit All -Filter "Url -like '-my.sharepoint.com/personal/'"

Export all OneDrive for Business users to CSV

The below powershell script get and export all personal sites and site owner name details to csv file.
$Result=@()
#Get all office 365 personal sites
$oneDriveSites = Get-SPOSite -IncludePersonalSite $true -Limit All -Filter "Url -like '-my.sharepoint.com/personal/'"
$oneDriveSites | ForEach-Object {
$site = $_
$Result += New-Object PSObject -property @{ 
UserName = $site.Owner
OneDriveSiteUrl = $site.URL
}
}
$Result | Select UserName, OneDriveSiteUrl |
Export-CSV "C:\\OneDrive-for-Business-Users.csv" -NoTypeInformation -Encoding UTF8

CSV output of OneDrive for Business (ODFB) users:

Export OneDrive for Business Users (ODFB) Sites using Powershell

Convert CSV string to PS Object in PowerShell

You might have used the powershell command Import-Csv to import content from csv file. Sometimes we may required to convert csv (comma-separated-values) string content to object, we can easily achieve this using the cmdlet ConvertFrom-Csv.
$csv_content = "col1,col2`
val11,val12`
val21,val22"

$ps_object = $csv_content | ConvertFrom-Csv -Delim ','

Powershell Object:

PS C:\> $ps_object

col1  col2
----  ----
val11 val12
val21 val22

Find Installed Software’s Product code and Upgrade code using PowerShell

Sometimes we may required to find installed applications product and upgrade code for maintenance purpose or any other reason. In this post, I am going to share powershell script to get product id and upgrade code of installed tool.

Find Product Code:

The below command lists all the installed software’s name and product code
get-wmiobject Win32_Product | Select-Object @{ n='Name'; e={$_.Name}}, @{n='ProductCode'; e={$_.IdentifyingNumber}}
If you know the product name, you can just run the below command to get product code for a specific application.
$productName = “Name of your product”
$info = get-wmiobject Win32_Product | Where-Object { $_.Name –eq $productName}
$productCode = $info. IdentifyingNumber
In latest powershell (Windows 10 and later), we can use the command Get-Package to retrieve installed applications.
Get-Package | Select-Object @{ n='Name'; e={$_.Name}}, @{n='ProductCode'; e={$_.Metadata["ProductCode"]}}

Find Upgrade Code:

Once you find product code from above script, you can easily find upgrade code by using product code. Replace your product code in below script and run the commands to get upgrade code.
gwmi -Query "SELECT Value FROM Win32_Property WHERE Property='UpgradeCode' AND ProductCode='{your product code}'" | Format-Table Value

Tuesday, 19 June 2018

How to Install and Connect SharePoint Online PowerShell Module

SharePoint Online team focusing Microsoft Graph Api to provide common api experience for Office 365 users, but some Admin related activities still we need to use powershell module. Follow the below steps to install and connect SharePoint Management Shell.
Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking
Note: If powershell console is already opened, close and open the powershell again after installing the above setup.
  • Now run the following command after replacing your tenant name to connect spo service. Actually you have to set your spo admin site url, you can refer this post for more info: how to get SharePoint Online Admin Site Url
Connect-SPOService -url https://<your tenant name>-admin.sharepoint.com
  • Once you have connected the SPO service, then you can run SPO management commands. The below command lists all spo sites.
Get-SPOSite | Select Title, Url

Friday, 15 June 2018

How to increase Windows service startup timeout period

Problem:

Some software services may failed to start in slower machine and you will get following error events in Application event log.

Event ID: 7000

The ServiceName service failed to start due to the following error:
The service did not respond to the start or control request in a timely fashion.

Event ID: 7009

A timeout was reached (30000 milliseconds) while waiting for the ServiceName service to connect.

Solution:

To fix this service startup problem, we need to increase default startup timeout period 30000 milliseconds (30 seconds). Follow the below steps to increase all windows services startup timeout.
  • Open Run window by clicking Start button -> click Run.
  • In Run window, type regedit, and then click OK to open Registry Editor.
  • Locate and then click the following registry subkey: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
  • In the right pane, locate the ServicesPipeTimeout entry.
Note: If the ServicesPipeTimeout entry does not exist, first you should create it. Follow below steps:
  1. On the Edit menu, point to New, and then click DWORD Value.
  2. Type ServicesPipeTimeout, and then press ENTER.
  • One you locate (or created) ServicesPipeTimeout, right-click ServicesPipeTimeout, and then click Modify. Click Decimal, type 120000 (2 mins), and then click OK.
This value (120000) represents the time in milliseconds to wait for windows service to start before timeout.
  • Restart the computer once you done the changes.
How to increase Windows service startup timeout period

Thursday, 14 June 2018

Find and Export all SharePoint Online Sites using Powershell

In this post, I am going to share powershell script to get a list of sites in Office 365. We can easily extract all sites using the SharePoint Online Management shell cmdlet Get-SPOSite.

Before proceed Install the SharePoint Online Management Shell:
Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking
Note: If powershell console already opened, close and open the powershell again after installing the above setup.

We need admin site url to connect SharePoint Online service, you can refer this post to Get SharePoint Online Admin Site Url. Once you got the admin site url run the below script after replacing your AdminUrl to list all sites.
#Replace your admin site url
$AdminUrl = "https://contoso-admin.sharepoint.com/"
#Retrieve all site collections
Connect-SPOService -Url $AdminUrl
Get-SPOSite | Select Title, Url, Owner
If you want to retrieve all the available properties, run the below command, it will list all the attributes of first site.
Get-SPOSite | Select -First 1 | FL
You can also filter the sites based on any available property, the below command lists only sites with sharing capability enabled as ExternalUserSharingOnly.
Get-SPOSite | Where-Object {$_.SharingCapability -eq "ExternalUserSharingOnly"}
Run the below command to list sites with share capability disabled.
Get-SPOSite | Where-Object {$_.SharingCapability -eq "Disabled"}

Export all SharePoint Online Sites to CSV:

Run the below command to export all the required details of spo sites to csv file.
Get-SPOSite | Select Title, Url, Owner, SharingCapability, LastContentModifiedDate |
Export-CSV "C:\\SharePoint-Online-Sites.csv" -NoTypeInformation -Encoding UTF8

Tuesday, 12 June 2018

Powershell : The term 'Connect-SPOService' is not recognized as the name of a cmdlet

Problem :

I have got the error message "The term 'Connect-SPOService' is not recognized as the name of a cmdlet" when I run the powershell cmdlet Connect-SPOService to connect SharePoint Online site.
Connect-SPOService : The term 'Connect-SPOService' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ Connect-SPOService -url https://conotoso-admin.sharepoint.com
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Connect-SPOService:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Solution :

The command Connect-SPOService belongs to SharePoint Online Management Shell, so before using this command we need to install the SPO Management Shell and import the module. You only need install once for each computer from which you are running SPO Powershell commands.

Install SharePoint Online Management Shell:

You can download and install the setup from this path : Download SharePoint Online Management Shell

Connect SharePoint Online Module:

Once you have installed the above setup, run the following command to import the SharePoint online powershell module.
Import-Module Microsoft.Online.SharePoint.Powershell
Then run the following commands to connect spo service and list all sites.
Connect-SPOService -url https://conotoso-admin.sharepoint.com 
Get-SPOSite | Select Title, Url

Friday, 8 June 2018

Office 365 : How to get SharePoint Online Admin Site Url

You have to give your SharePoint admin site url as root scope when you work with SharePoint online PowerShell module and SharePoint Client Object Model (CSOM). The possible admin site url would be like below sample url.
https://tenantname-admin.sharepoint.com/
Consider your office 365 user id (userPrincipalName) is : "admin@contoso.onmicrosoft.com" and most probably your tenant name is "contoso" then your sharepoint admin site url should be below one.
https://contoso-admin.sharepoint.com/
You can test the url is correct or not by using this url as root scope with SharePoint Online Powershell module. The below connect your sharepoint admin site and list all sites.
$cred = Get-Credentials
Connect-SPOService -url "https://contoso-admin.sharepoint.com" -Credential $credential
Get-SPOSite | Select Title, Url
You can also get the correct url by connecting Office 365 Admin center site:
Steps to get sharepoint admin site url from Office 365 admin center
  • Now, you can view your admin site and get the correct admin site url as shown in below image.
how to get sharepoint admin site url

Thursday, 7 June 2018

Powershel : Convert JSON String to PS Object and Vice-versa

Many software services moving towards cloud environment and providing APIs to communicate with service. To standardize this communication many software APIs use JSON format to receive and return data. In this post, I am going to share powershell script to convert json to object and convert object to json string.

Convert JSON content to PS Object :

You can easily convert json text into object using the powershell cmdlet ConvertFrom-Json. Consider the below sample JSON that might be a HTTP/HTTPS response content returned from some API.
$usersJson = '{"users":[
    { "username":"kevin", "email":"kevin@test.com" },
    { "username":"morgan", "email":"morgan@test.com" },
    { "username":"smith", "email":"smith@test.com" }
]}'
Run the following command to convert the above json string to ps object.
$usersObject = ConvertFrom-Json –InputObject $usersJson
Now you can easily list the ps object properties
PS C:\> $usersObject.users

username email
-------- -----
kevin    kevin@test.com
morgan   morgan@test.com
smith    smith@test.com

Convert PS Object to JSON String :

You can convert the above ps object into json text using the powershell cmdlet ConvertTo-Json.
$newUsersJson = $usersObject | ConvertTo-Json

parse json string as ps object and convert ps object to json string

Wednesday, 6 June 2018

Powershell : The term 'Get-AzureADUser' is not recognized as the name of a cmdlet

Problem :

You might have received the error message "The term Get-AzureADUser is not recognized as the name of a cmdlet" when you run the Azure AD powershell cmdlet Get-AzureADUser to get Office 365 users.
The term 'Get-AzureADUser' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:16
+ Get-AzureADUser <<<<
    + CategoryInfo          : ObjectNotFound: (Get-AzureADUser:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Solution :

The command Get-AzureADUser belongs to Azure Active Directory Powershell for Graph module, so before using this command we need to install and connect AzureAD powershell v2 module.

Install AzureAD module:

Open Powershell console with Run as administrator privilege and run the following command:
Install-Module AzureAD -Force

Connect/Load AzureAD module:

Once you have installed the Azure AD module, run the following command to load the module.
Connect-AzureAD
# Once you connected the AzureAD module, now run the Get-AzureADUser command.
Get-AzureADUser

Powershell : The term 'Get-MsolUser' is not recognized as the name of a cmdlet

Problem :

You may receive the error "The term Get-MsolUser is not recognized as the name of a cmdlet" when you run the Azure AD powershell command Get-MsolUser to fetch Office 365 users.
The term 'Get-MsolUser' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:13
+ Get-MsolUser <<<<
    + CategoryInfo          : ObjectNotFound: (Get-MsolUser:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Solution :

The cmdlet Get-MsolUser belongs to Azure AD Powershell (V1) module (MSOnline), so before using this command we need to install and connect MSOnline module.

Install MSOnline module:

Earlier you need to download an executable (exe binary) file to install this module, but now Microsoft expired that file and you can install only through powershell. Open Powershell console with Run as administrator privilege and run the following command:
Install-Module MSOnline -Force

Connect/Import MSOnline module:

Once you have installed the MSOnline module, run the following command to connect MSOnline module.
Connect-MsolService
# Once you connect MsolService, now run the Get-MsolUser command.
Get-MsolUser

Tuesday, 5 June 2018

Find and List MFA Enabled Status of Office 365 Users using Powershell

Multi-Factor Authentication (MFA) is a method of Azure AD authentication that requires more than one verification method and adds a critical second layer of security to user sign-ins and transactions. You can easily enable MFA solution for Azure AD users using Azure MFA portal. In this post, I am going to share powershell script to list office 365 users MFA status.

List Office 365 Users MFA Status:

Before proceed run the following command to connect Azure AD powershell module.
Connect-MsolService
The following command lists MFA status of all the Azure AD users.
$Result=@() 
$users = Get-MsolUser -All
$users | ForEach-Object {
$user = $_
if ($user.StrongAuthenticationRequirements.State -ne $null){
$mfaStatus = $user.StrongAuthenticationRequirements.State
}else{
$mfaStatus = "Disabled" }
  
$Result += New-Object PSObject -property @{ 
UserName = $user.DisplayName
UserPrincipalName = $user.UserPrincipalName
MFAStatus = $mfaStatus
}
}
$Result | Select UserName,UserPrincipalName,MFAStatus

Export 365 users MFA status to CSV file :

$Result | Select UserName,UserPrincipalName,MFAStatus |
Export-CSV "C:\\O365-Users-MFA-Status.csv" -NoTypeInformation -Encoding UTF8

List only MFA enabled users :

$Result | Where-Object {$_.MFAStatus -ne "Disabled"}

Monday, 4 June 2018

Hide Office 365 Groups from Outlook and OWA using Powershell

As you know Office 365 Group is the base service for other O365 services like Planner, Teams, Yammer, etc... So in some situations you may need to hide some groups from Exchange clients like Outlook and OWA. If you use Microsoft Teams, every team will use its own office 365 group as base service, as you know Teams is the best communication tool to have complete conversation within a team, so there is no need to use teams group in exchange client for conversation, in this case we can hide teams based office 365 groups in Exchange clients.

Hiding Office 365 groups from Exchange clients is easily achievable by using the Exchange Online Powershell cmdlet Set-UnifiedGroup with the parameter -HiddenFromExchangeClientsEnabled. Run the following command to hide a single office 365 group from OWA and Outlook client.
Set-UnifiedGroup "TeamsO365Group" -HiddenFromExchangeClientsEnabled:$true
You can disable the setting by just passing he value $false to the parameter HiddenFromExchangeClientsEnabled
Set-UnifiedGroup "TeamsO365Group" -HiddenFromExchangeClientsEnabled:$false

Lists Office 365 Groups Exchange Client Status :

You can easily check the exchange client status of all office 365 groups by running below command.
 Get-UnifiedGroup -ResultSize Unlimited | Select Name, HiddenFromExchangeClientsEnabled 
The below command lists only the groups that are hidden from exchange client.
 Get-UnifiedGroup -ResultSize Unlimited | Where-Object {$_.HiddenFromExchangeClientsEnabled -eq $true}

Export Office 365 Groups Exchange client status to CSV:

 Get-UnifiedGroup -ResultSize Unlimited | Select Name, HiddenFromExchangeClientsEnabled |
Export-CSV "C:\\O365-Groups-Exchange-Client-Status.csv" -NoTypeInformation -Encoding UTF8

Hide Bulk Office 365 Groups from Outlook and OWA :

We may required to hide multiple office 365 groups in single execution, in this case we can have group names in csv. We need to import csv file, and then pass every group to Set-UnifiedGroup cmdlet. Consider the csv file TeamGroups.csv that has unified groups with the column header GroupName.
Import-Csv 'C:\TeamGroups.csv' | ForEach-Object {
$o365group = $_."GroupName"
Set-UnifiedGroup $o365group -HiddenFromExchangeClientsEnabled:$true
} 

Note: All O365 Groups in which HiddenFromExchangeClientsEnabled is set to True will not be visible on the left navigation menu in Outlook and OWA, but you can still access them on demand (ex: use Browse Groups in Outlook)

Friday, 1 June 2018

Export Office 365 Users Mailbox Size to CSV using Powershell

Occasionally we need to get how much space is used by every office 365 user in their mailbox. In this post, I am going to share powershell script to export mailbox size, mail items count and last logon date of all users in your O365 tenant. We can use the Exchange Online powershell cmdlet Get-MailboxStatistics to extract mailbox statistics data.

Before proceed, first we need to connect Exchange Online powershel module by running below command:
$LiveCred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $LiveCred -Authentication Basic -AllowRedirection
Import-PSSession $Session
Run the following command to get mailbox size for a single Office 365 user:
Get-MailboxStatistics -Identity "alexw@contoso.com" | Select TotalItemSize

Export Office 365 users mailbox size, mails count and last logon date:

Run the following powershell script to export all o365 users mailbox sizes to CSV file.
$Result=@() 
$mailboxes = Get-Mailbox -RecipientTypeDetails UserMailbox -ResultSize Unlimited
$totalmbx = $mailboxes.Count
$i = 1 
$mailboxes | ForEach-Object {
$i++
$mbx = $_
$mbs = Get-MailboxStatistics -Identity $mbx.UserPrincipalName

if ($mbs.LastLogonTime -eq $null){
$lt = "Never Logged In"
}else{
$lt = $mbs.LastLogonTime }
 
Write-Progress -activity "Processing $mbx" -status "$i out of $totalmbx completed"
 
$Result += New-Object PSObject -property @{ 
UserPrincipalName = $mbx.UserPrincipalName
TotalSize = $mbs.TotalItemSize
TotalMessages = $mbs.ItemCount
LastLogonTime = $lt }
}
$Result | Select UserPrincipalName, TotalSize, TotalMessages, LastLogonTime |
Export-CSV "C:\\O365-Mailbox-Statistics.csv" -NoTypeInformation -Encoding UTF8

CSV Output of Mailbox Statistics Report:


export office 365 users mailbox sizes to csv using powershell

Wednesday, 30 May 2018

RDP : An authentication error occurred This could be due to CredSSP encryption oracle remediation

Problem:

I am trying to connect a remote machine through Remote Desktop Connection (RDP client) from my local Windows 10 machine and receiving the error "An authentication error has occurred. The function requested is not supported. This could be due to CredSSP encryption oracle remediation."

RDP An authentication error has occurred. The function requested is not supported. This could be due to CredSSP encryption oracle remediation.

Cause:

After analyzing some time, found that this error is occurring after May 2018 Security update . Please check this link for more info: https://blogs.technet.microsoft.com/yongrhee/2018/05/09/after-may-2018-security-update-rdp-an-authentication-error-occurred-this-could-be-due-to-credssp-encryption-oracle-remediation/

Solution:

  • Connect the problematic remote machine from different computer (other than your current computer).
  • In remote computer, right-click on My Computer (This PC) -> click Properties.
  • Now click Remote Settings and un-check the option "Allow connections only from computers running Remote Desktop with Network Level Authentication" and Apply the settings.
Remote Desktop Connection An authentication error has occurred. The function requested is not supported. This could be due to CredSSP encryption oracle remediation.

  • Now try to connect from your local machine.

Tuesday, 29 May 2018

Azure AD Login - The browser based authentication dialog failed to complete. Reason: the server or proxy was not found

Problem:

I am receiving the error "The browser based authentication dialog failed to complete. Reason: the server or proxy was not found" when I try to connect Azure AD powershell command.
Connect-AzureAD : One or more errors occurred.:  The browser based authentication dialog failed to complete. Reason:
The server or proxy was not found.
At line:1 char:1
+ Connect-AzureAD
+ ~~~~~~~~~~~~~~~
    + CategoryInfo          : AuthenticationError: (:) [Connect-AzureAD], AadAuthenticationFailedException
    + FullyQualifiedErrorId : Connect-AzureAD,Microsoft.Open.Azure.AD.CommonLibrary.ConnectAzureAD

Cause:

This issue may occur if your proxy server not allowing to connect internet (especially login portal: https://login.microsoftonline.com) or the proxy settings may not be configured properly to connect internet.

Solution:

Open Internet Explorer (with Run as administrator privilege)-> click Settings (gear icon) in top-right corner -> Internet Options -> select Connections tab -> LAN Settings -> set Automatically detect settings and remove Proxy settings if configured.
Azure AD Login - The browser based authentication dialog failed to complete. Reason: the server or proxy was not found


Tuesday, 15 May 2018

Find and Export Office 365 Users Profile Picture Status using PowerShell

In this post, I am going to share powershell script to find a list of users without profile picture in Office 365. We can extract this report using Exchange Online powershell cmdlets Get-Mailbox and Get-Userphoto.

Before proceed run the following command to connect Exchange Online powershell module.
$365Logon = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $365Logon -Authentication Basic -AllowRedirection
Import-PSSession $Session

Check if specific user has profile picture or not :

The following command checks whether profile photo set or not set for the user "alexw@contoso.com".
$photoObj = Get-Userphoto -Identity "alexw@contoso.com" -ErrorAction SilentlyContinue
If($photoObj.PictureData -ne $null)
{
Write-Host "User has profile picture"
}
Else
{
Write-Host "Profile picture not configured"
}

Export Office 365 Users without profile picture to CSV file :

Run the following powershell script to get a list of users who do not have profile picture and export user details to csv file.
$Result=@()
$allUsers = Get-Mailbox -RecipientTypeDetails UserMailbox -ResultSize Unlimited
$totalusers = $allUsers.Count
$i = 1 
$allUsers | ForEach-Object {
$user = $_
Write-Progress -activity "Processing $user" -status "$i out of $totalusers completed"
$photoObj = Get-Userphoto -identity $user.UserPrincipalName -ErrorAction SilentlyContinue
If($photoObj.PictureData -eq $null) 
{
$Result += New-Object PSObject -property @{ 
UserName = $user.DisplayName
UserPrincipalName = $user.UserPrincipalName
}}
$i++
}
$Result | Export-CSV "C:\\office-365-users-without-photo.csv" -NoTypeInformation -Encoding UTF8

Export all O365 Users with profile picture status :

The following powershell script exports all mailbox users with their profile picture status (photo uploaded or not) to csv file.
$Result=@()
$allUsers = Get-Mailbox -RecipientTypeDetails UserMailbox -ResultSize Unlimited
$totalusers = $allUsers.Count
$i = 1 
$allUsers | ForEach-Object {
$user = $_
Write-Progress -activity "Processing $user" -status "$i out of $totalusers completed"
$photoObj = Get-Userphoto -identity $user.UserPrincipalName -ErrorAction SilentlyContinue
$hasPhoto = $false
if ($photoObj.PictureData -ne $null)
{
$hasPhoto = $true
}
$Result += New-Object PSObject -property @{ 
UserName = $user.DisplayName
UserPrincipalName = $user.UserPrincipalName
HasProfilePicture = $hasPhoto 
}
$i++
}
$Result | Export-CSV "C:\\office-365-users-photo-status.csv" -NoTypeInformation -Encoding UTF8


CSV Output of Profile Picture Status Report:

Find and Export O365 Profile Photo Status Report to CSV file

Friday, 11 May 2018

Microsoft Teams : Get all your teams data using Powershell

Now we can get the list of teams where the current user is being a member using Microsoft Teams Powershell. Before proceed first you have to install Microsoft Teams Powershell using below command.
Install-Module MicrosoftTeams -Force
Note: You have to run the powershell with "Run as administrator" privilege to install this module.

Once you have installed the Teams module, then run the following command to connect Microsoft Teams and it will ask your credentials to proceed.
Connect-MicrosoftTeams

List all your Teams:

Once you have completed the login step, run the Get-Team command to list all your teams.
PS C:\> Get-Team

GroupId                              DisplayName        Description
-------                              -----------        -----------
9b614bd6-6710-44ae-a9e7-3446334546d7 Team 1             Team 1 Description
7d6143d6-2612-44ae-a9e7-2473364843f5 Team 2             Team 2 Description

List all channels in a Team:

You can get channels of a specific team by running following command. You can get the <Group Id> of the specific team from Get-Team command.
Get-TeamChannel -GroupId <Group Id>

Get Team members and their role:

You can also get members of a specific team and their role (owner or member) by running following command.
Get-TeamUser -GroupId <Group Id>
Note : Using Get-Team cmdlet you can get only your own teams, you can't get teams list of specific user even if you have administrator privilege. The Get-Team cmdlet actually included the parameter -User to get other user teams information, but as of now you will get only access denied ('Get-Team : Error occurred while executing Code: AccessDenied') error message even for global administrator.
PS C:\Windows\system32> Get-Team -User AlexW@contoso.onmicrosoft.com
Get-Team : Error occurred while executing
Code: AccessDenied
Message: Invalid UserId. UserId does not match Access token UserObjectId
InnerError: RequestId: f8664d28-5514-4bef-907e-f7a880907bc7 DateTimeStamp: 2018-05-11T16:59:53
HttpStatusCode: AccessDenied
At line:1 char:1
+ Get-Team -User AlexW@contoso.onmicrosoft.com
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-Team], ApiException
    + FullyQualifiedErrorId : Microsoft.TeamsCmdlets.PowerShell.Custom.ErrorHandling.ApiException,Microsoft.TeamsCmdle
   ts.PowerShell.Custom.GetTeam

Thursday, 10 May 2018

How to get password from user with a mask using Powershell

You can easily prompt and ask input from user by using the Read-Host cmdlet, but by default this command accepts the user input as plain text. If you get some secured data like password from user by using this command, when user type the input the password text will be clearly visible as shown in below example.
PS C:\> Read-Host "Enter password"
Enter password: myPassword
myPassword
If you want to hide or mask the password text from user, then you need to just pass the parameter –AsSecureString with Read-Host powershell command.
PS C:\> Read-Host "Enter password" -AsSecureString
Enter password: **********
System.Security.SecureString
The hard part of the above step is, it will read password as SecureString object not as clear text value. Most of the powershell commands (i.e. Set-ADAccountPassword, Set-MsolUserPassword , etc..) will accept the password input only as SecureString object, you don't need to worry if you are going to use the password with these kind of commands, but if you need that secured text for some other purpose then you should convert the secure string password to clear text password.

The following powershell code shows how to convert secure password into plain text password.

#Step 1: get secure password from user.
$securePwd = Read-Host "Enter password" -AsSecureString
#Step 2: convert secure password into normal plain text password.
$plainPwd =[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($securePwd))
Write-Host "You password is : $plainPwd" -ForegroundColor Yellow

Monday, 7 May 2018

PowerShell : Show Progress Bar, Status and % Completed for Long Running Script

You can use the Write-Progress cmdlet to display progress status and percentage of process completed for a long running command or script. In normal cases you can use Write-Host command but if your script is going to run more time then you should use Write-Progress command to display the clear progress status.

The following command run the timer for 10 seconds and it update progress status for every second.
1..10 | ForEach {
Start-Sleep -s 1
Write-Progress -Activity "Process Started : " -Status "Total items processed: $_"
}
We can also display the progress bar by setting the parameter -PercentComplete
1..100 | ForEach {
Start-Sleep -m 100
Write-Progress -Activity "Process Started" -Status "Total items processed: $_" -PercentComplete $_
}
Show PowerShell Process Output Status 

We can also show the remaining time in seconds by setting the parameter -SecondsRemaining
1..10 | ForEach {
Start-Sleep -s 1
Write-Progress -Activity "Process Started" -Status "Total items processed: $_"  -SecondsRemaining (10-$_)
}
Display PowerShell Progress Bar Status

PowerShell : Sleep, Wait or Suspends the activity for some period of time

You can use the Start-Sleep cmdlet to suspend the activity in a script for the specified period of time. You can use this command for the tasks, such as waiting for an operation to complete or pausing before repeating an operation.

This command wait for 5 seconds.
Start-Sleep -Seconds 5
------- or ---------
Start-Sleep -s 5
The following command makes all the commands to sleep for 500 milliseconds (half of a second)
Start-Sleep -Milliseconds 500
------- or ---------
Start-Sleep -m 500

Timer Job using the cmdlets Start-Sleep and Write-Progress:

The following command run the timer for 60 seconds (1 minute).
1..60 | ForEach { 
Start-Sleep -s 1
Write-Progress -activity "Timer Started: " -Status $_
}

Wait, Sleep or Suspend in PowerShell script

Thursday, 26 April 2018

Export Office 365 Distribution Group Members to CSV using PowerShell

This post will help you to find and export distribution group members in Office 365 by using powershell script. We can list all the office 365 distribution lists by using the Exchange online powershell cmdlet Get-DistributionGroup and its group members by Get-DistributionGroupMember cmdlet.

Before proceed run the following command to connect Exchange Online powershell module.
$365Logon = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $365Logon -Authentication Basic -AllowRedirection
Import-PSSession $Session
Run the following command to list all the distribution groups.
Get-DistributionGroup -ResultSize Unlimited
The following command lists all the members for the given distribution list.
Get-DistributionGroupMember -Identity "<group name>" -ResultSize Unlimited

Export Members of a Single Distribution List to CSV:

The following powershell script gets members of a given distribution group and export members list to CSV file. You can replace the parameter <group name> with your own group name in the below script.
$DGName = "<group name>"
Get-DistributionGroupMember -Identity $DGName -ResultSize Unlimited | Select Name, PrimarySMTPAddress, RecipientType |
Export-CSV "C:\\Distribution-Group-Members.csv" -NoTypeInformation -Encoding UTF8

Export All Distribution Groups and Members List to CSV:

First we can get all the distribution groups by using Get-DistributionGroup cmdlet and retrieve its members by iterating every group with Get-DistributionGroupMember cmdlet. The following script exports all the distribution lists and their memberships to CSV file.
$Result=@()
$groups = Get-DistributionGroup -ResultSize Unlimited
$totalmbx = $groups.Count
$i = 1 
$groups | ForEach-Object {
Write-Progress -activity "Processing $_.DisplayName" -status "$i out of $totalmbx completed"
$group = $_
Get-DistributionGroupMember -Identity $group.Name -ResultSize Unlimited | ForEach-Object {
$member = $_
$Result += New-Object PSObject -property @{ 
GroupName = $group.DisplayName
Member = $member.Name
EmailAddress = $member.PrimarySMTPAddress
RecipientType= $member.RecipientType
}}
$i++
}
$Result | Export-CSV "C:\\All-Distribution-Group-Members.csv" -NoTypeInformation -Encoding UTF8

CSV output of O365 Distribution Groups and Members:


Export Office 365 Distribution Groups and their Memberships to CSV

Tuesday, 24 April 2018

Get List of Registered Azure AD Applications using PowerShell

In this post, I am going to share powershell script to find and retrieve the list of Azure AD applications that are registered by your company in current tenant. We can use the Get-AzureADApplication cmdlet to fetch all the registered apps.

Before proceed install Azure Active Directory PowerShell for Graph and run the below command to connect Azure AD PowerShell module:
Connect-AzureAD
Run the following command to list all the applications that are registered by your company. This command returns both web applications and native applications (run in desktop/mobile device).
Get-AzureADApplication -All:$true
You can filter the results by application display name.
Get-AzureADApplication -Filter "DisplayName eq 'TestAppName'"
You can also filter the results by application id.
Get-AzureADApplication -Filter "AppId eq 'ca066717-5ded-411b-879e-741de0880978'"

Find and list only Web applications :

Use the below command to get all azure ad applications with the application type "Web app/API"
Get-AzureADApplication -All:$true | Where-Object { $_.PublicClient -ne $true } | FT

Find and list Native applications alone :

Run the following command to get all the native client (desktop/mobile device) applications.
Get-AzureADApplication -All:$true | Where-Object { $_.PublicClient -eq $true } | FT

Export All Registered Azure AD Application Details to CSV :

The below command exports all the all azure ad apps with required details to csv file.
Get-AzureADApplication -All:$true |
Select-Object DisplayName, AppID, PublicClient, AvailableToOtherTenants, HomePage, LogoutUrl  |
Export-Csv "C:\AzureADApps.csv"  -NoTypeInformation -Encoding UTF8

Thursday, 19 April 2018

How to: Add Mailbox Import Export Role in Office 365 using PowerShell

When you are in Exchange Online environment, you might have required (or asked) to assign "Mailbox Import Export Role" for some kind of mailbox operation, like importing PST files, delete messages from mailbox using Search-Mailbox cmdlet, restore deleted mails using Restore-RecoverableItems cmdlet, etc. When you import PST files without this role you will probably receive this error message: "Please add Mailbox Import Export role for use running import and check back in 60 minutes".

By default, the "Mailbox Import Export" role is not assigned to any role group, even to the Organization Management role group. Typically, you assign a role to a built-in/custom role group, or you can assign a role to a user, or a universal security group. In this post, I am going to share PowerShell script to find who has access to Mailbox Import Export role and how to assign this role to user, security group and existing build-in/custom role group.

Before proceed, run the following commands to load Exchange Online powershel module:
$o365Cred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $o365Cred -Authentication Basic -AllowRedirection
Import-PSSession $Session

Summary:

Assign Mailbox Import Export role to user, security group and existing role group

Run the following command to assign the role for the individual user account.
New-ManagementRoleAssignment –Role "Mailbox Import Export" –User "user name"
Run the following command to set this role for the universal security group.
New-ManagementRoleAssignment –Role "Mailbox Import Export" –SecurityGroup "group name"
Use the below command to add this role to existing management role group.
New-ManagementRoleAssignment -Role "Mailbox Import Export" -SecurityGroup "Organization Management" -Name "Import Export Org Management"
Note: You have to create a new Exchange Online PowerShell session to get new role permissions.

Find who has access to Mailbox Import Export role

You can run the following command to find out who has the role already.
Get-ManagementRoleAssignment –Role "Mailbox Import Export" | FL RoleAssigneeName, Name
In the result, you may see the Organization Management role group even though you haven’t explicitly given the rights , this is because of the members of the Organization Management role group can delegate the "Mailbox Import Export" role to themselves and other groups or users.

Remove Management Role Assignment

If you want to remove the existing role assignment, first you have to find the name of the role assignment that you want to delete using the command Get-ManagementRoleAssignment and run the following powershell command to clear the existing role.
Remove-ManagementRoleAssignment "Import Export Org Management" -Confirm:$false

Wednesday, 18 April 2018

Recover Deleted Office 365 Groups using PowerShell

Microsoft using Office 365 Group as a base service for other products like Planner, MS Teams, Yammer, etc... , so keeping its identity is very important. You might have deleted an O365 group without knowing its usage in other services, in this case you will also loose the group's dependent contents. If you soft-deleted the office 365 group, by default the deleted object retained for 30 days (retention period) and you can easily restore the group and its associated content within this retention period, after the retention period the group and its associated content will be permanently deleted and cannot be restored.

When a group is restored, the following group associated content also get recovered: Office 365 Group's Azure AD object and its properties, group SMTP address, Exchange Online shared inbox and calendar, SharePoint Online team site and files, OneNote notebook, Planner buckets and tasks, Microsoft Teams and other associated contents.

We can recover deleted unified groups using Restore-AzureADMSDeletedDirectory cmdlet from Azure AD PowerShell V2 module. Before proceed install Azure Active Directory PowerShell for Graph and run the below command to connect Azure AD PowerShell module:
Connect-AzureAD
Recovering a deleted office 365 group includes following two steps:

Find Id of the deleted office 365 group

Actually we need to pass the object Id of a deleted group to Restore-AzureADMSDeletedDirectory cmdlet, so we need to first get the object id of the deleted group that we want to restore.
Get-AzureADMSDeletedGroup
The above command retrieves all the soft deleted groups in a directory that are recoverable. You can also filter the groups by name using the parameter -SearchString.
Get-AzureADMSDeletedGroup -SearchString "Test Group"
After running any one of the above two commands , note down the Id of the office 365 group that you want to restore.

Restore the deleted office 365 group

Once you got the Id of the deleted group from the above step, you can just run the following command after replacing the Id parameter with your target group object Id.
Restore-AzureADMSDeletedDirectoryObject –Id <deleted group id>
If you believe there is no duplicate entries in the deleted groups with the same name, you can use the following commands to get the deleted group Id and recover the object in single execution.
$groupId = (Get-AzureADMSDeletedGroup -SearchString "Test Group").Id
Restore-AzureADMSDeletedDirectoryObject –Id $groupId
Once you run the above command, the restoring process will be completed in few minutes. Run the following powershell command to verify that the group has been restored successfully.
Get-AzureADGroup -ObjectID $groupId

Monday, 16 April 2018

Recover Deleted Emails in Office 365 Mailbox using PowerShell

As an Administrator you might requested by an Outlook user to restore the deleted e-mail messages. In Office 365, you can search and restore the deleted items using Exchange Online Powershell cmdlets Get-RecoverableItems and Restore-RecoverableItems.

Before proceed, first we need to connect Exchange Online powershel module by running below commands:
$o365Cred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $o365Cred -Authentication Basic -AllowRedirection
Import-PSSession $Session

Summary:


Permissions Required :

To run the cmdlets Get-RecoverableItems and Restore-RecoverableItems, you must have one of the Exchange RBAC roles with the "Mailbox Import Export Role" assigned. By default, this role isn't assigned to any role group. Typically, you assign a role to a built-in or custom role group. Or you can assign a role to a user, or a universal security group. The below example add the role to the Organization Management role group:
New-ManagementRoleAssignment -Name "Import_Export_Organization_Management" -SecurityGroup "Organization Management" -Role "Mailbox Import Export"
Note: You have to create a new Exchange Online PowerShell session to get new role permissions.

Restore deleted messages to their original folder location:

We can use the Restore-RecoverableItems cmdlet to restore each item to its original location and this cmdlet takes the same search parameters that you used to find items.
Restore-RecoverableItems -Identity "AlexW" -SourceFolder RecoverableItems -SubjectContains "Important”

Restore deleted messages from bulk users mailbox:

You can use the below powershell commands if you want restore deleted emails from set of users' mailbox by importing user details from CSV file.
Import-Csv 'C:\Users.csv' | ForEach-Object {
$mailbox = $_."UserPrincipalName"
Write-Host "Recovering messages for" $mailbox -Foreground Yellow
Restore-RecoverableItems -Identity $mailbox -SourceFolder RecoverableItems -SubjectContains "Important" -FilterItemType Ipm.Note
}

Tuesday, 27 March 2018

Add Secondary Site Administrator to OneDrive for Business Users using PowerShell

As an Office 365 Admin, in some situations you might need to gain access to users' OneDrive for Business site when some users are terminated and if they are marked for deletion . By default, each user is added as primary & secondary site collection administrators to their personal OneDrive site, so you have to add your account as secondary admin in the requiresd user's OneDrive site to gain full access.

In this post, I am going to explain how to add secondary admin for single OneDrive user's site and for all users OneDrive for Business (ODFB) sites using PowerShell. Before proceed install SharePoint Online Management Shell.

Summary:


Add Site Administrator for single user's OneDrive site:

Run the below powershell commands after replacing the variable <tenant name> with your Office 365 tenant name in all the occurrences, set the required user's OneDrive site url (you can copy your own OneDrive Site url and just replace your name with the required username) and provide global admin credentials.
# Specify your organization admin central url 
$AdminURI = "https://<tenant name>-admin.sharepoint.com"
 
# Specify Office 365 global admin in your organization
$AdminAccount = "admin@<tenant name>.onmicrosoft.com"
$AdminPass = "admin_password"

# Specify the secondary admin account 
$secondaryAdmin = "username@<tenant name>.onmicrosoft.com"
# Specify the target user's OneDrive Url. You can copy your OneDrive Site url and just replace your name with the required username.
$oneDriveSiteUrl = "https://<tenant name>-my.sharepoint.com/personal/<username>_<tenant name>_onmicrosoft_com/" 
 
$sstr = ConvertTo-SecureString -string $AdminPass -AsPlainText -Force
$AdminPass = ""
$UserCredential = New-Object System.Management.Automation.PSCredential -argumentlist $AdminAccount, $sstr
 
Connect-SPOService -Url $AdminURI -Credential $UserCredential
Set-SPOUser -Site $oneDriveSiteUrl -LoginName $secondaryAdmin -IsSiteCollectionAdmin $true -ErrorAction SilentlyContinue
Write-Host "Secondary site admin added successfully"

Set Secondary Site Collection Admin for all OneDrive for Business sites

To give admin access for all OneDrive profiles, first we need to find list of users with OneDrive feature provisioned by using SharePoint Online UserProfileService and we can grant administrator access for all OneDrive sites by using the Set-SPOUser cmdlet.
# Specify your organization admin central url 
$AdminURI = "https://<tenant name>-admin.sharepoint.com"

# Specify the secondary admin account 
$secondaryAdmin = "username@<tenant name>.onmicrosoft.com"
 
# Specify the User account for an Office 365 global admin in your organization
$AdminAccount = "admin@<tenant name>.onmicrosoft.com"
$AdminPass = "admin_password"
 
$loadInfo1 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
$loadInfo2 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
$loadInfo3 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.UserProfiles")
 
$sstr = ConvertTo-SecureString -string $AdminPass -AsPlainText -Force
$AdminPass = ""
$creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($AdminAccount, $sstr)
$UserCredential = New-Object System.Management.Automation.PSCredential -argumentlist $AdminAccount, $sstr
 
# Add the path of the User Profile Service to the SPO admin URL, then create a new webservice proxy to access it
$proxyaddr = "$AdminURI/_vti_bin/UserProfileService.asmx?wsdl"
$UserProfileService= New-WebServiceProxy -Uri $proxyaddr -UseDefaultCredential False
$UserProfileService.Credentials = $creds
 
# Set variables for authentication cookies
$strAuthCookie = $creds.GetAuthenticationCookie($AdminURI)
$uri = New-Object System.Uri($AdminURI)
$container = New-Object System.Net.CookieContainer
$container.SetCookies($uri, $strAuthCookie)
$UserProfileService.CookieContainer = $container
 
# Sets the first User profile, at index -1
$UserProfileResult = $UserProfileService.GetUserProfileByIndex(-1)
Write-Host "Starting- This could take a while."
$NumProfiles = $UserProfileService.GetUserProfileCount()
$i = 1
 
Connect-SPOService -Url $AdminURI -Credential $UserCredential
 
# As long as the next User profile is NOT the one we started with (at -1)...
While ($UserProfileResult.NextValue -ne -1) 
{
Write-Host "Checking profile $i of $NumProfiles"
# Look for the Personal Space object in the User Profile and retrieve it
# (PersonalSpace is the name of the path to a user's OneDrive for Business site. 
# Users who have not yet created a  OneDrive for Business site might not have this property)
$Prop = $UserProfileResult.UserProfile | Where-Object { $_.Name -eq "PersonalSpace" } 
$Url= $Prop.Values[0].Value
  
# If "PersonalSpace" exists, then OneDrive Profile provisioned for the user...
if ($Url) {
$oneDriveSiteUrl = "https://<tenant name>-my.sharepoint.com"+ $Url.Substring(0,$Url.Length-1)
 
# Set the secondary admin
Set-SPOUser -Site $oneDriveSiteUrl -LoginName $secondaryAdmin -IsSiteCollectionAdmin $true -ErrorAction SilentlyContinue
Write-Host "Site admin added successfully: "$oneDriveSiteUrl 
}
# And now we check the next profile the same way...
$UserProfileResult = $UserProfileService.GetUserProfileByIndex($UserProfileResult.NextValue)
$i++
}