Archive for the ‘Programming’ Category

Restoring OneDrive for Business from a user who has been deleted

28th February, 2017 Leave a comment
OneDrive for Business is based on SharePoint and I have seen it referred to in several different ways:
  • OneDrive for Business
  • A SharePoint personal site
  • A SharePoint “my site”
This means that it can be quite difficult to search for the method of restoring a complete OneDrive For Business, but essentially you have to recover a SharePoint site.
There is a Microsoft Knowledge Base article describing OneDrive for Business retention and deletion (KB3042522). Read this before you proceed any further so you can check if it can be recovered by the GUI interface in Office 365.
If you need to recover the OneDrive site, firstly install the SharePoint Online Management Shell and connect to the admin site (the example uses as the Office 365 tenant):
Connect-SPOService -Url
Then obtain a list of all the OneDrive for Business sites that are in the recycle bin:
Get-SPODeletedSite -IncludePersonalSite -limit ALL
Or the following for a specific user:
Get-SPODeletedSite -IncludePersonalSite -limit ALL | where {$_.url -like "*jsmith*"}
Once we have identified the URL, we can use the following command to restore the site:
Restore-SPODeletedSite -Identity
You may also need to give yourself access to the newly restored site:
Set-SPOUser -Site -LoginName -IsSiteCollectionAdmin $true
You can then navigate to the URL and download the required files. Once complete, you can delete the site by appending “/_layouts/15/deleteweb.aspx” to the URL:
By using a bit of scripting we can automate the process a bit (requires PowerShell 3.0 for the Out-Gridview -passthru command):
$domainPrefix = "contoso"
$adminAccount = ""
$Credentials = Get-Credential -UserName $adminAccount -Message "Enter your password."
Connect-SPOService -Url "https://$" -Credential $Credentials
$site = Get-SPODeletedSite -IncludePersonalSite -limit ALL | Out-Gridview -title "Highlight the site and click OK" -passthru
If ($site) {
Restore-SPODeletedSite -Identity $site.Url
Set-SPOUser -Site $site.Url -LoginName $adminAccount -IsSiteCollectionAdmin $true
Write-host "To delete the account, navigate to:`n$($site.Url)/_layouts/15/deleteweb.aspx"

Exchange – Get all active Out Of Office responses

29th October, 2016 2 comments

Today, I got asked to change an Out Of Office reply for a member of staff who had left the organisation. There wasn’t anything rude in what they had written, it just wasn’t as professional as we would have liked.

As we are currently having a larger than usual turnover of staff, it occurred to me that it would be quite useful to have a list of all the active Out Of Office messages.

The following PowerShell script creates an html with the active Out Of Office messages:

$OutputFile = "C:\Scripts\OutOfOfficeReplies.htm"

$autoReplies = Get-Mailbox -ResultSize Unlimited | Get-MailboxAutoReplyConfiguration | Where-Object { $_.AutoReplyState –eq "scheduled" } | select @{Name="User";Expression={$_.identity.Name}}, ExternalMessage, InternalMessage
"<html><head><title>Auto Replies</title><style>" | Out-File -filepath $OutputFile 
"table { border-collapse: collapse; border: 1px solid black; }" | Out-File -filepath $OutputFile -Append
"td { border: 1px solid black; vertical-align: top; }" | Out-File -filepath $OutputFile -Append
"</style></head><body><table>" | Out-File -filepath $OutputFile -Append
"<tr><th>User</th><th>External Message</th><th>Internal Message</th></tr>" | Out-File -filepath $OutputFile -Append

foreach ($autoReply in $autoReplies) {
    "<tr><td>$($autoReply.User)</td><td>$($autoReply.ExternalMessage)</td><td>$($autoReply.InternalMessage)</td>" | Out-File -filepath $OutputFile -Append

"</table></body></html>" | Out-File -filepath $OutputFile -Append
Categories: PowerShell

PowerShell – Get User Principal Name (One-liner)

2nd October, 2016 Leave a comment

As part of our Windows 10/Office 2016 project, we wanted to get the current user’s User Principal Name (UPN). There are several posts on the web with regards on how to do this, including utilising the ADSystemInfo COM object, or obtaining the current user’s ID and then searching Active Directory, however, neither are a clean PowerShell one-liner!

So, after a bit of research, here it is:


This command gets the current user’s Windows Security Principal’s value (or SID), which we then use to bind to its LDAP object. From this object, we can obtain the User Principal Name (or any other Active Directory value).

For our purpose, we wanted to put this value into a user environment variable. Here’s the script I came up with:

$UserUPN = ([ADSI]"LDAP://<SID=$([System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value)>").UserPrincipalName
If ($UserUPN) { [Environment]::SetEnvironmentVariable("UPN", $UserUPN, "User") }

PowerShell – Quick way to iterate through a list of items

29th September, 2016 Leave a comment

In PowerShell, I sometimes I want to quickly iterate through a list of items that another system has produced. One option would be to export the data to a file and read it in, but sometimes it’s not practical or may be quite complicated to parse the file. As a “quick and dirty” solution, it’s possible to create a string spanning multiple lines. We can then use the split method to iterated through each string.


$data = ('65c43d1cb95b8646a0a8d1342d0e9326

$guids = $data.split("`n")

foreach ($guid in $guids) {
Categories: PowerShell Tags: ,

Batch file to check if user is a member of an Active Directory Group

9th August, 2013 Leave a comment

Due to a limitation of our software deployment software, I was asked if it was possible to copy a file based on an Active Directory group membership. After a bit of research I decided the best course of action was to utilise the DSquery and DSget commands that are part of the Windows 7 operating system.

Let’s examine the core of the script below.

  • Firstly, we specify the distinguishedName of the group that we want to check and put it into a variable – we’ll use this later in our code.
  • We then use “dsquery user -samid %username%” to obtained the distinguishedName of the currently logged in user by using the %username% environment variable, which is the SAMid (sAMAccountName) in Active Directory.
  • We pipe the result into “dsget user -memberof -expand”. This generates a list of distinguishedNames of all the group that the user is a member of. The “-expand” parameter ensures that all nested groups are listed as well.
  • We then pipe the result of this into the FindStr utility and search for the group name the we specified at the start of the process. We perform a case insensitive search and also redirect STDOUT and STDERR to NULL to stop anything being shown on the screen.
  • Finally, we check the %ERRORLEVEL% value to determine if the string has been found or not.

And here’s the script:

set group="CN=Network Team - ICT Services,OU=Test,DC=domain,DC=net"
dsquery user -samid %username% | dsget user -memberof -expand | findstr /i /c:%group% 1>NUL 2>NUL
If %ERRORLEVEL% EQU 1 echo Not found group!!
If %ERRORLEVEL% EQU 0 echo Found group!!

Batch File ISO 8601 Date Format – Version 2.0

16th March, 2013 7 comments

Last year I wrote about using the ISO 8601 date format in Batch Files. One of the issues I had was that times before 10:00 were not preceded with a zero.

The solution was quite simple, in that you can use an in-built replace function. For example, the following creates a variable called MyTime that has any spaces (ASCII 32) replaced with a zero (0).

SET MyTime=%time: =0%

So I’ve used my previous code to generate the ISO date into a variable and then replaced any spaces within that variable with a zero. I’ve also update the code to use the correct delimiters for ISO 8601 and given a few examples that you can copy and paste into your own code.

ECHO ISO 8601 date and time formats in Batch files.
ECHO The following are generated from the system date (%date%) and time (%time%).

REM ISO 8601 Date and Time in extended format (YYYY-MM-DDTHH:MM:SS)
SET isodt=%date:~6,4%-%date:~3,2%-%date:~0,2%T%time:~0,2%:%time:~3,2%:%time:~6,2%
SET isodt=%isodt: =0%
ECHO ISO 8601 Date and Time in extended format (YYYY-MM-DDTHH:MM:SS): %isodt%

REM ISO 8601 Date and Time in basic format (YYYYMMDDTHHMMSS)
SET isodt=%date:~6,4%%date:~3,2%%date:~0,2%T%time:~0,2%%time:~3,2%%time:~6,2%
SET isodt=%isodt: =0%
ECHO ISO 8601 Date and Time in basic format (YYYYMMDDTHHMMSS): %isodt%

REM ISO 8601 Date in extended format (YYYY-MM-DD)
SET isodt=%date:~6,4%-%date:~3,2%-%date:~0,2%
SET isodt=%isodt: =0%
ECHO ISO 8601 Date in extended format (YYYY-MM-DD): %isodt%

REM ISO 8601 Date in basic format (YYYYMMDD)
SET isodt=%date:~6,4%%date:~3,2%%date:~0,2%
SET isodt=%isodt: =0%
ECHO ISO 8601 Date in basic format (YYYYMMDD): %isodt%

REM ISO 8601 Time in extended format (HH:MM:SS)
SET isodt=%time:~0,2%:%time:~3,2%:%time:~6,2%
SET isodt=%isodt: =0%
ECHO ISO 8601 Time in extended format (HH:MM:SS): %isodt%

REM ISO 8601 Time in basic format (HHMMSS)
SET isodt=%time:~0,2%%time:~3,2%%time:~6,2%
SET isodt=%isodt: =0%
ECHO ISO 8601 Time in basic format (HHMMSS): %isodt%

REM ISO 8601 Date and Time (not including seconds) in basic format (YYYYMMDDTHHMM)
SET isodt=%date:~6,4%%date:~3,2%%date:~0,2%T%time:~0,2%%time:~3,2%
SET isodt=%isodt: =0%
ECHO ISO 8601 Date and Time (not including seconds) in basic format (YYYYMMDDTHHMM): %isodt%
Categories: Batch File, Programming Tags: , ,

NDR for disabled Active Directory accounts

10th December, 2012 Leave a comment

When staff leave the organisation, are on long term sick, or take a sabbatical we disable their account in Active Directory. This also used to stop emails being delivered to their mailbox (returning a None Delivery Report [NDR] to the sender), which was very useful to let other staff know they were no longer available and stopped important emails sitting in mailboxes that were no longer checked.

Unfortunately, one of the Service Packs (for Exchange 2003, if I recall correctly) “fixed” this issue. Our workaround was to restrict disabled accounts to only accept emails from themselves. Whilst this can be done via the GUI, a script is a lot quicker.

The PowerShell script below adds restrictions to disabled accounts, the removal is removed on accounts that are re-enabled.

# Constants to modify multi-valued AD attributes.

# LDAP path to start search from
$RootOU = "LDAP://OU=User Accounts,DC=domain,DC=net"

Write-Host "Accounts that are disabled but accepting emails"

$search = New-Object DirectoryServices.DirectorySearcher([ADSI]$RootOU)
$Search.PageSize = 1000
$search.filter = "(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2)(!authOrig=*)(|(homeMDB=*)(msExchHomeServerName=*))(!sAMAccountName=command*))"
$results = $search.FindAll()

foreach($result in $results){
   $User = $result.GetDirectoryEntry()
   $distinguishedName = $User.distinguishedName

Write-Host "Accounts that are enabled but not accepting emails"

$search = New-Object DirectoryServices.DirectorySearcher([ADSI]$RootOU)
$Search.PageSize = 1000
$search.filter = "(&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(authOrig=*)(|(homeMDB=*)(msExchHomeServerName=*)))"
$results = $search.FindAll()

foreach($result in $results){
   $User = $result.GetDirectoryEntry()
   $distinguishedName = $User.distinguishedName
Categories: Accounts, PowerShell