July 2009 - Posts
The following script lists all the groups or users that have been delegated as exchange admins at the organizational level. There are three types of administrative roles:
- Exchange Full Administrator
- Exchange Administrator
- Exchange View Only Administrator
$cnc = (Get-QADObject (Get-QADRootDSE).ConfigurationNamingContext).DN
$DN = "CN=Microsoft Exchange,CN=Services,$cnc"
Get-QADPermission $DN -Inherited -SchemaDefault | `
Where-Object {$_.Rights.value__ -match '983551|131220|197119'} | `
Foreach-Object {
$account = $_.AccountName
$pso = "" | Select-Object User,Role
$pso.user = $account
switch($_.Rights.value__)
{
983551 { $pso.role="Exchange Full Administrator" }
131220 { $pso.role="Exchange View Only Administrator" }
197119 { $pso.role="Exchange Administrator" }
}
$pso
}
User Role
---- ----
DOMAIN\Exchange Services Exchange Full Administrator
DOMAIN\User1 Exchange View Only Administrator
DOMAIN\ShayL Exchange Full Administrator
DOMAIN\Enterprise Admins Exchange Full Administrator
You can read more about Exchange administrative role permissions in Exchange 2003 HERE. In Exchange 2007 you can use the Get-ExchangeAdministrator cmdlet to retrieve information about the users or groups that have a particular Microsoft Exchange Server 2007 role.
Keep your eyes open on the PowerGUI.org website, v1.9 will be released sometime next week or so. Lots of goodies :)
Microsoft announced yesterday the release dates for RTM (Release to Manufacturing) version of Windows 7 and Windows Server 2008 R2. As you probably know, these platforms are shipped with PowerShell v2 as a Windows component. Yes, it is now a part of the OS!
A separate download will be available for Windows XP/Vista/2003 in the next few months, as tweeted by Jeffrey Snover.
I was tasked this morning with the following:
Get all groups from Active Directory and produce a report that includes each group Name,distinguishedName, the type of the group, its scope, mail address, description and group membership count. Armed with Quest's AD cmdlets I wrote the following. It took 3 minutes to write the code and send it to my manager with PowerShell v2 Send-MailMessage cmdlet:
Get-QADGroup -SizeLimit 0 | Select-Object Name,DN,GroupType,GroupScope,@{Name="MemberCount";Expression={ @(Get-QADGroupMember -SizeLimit 0 -Identity $_).Count }},Mail,Description | Sort-Object MemberCount -Descending | Export-Csv .\ADGroupsReport.csv
#This section requires PowerShell v2
$PSEmailServer= "EmailServerName"
Send-MailMessage -From "Me@domain.com" -To "Manager@domain.com" -Attachments .\ADGroupsReport.csv -Subject "AD Groups Report"
Once again, PowerShell and Quest saved my butt ;)
In this post (hebrew), Shlomo Goldberg, shows how we can receive currency exchange rates from Bank Of Israel website in C#. This is a great way to show how with a few lines of code we can get the rates with PowerShell.
We create a webclient object, use its DownloadString method and cast the result to XML using PowerShell's XML type shortcut and then we format the results:
$wc = New-Object System.Net.WebClient
$rates = [xml]$wc.DownloadString("http://www.bankisrael.gov.il/currency.xml")
$rates.CURRENCIES.CURRENCY | Format-Table -Auto Name,Country,CurrencyCode,Rate,Change,Unit
NAME COUNTRY CURRENCYCODE RATE CHANGE UNIT
---- ------- ------------ ---- ------ ----
Dollar USA USD 3.904 0.051 1
Pound Great Britain GBP 6.3672 -0.801 1
Yen Japan JPY 4.1685 0.26 100
Euro EMU EUR 5.5041 -0.256 1
Dollar Australia AUD 3.1259 -0.144 1
Dollar Canada CAD 3.4904 0.043 1
krone Denmark DKK 0.7393 -0.256 1
Krone Norway NOK 0.6108 -0.294 1
Rand South Africa ZAR 0.4821 -0.021 1
Krona Sweden SEK 0.4981 -0.678 1
Franc Switzerland CHF 3.6227 -0.519 1
Dinar Jordan JOD 5.5176 0.256 1
Pound Lebanon LBP 0.0259 0 10
Pound Egypt EGP 0.6995 0.057 1
Note: The 'Change' column represent the change in percents. We can change the column display by using a calculated property:
PS > $change = @{Name="Change";Expression={ $_.Change+"%"}}
PS > $rates.CURRENCIES.CURRENCY | FT -Auto Name,Country,CurrencyCode,Rate,$Change,Unit
NAME COUNTRY CURRENCYCODE RATE Change UNIT
---- ------- ------------ ---- ------ ----
Dollar USA USD 3.904 0.051% 1
Pound Great Britain GBP 6.3672 -0.801% 1
Yen Japan JPY 4.1685 0.26% 100
Euro EMU EUR 5.5041 -0.256% 1
Dollar Australia AUD 3.1259 -0.144% 1
Dollar Canada CAD 3.4904 0.043% 1
krone Denmark DKK 0.7393 -0.256% 1
Krone Norway NOK 0.6108 -0.294% 1
Rand South Africa ZAR 0.4821 -0.021% 1
Krona Sweden SEK 0.4981 -0.678% 1
Franc Switzerland CHF 3.6227 -0.519% 1
Dinar Jordan JOD 5.5176 0.256% 1
Pound Lebanon LBP 0.0259 0% 10
Pound Egypt EGP 0.6995 0.057% 1
EDIT: We can also use .NET custom numeric format strings to apply the percent sign and retain the original values (see the 'Section Separators and Conditional Formatting' section on MSDN):
$change = @{Name="Change";Expression={ "{0:0.### %;-0.### %;0}" -f ($_.Change/100) }}
You can specify other URLs to get information for specific date and/or currency code:
Get the previous day rates:
http://www.bankisrael.gov.il/heb.shearim/currprev.php
Use the following URL to get an xml file for USA Dollar only (use the curr parameter - currency code ):
http://www.bankisrael.gov.il/heb.shearim/currency.php?curr=01
Get exchange rates for a specific date (use the rdate parameter):
http://www.bankisrael.gov.il/heb.shearim/currency.php?rdate=20030505
Get exchange rates for a specific date and currency:
http://www.bankisrael.gov.il/heb.shearim/currency.php?rdate=20030505&curr=01
I should note that you need to get explicit permission to display the rates on your website. You can ask for permission here.
Few days ago I got a request from a reader of my blog:
"I found the WMI commands to get info from Exchange 2003 servers and the following gets me the displayname, servername, storagegroupname, and storename but am I able to get the SamAccountName? Do you know any way?"
Get-WmiObject -Class Exchange_Mailbox -NameSpace root\microsoftexchangev2 -ComputerName ExchangeServer | Sort-Object MailboxDisplayName | Format-Table MailboxDisplayName, ServerName, StorageGroupName, StoreName, Size -auto
First, lets see how a sample mailbox output looks like when we issue the above WMI command (without piping to sort and format-table):
(...)
AssocContentCount : 159
Caption :
DateDiscoveredAbsentInDS :
DeletedMessageSizeExtended : 0
Description :
InstallDate :
LastLoggedOnUserAccount : Domain\User1
LastLogoffTime : 20090716113423.000866+***
LastLogonTime : 20090716113027.000840+***
LegacyDN : /O=MyOrg/OU=domain.com/CN=RECIPIENTS/CN=USER1
MailboxDisplayName : User1
MailboxGUID : {AB7AE3FC-0FD4-47C1-841C-5EA0857F8093}
Name :
ServerName : EX1
Size : 634673
Status :
StorageGroupName : Second Storage Group
StorageLimitInfo : 8
StoreName : Second Storage Group (EX1)
TotalItems : 33580
We can map each mailbox to its AD user object using one of the following properties:
1. LastLoggedOnUserAccount
2. LegacyDN
3. MailboxDisplayName
4. MailboxGUID
I wouldn't count much on the first one, not on my environment anyway. We have a special user account that archives all mailboxes each night so the mailbox is stamped with that user instead of the mailbox owner user name. I would also skip option #3, I'm not sure if MailboxDisplayName is in sync with the user DisplayName AD attribute. I choosed to use LegacyDN since MailboxGUID needs to be formatted first (remove the hyphens and curly braces).
OK, with Quest's Get-QADUser cmdlet we can get each user by binding LegacyDN to the Identity parameter and introducing the result as additional property (column) to Format-Table using a calculated property:
Get-WmiObject -Class Exchange_Mailbox -NameSpace root\microsoftexchangev2 -ComputerName ExchangeServer | Sort-Object MailboxDisplayName | Format-Table MailboxDisplayName, @{Label='SamAccountName';Expression={(Get-QADUser -Identity $_.LegacyDN).SamAccountName}}, ServerName, StorageGroupName, StoreName, Size -auto
MailboxDisplayName SamAccountName ServerName StorageGroupName StoreName Size
------------------ -------------- ---------- ---------------- --------- ----
User1 User1 EX1 First Storage Group Store1 (EX1) 103546
User2 User2 EX1 Second Storage Group Store2 (EX1) 16621
User3 User3 EX1 Third Storage Group Store3 (EX1) 64663
"Mastering PowerShell" by Dr. Tobias Weltner, Windows PowerShell MVP, is now available as a free PDF eBook. You can download it here or read the online version.
The book's technical editor is Aleksandar Nikolic, a good friend of mine and a PowerShell skillful scripter. Congratulations Tobias and Alek!
Earlier today a colleague of mine asked me for a script solution:
"I want to get all users that cannot change their password from Active Directory but I can't find any attribute on the user account with that info."
Correct, there is no such attribute. When a user account is set with the 'User cannot change password' account option, two (Deny) Access Control Entries (ACEs) are added to the account in question:
1. Deny for the user account (SELF)
2. Deny for everyone else (Everyone built-in group)
To see the ACEs go to the 'Security' tab and then click the 'Advanced' button:
With Quest AD Cmdlets you can get all users that cannot change their password from your active directory domain with a simple one-liner, lets start by querying just one user:
PS > Get-QADPermission -Identity user1 -Deny -ExtendedRight User-Change-Password `
-Account everyone,self
Permissions for: domain/TEST/Users/User1
Ctrl Account Rights Source AppliesTo
---- ------- ------ ------ ---------
Deny Everyone Change Password Not inherited This object only
Deny NT AUTHORITY\SELF Change Password Not inherited This object only
WARNING: Only explicit permissions were displayed. To display inherited and AD
default permissions use -Inherited and -SchemaDefault switches respectively.
As you can see User1, and 'Everyone' group members, cannot change the password. Notice that we get a yellow warning, we can suppress warnings by adding the -WarningAction parameter with a value of SilentlyContinue (currently, we cannot suppress the green messages).
To get all users we start by asking Get-QADUser to get ALL (-SizeLimit 0) Enabled user accounts (-Enabled) and then we filter the results by calling the same Get-QADPermission command we executed above inside Where-Object, only now we change the user Identity (User1) with the current pipeline object ($_):
Get-QADUser -Enabled -SizeLimit 0 | Where-Object { Get-QADPermission -Identity $_ -Deny -ExtendedRight User-Change-Password -Account everyone,self -WarningAction SilentlyContinue }
EDIT
: See the comments for this post below If you get an error for the -WarningAction parameter.
A few days ago Alan Renouf asked me if there is a way to get access to the popular PowerShell IRC channel (from Freenode.net) via PowerShell Toolbar. Guess what? I'm happy to announce that this feature is Alive & Kicking directly from the toolbar. Thanks for a great idea Alan!!
On the toolbar, click on the 'Chat' Icon (the old chat room is no longer available)
A floating dialog appears, choose your user name (Nickname) and press the 'Connect' button.
Starting chatting!

This evening (18:12), after a lot of fingernails biting I got the email I was waiting for! And if you've ever wondered how the message looks like:
Dear Shay Levy,
Congratulations! We are pleased to present you with the 2009 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others. We appreciate your outstanding contributions in PowerShell technical communities during the past year.
I want to thank my Mom, Dad .... :) and also welcome two new guys to the PowerShell MVP ranks: Joel 'Jaykul' Bennett and Jonathan Noble. Congratulations guys, well deserved!
EDIT: Mazal Tov to all new/renewed Israeli MVPs! The complete list of 'MEA MVP July Award Cycle' can be found on Ruari's blog (MEA MVP Lead)