05 November 2019

Delegate permissions for managing MFA - Reset MFA rights for the helpdesk

There is a request for this on uservoice :


To be able to delegate the permission of administering user account MFA setting like enable/disabled forcing reset of MFA code etc.
Currently the Global Admin permission is needed. It would be able very useful to delegate this to a service desk function without having to provide full admin access to the tenant.
But there is a way, it's called the "Authentication Administrator" role in AzureAD.
Adding a "Support" user to this role gives him the rights to reset MFA settings for users that have MFA setup, and non-admin accounts. 
Also they can't reset their own accounts.

23 October 2019

Known solutions for hybrid migration errors - Lifesaver

This saved my life on numerus occasions:

1 - MigrationPermanentException: You must specify the PrimaryOnly parameter.

This error can occur when you attempt to migrate to cloud an on-prem mailbox via a migration batch from EAC, where the online archive already exists for this user.

FIX: In order to migrate the primary mailbox to Office 365, you will need to start the mailbox move with the following command, from Exchange Online PowerShell:

New-MoveRequest –Identity user -RemoteCredential (Get-Credential) -Remote -RemoteHostName 'mail.contoso.com' -TargetDeliveryDomain tenant.mail.onmicrosoft.com -PrimaryOnly

2 - Couldn't switch the mailbox into Sync Source mode. This could be because another administrator is currently moving the mailbox into the destination database,
the mailbox is locked, or the Microsoft Exchange Mailbox Replication service doesn't have the correct permissions.
FailureType: SourceMailboxAlreadyBeingMovedTransientException.
This error can also be correlated with slow migration performance.
Possible solutions:
-Check if there is any local move request for this user on the on-prem Exchange Server.
-In case you have Exchange 2010 with multiple CAS servers that are load balanced, make sure that your Load Balancer maintains the session affinity,
 more exactly all the incoming migration requests for a mailbox should be processed by the same CAS server.
-Try to see if setting the TCP KeepAliveTime on the server hosting the source mailbox to 5 minutes (instead of 2 hours) will fix the issue.

More details can be found into this article: https://blogs.msdn.microsoft.com/brad_hughes/2016/12/16/source-mailbox-already-being-moved-errors-while-moving-mailboxes/

3 - Failed to convert the source mailbox 'mailboxID' to mail-enabled user after the move.
FailureTpe: UpdateMovedMailboxPermanentException.

- The user might end with 2 mailboxes: 1 in the cloud and 1 in local Exchange.
- Such issues can occur if the affected user have the inheritance disabled in local AD.
- There is a property called AdminCount on each user in local AD, that by default is not populated or it gets set to “1”, once the account is added to a privileged group.
- The AdminCount value is used as a flag to indicate the account is, or was, protected.
- More information about inherited AD permissions can be found in the next article:


4 - MapiExceptionTooComplex: Unable to query table rows. (hr=0x80040117, ec=-2147221225)

To prevent this failure during the move process (onboarding or offboarding) you need to skip moving the folder views or folder restrictions along with the mailbox, by starting the move from EXO PowerShell as below:
New-MoveRequest –Identity user@contoso.com -SkipMoving: FolderViews, FolderRestrictions -Remote -RemoteCredential(Get-Credential)-RemoteHostName "mrsproxy.contoso.com" -TargetdeliveryDomain contoso.com

5 - MigrationPermanentException: You can’t use the domain because it’s not an accepted domain for your organization. –> You can’t use the domain because it’s not an accepted domain for your organization.

FIX: Check on the AD user object if there are any proxy addresses in some domains that are not verified in Exchange Online.
Once you identified the faulty email addresses, remove them and force the AADconnect sync. Then start a new migration for the affected user.

6 - MigrationPermanentException: The target mailbox doesn’t have an SMTP proxy matching ‎'contoso.mail.onmicrosoft.com‎'.

This issue may occur if the source mailbox isn't stamped with a <domain.mail.onmicrosoft.com> SMTP address.

FIX: https://support.microsoft.com/en-gb/kb/2939340

