Friday, December 6, 2019

alternative code not alternative facts



$winver = Get-wmiobject win32_operatingsystem | select -ExpandProperty version

The above produces the same value as the line below.  Below seems a much neater.

$winver = (get-wmiobject Win32_OperatingSystem).version




That's the alternative code but what is an alternative fact !?
Find out here:

Tuesday, August 13, 2019

Users Mailbox status


Quick post about querying a users mailbox status

https://answers.microsoft.com/en-us/msoffice/forum/msoffice_o365admin-mso_exchon-mso_o365b/recipient-type-values/7c2620e5-9870-48ba-b5c2-7772c739c651


This command returns all the users with migrated mailboxes

get-aduser -SearchBase "OU=OU2,OU=OU1,OU=OU0,DC=corp,DC=ad,DC=name,DC=com" -Properties msExchRemoteRecipientType -Filter {name -like "*"} | ?{$_.msExchRemoteRecipientType -eq 4} | select name,samaccountname,msExchRemoteRecipientType 

Friday, August 2, 2019

Function that calls itself

This was an interesting function that I've come across.  It calls itself to work out the list of reports of a user and the reports of any of their reports from a particular AD arrangement where users' managers are held in a manager field.........! er yes, you can read that again now.



function Get-DirectReports([string] $Dn) {
    $Reports = Get-ADUser -LDAPFilter "(&(manager=$dn)(mail=*))" -Properties "mail", "title" -SearchBase "OU=EUC,DC=corp,DC=ad,DC=domain,DC=com"

    if ($Reports) {
        foreach ($Report in $Reports) {
                Write-Output $Report.DistinguishedName

            if ($Report.DistinguishedName -ne $Dn) {
                Get-DirectReports $Report.DistinguishedName
            }
        }
    }
}

Tuesday, April 30, 2019

Add Ribbon Buttons in Outlook


The goal was to place buttons to certain positions in users' Outlook 2016 ribbons.

The code below is a modified version of this blog post.
https://blogs.msdn.microsoft.com/emeamsgdev/2017/02/21/powershell-deploying-outlook-ribbon-customisations/

Outlook ribbon buttons are controlled in the users' roaming or local profile folder locations e.g. %APPDATA%\Microsoft\Office   (depending on the environment configuration)

An example file name is olkexplorer.officeUI.  When a user customises their ribbon, it is written to XML in this file.

The script below enables XML code segments to be either, injected into existing files, or written into new ones where they do not already exist.

In this example an Report Spam button that exists on another ribbon tab is created on the home and message ribbons for easier access.

#

# Add-OutlookReportSpamButton.ps1
#  
# Original concept obtained from https://blogs.msdn.microsoft.com/emeamsgdev/2017/02/21/powershell-deploying-outlook-ribbon-customisations/

#Set Values - the files will receive the XML from the InjectionStings array. i.e. file1 gets the first injection string and so on.
$TargetFiles = @("olkexplorer.officeUI", "olkmailread.officeUI")

$InjectionStrings = New-Object System.Collections.Generic.List[System.Object]
$InjectionStrings.Add("<mso:customUI xmlns:x1=""MimecastServicesForOutlook.AddinModule"" xmlns:mso=""http://schemas.microsoft.com/office/2009/07/customui""><mso:ribbon><mso:qat/><mso:tabs><mso:tab idQ=""mso:TabMail""><mso:group id=""mso_c1.41340A1"" label=""Spam"" insertBeforeQ=""mso:GroupMailDelete"" autoScale=""true""><mso:control idQ=""x1:ui_main_ribbon_gateway_report_spam_phishing_split_button"" imageMso=""GreenBall"" visible=""true""/></mso:group></mso:tab><mso:tab idQ=""x1:adxRibbonTab_c4dc3496375345748858382774b12030""/></mso:tabs></mso:ribbon></mso:customUI>")
$InjectionStrings.Add("<mso:customUI xmlns:x1=""MimecastServicesForOutlook.AddinModule"" xmlns:mso=""http://schemas.microsoft.com/office/2009/07/customui""><mso:ribbon><mso:qat/><mso:tabs><mso:tab idQ=""mso:TabReadMessage""><mso:group id=""mso_c2.13FA7E9B"" label=""Spam"" insertBeforeQ=""mso:GroupRespond"" autoScale=""true""><mso:control idQ=""x1:adxRibbonMenu_eee1842485324bc18a9a64adbd2147fd"" visible=""true""/></mso:group></mso:tab></mso:tabs></mso:ribbon></mso:customUI>")

