Exchange get all users and list names and which database they are located on

At work we sometimes get restore cases on mailboxes where the backup is located on tapes outside of the tape robot. We the have to restore all databases and then manually find which database the user is located on. This is very time consuming and to cut restore time and to make it easier for the technician doing the restore I came up with this script that will export which database the user is located on the specific date. with this information the technician will only have to restore a single database. The script will mail the result as an attachment to one of our function mailboxes and store it locally on the server where the script will run as a scheduled task.

# Filepath with uniqe date.
$date = get-date -Format yyyy.MM.dd
$result = "C:\backup\Resultat_" + $date +".txt"

# Get all mailboxes in Exchange, sort after database and name, select name and database and then export to text file.
Get-Mailbox -Resultsize Unlimited | Sort-Object database, name | Select-Object name, displayname, database | Export-csv $result  -NoTypeInformation

#Mail the text file to mail@domain.se
Send-MailMessage -Attachments $result -Subject "Users and Databases Exchange" -Body "Bifogad fil innehaller vilka anvandare som ligger pa vilken databas för tillfallet i Exchange" -To "mail@domain.se" -From "backup.exchange@daomain.se" -SmtpServer "smtp.server@domain.se" 

Progress bar Example

progress_bar

 

 

When working with large loops that take a lot of time it’s nice to know that something happens and the script is making progress. You can use write-host $item to write something that is  unique in the loop or even better use the count method on the variable that you have stored the data you want to loop and then use an integral to count up. if you do that you can easily use the write-progress cmdlet to get a nice progress bar.

I often end up working with foreach  loops and here is an example how to use the write-progress in an foreach loop. In this example I use the status-parameter to get the xxx services out of 235 is done counter and the PercentComplete-paratmeter. I use an integral that I set to 0 in the beginning and then ad 1 in each foreach loop,in that way I can easily track how many of the 235 items that I have looped through. To get the percentage I need to divide the int every time with the total I got from the count method, in this case 235 and then multiply it with 100 to get the percent.

 

$service = Get-Service
$i = 0
$int = $service.Count 


foreach ($item in $service)
{ 
    Write-Host $item
    $i++
    Write-Progress -Activity "List all services" -PercentComplete ($i / $service.Count*100) -Status "$i services out of $int is done"
   
  
}

First help desk GUI tool

helpdeskDelivered my first GUI tool to our help desk today. They needed a tool to find out which users populated distribution groups and they also wanted to be able to export three different attributes to a csv. I did the GUI design in visual studio and used XAML because it looks a little nicer then the old windows forms. the application got real-time check against the Active directory as you type to check if the group exist and it doesn´t enable the list user(Lista användare) button until you type the name of a group that exist. When the listing is done you can choose which attributes to export. This is a 1.0 and it doesn’t handle nested groups, if they want that functionality or some other functionality in the future I will update this post.

 

<#

.SYNOPSIS

Få reda på och exportera vilka medlemmar en AD-grupp har.



.DESCRIPTION

Kör skriptet och fyll grupp, applikationen kollar så att gruppen finns i AD:et annars går det inte att söka. Vid export bockar man i vilka attribut 
man vill exportera och trycker på exportknappen, det skapas då en fil under c:\temp som heter resultat[timme.minut.sekund].csv tex c:\temp\resultat10.30.21.csv.

.NOTES
Made by: Viktor Lindström
http://powerhell.nu
Version 1.0 fyll på med förändringar här under.
#>

#build GUI

