Home » Posts tagged 'powershell' (Page 2)

Tag Archives: powershell

Get List of Users and Associated Office 365 Licences

Just a quick memory dump for myself really.

To export a report of all users from Office 365 and their associated licences run the following command in Azure Powershell Module

Get-MsolUser -All | Select UserPrincipalName, Licenses | fl | Out-File c:\office365users.txt

To only export licenced users

Get-MsolUser -All | Where {$_.IsLicensed -eq "True"} | Select UserPrincipalName, Licenses | fl | Out-File c:\office365users.txt


Create vCard From Active Directory

I had a requirement to export all users’ contact information from active directory to vCard so they could be imported into a mobile phone.

Turns out it is really easy once you understand the VCARD formatting. Run the following script from a server or workstation with AD Powershell Module

Import-Module ActiveDirectory
$vCardPath = "C:\mobile.vcf"
#test to see if vcard file already exists
$outputvcard = Test-Path $vCardPath 
If (!$outputvcard){
 #if not then create the file
 $outputvcard = New-Item -Path $vCardPath -ItemType File -Force
#get AD users
$ADUsers = Get-ADUser -SearchBase "OU=My users,DC=domain,DC=com" -Filter {(ObjectClass -eq "User") -and (Enabled -eq $true) } -Properties * | Select givenName,SN,Mail,Mobile,OfficePhone 
ForEach ($user in $ADUsers){ 
 Add-Content -Path $vCardPath -Value "BEGIN:VCARD"
 Add-Content -Path $vCardPath -Value "VERSION:2.1"
 Add-Content -Path $vCardPath -Value "N:$($user.SN);$($user.givenName)"
 Add-Content -Path $vCardPath -Value "FN:$($user.givenName) $($user.SN)"
 Add-Content -Path $vCardPath -Value "ORG:Company name here"
 Add-Content -Path $vCardPath -Value "TEL;WORK;VOICE:$($user.Mobile)"
 Add-Content -Path $vCardPath -Value "TEL;HOME;VOICE:$($user.OfficePhone)"
 Add-Content -Path $vCardPath -Value "ADR;WORK;PREF:Street Address here;Postcode;City;UK"
 Add-Content -Path $vCardPath -Value "EMAIL;PREF;INTERNET:$($user.Mail)"
 Add-Content -Path $vCardPath -Value "END:VCARD"

Once finished copy the vcf file to your mobile phone and import.

Move Arbitration Mailboxes to New Database

To Move all the hidden system mailboxes from a database to another (or arbitration mailboxes) use the following powershell commandlet in EMS

Get-Mailbox -Arbitration | New-MoveRequest -TargetDatabase <target databse>


Remove Soft Deleted Mailboxes from Exchange Database

When moving mailboxes between databases you sometimes experience the moves completing with a warning. The warning may be that post move cleanup could not be completed on the source mailbox database. This means that you will see disconnected mailboxes in EMC even though the users mailbox is live on the other database. In this circumstance you need to remove the disconnected or soft deleted mailboxes from the old database to free up space.

You can do this by first obtaining the mailbox GUID of the soft deleted mailbox using this command

Get-MailboxStatistics -Database <dbname> | Where {$._DisconnectREason -eq "SoftDeleted"} | fl MailboxGuid

Then you can use the output of this to then remove the mailbox using this command

Remove-StoreMailbox -Database <dbname> -Identity <mailboxguid> -MailboxState SoftDeleted -Confirm:$false

To remove all soft deleted mailboxes from a database in one go you can use this command

Get-MailboxStatistics -Database MBD01 | where {$_.DisconnectReason -eq "SoftDeleted"} | foreach {Remove-StoreMailbox -Database $_.database -Identity $_.mailboxguid -MailboxState SoftDeleted}

Adding Out Of Office Notice to Exchange User’s Mailbox Using Powershell

Administrators can set user’s OOO notifications directly from EMS by using the following command

Set-MailboxAutoReplyConfiguration <alias> -AutoReplyState enabled -ExternalAudience all -InternalMessage <Message to internal senders> -ExternalMessage <Message to external senders>

Add Security Groups from Trusted Domain to Trusting Domain Local Groups

I needed a quick way to add domain global groups from a trusting domain to domain local groups in the trusting domain with the same name for a project I was undertaking. The trusting domain was Windows 2003 and we did not have access to any AD Powershell module in the trusting domain so the only way to do this is using DSMOD. Here is the powershell script I made and ran from the trusted domain side to quickly add the trusted groups to the domain local groups of the trusting domain. It produces a batch file you run on the trusting domain DC so that it gives you a chance to review the commands being executed.

$bat = New-Item -Path C:\legacygroupadd.bat -ItemType File -Force
Import-Module ActiveDirectory
$newgroups = Get-ADGroup -searchbase "ou=groups,ou=rs,dc=ad,dc=domain,dc=com" -Filter *
Foreach ($g in $newgroups){ 
 $legacyquery = cmd.exe /c dsquery group -name $g.Name -d legacydomain.local -u legacyndomain\mvale -p MyP@ssw0rd
 if ($legacyquery){
 $write = "dsmod group $($legacyquery) -addmbr $($g.DistinguishedName) -d legacydomain.local -u legacydomain\mvale -p MyP@ssw0rd" 
 Add-Content -Path $bat -Value $write


Removing Foreign Security Principals from Groups

Today I had a requirement to migrate users and groups from a legacy domain to a new domain using ADMT. All legacy groups were domain local with members from other groups on other domains via existing trusts. Performing a migration of a Domain local groups using ADMT also migrates across members who have no user accounts in the new domain. These are called Foreign Security Principals.

I needed to convert these groups into Global groups in the new domain, but before I could do this I needed to remove these foreign security principals as members. I looked at Powershell and the Get-ADGroupMember Commandlet and this does not work with FSP’s as members producing an “Unspecified Error”. I looked at the old dsmod command and this could achieve what I was looking for. However DSMOD required the full LDAP canonical name of the group and member to remove. This is a real pain when you have to modify over 2000 values!

I looked at piping a dsquery command into a dsget and then into a dsmod command which would have worked, but there is no filter or where clause in these commands where I could remove the FSPs but leave migrated user accounts.

The solution I came up with took 5 minutes to build and 1 minute to execute. I realised I could use a mixture of powershell and DS commands to achieve what I wanted. The Powershell I would use for looping and writing out content and DS commands to do the work.

The PS script I came up with basically queries AD using DSQUERY collecting the results into a array variable. I then loop through the array and peform a DSGET command to grab the members of that group. Then there is an IF command that says if the member of the group is an FSP issue a DSMOD command to remove it. It also converts the group to Domain Global from Local. The other script is based on the same principal but produces a batch file to run separately. I chose this because I can double check the commands built.

Anyway here are both scripts, you will see the differences (albeit slight)

Script to Output to Batch File

$bat = New-Item -Path c:\groupmod.bat -ItemType File -Force
$group = cmd.exe /c dsquery group "ou=groups,ou=rs,dc=ad,dc=domain,dc=com"
foreach ($g in $group){ 
 $members = cmd.exe /c dsget group $g -members 
 Foreach ($m in $members){ 
 if ($m -like "*CN=ForeignSecurityPrincipals*"){ 
 $write = "dsmod group $($g) -rmmbr $($m)"
 Add-Content -Path $bat -Value $write
 Add-Content -Path $bat -Value "dsmod group $($g) -scope u"
 Add-Content -Path $bat -Value "dsmod group $($g) -scope g"

Script to execute on the fly

$group = cmd.exe /c dsquery group "ou=groups,ou=rs,dc=ad,dc=domain,dc=com"
foreach ($g in $group){ 
 $members = cmd.exe /c dsget group $g -members 
 Foreach ($m in $members){ 
 if ($m -like "*CN=ForeignSecurityPrincipals*"){ 
 cmd.exe /c dsmod group $($g) -rmmbr $($m)
cmd.exe /c dsmod group $($g) -scope u 
cmd.exe /c dsmod group $($g) -scope g



How to Pass variables from local PS Session to Remote PS Session

When writing scripts for admin tasks I wanted to explore the idea of running scripts locally on a management workstation rather than RDP to each server and run a command. The Invoke-Command can achieve this nicely. However, what if I wanted to pass a declared variable from my management workstation to the remote PS Session?

e.g. $Ping = “www.google.co.uk”

This is set on my management workstation Powershell session. But I want to test I can ping this from another server or web address. In order to do this we need to declare the variable $Ping in our Invoke-Command -Scriptblock  and -ArgumentList parameters.

Invoke-Command -Session $PSSessionName -ArgumentList -Scriptblock {
Test-Connection -Computername $Ping

This will output

Source        Destination     IPV4Address      IPV6Address                              Bytes    Time(ms)  PSComputerName
——        ———–     ———–      ———–                              —–    ——–  ————–
WIN-83AIC7… http://www.google.c&#8230;                                             32       38        WIN-83AIC7KIGI1.test.domain
WIN-83AIC7… http://www.google.c&#8230;                                             32       42        WIN-83AIC7KIGI1.test.domain
WIN-83AIC7… http://www.google.c&#8230;                                             32       36        WIN-83AIC7KIGI1.test.domain
WIN-83AIC7… http://www.google.c&#8230;                                             32       36        WIN-83AIC7KIGI1.test.domain

If you are using Powershell 3.0 you can use the $using scope modifier instead of declaring Parameters or Argumentlists like so

Invoke-Command -Session $PSSessionName -Scriptblock {
Test-Connection -Computername $using:Path



Removing Soft Deleted Mailboxes from Exchange

When performing mailbox moves sometimes they complete with warnings. When you interrogate the move log you may find that the move was successful but the request failed to clean up the source database.

Microsoft say they resolved this in Microsoft Exchange 2010 SP3 but I have seen this happen in later releases SP3 CU5 and 2013.

To manually remove these disconnected mailboxes you need to use EMS. First find the disconnected mailbox in the source database

Get-MailboxStatistics -Database <source database name> | Where { $_.DisconnectReason -eq "SoftDeleted" } | fl DisplayName, MailboxGUID

Then use the following command to remove them

Remove-StoreMailbox –Database <source database name> –Identity <user mailbox GUID> –MailboxState Softdeleted

You will need to wait for the maintenance routine to run on the database before the white space is reclaimed

Forcing SSL Certificate to Associate with Server’s Private Key

Have you ever been handed a certificate exported (without the private key) from a server or directly from a CA to install on a different server than the one used to create the CSR? Whilst some IIS functions and apps allow you to use a certificate without a private key, there are others that demand it. In any case best practice is to import a certificate with the private key used to create the CSR in the first place. However, there are circumstances where this may not be possible. Perhaps the admin who installed the certificate on the original server forgot (or intentionally) to mark the private key as exportable. Perhaps this is not the first export of the certificate and the private key has got lost. In these events using these certificates without the proper private key can prevent applications and web services functioning. Classic examples are Lync and UM for Exchange.

Fortunately, there is a way to resolve this issue without purchasing a new certificate.

First we need to get the serial number of the certificate. If your certificate is not yet imported, please import this now. You can use the Certificate MMC Snap-in or if PFX file you can double click and install it. To get the serial number of the certificate either open the certificate and browse the details tab for the serial number or run this PowerShell command

Get-ChildItem -Path cert:\LocalMachine\my | Select-Object Subject,Serialnumber

Replace the Path with the correct one you installed the certificate. the above command uses the local machine personal store, which is usually the place certificates get installed.

This command will produce a similar output to this

Subject                                                     SerialNumber
-------                                                     ------------
CN=localhost                                                4CA2A1EF3CF850B24A6F8841382950AC
E=admin@goldenfrog.com, CN=goldenfrog-client, O=GoldenFr... 1A
E=admin@goldenfrog.com, CN=GoldenFrog-Inc CA, O=GoldenFr... 00D776530B7B49A6EC

Copy the serial number of the certificate you want to edit from the table

Next we need to associate forcefully the private key of the server to the certificate we have imported.

Open Command Prompt as an administrator and type on the following command

certutil.exe -repairstore my <serial number of cert>

And Magic the certificate is now associated with the server’s private key

%d bloggers like this: