Replacing Azure AD and MSOL with Graph PowerShell Module

Support for both Azure AD and MSOL modules have been extended to allow the updating of scripts and I would presume due to some command not existing in Graph yet. The modules will be deprecated in June 30th 2023 so any scripts using command with either of these modules should be updated as soon as possible.

In this post we will be going through some common commands that use either the Azure AD or MSOL PowerShell modules and how to find commands that will replace them in Graph and using the scope roles to set required API permissions.

First stop I usually do is to check if the commands have direct replacements, we can use the below learn page to check. The page will have tables with the Azure AD / MSOL command and then the replacement command if one exist in the second row.

For the below reference we will be using Get-MsolUser if we check the document that command is replaced by Get-MgUser.

Now when connecting to Azure AD or MSOL all commands and permission are based on the role of the account you sign-in with.

If we connect with MSOL we can query users once we have the required role.

For Graph the way to connect is slightly different if we don’t specify a scope when connecting, we can connect but we don’t automatically have the require API permission assigned so if we run the Get-MgUser command we will get an error for insufficient privilege’s

If we add the -scope User.Read.All

If we want to check what permission are available for a command we can use Find-MgGraphCommand with the command we want to check. We can also use the apiversioni (v1.0 or beta)

Find-MgGraphCommand -Command Get-MgUser -ApiVersion v1.0 |fl

To just return the permission we can use parenthesis to select just the permissions.

(Find-MgGraphCommand -Command Get-MgUser -ApiVersion v1.0).Permissions

Depending on what task we are trying to do we can select the required permission, one example is if I just want to get back information on account’s I would just use User.Read.All. If I wanted to change a users settings I would use the User.ReadWirte.All.

Another difference between modules is that in Graph there is no -userprinicpalname parameter and uses UserID instead

To get licenses assigned to a user we can use.

Get-MgUserLicenseDetail -UserId UPN

As we can see Microsoft Graph has a few differences and instead of having most data under single objects like Get-MsolUser we have to now use multiple commands to return the same data which can be a bit more difficult when starting out.

VMware Distributed Port Group Configuration Report Using PowerCLI

From time to time we need to check that VMware Distributed Port Groups are following our standard configuration. If there is only a few port group this can be done manually but in my case I need to check a few hundred.

Since there are so many I wanted to make a script that will export the configuration of each port group and out put to a CSV.

In this post we will be going through using PowerCLI to report on the configuration setting for all distributed virtual switch port groups.

I used the PowerCLI developer doc to find the required commands to check each port group configuration settings and policies.

First we need to get the list of Distributed Virtual Switches (VDS)

Once we have the list of switches we can use the below command to return all port groups.

Get-VDPortgroup -VDSwitch switchname

Next we can take one port group and start to view the properties to get the required info.

The below will view the general port group settings like VLAN, port bindings and Numbers or ports.

Get-VDPortgroup -Name portgroupname |fl

To view the override policy use the below command.

Get-VDPortgroup -Name portgroupname | Get-VDPortgroupOverridePolicy

To view the teaming policy use the below.

Get-VDPortgroup -Name portgroupname | Get-VDUplinkTeamingPolicy

For team policies the name in PowerCLI is different than in the web UI, the below table will match up the names

LoadBalancingPolicyLoad balancing
LoadBalanceLoadBasedRoute Based on Physical NIC Load
LoadBalanceSrcMacRoute Based On Source MAC Hash
LoadBalanceSrcIdRoute Based On Originating Virtual Port
ExplicitFailoverUse Explcit Failover Order
LoadBalanceIPRoute Based on IP Hash

To view the security policy use the below.

Get-VDPortgroup -Name portgroupname | Get-VDSecurityPolicy

Now that I have all the different policy and configuration settings I can create the script.

I will be using a hash table for all export the configuration and policy settings.

The full script can be download from my GitHub repository link below.

The script can be run to either output the configuration details to the PowerShell console using the below command.

.\VMwarePortGroupConfig.ps1 -VCServer vCenter

The second option is to export to CSV file by using the -ReportExport parameter.

.\VMwarePortGroupConfig.ps1 -VCServer vCenter -ReportExport .\

The below is what the CSV output should look like.

Create Local ESXi Account Using PowerCLI

In this post we will be going through creating local ESXi account using PowerCLI.

Recently I have had to create local account to allow a monitoring tool to pull information from all ESXi hosts.

We want to automate the user creation and assign the required permissions so that they only have the permission required for a limited time.

First we need to connect to the ESXi Host using PowerCLI

Connection to vCenter

To check what account already exist use the below.

List Accounts

To create a new account we will use the New-VMHostAccount command

New-VMHostAccount -Id accountname -Password password -Description Account Description
Create new account

Next we need to assign the required permissions. We can list the current roles using

List VMware Roles

We also need an entity to set the permission or the command will error out.


To list the entity use the

List Folder

Select the entity that will have the role applied. In this case we will be applying to the root object so it applies to all objects on the host and will assigning the admin role.

New-VIPermission -Entity (Get-Folder root) -Principal accountname -Role Admin
Set Permission

To remove the account use the below command.

Get-VMHostAccount -User account name | Remove-VMHostAccount -Confirm:$false

Once we have the commands, we can create the script to automate the account creation and role assignment to configure multiple hosts.

Account Creation Script

The scripts uses EsxiHost as the heading for the CSV if you want to use something different the script will need to be updated.

Below is the script running against my test hosts.

.\Create-LocalESXiUser.ps1 -ESXiHostList .\EsxiHosts.csv -ESXiUser useraccount -ESXipass password -ESXiNewUser accountname -ESXiUserPass accountpass -ESXiPermission Permission -ESXiUserdesc "Account Description"
Account creation script

This process can also be used to update the permission for a specific account.

Updating permissions

To download the full script use the below link to github.

Configure SNMP On VMware ESXi Using PowerCLI

In this post we will be going through deploying new SNMP configuration to a list of ESXi hosts using PowerCLI. We can add SNMP using ssh and esxcli commands but this will required SSH to be enabled and connecting to each host.

We can use Set-VMHostSNMP command to set the SNMP configuration by conecting to the host using connect-viserver which uses https to connect and does not required SSH to be enabled.

First we need to connect to the ESXi host

Connect-VIServer -Server esxihost.domain.local

use a local account like root to connect

PowerCLI SNMP Command

If you get a certificate error and can’t connect you might need to update the PowerCLI Configuration or install the root cert to trust the self singed cert of the ESXi hosts.

Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false

Once connected we will be using the below set of command to configure the SNMP settings.

Get-VMHostSnmp | Set-VMHostSnmp

First we will enabled and set the community string

Get-VMHostSnmp | Set-VMHostSnmp -Enabled:$true -ReadOnlyCommunity communityname

PowerCLI SNMP Command

Next we will set the target that traps will be sent.

Get-VMHostSnmp | Set-VMHostSnmp -TargetCommunity communityname -TargetHost snmp.domain.local -TargetPort 162 -AddTarget
PowerCLI SNMP Command

To test I have setup snmp on Ubutu

Ubuntu SNMP check

Now that we have set of command we can create the script. I will be doing a loop through each host and configuring the SNMP.

I also added in some if statement to check if SNMP is already enabled and to check if the target host matches the one that is set in the parameters.

SNMP Script

The full script can be downloaded from the below github link.

Below is an example of what the csv file should look like if you want to use a different heading the script will need to be updated.

Each of the values will be called as parameter to allow easy re-use below is an example of the SNMP script running against my test hosts.

Using PowerCli can be a quicker way to set and enabled SNMP on a list of hosts rather than having to SSH and use esxcli command. This can also be used to update the existing SNMP configuration to a new traps target.

VMware List All Port Groups and Associated VM’s Using PowerCLI

During a recent project we have been starting to use network segregation to give more security and control instead of using a flat network.

This has lead to VM’s being broken up in to there own VMware port groups and segregated VLAN’s.

There are now old port groups that have had all VM’s removed, so we wanted to report on any port groups that have no VM’s associated so that they can be removed as we will hit a issue with max VLAN limit per physical interface.

The quickest way I could think of to create the report was to use PowerCLI, in this post we will go through the process and commands used to create the report.

First we need to connect to vCenter using PowerCLI

We will be using a few different commands in the script.

First we will need to get list of port groups will only be getting distributed port groups as we don’t use standard port groups.


Second part of the script is to get the port group view using get-view

Get-View -ViewType Network -Property Name -Filter @{"Name" = "portgroup name"}

We will be using UpdateViewData to add some addtional values to the view to make the script quicker and easier to read see below link for more details on UpdateViewData.

To find the properties we wanted to report on we used

Get-VM -Name VMName | Get-View

Use Get-VIObjectByVIView to get the host information.

