Configure Azure Arc for servers

Azure Arc for servers is a tool that can be used to add on-prem physical / virtual servers or servers running in other cloud providers to Azure, this allow these servers to be centrally organised and to be connected to Azure services like Azure policy or log analytics.

Azure Arc for servers is in public preview, so this should not be used on production system until there is a full release version. Currently the only support OS version’s are below.

  • Windows Server 2012 R2 and newer
  • Ubuntu 16.04 and 18.04

If there is a content filter or proxy, the URL’s in the below link will  need to be white-listed all traffic will go over HTTPS (Port 443)

To add a server to Azure Arc, logon to the Azure portal.

Go to All services > Machines – Azure ArcArc13

Click on create machine – Azure ArcArc1There are two options add machines using interactive script or add machines at scale. In this post we will be using the scripted method. Arc2

Select the subscription, resource group and region. When selecting  the operating system we can chose between Windows or Linux. Windows will create a PowerShell script and Linux will create a Linux .sh script.Arc3

As this feature is currently preview it will ask you to register before completing the download. Arc4Arc5Once the registration is completed, we can either copy the command or click download to get a copy of the PowerShell script. Below is how the script should look the only difference would be the Azure specific setting like resource group, tenantid…Arc6Once the script has run and the connect command has completed it will request that we connect to the device login site and put in the authentication code. Arc7Arc8

Once completed go back to the PowerShell windows that the script was run from and we should see successfully onboarded to Azure resource. Arc9After a few minutes the device should show in Azure Arc. Arc10We can now apply Azure policies .Arc11

There are some additional steps required to configure the servers to integrate with Azure log analytics.

First step is to install the MMA (Microsoft Monitoring Agent) agent, to download the agent go to Log Analytics workspace and select the require workspace > Advanced settings


Select the required connection source, then OS version. We will also need to take note of the workspace ID and Primary Key which will be used during the agent install to connect to the log workspace.Arc15

Go through the agent install.Arc16

Select Azure connect the agent to Azure Log Analytics (OMS).Arc22

To connect to Azure log analytics put in the workspace id and key.Arc18

Once the install has finished we can check the agent in control panel > All Control Panel Items > Microsoft monitoring agent.Arc20

We should now be able to query log from the server in Azure Arc for servers. Arc21


Remove WINS & Disable Netbios over Tcpip PowerShell

As part of  a recent decommission / security audit, we needed to remove an old WINS server. For desktop client this is fairly easy as they are all assigned through DHCP so it was just a case of removing WINS from the DHCP scope options.

For the hundreds of servers it is set manually, which to remove one by one would take a long time and be pretty boring for the person tasked with it. So I decided the simplest option would be to use PowerShell.

First I wanted to check if servers had WINS enabled so I could reduce the amount of server I would need to run the disable script against.

I am going to use Get-WmiObject and the Win32_NetworkAdapterConfiguration class as this is the simplest way I found to do this in PowerShell.

We will use a text file with a list of server names and a variable called $WINSServer that will be used to filter only network interfaces that have WINS set.

Below is the script to check for WINS and output to PowerShell windows I am just getting all adapters that have WINSPriamryServer value set to the IP in the $WINSServer variable and then selecting the objects to be outputted.

If you wanted to export to a csv or text file just add a | after the WINSPrimaryServer at the end of the script and do either Out-file or Export-csv and the path to export too. 

Below is the script to check WINS:

