Category Archives: PowerShell

Microsoft Teams: Admins can use cloud shell from Teams admin center

Microsoft has now launched Cloud Shell within the Microsoft Teams Admin Center (13th January 2022), to enable Admins the ability to run PowerShell scripts direct from the browser.

The ability to use Cloud Shell for Microsoft Teams has been available for a while now but this small addition to the Admin Center resolves the need to have more than one window open to administer your Teams environment.

So if you are a Microsoft Teams Admin, go and check it out today.

The Author

WARNING: Unable to download the list of available providers. Check your internet connection.

When executing one of my scripts today which I havent used in a while, I ran into the following error.

WARNING: Unable to download from URI ‘’ to ”.
WARNING: Unable to download the list of available providers. Check your internet connection.
PackageManagement\Install-PackageProvider : No match was found for the specified search criteria for the provider
‘NuGet’. The package provider requires ‘PackageManagement’ and ‘Provider’ tags. Please check if the specified package
has the tags.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\\PSModule.psm1:7405 char:21

  • … $null = PackageManagement\Install-PackageProvider -Name $script:N …
  • ~~~~~~~~~~~~~
    • CategoryInfo : InvalidArgument: (Microsoft.Power…PackageProvider:InstallPackageProvider) [Install-Pac
      kageProvider], Exception
    • FullyQualifiedErrorId : NoMatchFoundForProvider,Microsoft.PowerShell.PackageManagement.Cmdlets.InstallPackagePro

PackageManagement\Import-PackageProvider : No match was found for the specified search criteria and provider name
‘NuGet’. Try ‘Get-PackageProvider -ListAvailable’ to see if the provider exists on the system.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\\PSModule.psm1:7411 char:21

  • … $null = PackageManagement\Import-PackageProvider -Name $script:Nu …
  • ~~~~~~~~~~~~~
    • CategoryInfo : InvalidData: (NuGet:String) [Import-PackageProvider], Exception
    • FullyQualifiedErrorId : NoMatchFoundForCriteria,Microsoft.PowerShell.PackageManagement.Cmdlets.ImportPackageProv

Thankfully the issues was easily resolved by running the following powershell command

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

After running this command in my PowerShell window I was ability to successfully run my script.

The Author – Blogabout.Cloud

Create Shortcuts on Desktops using Powershell

Here’s a quick script to create a shortcut to Notepad and put it on the desktop, I had to implement the create of a shortcut recently within a script so breaking it out for a dedicated post.

Step #1: The First step is to define the location and name of your shortcut. The following example will add the shortcut to the user’s desktop with a name of Your Shortcut.

$SourceFileLocation = “$env:SystemRoot\System32\notepad.exe”
$ShortcutLocation = “$env:userprofile\Desktop\Notepad.lnk”

Step #2: The second step is to create a variable referencing a Wscript.Shell COM Object.

$WScriptShell = New-Object -ComObject WScript.Shell

Step #3: The third step is to add the target path to the method

$Shortcut = $WScriptShell.CreateShortcut($ShortcutLocation)
$Shortcut.TargetPath = $SourceFileLocation

Step #4: The final step is to envoke the Save() method to save your shortcut.


Final Code

# Create a Shortcut with Windows
PowerShell$SourceFileLocation = "$env:SystemRoot\System32\notepad.exe"
$ShortcutLocation = "$env:userprofile\Desktop\Notepad.lnk"#New-Object : 
Creates an instance of a Microsoft .NET Framework or COM object.
#-ComObject WScript.Shell: This creates an instance of the COM object that represents the WScript.Shell for invoke 
CreateShortCut$WScriptShell = New-Object -ComObject WScript.Shell$Shortcut = $WScriptShell.CreateShortcut($ShortcutLocation)
$Shortcut.TargetPath = $SourceFileLocation
#Save the Shortcut to the TargetPath

The Author – Blogabout.Cloud

Understand how many emails have been sent or received by an Exchange Online Mailbox using Powershell

So had a bit of a weird question today from a colleague, who wanted a quick way to find out how many emails have been sent or received by an individual mailbox.

So Windows PowerShell to the rescue .. First of all you will need the ExchangeOnline module which can be easily installed via the following cmdlet

Install-Module -Name ExchangeOnlineManagement

Type Connect-ExchangeOnline and login using the relevant permissions

Received Message Count

# Receive Messages
$messages = Get-MessageTrace -RecipientAddress -StartDate (Get-Date).AddDays(-1) -EndDate (Get-Date)

Sent Message Count

# Sent Messages
$messages1 = Get-MessageTrace -SenderAddress -StartDate (Get-Date).AddDays(-1) -EndDate (Get-Date)

You will now get a number of received and sent messages.

The Author – Blogabout.Cloud

Invoke-WebRequest: The response content cannot be parsed when adapting a local powershell script for Azure Automation.

I have been recently adapting a PowerShell script that collects the Microsoft 365 Service Health using the Office 365 Service Communication API publishing the information into ServiceNow to log a support ticket to make the helpdesk aware of a potential issue in the service. The script was working is no issues when run manually out of PowerShell ISE but failed when ran by Azure Automation.

The focus of this post is to show two specific steps for adapting a locally executed PowerShell script for an Azure Automation runbook. In addition to standard work in Automation to add credentials/connections and create parameters where needed, the following changes were required to adapt a local script for my runbook.

1) Add -UseBasicParsing to Web Requests

The Management API script is filled with various requests using Invoke-WebRequest. Initially, I received numerous errors stating that the Internet Explorer engine is not available.

Invoke-WebRequest : The response content cannot be parsed because the Internet Explorer engine is not available, or 
Internet Explorer's first-launch configuration is not complete. Specify the UseBasicParsing parameter and try again. 
At line:46 char:9
+ $subs = Invoke-WebRequest -Headers $headerParams -Uri "https://manage ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotImplemented: (:) [Invoke-WebRequest], NotSupportedException
    + FullyQualifiedErrorId : WebCmdletIEDomNotSupportedException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

To overcome this, I needed to add the parameter UseBasicParsing.

Original: $oauth = Invoke-RestMethod -Method Post -Uri $loginURL/$tenantdomain/oauth2/token?api-version=1.0 -Body $body
Adapted: $oauth = Invoke-RestMethod -Method Post -Uri $loginURL/$tenantdomain/oauth2/token?api-version=1.0 -Body $body –UseBasicParsing

2) Alter $ProgressPreference

PowerShell shows progress using $ProgressPreference, which defaults to “continue”. For Automation, I needed to change the option to “silently continue” and suppress progress bars. Locally, the progress can be convenient to see, but it was causing issues with

Automation.Adapted: $ProgressPreference = “silentlyContinue”

The Author – Blogabout.Cloud

Configuring Password Expiry within Microsoft 365 admin center and with PowerShell

In this brief blog post I am going to demonstrate how simple it is to configure or modify password expiry policy within the Microsoft 365 Admin Center or using PowerShell to make the necessary change.

Configure using Admin Center

Launch and go to Settings –> Org Settings –> Security & Privacy –> Password expiration policy

Here you can untick Set user passwords to expire which will disable this setting or configure/modify “Days before passwords expire”

Configure using PowerShell

Running the following commands has the same effect as changing the configuration in the Microsoft 365 Admin Center.

# Connect to M365
$cred = Get-Credential
Connect-MsolService -Credential $cred

# Configure Password Policy
Set-MsolPasswordPolicy -ValidityPeriod 60 -NotificationDays 14 -DomainName ""

The Author – Blogabout.Cloud

Pushing Microsoft Health Status to Microsoft Teams using Azure Automation.

In this post I am going to demostrate how to push Microsoft Health Status to Microsoft Teams using Azure Automation

In this post it is expected you have configured Office 365 Service Communications API. If not, visit this blog post

Configuring Microsoft Teams for Incoming Webhook

Launch Microsoft Teams right click a channel within a Team and select Connectors. Search for Incoming Webhook and click Add

Click Add

Specify the name of the Webhook and click Create

Make a note of the URL below as you will need this for the PowerShell script later and click Done

Create Automation Account

Launch your Azure Portal and search for Automation Account to create a new account.

– Name
– Subscription
– Resource Group
– Location

No should be selected for “Create Azure Run As Account” as this is will enable the Account to run against Office 365.
Click Create

Once the resources has successful created, go into the resource

First of all we need to create a number of variables, these variables will use within the PowerShell script we are going to add to the Runbook.

You will need to add the following variables

– AzO365ServiceHealthApplicationID = Client ID
– AzO365ServiceHealthApplicationKey = Client Secrey
– AzO365TeamsURI = This is the url we created earlier in the post
– AzO365TenantDomain = Tenant ID

If you unsure how to obtain these values, please visit this blog post for more details

We now need to launch Runbooks

Select Create a runbook
– Provide a name
– Runbook Type should equal PowerShell
– Description (is optional)

Press Create

I am now going to use the following PowerShell script available from GitHub within my Runbook. This script has been created for the sole purpose of extracting the Microsoft 365 Service Health using the Office Service Communication API, which I demonstrated how to configure in another post.

Under the “User Defined Variables” you will need to edit;

Mintues to reflect the same time as your schedule.

Pushover notifications and Services to monitor as shown below

# ------------------------------------- USER DEFINED VARIABLES -------------------------------------

$ApplicationID = Get-AutomationVariable -Name 'AzO365ServiceHealthApplicationID'
$ApplicationKey = Get-AutomationVariable -Name 'AzO365ServiceHealthApplicationKey'
$TenantDomain = Get-AutomationVariable -Name 'AzO365TenantDomain'
$URI = Get-AutomationVariable -Name 'AzO365TeamsURI'
$Minutes = '1440'

# Pushover notifications in case Teams is down.
# Due to limitations and readability, the script will only send the title of the incident/advisory to Pushover. 

#$Pushover = 'yes' # Comment out if you don't want to use Pushover. I use 'yes' for readability.
#$PushoverToken = Get-AutomationVariable -Name 'AzO365PushoverToken' # Your API token. Comment out if you don't want to use Pushover
#$PushoverUser = Get-AutomationVariable -Name 'AzO365PushoverUser' # User/Group token. Comment out if you don't want to use Pushover
#$PushoverURI = '' # DO NOT CHANGE! Default Pushover URI. Comment out if you don't want to use Pushover

