Powershell Needful Things put that in your pipeline

17Aug/090

The OWA saga continues…

Posted by Jean Louw

After solving the msExchVersion mystery, it has become apparent that even more of our Exchange 2007 users were unable to access OWA.

After logging onto the site, a very similar error is displayed: Exception type: Microsoft.Exchange.Data.Storage.StoragePermanentException Exception message: There was a problem accessing Active Directory. My first step was obviously to verify the msExchVersion.

After ensuring that this was correct, and that the users were still unable to use OWA, I had to do more digging. Deeper delving into this issue, yielded the following KB from Microsoft: http://support.microsoft.com/kb/949527

To use OWA the Exchange Servers group must have write permissions to the msExchUserCulture attribute. Easy to resolve, just allow inheritable permissions from the parent to filter to the faulty object / objects, as per the KB article.

Easy enough on one account, but if you had to change this setting manually on multiple accounts, you could use Set-QADObjectSecurity –UnlockInheritance to accomplish the task.

For more information see Dimitri’s blog

5Aug/091

Legacy mailboxes on Exchange 2007

Posted by Jean Louw

One of our users had a problem logging onto OWA today, and I noticed that the icon for his mailbox in the GUI displayed as a legacy mailbox, although he was located on an Exchange 2007 mailbox server.

After countless searches, I came across this article: http://support.microsoft.com/kb/941146. It explains that the msExchVersion property on the AD object is not set correctly, and that using set-mailbox –ApplyMandatoryProperties would resolve the problem. Looking at the help information on set-mailbox this could also be caused by users being created on Exchange 2007 server using the Exchange 2003 tools, although these users were migrated from Exchange 2003.

So, how to correct this? First get a list of all mailboxes on the Exchange 2007 server with the incorrect version. Using get-mailbox, the incorrect Exchange version displays as 0.0 (6.5.6500.0) The following command returns a list of these mailboxes by server (where SERVER1 is your Exchange 2007 server):

get-mailbox -server SERVER1 -resultsize unlimited | where {$_.ExchangeVersion -like "*0.0*"} | select Name, ExchangeVersion

Once you verify the list, pipe them to set-mailbox.

get-mailbox -server SERVER1 -resultsize unlimited | where {$_.ExchangeVersion -like "*0.0*"} | Set-Mailbox –ApplyMandatoryProperties

This resolved the problem for me, easily, on multiple Exchange mailboxes. Running the get-mailbox command again, returned no results after applying set-mailbox to the problematic mailboxes.

30Jun/096

Cleanup unused Exchange 2007 mailboxes

Posted by Jean Louw

I often use my orphaned home directory cleanup script at work, to recover unused space from our file and print clusters. So my manager recently suggested that I do something similar for Exchange. Knowing that the orphan folder cleanup utility is still my responsibility as the administrators are not too comfortable with running scripts, I decided to give this utility a nice GUI.
To generate the code for the forms, I used SAPIEN PrimalForms. What beautiful tool. Very short learning curve, and very, very powerful. When the form loads, it will get a list of all the Exchange mailbox servers using get-mailboxserver.
This excludes Exchange 2003 servers as get-mailboxstatistics does not work with legacy mailboxes. I may develop a solution for that later. The three query buttons (Disabled, Hidden, Stale) will perform the following actions respectively: Disabled – Find mailboxes linked to disabled AD accounts Hidden – Find mailboxes hidden from the address book.  Stale – Find mailboxes linked to accounts which have not logged on in the last 3 months.
This search may take a little time to complete and this button is not supported against Exchange 2003 servers. These queries will populate the listbox with the names of the mailboxes. Besides the “Export List” button, the Action buttons at the bottom will action only selected items.
You can select items using SHIFT or CTRL. Export List will create a text file containing your search results. Export PST will grant the current user Full Mailbox with Send As and Receive As permission, and then export the mailbox to the path specified. Rename will change the display name based on the query performed. For mailboxes found with the “Disabled” button the display name will be prefixed with “DISABLED-MBXCleaner-“, for “Hidden” with “HIDDEN-MBXCleaner-“ and so forth. Users previously renamed will be excluded from subsequent searches. The “Disable” action will remove Exchange Attributes without deleting the AD account. The mailbox will be removed when the retention time expires. Delete will remove the mailbox and AD account completely.
I have not had a chance to test the Delete button as I would need to submit a change control request before using the utility in our live environment. All of the Action buttons are set to –whatif mode by default. The “Go Hot” checkbox will activate the heavy hitters (Export PST; Rename; Disable and Delete) so you can safely test each button first before taking any action. The “Reserved” button, currently, does nothing. I plan to allow this button to read or build a custom search for users, either by Name or other criteria.
 