$comps = Get-Content “C:\Temp\complist.txt”
$WINSServer = “”
foreach ($comp in $comps){
Write-Warning “Checking $comp”
$NETBios = Get-WmiObject -ComputerName $comp -Class Win32_NetworkAdapterConfiguration -Filter “WINSPrimaryServer=’$WINSServer'”
foreach($net in $NETBios){
$net | Select-Object @{N=”ComputerName”;E={$comp}},IPAddress,DefaultIPGateway,IPSubnet,WINSPrimaryServer

WINSTo remove the WINS IP and set NetBios option, we will use the set method in the WMI classs.

Below is the script:

$comps = Get-Content “C:\Temp\complist.txt”
$WINSServer = “”
foreach ($comp in $comps){
Write-Warning “Checking $comp”
$NETBios = Get-WmiObject -ComputerName $comp -Class Win32_NetworkAdapterConfiguration -Filter “WINSPrimaryServer=’$WINSServer'”
foreach($net in $NETBios){
Write-Warning “WINS currently set to $($net.WINSPrimaryServer) on $comp ”
Write-Warning “Removing WINS and Disabling NetBios on Interface $($net.InterfaceIndex) with IP:$($net.IPAddress)”
$NETBios.SetWINSServer(“$Null”,”$Null”) | Out-Null
$NETBios.SetTcpipNetbios(“2”) | Out-Null

WINS01Once the script has run WINS should be removed and NetBios over Tcpip should be disabled this can be checked under the advanced properties on the NIC.


Remove RDS Profile from AD PowerShell

I was having a issue with slow logon times and temporary profile when users where logging on to an Windows RDS 2012 farm. I had a look at the issue and it was down to the RDS profile path in AD being set to use an old decommissioned server.RDS1

Once I found the issue, I need to figure out how many users where affected so the easiest way I could do this was to use PowerShell.

Below is the report script that I used.  The distinguished name used in Get-ADUser -searchbase will need to be update and the export path.  (Test before running any script and also check the quotes and doubles quotes when copying) 

## Get list of Users
$RDUsers = Get-aduser -SearchBase “OU=TestUsers,OU=Users,DC=Domain,DC=Local” -Filter *

## Set Results Array
$Results = @()

foreach ($user in $RDUsers){
$RD = [ADSI]”LDAP://$($user.DistinguishedName)”
if ($RD.Properties.Contains(“userParameters”)){

$profilepath = $RD.psbase.Invokeget(“terminalservicesprofilepath”)
$profileHome = $RD.psbase.Invokeget(“terminalServicesHomeDirectory”)
$props = @{
UserName = $user.SamAccountName
RDSProfile = $profilepath
RDSHome = $profileHome
DistinguishedName = $user.DistinguishedName

$Results += New-Object psobject -Property $props

else {
Write-Host “No UserParameters set on” $user.SamAccountName -ForegroundColor Green
$Results | Export-Csv C:\Temp\Logs\RDSProfile.csv -NoTypeInformation


Once the script has completed the results will be export to a CSV with all user and there profile pathsRDS3Once we have the list we can either remove manually or the better option use the CSV and remove the profiles using the invokeset method.

Below is the script I used. The script could be run against all AD users but I prefer to limit the amount of object I have to run against. (This will replace values on users so should be fully tested before apply to large amount of users.)

$RDProfile = Import-Csv -Path C:\Temp\Logs\RDSProfile.csv
foreach ($RDU in $RDProfile){
Write-Warning “Removing Profile from $($RDU.UserName)”
$RD = [ADSI]”LDAP://$($RDU.DistinguishedName)”


After the script has run the profiles should now be cleared.RDS5

Bulk add and remove Office 365 Licences

I recently had a to move around a few thousand EMS licences to enable MFA for Office 365 and Azure, I decided to do two quick scripts to remove and add back the licences to the required users. I thought I would do a quick post on how I moved the licences.

As always any scripts should be tested on a subset of users before running on larger groups to test that they work as expected.

For this script we need the Office365 PowerShell module installed.

To check if the module is installed run

Get-Module -ListAvailable MSOnlineBulkAdd

First step is to get the AccountSKU to do this run

Import-Module MSonline and then Connect-MsolServiceBulkAdd2

Get-MsolAccountSku | Select-Object AccountSkuIdBulkAdd3

To make things easier and more repeatable in case I need to remove or add other licence I am using Out-GridView -PassThru to select the CSV file and also the licence SKU.

First Out-GridView is for the Csv file with UserPrincipalName (UPN)BulkAdd4

The second is to select the SKU to be removedBulkAdd5

Once the two items are selected the script will then runBulkAdd6

The full remove licence script is below. The only part that needs to be updated is the $csv variable to point to the correct folder where the csv files will be kept.
## Bulk Remove EMS licences ##
## Select Csv file
$csv = Get-ChildItem -Path “C:\temp\Office365Licence\Remove\Csv\” -File | Out-GridView -PassThru
## Import Csv
$users = Import-Csv $csv.FullName
## Select Account SKU to be removed
$accountSKU  = Get-MsolAccountSku | Select-Object AccountSkuId | Out-GridView -PassThru
## Loop through each user in the Csv
foreach($user in $users){
Write-Host “Removing $($accountSKU.AccountSkuId) licence from $($user.UserPrincipalName)” -ForegroundColor Yellow
## Remove licence
Set-MsolUserLicense -UserPrincipalName $user.UserPrincipalName -RemoveLicenses $licenceSKU

The add script is the same only I added a check to confirm if the user requires the licence. The only part that needs to be updated is the $csv variable to point to the correct folder where the csv files will be kept.

Just a note on this I was applying the licence to existing users who where already setup with a usage location so if this is not set the script will error out. 

## Bulk Add EMS licences ##
## Select Csv file
$csv = Get-ChildItem -Path “C:\temp\Office365Licence\Remove\Csv\” -File | Out-GridView -PassThru
## Import Csv
$users = Import-Csv $csv.FullName
## Select Account SKU to be added
$accountSKU  = Get-MsolAccountSku | Select-Object AccountSkuId | Out-GridView -PassThru
## Loop through each user in the Csv
foreach ($user in $users) {
## Check if Licence is already applied
$EMS = Get-MsolUser -UserPrincipalName $user.UserPrincipalName | Select-Object UserPrincipalName, Licenses
if ($EMS.Licenses.AccountSkuId -notcontains “$accountSKU”){
## Add licence
Write-Warning “Adding EMS licnece from $($user.UserPrincipalName)”
Set-MsolUserLicense -userprincipalname $user.UserPrincipalName -AddLicenses $accountSKU
## Licence already applied
Write-Host “$($user.UserPrincipalName) has $($accountSKU) licence assigned” -ForegroundColor Green

HPE Gen 10 SUM Integrated Smart Update Tools VMware

I was installing some new ESXi host using HPE Gen 10 blade servers and was getting a warning when trying to update the firmware using HPE SPP (Service pack for proliant). The issue is due to HPE changing from installing updates directly to the ESXi OS level and instead using HPE ILO.


If iSUT is not installed the update will be staged on the host but wont install. To install, download iSUT from the HPE Support site. Below is the link to version 2.3.6 which was the version I used. ISUT_Tool

HPE15Once download and extracted we need to copy the file to the ESXi host, the easiest way to copy is by enabling SSH on the host and using WinSCP.     HPE04I created a folder called hpe_isut on the ESXi host to copy the file to. HPE05Once the files are copied over, use either SSH or ESXi Shell to install the tools. I used SSH with putty as it was easier.

To install use esxcli command, this is the command I used.

esxcli software vib install -d /hpe_sut/sut-esxi6.0-bundle- the install has completed, a restart is required to finish the install. After the reboot the next step is to set the iSUT mode there are 4 <OnDemand/AutoStage/AutoDeploy/AutodeployReboot>

I chose AutoDeploy, to set the mode use the below command.

sut –set mode=AutoDeployHPE09

Once this has completed, run the inventory again from the SPP and the warning should now be gone and the firmware and driver updates should now apply. HPE10


MBAM Policy Error code: -2147217402 on Windows 10 1903

I was installing MBAM 2.5 SP1 client on Windows 10 1903 during SCCM task sequence. Once the device was built and the user tried to put in a pin and start the encryption it would fail.

The below error was showing in the MBAM event logs. fail1We currently install MBAM successfully on Windows 1809 so it didn’t look like a MBAM server issue or connection issue. I checked and there was a newer servicing release from May 2019

This update adds support for Windows 10 1903. I applied this update and can now encrypt successfully.

Surface Pro 6 1TB Disk 0 not found SCCM OSD

We recently started to build the new surface pro 6 1TB using SCCM. When imaging the task sequence kept failing at the format and partitioning step. When I checked the SMSTS log I could see the below errors

Invalid disk number specified: 0

OSDDiskPart.exe failed: 0x80070490


From the error the problem was that there was no disk 0 available, I usually only see this when there are driver issues with the storage controller.

To check and see what disk where available, we can open a command prompt in the task sequence (As long as it’s enabled on the boot image) with F8 and run diskpart, once diskpart has opened use the list disk command to view available disk.

On the surface pro there was no disk 0 or 1 but instead the 1TB disk shows as disk 2 which is the reason the format is failing as by default the disk that is to be formatted and partitioned is disk 0.

I had a look online and the reason seems to be that the 1TB disk in the Surface Pro 6 is actually 2 x 512GB disk mirrored using Storage Spaces technology. See support KB below.

This is why the disk shows as 2 and the default disk number is set to 0.


The support KB says to change the format task to use disk 2 but this would require a second task sequence which is not ideal as it means more management overhead.

To work around this I have created an additional format and partition step in my existing task sequence and use WMI query’s to apply the specific format step for the Surface Pro 6 1TB.

WMI query to exclude device with no disk 0

Disk index: SELECT * FROM Win32_DiskDrive WHERE Index = “0”error3

WMI query for surface pro 6 1TB

Disk index: SELECT * FROM Win32_DiskDrive WHERE Index = “2”

Select surface pro device: SELECT * from Win32_ComputerSystem WHERE Model LIKE “%Surface Pro 6%”error4

Once the query is set on the format and partition disk step in the task sequence, set the disk number to 2.error5Now I can image the surface pro 6 1TB model successfully.

Create Windows 10 Answer file

In a previous post we went through creating and deploying language packs there was an additional step to create a Windows 10 answer file, I though it might be helpful to do a post on creating a basic answer file using Windows System Image Manager (SIM).

First step is to install Windows Assessment and deployment kit (ADK). To download the latest ADK use the below link:

UASelect deployment tools. UA2Once the install has finished, go to the start menu and down to Windows Kits and open Windows System Image Manager .


First step is to select a Windows image file, to get the image file just need to extra the required Windows ISO to a folder.UA5Below is the extracted ISO.UA12Go to Sources > install.wim.UA6Select the version.UA7Next create a new answer file.UA8Go to Windows Image


Select Components, on the components below is the different type and examples

amd_64 =64bit components, only used on x64 installs

wow_64 = 32bit components or support components for 32bit installed on x64, only used on x64 installs

x86 = 32bit components installed on x86, only used on x86 installs

I used “amd64_Microsoft-Windows-Shell-Setup_10.0.17763.1_neutral” > “OOBE” and click Add settings to Pass 7 oobeSystem.

UA9.pngEdit “amd64_Microsoft-Windows-Shell-Setup__neutral” to add in Register Owner and any other details as required.UA11Next edit the required OOBE settings.UA10Once all the settings have been added save the answer file.UA14Last step is to create a package for the answer file and apply the answer file in the SCCM task sequence.UA15

Below is the content of the XML file.

<?xml version=”1.0″ encoding=”utf-8″?>
<unattend xmlns=”urn:schemas-microsoft-com:unattend”>
<settings pass=”oobeSystem”>
<component name=”Microsoft-Windows-Shell-Setup” processorArchitecture=”amd64″ publicKeyToken=”31bf3856ad364e35″ language=”neutral” versionScope=”nonSxS” xmlns:wcm=”; xmlns:xsi=””&gt;
<cpi:offlineImage cpi:source=”” xmlns:cpi=”urn:schemas-microsoft-com:cpi” />


Deploying Microsoft LAPS Part 3

In the last post we went through deploying the LAPS agent using a script, GPO or SCCM. The next step is to configure the GPO settings to apply LAPS management policy’s

First, we create a new GPO to apply the LAPS management policy’s, the LAPS policy’s are under Computer Configuration > Polices > Administrative Templates > LAPS (If this doesn’t show the ADMX template is probable missing and will need to be installed. This can be done using the LAPS installer)LAPSGP1Password settings policy used to set the password complexity, length and ageLAPSGP2Specify the account that the password policy will apply to if this is the default administrator account this should be left at defaultLAPSGP3LAPSGP4Enabled management of local admin accountLAPSGP5Once the policy is configured apply the policy against the required OULAPSPass1To confirm that all settings are working, run a gpupdate on a test device. Once applied we can check the password in a few different ways

First way is to run PowerShell command:LAPSPass

Second way is to use the LAPS UI , this can be either used from the management server or installed on local computer using the LAPS installer and selecting the LAPS management tools


The third method is to check the AD computer attribute ms-Mcs-AdmPwd:LAPSPass4

Last step is to set delegated access to a security group or set of users to view and reset the local administrator password. Use the below command to verify the current rights

Find-AdmPwdExtendedRights -identity:OU distinguishedName

LAPSPass5There are two command to set the rights, one for read and one for reset rights

Set-AdmPwdReadPasswordPermission -OrgUnit OU distinguishedName -AllowedPrincipals “HelpDesk_LAPS_Access”

Set-AdmPwdResetPasswordPermission -OrgUnit OU distinguishedName -AllowedPrincipals “HelpDesk_LAPS_Access”

LAPSPass6Last step is to verify the permission have been appliedLAPSPass7

LAPS is now deployed and ready to use.


Deploying Microsoft LAPS Part 2

In the last post we went through installing LAPS management tools, extending the AD schema and setting the delegation rights for computer OU to allow computer to write back to the LAPS password attribute.

The next step is to install the LAPS client this can be done either by using a script, group policy or SCCM.

I used the below the script to install remotely just need to create the complist with host name of devices and update the sharename and verions of LAPS that is required

$Computers = Get-Content “C:\Temp\complist.txt”
foreach ($Computer in $Computers){
Write-Warning “installing LAPS on $Computer”
$command = “msiexec /i C:\windows\temp\LAPS.x64.msi /quiet”
$Remotecmd = “CMD.EXE /c ” + $command
Copy-Item \\sharename\LAPS.x64.msi -Destination \\$Computer\c$\windows\temp\
Invoke-WmiMethod -class Win32_process -name Create -ArgumentList $Remotecmd -ComputerName $Computer | Out-Null

The second option is to deploy using GPO software install

Craete a new GPO > Policies > Software settings > software installtion > New packageLAPS6Add the installerLAPS7LAPS8LAPS9Next apply the policy agaist the OU or use security filtering to apply to specific devices once the policy is applied logon to the device and run gpupdate /force to apply LAPS10

Third option is to use a tool like SCCM to package the application and deploy to devices. This would be my preferred way as its gives the best reporting.

We won’t go through the process but the command line install will  msiexec /i C:\windows\temp\LAPS.x64.msi /quietLASCCMLASCCM1