DCSIMG
July 2009 - Posts - Shay Levy

Shay Levy

If you repeat it, PowerShell it!

July 2009 - Posts

List of Exchange 2003 Administrators


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.

PowerGUI 1.9

pg

Keep your eyes open on the PowerGUI.org website, v1.9 will be released sometime next week or so. Lots of goodies :)

Get your hands on Windows PowerShell v2

 v2
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.

How to audit AD groups in one line of PowerShell

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 ;)

Bank Of Israel - Currency exchange rates

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.

Mapping WMI mailbox object to its AD user account


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

Free eBook: Mastering PowerShell with Dr.Tobias Weltner

mps

"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!

Get all users that cannot change their password


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.

 

PowerShell IRC channel chat from PowerShell Toolbar

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!

PowerShell MVP for another year

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)

Name Competency  
Eyal Teler XNA/DirectX  
Daniel Petri Exchange Server  
Roy Osherove Visual C#  
Udi Dahan Solutions Architect  
Ohad Israeli Connected System Developer  
Alon Fliess Visual C++  
Meni Milstein Communications Server  
Eliyahu Goldin ASP/ASP.NET  
Pnina Zinger Project  
Aviv Liberman Visio  
Gilad Eisenberger XNA/DirectX  
Michael Avidan Excel  
Alex Golesh Silverlight  
Noam King ASP/ASP.NET