7 - MigrationPermanentException: Cannot find a recipient that has mailbox GUID <GUID>" error message when you try to move a mailbox in an Exchange hybrid deployment.

This behavior occurs because the value of the ExchangeGUID attribute from Exchange Online user isn't stamped on the associated remote mailbox from the on-premises organization.

FIX:  https://support.microsoft.com/en-us/kb/2956029

8 - Fatal error TooManyMissingItemsPermanentException has occurred.
or Fatal error TooManyBadPermanentException has occurred.

This issue can occur because the bad items limit for the move request has been reached.

FIX: In order to fix the issue, you should increase the bad items limit to a higher value:
Set-MoveRequest user –BadItemLimit 100
Resume-MoveRequest user

9 - The call to 'https://mail.contoso.com/EWS/mrsproxy.svc' timed out. Error details: The request channel timed out attempting to  send after 00:00:00.
Increase the timeout value passed to the call to Request or increase the SendTimeout value on the  Binding.
The call to 'https://mail.contoso.com/EWS/mrsproxy.svc' failed because no service was listening on the specified endpoint.
Error details: There was no endpoint listening at https://mail.contoso.com/EWS/mrsproxy.svc that could accept the message.
This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details. --> The remote server returned an error: (404) Not Found.

These errors are usually occurring only for particular users, while other mailboxes can be moved successfully.
They are caused by the ExchangeGuid mismatch between EXO and local Exchange:

FIX: https://support.microsoft.com/en-us/kb/306575

10 - The call to ‘https://mail.domain.com/EWS/mrsproxy.svc ‘ failed. Error details: The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults
(either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation  and inspect the server trace logs.. –>
The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior)
on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.

The failure type for this error is CommunicationErrorTransientException.

This error is caused by some particular folders views from source mailbox. MRS fails to create these folders into the hierarchy of the destination mailbox.

FIX: https://blogs.technet.microsoft.com/latam/2016/01/05/o365-error-when-trying-to-move-a-mailbox-to-the-cloud-creatingfolderhierarchy-communicationerrortransientexception/ https://support.microsoft.com/en-us/help/3063045/-transientexception-errors-when-you-try-to-move-mailboxes-from-exchange-online-to-exchange-server-2007-in-the-on-premises-environment

11 - Failed to find a principal in the target forest that corresponds to a source/target forest principal ( A corrupted item was encountered: Folder ACL “Foldername").

This message is related to mailbox/mailboxfolder permissions that cannot be migrated, since MRS cannot find the object from permissions list in the source or destination forest, being unable to map the permissions.

FIX: See below article for more details:

12 - Cannot query rows in a table. --> MapiExceptionMaxObjsExceeded: Unable to query table rows.
FailureType       : StoragePermanentException

FIX: Increase limit of Search Folders in the on-premises Exchange Server as per below steps:

1.On the Exchange server hosting the target database where cloud mailbox will be offboarded, look for and open the following config file:
 Microsoft.Exchange.Store.Worker.exe.config, found in Bin folder of %ExchangeInstallPath% .

2.Add the following lines in Configuration tag, between </runtime> and </configuration>
<add key="DynamicSearchFolderPerScopeCountReceiveQuota" value="250" />

3.Restart Microsoft Exchange Information Store service after modifying this file and try again the move.

13 - The call to 'https://MRSPROXYHOST/EWS/mrsproxy.svc SERVER.domain.com ( caps:05FFFF)' failed.
Error details: The remote endpoint no longer recognizes this sequence. This is most likely due to an abort on the remote endpoint. The value of wsrm:Identifier is not a known Sequence identifier. The reliable session was faulted.

This error is usually caused by a wrong load-balancing configuration, when using multiple Exchange 2010 CAS servers.

FIX: To prevent this issue to occur, make sure that your load-balancer is keeping the session affinity/persistence. This behavior is explained in the next article:

14 - Error:MissingExchangeGuidException: The user object for ‎'user@domain.com‎' does not have a valid ExchangeGuid property and cannot be migrated.
This issue occurs when EXO fails to provision the ExchangeGUID attribute for an user(msoluser will have a validation error), because this ExchangeGUID value is already used by another object from EXO, it could be an active mailbox/mailuser or a soft deleted mailbox/mailuser.

FIX: First use this command to get the ExchangeGUID/ArchiveGUID from the validation error:
(Get-MsolUser -UserPrincipalName affecteduser@domain.com).errors.errordetail.objecterrors.errorrecord| fl

Search in EXO PowerShell for the object that is using the mentioned EXchangeGUID or ArchiveGUID:
Get-Recipient -IncludeSoftDeletedRecipients 'ExchangeGUID value'|ft RecipientType,PrimarySmtpAddress,*WhenSoftDeleted*

Once you found the object that is using this guid, you have to purge it:
1.If it is a softdeleted MailUser:
Remove-MailUser 'ExchangeGUID value' -PermanentlyDelete
2.If it is a softdeleted UserMailbox, run: 
Remove-Mailbox 'ExchangeGUID value' -PermanentlyDelete
-if this command fails due to mailbox being protected by hold, you have to disable the hold first(check if data backup is required):
Set-Mailbox user@domain.com -LitigationHoldEnabled $false -InactiveMailbox
3. If it turns to be an active mailuser/mailbox that is using this ExchangeGUID/ArchiveGUID, you need to evaluate the option to purge that user(however, this is a very rare scenario though).
4. After the faulty object has been purged from EXO, we need to fix the validation error by forcing the object provisioning:
Get-MsolUser -UserPrincipalName user@domain.com |fl *objectID*
Redo-MsolProvisionUser -ObjectId 'paste the *objectID* value from above command'
5. After 5 minutes run this command to confirm if your validation error is fixed:
(Get-MsolUser -UserPrincipalName user@domain.com).errors.errordetail.objecterrors.errorrecord| fl
6. If the validation error is gone, you can try again the migration.

15 - The call to 'https://<ServerName>/EWS/mrsproxy.svc' failed. Error details: Access is denied”  error when you try to create a new migration batch or to start a new move request, using Exchange 2013 as the migration server.

This issue occurs if the computer account of the Exchange 2013 hybrid server is a member of one or more protected groups.

FIX: https://support.microsoft.com/en-us/help/2975731/access-is-denied-error-when-you-try-to-move-mailboxes-to-exchange-onli

16  The remote server returned an error: (403) Forbidden. The connection to the server 'mail.contoso.com' could not be completed.The call to 'https://mail.contoso.com/EWS/mrsproxy.svc' failed. Error details: The HTTP
request was forbidden with client authentication scheme 'Negotiate'.

This error is related to MRSproxy endpoint not being enabled on the CAS servers involved in the migration.

You need to enable MRsproxy endpoint on EWS virtual directory for every CAS server or in case it shows as being already Enabled, you might need to disable/re-enabled it, followed by and IIS reset.

More  details can be found into this article:

17 - The call to 'https://mail.contoso.com/ews/mrsproxy.svc' failed. Error details: Unable to cast object of type 'System.String' to type 'System.String[]'.. --] Unable to cast object of type 'System.String' to type 'System.String[]'.

This error can be caused by some restrictions or invalid properties on the "Search Folders" defined by the user.

FIX: Start Outlook client from where the affected user profile is configured, using the switch "outlook.exe /cleanfinders", and re-attempt the migration.

18 - Target database 'xxxx-xxxx-xxxx-xxxx' cannot be used: Database is excluded from provisioning: 'True'.
This error can occur when the migration service is assigning you a target database that might be under maintenance work.

FIX: The fastest solution is to delete the affected move request and to start a new one, in order for the migration service to select a new database.

19 - Failuretype: MailboxIsNotInExpectedMDBPermanentException /Error Message: The mailbox is in not in the expected mailbox database.

FIX: This error can be expected when the source mailbox being relocated to another database during the remote move.(can be the result of a local move or a database failover).
Usually this error can be fixed when you resume the moverequest. If the error persists, you can try moving the affected mailbox to another local database, then to start a new move request to Exchange Online.