WARNING: This is a dangerous utility, and can wreck your Exchange system if you are not careful. Please test this in your test environment first, and adhere to your change control procedures before using this utility in the live environment. I take absolutely no responsibility for any damage caused by using this tool. The utility requires the Exchange Management shell, and if launched from a Vista / Windows 7 needs to be “Run as Administrator”

Full information and the download location for this script can be found here:
http://www.powershellneedfulthings.com/?page_id=293

16Mar/098

Audit the local Administrators group on a list of remote computers

Posted by Jean Louw

This is a very basic script which collects a list of server names from a local text file called servers.txt. The script reports the list of users, sorted by server name to a local text file in the root of drive C. I am working on cleaning up the results, as currently the "Adspath" reports to the text file in the following format: WinNT://DOMAIN/COMPUTER/Administrator This was the only true distinction between local or domain users, as "Name" reports only the name of the user or group. So you are never really sure if it is a domain or local entry. Finally I need to enable the script to report its results to Excel or HTML.

$Result = @()

foreach($server in (gc .\servers.txt)){

$computer = [ADSI](”WinNT://” + $server + “,computer”)
$Group = $computer.psbase.children.find(”Administrators”)

function getAdmins
{$members = $Group.psbase.invoke(”Members”) | %{$_.GetType().InvokeMember(”Adspath”, ‘GetProperty’, $null, $_, $null)}
$members}

$Result += $server
$Result += ( getAdmins )
$Result += " "
}

$Result > c:\results.txt
Invoke-Item c:\results.txt

I had a little extra time today, and managed to clean up the members using the -replace parameter, replace "DOMAIN" with your domain name. The updated code looks something like this:

$Result = @()

foreach($server in (gc .\servers.txt)){

$computer = [ADSI](”WinNT://” + $server + “,computer”)
$Group = $computer.psbase.children.find(”Administrators”)

function getAdmins
{$members = ($Group.psbase.invoke(”Members”) | %{$_.GetType().InvokeMember(”Adspath”, ‘GetProperty’, $null, $_, $null)}) -replace ('WinNT://DOMAIN/' + $server + '/'), '' -replace ('WinNT://DOMAIN/', 'DOMAIN\') -replace ('WinNT://', '')
$members}

$Result += Write-Output "SERVER: $server"
$Result += Write-Output ' '
$Result += ( getAdmins )
$Result += Write-Output '____________________________'
$Result += Write-Output ' '
}



$Result > c:\results.txt

Invoke-Item c:\results.txt

You can simply add another -replace ('WinNT://DOMAIN/', 'DOMAIN\') for each domain in the system. I know its a little hack 'n slash but it will do for now.

11Mar/0922

Automatically clean up orphaned user directories

Posted by Jean Louw

We've had a huge problem where users were removed from Active Directory, but somehow the administrators neglected to remove the home folder for the user from the file servers. This left someone with the nasty task of cleaning up the mess.
This script will work through a directory of home folders and lookup the user in AD. This is assuming that the home folder and the user id are the same. If the user is not found, or the account is disabled, the folder will be renamed with a leading "orphan-" followed by the original name. The script requires a parameter, which is the path where the folders are located. e.g. "findorphans.ps1 c:\users" The script requires that the Quest Powershell Commandlets are installed, and they can be downloaded free, here.

param($target)
$folders=Get-ChildItem -Path $target | Where-Object {$_.Name -notlike "orphan*" -and ($_.PSISContainer)} | Select-Object name
foreach ($folder in $folders){
Write-Host ""
$userid=""
"PROCESSING FOLDER: {0} "   -f $folder.name
write-host "Searching for a possible owner..."
$user=Get-QADUser $folder.name
$useracc=$user.AccountIsDisabled
$userid=$user.samaccountname
$newid="orphan-" + $folder.name
$fullpath=$target + "\" + $folder.name
$fullpath
"Account Disabled: {0} "   -f $user.AccountIsDisabled

if ($userid.length -lt "0" -or $user.AccountIsDisabled -eq "True") {
Write-Host "No owner found or account disabled, orphan folder renamed to" $newid -ForegroundColor Red
rename-Item -Path $fullpath -NewName $newid
}
else {
Write-Host "Owner found" $user -ForegroundColor Green
}
}