[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')

[xml]$XAML = @'

<Window 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Medlemmar i AD-grupp" Height="350" Width="687.807">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="258*"/>
            <ColumnDefinition Width="259*"/>
        </Grid.ColumnDefinitions>
        <TextBox Name="textBox" HorizontalAlignment="Left" Height="23" Margin="99,28,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="230"/>
        <Label Name="LabelGruppnamn" Content="Gruppnamn:" HorizontalAlignment="Left" Margin="10,25,0,0" VerticalAlignment="Top" Width="76" RenderTransformOrigin="0.005,0.483"/>
        <ListBox Name="ListboxResult" Grid.Column="1" HorizontalAlignment="Left" Height="202" Margin="32,70,0,0" VerticalAlignment="Top" Width="279"/>
        <Button Name="ButtonSearch" Content="Lista användare" HorizontalAlignment="Left" Margin="99,70,0,0" VerticalAlignment="Top" Width="230" Height="35"/>
        <Label Name="LabelAnvändare" Content="Användare i gruppen:" Grid.Column="1" HorizontalAlignment="Left" Margin="185,25,0,0" VerticalAlignment="Top" Width="126"/>
        <CheckBox Name="checkBoxAnvändarnamn" Content="Användarnamn" HorizontalAlignment="Left" Margin="99,143,0,0" VerticalAlignment="Top" Width="240"/>
        <CheckBox Name="checkBoxNamn" Content="Namn" HorizontalAlignment="Left" Margin="99,169,0,0" VerticalAlignment="Top" Width="240"/>
        <CheckBox Name="checkBoxMail" Content="E-mailadress" HorizontalAlignment="Left" Margin="99,195,0,0" VerticalAlignment="Top" Width="240"/>
        <Label Name="labelExport" Content="Vad ska exporteras?" HorizontalAlignment="Left" Margin="10,117,0,0" VerticalAlignment="Top" Width="116"/>
        <Button Name="buttonExport" Content="Exportera" HorizontalAlignment="Left" Margin="99,230,0,0" VerticalAlignment="Top" Width="230" Height="31"/>
        <CheckBox Name="checkboxGruppnamn" Content="Grupp finns?" Grid.Column="1" HorizontalAlignment="Left" Margin="32,31,0,0" VerticalAlignment="Top"/>
        <Label Name="labelExport1" Content="" HorizontalAlignment="Left" Margin="10,279,0,0" VerticalAlignment="Top" Width="319"/>

    </Grid>
</Window>


'@

$reader=(New-Object System.Xml.XmlNodeReader $xaml) 
try{$Form=[Windows.Markup.XamlReader]::Load( $reader )}
catch{Write-Host "Unable to load Windows.Markup.XamlReader. Some possible causes for this problem include: .NET Framework is missing PowerShell must be launched with PowerShell -sta, invalid XAML code was encountered."; exit}
$xaml.SelectNodes("//*[@Name]") | foreach {Set-Variable -Name ($_.Name) -Value $Form.FindName($_.Name)}

# Global variable for result
$resultArray = @()

# Disable button by default
$ButtonSearch.IsEnabled = $false


# Funtion to test if AD-group exists.
function Test-Group 
{

if ((Get-ADGroup -Filter {SamAccountName -eq $textBox.Text}) -ne $null)
{$checkboxGruppnamn.IsChecked = $true
  $ButtonSearch.IsEnabled = $true} else {$checkboxGruppnamn.IsChecked = $false
  $ButtonSearch.IsEnabled = $false}
    }

# Searchbutton, gets all memebers of the group specified in the textbox, puts result in $resultarray
$ButtonSearch.add_click({
    $script:resultArray = @()
    $ListboxResult.Items.Clear()
    $allMembers = Get-ADGroupMember -Identity $textBox.Text
    $members = $allMembers | Where-Object {$_.objectClass -eq "user"}
    $groups = $allMembers | Where-Object {$_.objectClass -eq "group"}

    
        foreach ($item in $members)
        {
         $member = Get-ADObject -Identity $item -Properties mail, displayname, samaccountname | Select-Object samaccountname, mail, displayname
         $ListboxResult.Items.Add($member.displayname)
         $script:resultArray += $member
        }
          foreach ($group in $groups)
          {
              $ListboxResult.Items.Add($group.name)
              $script:resultArray += $group | Select-Object name
          }
                        })

# Exportbutton, exports attributes that has been checked in the checkboxes, exports to an CSV-file c:\temp\resultat[HH.mm.ss].csv to uniq it.
                $buttonExport.add_click({
                $export = @()
                
                $date = get-date -Format HH.mm.ss
                $exportdate =  "c:\temp\resultat$date.csv"
                if (Test-Path $exportdate) {Remove-Item $exportdate}

                    foreach ($object in $resultArray)
                    {
                     $export += New-Object psobject -Property @{
               
                      "Användarnamn" = if ($checkBoxAnvändarnamn.IsChecked -eq $true) {$object.samaccountname};
                      "Namn" = if ($checkBoxNamn.IsChecked -eq $true) {$object.displayname};
                      "E-mailadress" = if ($checkBoxMail.IsChecked -eq $true) {$object.mail};
                    }
                    }

                    $export | Export-Csv $exportdate -NoTypeInformation -Encoding UTF8 -Delimiter ";"
                    $labelExport1.Content = "Export klar, filen hittar du här: $exportdate"
                    

                    
                 })
# Runs the AD-test group function in realtime as you write in the textbox.
$textBox.add_Keyup({ 
    
    Test-Group
})

$Form.ShowDialog() | out-null