I was recently working on a solution for a customer where user photos needed to be synchronized from exchange online into sharepoint. The default sync seems a bit flakey and can take up to 72 hours for images to appear. 


This led me to create 2 powershell scripts, one to grab the existing images in AD and create 2 columns in a csv – one with the userprincipal name and the other the path to the photo. Using this information and the photo extract, i am then able to upload the photo to Exchange using the Set-UserPhoto command. After user photos have been uploaded,  the second script then grabs the images from the mailboxes and applies them to the sharepoint profile. 

While this works fine and user images stay in sync everywhere within 365, the location of the user photos in https://company-my/User Photos/Profile Pictures  takes up quite a bit of space once all images are uploaded.  By default, the quote seems to be about 50mb which isn’t big enough for large enterprise environments who may have thousands of employees.

To get the size of the current quota, I used the following command:


Get-PnPTenantSite $siteUrl | fl


This gave me the output which contained the current maximum storage value


Then using the Set-PnPTenantSite command, i was able to increase this to the desired amount

Set-PnPTenantSite -Url $siteUrl -StorageMaximumLevel 10240

Looking at the value after running the command shows the maximum value has increased



This should allow for a whole lot of profile images!

Recently had a request to automate the shutdown (Stop) of VMs within and azure environment based on CPU usage. The scenario is there are high powered virtual machines that run workloads that can last anywhere from 3 – 14 hours, once these jobs are complete, the user returns and then shuts the virtual machine down at which point it gets deallocated. This can be quite costly especially if the jobs finish right before a weekend, thats at least 48 hours of a high spec VM running while not being used!

Using Azure Alerts on the VM and Web hooks in automation accounts, I was able to come up with a way to shut the virtual machines down and de-allocated when the CPU reached a certain threshold. 

This is how I achieved that:

Create an automation account if you don’t have one already; In the Automation account create a new runbook for shutting down virtual machines


I used the following runbook type – “Powershell”

Once the runbook is created, I used the following powershell code to actually do the dealloction and stop of the VM.






$connectionName = "AzureRunAsConnection"



#Use the Azure Run As Connection defined above

$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName

"Logging in to Azure..."

Add-AzureRmAccount  -ServicePrincipal -TenantId $servicePrincipalConnection.TenantId -ApplicationId $servicePrincipalConnection.ApplicationId -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint


catch {

if (!$servicePrincipalConnection)


#Display any errors while logging in using Run As Account

$ErrorMessage = "Connection $connectionName not found."

throw $ErrorMessage

} else{

#Display any other errors

Write-Error -Message $_.Exception

throw $_.Exception

} }

# Required Modules - AzureRm.Profile and AzureRM.Insight. Define the Virtual machine being shutdown by this script.

$vm = Get-AzureRmVM -Name $vmname -ResourceGroupName $resourcegroup


Stop-AzureRMvm -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -Force

Write-Host "Shutdown of $($vm.Name) Successful"




Write-Host "Error"



Click publish to save the runbook


Then click on Webhooks under the Resources section


Add a new webhook with the parameters of the VM Name and resource group of the VM



Once the web hook is created, go to the VM in the “VMNAME” parameter and click on the alerts option:



Add a new alert – Select the “Percentage CPU” metric and configure your thresholds, in this example, the machine will trigger an alert if the average CPU value for the past 5 minutes is less than 5%

Next, add a new action group and create an action of “Webhook”


Paste in the webhook URL from the webhook you created for the VM.


Once the action group is done, complete the alert config with a name and click ok to save the alert. Next time the alert triggers the VM will be stopped and deallocated.


Recently, I had to configure some storage accounts to consume Azure files for users. I decided to use private DNS servers and route all traffic down an existing Express route circuit.


The official documentation on configuring Private DNS and how it works can be found on the microsoft documentation site.


This article assume you already have a storage account setup with the appropriate container / file share already setup and these storage accounts are using private links.


To configure Private Link DNS – I did the following:


 Open up “Private DNS Zones” in the Azure portal

Once in Private DNS Zones, create a new zone and fill in the required details:

  • The name is the DNS name that will be applied to the storage account names. In a hub and spoke topology, deploy the new Zone in the hub subscription and network.


Once the Zone has been created, go to the required private links and select “DNS Configuration” then “+ Add Configuration”


Add the zone that was previously created


  • The configuration name is arbitrary, but it is recommended to use your storage account name or something that will help identify the resource


Once DNS zone configuration has been added – go back to the Private DNS zones and click on virtual network links


Then select Add, and add in the virtual network where your resources reside.


On your on-prem DNS servers you will need to create conditional forwarders for your cloud domains such as file.core.windows.net, blob.core.windows.net and any other ones you will be utilizing.  The conditional forwarders will need to point to an IaaS vm running DNS on it or any other DNS forwarder in the Azure environment. On the DNS forwarder in Azure you will need to point the same conditional forwarders to (internal Azure DNS server)

If you get errors stating that the DNS forwarder is not authoritative for the domain, you can safely ignore these. 


Once this is complete you should be able to resolve internal addresses without having to change the resource.file.core.windows.net addressing on the front end. Hopefully, this will help on how to configure azure private dns with private links