# xmlns:x1="MimecastServicesForOutlook.AddinModule" had to be added to the $ribbonXml to create the correct blank file.

# We set the Xml to a complete but empty ribbon UI, in case we don't have an existing one to update (in which case we just want the new Xml)
#$ribbonXml = '<mso:customUI xmlns:x1="MimecastServicesForOutlook.AddinModule" xmlns:mso="http://schemas.microsoft.com/office/2009/07/customui"><mso:ribbon><mso:qat/></mso:ribbon></mso:customUI>'
$ribbonXml = "<mso:customUI xmlns:x1=""MimecastServicesForOutlook.AddinModule"" xmlns:mso=""http://schemas.microsoft.com/office/2009/07/customui""><mso:ribbon><mso:qat/></mso:ribbon></mso:customUI>"



# Set Functions
function MergeNodes($sourceNode, $targetNode)
{
Write-Verbose "Merging $($sourceNode.Name) and $($targetNode.Name)"

    if ($sourceNode.Name -eq "mso:customUI")
    {
    # Need to copy namespaces from this element
    ForEach ($attribute in $sourceNode.Attributes)
        {
        if ( $attribute.Name.StartsWith("xmlns:") )
            {
            # Check whether this namespace already exists in target node
            $namespaceExists = $false
            ForEach ($targetAttribute in $targetNode.Attributes)
                {
                if ($targetAttribute.Name -eq $attribute.Name)
                {
                $namespaceExists = $true
                Write-Verbose "Namespace $($attribute.Name) already declared in target node"
                }
                }
            if (!$namespaceExists)
                {
                Write-Verbose "Adding namespace attribute $($attribute.Name): $($attribute.Value)"
                $namespaceAttribute = $ribbonXmlDoc.CreateAttribute($attribute.Name)
                $namespaceAttribute.Value = $attribute.Value
                [void]$targetNode.Attributes.Append($namespaceAttribute)
                }
            }
        }
     }

    if ($sourceNode.HasChildNodes)
        {
        ForEach ($node in $sourceNode.ChildNodes)
            {
            # Do we already have this node in the target Xml node?
            $targetChildNode = $null
            if ($targetNode.HasChildNodes)
                {
                ForEach ($tNode in $targetNode.ChildNodes)
                    {
                    if ( ($tNode.Name -eq $node.Name) -and ($tNode.NamespaceURI -eq $node.NamespaceURI) )
                        {
                        # Check idQ (or id) value
                        $idAttribute = "idQ"
                        if ($tNode.Name.Equals("mso:group")) { $idAttribute = "id" }
                        Write-Verbose "$($tNode.Name): Target $idAttribute = $($tNode.Attributes.ItemOf($idAttribute).Value), Source $idAttribute = $($Node.Attributes.ItemOf($idAttribute).Value)"

                        if ($tNode.Attributes.ItemOf($idAttribute).Value -eq $Node.Attributes.ItemOf($idAttribute).Value)
                            {
                            $targetChildNode = $tNode 
                            break
                            }
                        }
                    }
                }
            if ($targetChildNode -eq $null)
            {
            Write-Verbose "$($node.Name) not found in target, appending"
            Write-Verbose "$($node.Name) namespace is $($node.NameSpaceURI)"
            $targetChildNode = $targetNode.AppendChild($ribbonXmlDoc.ImportNode($node, $False))
            Write-Verbose "Imported $($targetNode.Name) namespace is $($targetNode.NameSpaceURI)"
            #$targetChildNode.NameSpaceURI = $node.NameSpaceURI
            }
            MergeNodes $node $targetChildNode
            }
        }
}



# Actions
$RunCount = -1
foreach ($TargetFile in $TargetFiles)
    {
    $RunCount +=1
    $RibbonXmlFile = "$env:userprofile\AppData\Roaming\microsoft\office\"+$TargetFile
    $XmlToAdd = $InjectionStrings[$RunCount]
    
    $xmlToAddDoc = [Xml]$xmlToAdd
    
    if ([System.IO.File]::Exists($RibbonXmlFile))
        {
        # We have existing ribbon customisations, so load those
        $ribbonXml = Get-Content $RibbonXmlFile -Encoding UTF8
        }
    $ribbonXmlDoc = [Xml]$ribbonXml
       
    #Do it!
    MergeNodes $xmlToAddDoc.DocumentElement $ribbonXmlDoc.DocumentElement
    
    # Now save the updated file
    $ribbonXmlDoc.Save($RibbonXmlFile)
    }