$vm = Get-VM -name VMName | get-view
(Get-VIObjectByVIView $

I want to report on the VM name, Host, Cluster and PowerState.

Below we will get the view for the port group and update the view with the additional details that I want in the report.

$networks = Get-View -ViewType Network -Property Name -Filter @{"Name" = "portgroup name"}

$networks | ForEach-Object{($_.UpdateViewData("Vm.Name","Vm.Runtime.Host.Name","Vm.Runtime.Host.Parent.Name","vm.Runtime.PowerState"))}

We can run the below to check if the addtional information has been added to the veiw


Once we have the view working and adding the properties we want we can start to create the full script.

The full script can be copied from the below github link.

There are two parameters in the script.

To just output to the console screen use -ConsoleOnly parameter.

To export to csv use the -ReportExport parameter.

Below is a example of the exported csv.

VMware PowerCLI Module 12.4 Update Error

With the release of VMware PowerCLI 12.4 I was updating the module on my LAB servers so I could check out the new command.

When upgrading I was getting the below error which is due to VMware changing the certificate authority used to publish the new module.

Authenticode issuer ‘, CN=”VMware, Inc.”, O=”VMware, Inc.”, L=Palo Alto, S=California, C=US’ of the new module ‘VMware.VimAutomation.Sdk’ with version ‘’ from root
certificate authority.

In the release notes from VMware there is a know issue with the certificate. The fix is to remove and re-install the module.

I though I would do a quick post on this incase anyone doesn’t know the process.

To check where the module is installed run the below command.

Get-Module -ListAvailable VMware.PowerCLI
This image has an empty alt attribute; its file name is image-21.png

In my case the module was installed in C:\Program Files\WindowsPowerShell\Modules.

Next we need to remove the old modules, below is a list of the folders that make up the VMware PowerCLI 12.0 module.

After removing the folder we now have to install the new module using Install-Module

Install-Module VMware.PowerCLI

Once completed we should now have PowerCLI version 12.4

Using VMware PowerCLI Get-EsxCli

In this post we will be going through using the PowerCLI Get-EsxCli commandlet, which is used to call EsxCli command from PowerShell instead of having to SSH directly to the the ESXi host.

This can be useful when trying to gather information from multiple hosts instead of connecting on to each host with SSH or updating configuration settings.

First step is to connect to vCenter, once connected we can run the Get-EsxCli command and this will return the list of namespaces that can be use to gather information or set configuration settings.

We will be using -V2 as this sets Get-EsxCli to use version 2 interface as version 1 is being deprecated and will be removed in a later version.

Get-EsxCli -VMHost esxihost -V2

We can set the Get-EsxCli command to a variable so that we can call the namespaces, below will call the network namespace, once called there will be a list of addtiaonl namespaces that can be called.

$vmhostesxcli = Get-EsxCli -VMHost esxihost -V2

Once we select a namespace there should also be a list of methods that can be called these can be used to run specific actions like list or get to return information.

To list all nic’s we can call the nic and then list namespace


To gather info on details like driver version we can use the get method, in v1 you use to be able to call the nic name directly but if you try this in v2 the below error will be returned.

If specified, the arguments parameter must contain a single value of type Hashtable.

This is due to the method requiring a hash table parameter. If we call the help method it should return the valid parameters. If the parameter has a hyphens remove this or the command wont work.

For the nic namespace the parameter is nicname and needs to be called as a hash table.


There might be some namespaces that have multiple properties like driverinfo under nic, these can be called by adding the property like below.


Now that we have the command we can start to build out a script to export information.

In this case we will be getting all hosts, listing all NIC’s and getting the drivers info.

The above shows that Get-EsxCli can be very good for retrieving information, if we wanted to set a configuration we can use similar command syntax but use the set method.

In this case we will update the Power policy settings on all host, we could do this manually by going to the Configure > Hardware > Overview > Power Management one each host and update the power policy settings

but doing this on a larger cluster is a lot of effort. To update using PowerCli we can first create the script to report on the current host power policy.

To update the policy settings we will use the set method like the below.


Below are the 4 different power policy’s.

IDPower Policy
1High Performance
3Lower Power

We can then take the above and create a re-usable script to report or set the power policy on all host in one go.

To download a copy of the either of the above script use the below link to my Github these can be used as reference if you want to create your own scripts for other settings.

Report on users MFA status in Office 365 using PowerShell

During a recent audit we wanted to confirm what users had MFA enabled in Office 365. We use conditional access policy to enforce MFA.

We wanted to check each users to see if they had setup MFA and had a method configured. We also wanted to get information on licensing status and assigned licenses.

The only pre-req for using the script is that the MSOnline Powershell module is installed.

To install the MSOline module open and admin PowerShell windows and run

Install-Module -Name MSOnline

To confirm the module is installed run the below command.

Get-Module -ListAvailable MSOnline
This image has an empty alt attribute; its file name is image-26.png

First we need to connect to MS Online to do this run


Once connected to check the MFA status I will be using the StrongAuthenticationMethods properties as if MFA is configured for the user there will be a default method set.

For users that haven’t configured MFA no StrongAuthenticationMethods is set.

Below are the 4 methods available for MFA.


In the script I only want to return the default method.

There is only one mandatory parameter for the export path where the report will be exported to.

The below is an example of how to run the report.

.\Office365_MFA_Report.ps1 -ExportPath C:\temp

Below is what the output will look like.

The full script can be downloaded from the below link.

Scripts/Office365_MFA_Report.ps1 at master · TheSleepyAdmin/Scripts (

Weekly Active Directory Audit Report PowerShell

Recently a request came in from our security team to audit recently create, deleted AD object, accounts due to expire (this is for third party users) and modified / created group policy objects so that they would be able to trace the changes happening in Active Directory.

I decided to write a PowerShell script that will export the required information and then send a the csv export to the user that require the information.

This could also be used to import the data to a dashboard by either using the CSV files or if the dashboard can use direct PowerShell script like PowerBI.

First there are some mandatory parameters. Exportpath and domain.

To allow the script to be run without emailing the csv I have left the smtpserver, to and from address as not mandatory parameters.

The script used two different modules

Group Policy:


To install these go on a Windows server go to add roles and features and select Group policy Management

and under RSAT enabled the Active Directory module.

Once all the features are enable we can run the script.

I have set the default time to last 7 days but if you want to go back further then update the date value.

To run the script so that it just export local without email the reports use the below.

.\WeeklyAD_AuditReport_V1.ps1 -exportPath c:\Temp\AD_Audit\ -domains domian.local

To email the report use the below

.\WeeklyAD_AuditReport_V1.ps1 -SMTPServer mailserver.domain.local -toAddress administrator@domain.local -FromAddress ADreport@domain.local -exportPath c:\Temp\AD_Audit\ -domains domian.local

Once the script completes we can check that the csv files have been created.

If the SMTP server parameter is set, the script will send a email and add the csv as attachments.

Below is what the outputs should look like.


Deleted Objects:

Account expire:

The full script can be downloaded from the below link to my GitHub.

Scripts/ActiveDirectory/WeeklyReport at master · TheSleepyAdmin/Scripts (

The script can then be set to run as a scheduled task to run on a weekly scheduled.

VMware Daily Health Check HTML Report PowerShell

I have been working on a daily check report for our VMware environment so that we don’t have to manually check each morning.

The report uses PowerCli to generate information and then output the results to a HTML file.

The report requires a few that either the old PowerCLI snapin is available or preferably the PowerCLi PowerShell module.

The script can either be run directly by a users with rights to query vCenter or by setting up a scheduled task.

The following prerequisite will be needed for the script to run.

  • PowerShell V4 or V 5
  • PowerCLI 6.0 or later version
  • vCenter 6.0 or later version

There will also need to be a mail server or relay server available for the report to be emailed.

This has been tested on PowerCLI version 6.0 and above. The version on the server I will be running from is 12.3.0 which is the latest release at this time.

The report checks

  • vCenter connection
  • VMware tools check
  • Snapshot older than the specified snapshots days
  • Host Alarms
  • VM Alarms
  • vCenter Alerts over the last 12 hours
  • Datastore under specified % free space

There are mandatory parameter that are required for the script to run and send the report.

  • VCServer = vCenter Server address
  • SMTPServer = Mail server address
  • Toaddress = destination email
  • Fromaddress = sending address
  • Report Export = folder report will be exported to

There are some variables at the start of the script that can be set to customize the report to only show the required snapshots days and datastore % free. In my case I wanted 3 days and below 20% free on datastores.

I have embedded the html CSS format in the script so it can be update to change the color, font size or font type.

Example of how to run the script is below

.\VMwareDailReportv1.ps1 -VCServer vcenter.domain.local  -SMTPServer mail.doamin.local -FromAddress VMwareReport@domain.local -toAddress Administrator@domain.local -ReportExport D:\Scripts\VMware\Daily_Report

Once completed the report should be emailed to the specified to address.

Below is an example of the report export.

The full script can be downloaded from.

Scripts/VMwareDailyReport.ps1 at master · TheSleepyAdmin/Scripts (

To create a scheduled task to run the report each morning go to scheduled task on the server or client that has PowerCLI installed.

Create a new task

Set the schedule.

Next we need to set PowerShell as the program to start and set the argument to similar to the below, updating the parameters and script location

-ExecutionPolicy Bypass -NoProfile -File D:\Scripts\VMware\Daily_Report\VMwareDailReportv1.ps1 -VCServer vcenter.domain.local -SMTPServer mail.doamin.local -FromAddress VMwareReport@domain.local -toAddress Administrator@domain.local -ReportExport D:\Scripts\VMware\Daily_Report

I don’t change anything on conditions tab and only update that stop task if running longer than an hour in the settings tab.

Once completed run the task to confirm all is working.

I will probable added to the script but this is just the initial version and thought it might be helpful to anyone who want to try automate some of there manual checks.