20 - FailureType: StoragePermanentException . Error Message: Cannot save changes made to an item to store. --> MapiExceptionMaxObjsExceeded: Unable to save changes.

FIX: This error is usually related to the max number of items from a mailbox folder being reached ( >1 million items).

In order to find the folder in question(it can be a folder under IPM subtree or from outside IPM), you can run below commands:

$root=Get-MailboxFolderStatistics -Identity user@domain.com

$root|sort itemsinfolder -descending |ft folderpath,itemsinfolder

$non_root=Get-MailboxFolderStatistics user@domain.com -FolderScope NonIpmRoot

$non_root|sort itemsinfolder -descending |ft folderpath,itemsinfolder

If the faulty folder is accessible from Outlook/MFC MAPI, then you can move some of the items to other folders, to have under 1 mil items per folder and resume the migration.
If this folder is a non IPM folder, for example "/"  root folder, there is no easy way to access the items from it and the best option would be to export the mailbox content into a PST file
and import it in the remote mailbox, after following this article: https://support.microsoft.com/en-us/help/2745710/a-user-can-t-access-a-mailbox-by-using-outlook-after-a-remote-mailbox


15 October 2019

How to set default retention policy for all existing and new users in Exchange Online - Set default retention policy for On-Premises users

In Exchange Online you can set a retention policy as the default for everyone within the tenant.
In Exchange On-Premises this isn't possible, therefore you have to set them every once in a while.

For Exchange Online:

To view all your retention policies:

The set the one you want as the default:
Set-RetentionPolicy "Company - Default Policy" -IsDefault:$true

For Exchange On-Premises:

To view all your retention policies:

To set the one you want as default for all existing users:
Get-Mailbox -Resultsize Unlimited | Set-Mailbox -RetentionPolicy "Company - Default Policy"

To check what the current retention policy is:
Get-Mailbox -ResultSize Unlimited | Select Retentionpolicy,Name

02 September 2019

Error: MigrationPermanentException: Cannot find a recipient that has mailbox GUID

Error: MigrationPermanentException: Cannot find a recipient that has mailbox GUID

After trying to move a mailbox from Exchange Online to Exchange On-premises the above error occurred.
This happend because the mailbox was created online and not on-premises, and therefore the GUID wasn't synced to AzureAD and vice versa.

Luckily there is a simple fix:

In Exchange Online PowerShell:
Get-Mailbox alias | FL ExchangeGUID

In the On-Premises Exchange PowerShell:
Set-RemoteMailbox Alias -ExchangeGUID 12345678-1234-1234-12345678
Then wait for replication to AzureAD and your mailbox move should go without a hitch.

02 July 2019

EdgeSync failed to decrypt the credential for Edge Transport - Eventid 1033 MSExchange EdgeSync - Renewed certificate lately?

EdgeSync failed to decrypt the credential for Edge Transport server sr-xxxx.domain.lan using the private key of the default Exchange certificate with exception Invalid provider type specified.
. The certificate's thumbprint is XXXXXXXXXXXXXXXXXXXX52F0283F5F8BDDD13058 and its subject is CN=autodiscover.domain.nl, OU=ICT, O=Company., L=City, S=State, C=NL.
Use either Enable-ExchangeCertificate or New-ExchangeCertificate to set the proper Exchange default certificate and re-subscribe the Edge Transport server sr-XXXX.domain.lan again.

Well...here we go again.
At least I'm not bored at work.

Quick recap, this was after renewing our old Exchange certificate that had the SMTP service assigned to it. The old certificate was an old SHA1 type, this is very important to keep in mind as it comes back later in the solution.