# Service(s) to monitor
# Leave the one(s) you DON'T want to check empty (with '' ), add a value in the ones you WANT to check (I added 'yes' for readability)

$ExchangeOnline = 'yes'
$MicrosoftForms = 'yes'
$MicrosoftIntune = 'yes'
$MicrosoftKaizala = 'yes'
$SkypeforBusiness = 'yes'
$MicrosoftDefenderATP = 'yes'
$MicrosoftFlow = 'yes'
$FlowinMicrosoft365 = 'yes'
$MicrosoftTeams = 'yes'
$MobileDeviceManagementforOffice365 = 'yes'
$OfficeClientApplications = 'yes'
$Officefortheweb = 'yes'
$OneDriveforBusiness = 'yes'
$IdentityService = 'yes'
$Office365Portal = 'yes'
$OfficeSubscription = 'yes'
$Planner = 'yes'
$PowerApps = 'yes'
$PowerAppsinMicrosoft365 = 'yes'
$PowerBI = 'yes'
$AzureInformationProtection = 'yes'
$SharePointOnline = 'yes'
$MicrosoftStaffHub = 'yes'
$YammerEnterprise = 'yes'

# Classification(s) to monitor
# Leave the one(s) you DON'T want to check empty (with '' ), add a value in the ones you WANT to check (I added 'yes' for readability)

$Incident = 'yes'
$Advisory = 'yes'

# ------------------------------------- END OF USER DEFINED VARIABLES -------------------------------------

You will now need to define a schedule within the Runbook for it to execute.

Once you have done all of the above, you will receive a nice notification in Microsoft Teams about the Service Health Status

In my next article I will show how simple it is too trigger this Runbook using Power Automate.

The Author – Blogabout.Cloud

Improvements for PowerShel scripts in Microsoft Endpoint Manager – Good or Bad?

As a big adovcate of PowerShell Scripts in Microsoft Endpoint Manager, I definitely welcome the recent changes which Microsoft have implemented. This will have some positive effects on most organisations but maybe not as welcomed by others and heres why?

In my experience some organisations like to leverage PowerShell to modify applications that have been installed using Win32 apps. An example I have experience within this space is Java ( Oh the horror ). This organisation still required a fat install of java to run a legacy application and Java was inserted using GPO with reg hive modified to prevent the regular and annoying pop up for updates.

So to address this we installed Java via W32 apps and used a PowerShell script from Microsoft Endpoint Manager to modify the key.

What you will probably need to do is allow your script to fail. Once the script has failed, the Win32 apps will then be installed, and If the script fails, the Intune management extension agent retries the script three times for the next three consecutive Intune management extension agent check-in. The check in period is every 60 minutes so in that time you should have succesfully installed all Win32 apps.

Here is the new channges for PowerShell scripts.

PowerShell scripts execute before apps, and time out reduced

There are some updates to PowerShell scripts:

  • Microsoft Intune management extension execution flow is reverted back to processing PowerShell scripts first, and then running Win32 apps.
  • To resolve an Enrollment Status Page (ESP) time out issue, PowerShell scripts time out after 30 minutes. Previously, they timed out after 60 minutes.

For more information, see Use PowerShell scripts on Windows 10 devices in Intune.

The Author – Blogabout.Cloud

PowerShell – Prompt for file using Windows Explorer

Sometimes when working with PowerShell scripts you may need to import a particular source file. You could specify a variable pointing directly to the file but using the below function provide a more flexible solution.

Function Get-FileName
  Add-Type -AssemblyName | Out-Null
    $OpenFileDialog = New-Object -TypeName System.Windows.Forms.OpenFileDialog
    $OpenFileDialog.initialDirectory = $initialdirectory
    $OpenFileDialog.filter = "All files (*.*)| *.*"
    $OpenFileDialog.ShowDialog() | Out-Null
Get-FileName -initialdirectory "$env:USERProfile\Desktop" 

The Author – Blogabout.Cloud

PowerShell – Checking whether a TCP port is open using PowerShell

Sometimes when working with customers you need to validate if a particular port has been opened on their Firewall. I am unable to count how many times I’ve had a discussion where a port hasnt been opened. So for simplicity the following PowerShell function allows you to check instantly;

Function Get-CheckPort{
Param (
# End of Parameters
  $Date = Get-Date
  $MyDate =  " " + $Date.Day + "." + $Date.Month + "." + $Date.Year + " " + $date.Hour + ":" + $date.Minute
     $connection = $null
     $connection = New-Object System.Net.Sockets.TcpClient($ipaddress, $port)

       Write-host "Warning: Port $port is closed - $MyDate" -ForegroundColor Red
  if ($connection.Connected){
     Write-Host "Info: Port $port is open - $MyDate" -ForegroundColor Green
Get-CheckPort -ipaddress '' -port ''

As you can see from the test above, I am to validate that port 80 to the is open

The Author – Blogabout.Cloud