In my quest to solve this as quickly as possible I came across some other strange things, which I will list later on.
But first let me sum up all the steps needed to resolve this:

  1. On the Edge server request a new Exchange certificate:
  2. Generate a new EdgeSubscription file:
    New-EdgeSubscription -FileName C:\Temp\Servername.xml
  3. Copy the EdgeSubscription file to an Exchange 2013 or 2016 or 2019 server (I'm assuming you installed multirole)
  4. Remove the current EdgeSubscription(s):
    Get-EdgeSubscription | select Name
    Remove-EdgeSubscription -Identity YourEdgesubscriptionName
  5. Find the current self signed Exchange Certificate with the servername as Subject. This certificate is created at installation. This certificate needs to get the SMTP service reassigned to it. Copy the thumbprint, we need it in the second command:
    Get-ExchangeCertificate | fl
    Enable-ExchangeCertificate -Thumbprint XXXXXXXXXXXXXXXXXX334EFEA37EFC7E5813 -DoNotRequireSsl -Services:SMTP
  6. Double check your existing subscription has been deleted:
  7. Create a new Edge Subscription with the file copied in step 3:
    New-EdgeSubscription -FileData ([byte[]]$(Get-Content -Path "C:\Temp\Servername.xml" -Encoding Byte -ReadCount 0)) -Site YourSiteName
  8. Then start your newly created subscription:
  9. Test the EdgeSynchronization:
  10. The last step is to sync everything:
    Start-EdgeSynchronization -ForceUpdateCookie -ForceFullSync
The problem I had was the certificate that got renewed initialy was a SHA1 certificate.
The one it got replaced with was a SHA256 certificate. When trying to renew the Edge Subscription the following error popped up:
A special Rpc error occurs on server sr-xxxxx Invalid provider type specified
This the SHA1 part I mentioned earlier. The Edge Subscription only works with SHA1 certificates.
Strange and not very secure, eventho it is meant for internal Exchange server traffic only.
Hence the default certificate created at installation of Exchange itself is needed, which is SHA1.


28 June 2019

Removing AccessRights - WARNING: An inherited access control entry has been specified and was ignored - WARNING: An inherited access control entry has been provided and was ignored

So this just happed:
Remove-MailboxPermission -Identity SharedMailboxAlias -User Username -AccessRights FullAccess -InheritanceType all
Are you sure you want to perform this action?
Removing mailbox permission "SharedMailboxAlias" for user "UserName" with access rights "'FullAccess'".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [?] Help (default is "Y"): y
WARNING: An inherited access control entry has been specified: [Rights: CreateChild, Delete, `
ReadControl, WriteDacl, WriteOwner, ControlType: Allow]  and was ignored on object `
"CN=SharedMailboxAlias,OU=Shared Mailboxes,OU=Mail,DC=Domain,DC=lan".
Checked to see what was keeping me from removing the access rights:
Get-MailboxPermission -Identity SharedMailboxAlias -User UserName

Identity             User                 AccessRights                 IsInherited Deny
========             ====                 ============                 =========== ====
Domain.lan/Mail/S... Domain\UserName      {FullAccess}                 True        True
Domain.lan/Mail/S... Domain\UserName      {FullAccess}, Delete...      True        False
And there it was, the "IsInherited" value True.
So its coming from above...

So I had to go through and remove some legacy permissions from Exchange. This can be added at multiple levels so it’s aways a diagnostic trail to where this was added. Go through each of these and if IsInherited is set to False you’ve found out where it’s being applied from.
Get-MailBoxPermission Domain\UserName

Get-MailboxDatabase | Get-ADPermission -User Domain\UserName

Get-ExchangeServer | Get-ADPermission -User Domain\UserName

Get-OrganizationConfig | Get-ADPermission -User Domain\UserName
Remove the Permissions per level with
Get-MailBoxPermission Domain\UserName | Remove-ADPermission

Get-MailboxDatabase | Get-ADPermission -User Domain\UserName | Remove-ADPermission

Get-ExchangeServer | Get-ADPermission -User Domain\UserName | Remove-ADPermission

Get-OrganizationConfig | Get-ADPermission -User Domain\UserName | Remove-ADPermission
Some of the permissions where also added from AD.

Open up ADSI Edit and Navigate to these :

In “Default Naming Context” OU=Microsoft Exchange Security Groups,DC=Domain,DC=lan
In “Default Naming Context” CN=Microsoft Exchange System Objects
In “Configuration” CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=Domain,DC=lan

Make sure the user is not in any of these.
After the User has been removed from any of these places its inheritance is gone is no longer listed.

18 June 2019

Disable/remove PowerShell V2.0 and why you should

Microsoft is planning to deprecate PowerShell V2.0 in the upcoming fall creator update.
The reason why you should remove or disable it is basically, it's old.
And old in computercountry doesn't work well when it comes to security.
Another reason to remove it is because PowerShell V2.0 can be used for lateral movement and persistence techniques with the same functionality. PowerShell V2.0’s extra value is that because it does not have native logging capabilities, it remains undetected and offers stealth in attacker operations.

PowerShell V2.0 was first seen on Windows XP and Server 2003 then on Vista and 7, Server 2008. When Windows PowerShell 3.0 was released as part of Windows 8, Server 2008 R2, and WMF 3.0, Windows PowerShell moved to a newer version of the .NET Framework (CLR4) that was not compatible older applications. In order to maintain backwards compatibility with these older applications, Microsoft kept Windows PowerShell 2.0 as an optional, side-by-side component in later versions of Windows and Windows Server.

As PowerShell Core 6.0 (and PowerShell 7 is in development) enters the marketplace, Microsoft will reduce the complexity of the PowerShell ecosystem. Removing an outdated version of .NET from the equation makes development easier for cmdlet and script authors by focusing on the .NET Standard ecosystem that includes only .NET Framework 4.6+ and .NET Core 2.0.

You can check whether Windows PowerShell 2.0 is installed by running the following (as an administrator).

On Windows 7/8.1/10, the following will return a State as either Enabled or Disabled:
Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2

On Windows Server, the following will return an InstallState of either Installed or Removed:
Get-WindowsFeature PowerShell-V2

To disable PowerShell V2.0 run PowerShell with elevated privileges (run as administrator).

Enter the following:

Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root

This command should disable both "MicrosoftWindowsPowerShellV2Root" and "MicrosoftWindowsPowerShellV2" which correspond to "Windows PowerShell 2.0" and "Windows PowerShell 2.0 Engine" respectively in "Turn Windows features on or off".

PowerShell v.2 can be used for lateral movement and persistence techniques with the same functionality. PowerShell v.2’s extra value is that because it does not have native logging capabilities, it remains undetected and offers stealth in attacker operations.

14 June 2019

Prevent account discovery - AzureAD read access and how to block it

This is some serious stuff from Mauricio Velazco.

Account discovery is the technique that allows an adversary to enumerate domain accounts in order to obtain situational awareness on a target network.

This can easily be prevented:

(Assuming you installed the MSOnline module)
Then Sign in with an account in Azure Active Directory that has the Global administrator role assigned.
Perform multi-factor authentication, when prompted.
Execute the following line of PowerShell to configure the Azure AD tenant:
Set-MsolCompanySettings -UsersPermissionToReadOtherUsersEnabled $false
Check to see the setting is active:
Get-MsolCompanyInformation | select UsersPermissionToReadOtherUsersEnabled            

28 May 2019

Create a PowerShellISE and PowerShell profile

Load all your favorite modules at startup, set locations, clear screens, start transcripts in a smart way.

First create your profile if none exists.
Open the PowerShellISE and in the console window run:
if (!(test-path $profile)) {new-item -type file -path $profile -force}
This will create the profile file used by the PowerShellISE only.

If you run this from the regular PowerShell window a profile file will also be created but it will be used by the regular PowerShell only.

The PowerShellISE profile file is always located at:

The PowerShell profile file is always located at:

Notice this profile file has a different name

Then open this file and add the following:
Add-PSsnapin *Exchange* -ErrorAction SilentlyContinue
Import-Module IsePackV2 -Force
Set-Location C:\
[system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy('http://proxy.domain.lan:8080')
[system.net.webrequest]::defaultwebproxy.credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
[system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true
Start-Transcript -Path "\\domain.lan\someshare$\userhome\Transscripts\$env:computername.txt"

Add PSGallery, NuGet and Chocolatey to PowerShelISE on Windows Server 2012R2

By default the "Install-Module" command-let isn't available on Windows Server 2012 (R2).

But there's a way:
Since the PackageManagement PowerShell Modules Preview is nolonger available for download, you need to install the WMF5.1 or PowerShell 5.1:
Be sure to check the compatibility matrix to see if your application supports WMF5.1.

First install the "PackageManagement PowerShell Modules Preview - March 2016" from here;

Once installed run the following:

PS C:\windows\system32> Get-PackageProvider -Name Chocolatey

The provider 'chocolatey v2.8.5.130' is not installed.
chocolatey may be manually downloaded from https://onegetcdn.azureedge.net/providers/ChocolateyPrototype-
and installed.
Would you like PackageManagement to automatically download and install 'chocolatey' now?
[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"): y
Name                     Version          DynamicOptions
----                     -------          --------------
Chocolatey             SkipDependencies, ContinueOnFailure, ExcludeVersion, ForceX86, PackageSave...


Name                     Version          DynamicOptions            
----                     -------          --------------            
Chocolatey             SkipDependencies, ContinueOnFailure, ExcludeVersion, ForceX86, PackageSave...
msi                      AdditionalArguments            
PowerShellGet            PackageManagementProvider, Type, Scope, InstallUpdate, NoPathUpdate, Packa...
Programs                 IncludeWindowsInstaller, IncludeSystemComponent            

Find-Package -Name Firefox

Name                           Version          Source                         Summary            
----                           -------          ------                         -------            
Firefox                        67.0             chocolatey                     Bringing together all kinds of awesom...

Get-PackageProvider -Name NuGet

The provider 'nuget v2.8.5.208' is not installed.
nuget may be manually downloaded from
https://onegetcdn.azureedge.net/providers/Microsoft.PackageManagement.NuGetProvider- and installed.
Would you like PackageManagement to automatically download and install 'nuget' now?
[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"): y

Name                     Version          DynamicOptions
----                     -------          --------------
NuGet                  Destination, ExcludeVersion, Scope, SkipDependencies, Headers, FilterOnTag...


Name                     Version          DynamicOptions
----                     -------          --------------
Chocolatey             SkipDependencies, ContinueOnFailure, ExcludeVersion, ForceX86, PackageSave...
msi                      AdditionalArguments
NuGet                  Destination, ExcludeVersion, Scope, SkipDependencies, Headers, FilterOnTag...
PowerShellGet            PackageManagementProvider, Type, Scope, InstallUpdate, NoPathUpdate, Packa...
Programs                 IncludeWindowsInstaller, IncludeSystemComponent

WARNING: Unable to find module repositories.

[system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy('http://proxy.domain.lan:8080')
[system.net.webrequest]::defaultwebproxy.credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
[system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true            

Register-PSRepository -Name PSGallery -SourceLocation https://www.powershellgallery.com/api/v2/-PublishLocation `
https://www.powershellgallery.com/api/v2/package/ -ScriptSourceLocation https://www.powershellgallery.com/api/v2/items/psscript/ `
-ScriptPublishLocation https://www.powershellgallery.com/api/v2/package/ -InstallationPolicy Trusted -PackageManagementProvider NuGet


Name                      PackageManagementProvider InstallationPolicy   SourceLocation            
----                      ------------------------- ------------------   --------------            
PSGallery                 NuGet                     Trusted              https://www.powershellgallery.com/api/v2/

Install-Module IsePackV2 -Force
Install-Module ShowUI -Force
Install-Module RoughDraft -Force
Install-Module Pipeworks -Force
Install-Module EZOut -Force
Install-Module ScriptCop -Force
cd "C:\Program Files\WindowsPowerShell\Modules"
Import-Module ezout -Force
Import-Module isepackv2 -Force

Now you can install any module or package you want :-)