The New Outlook.com and the Microsoft Account PaymentHub

Outlook.com Logo

While check­ing my RSS feeds for the night, I ran across this arti­cle describ­ing the new Outlook.com.  As an avid user of “Live for Domains”, I was inter­est­ed to see where Microsoft was going after announc­ing the renam­ing of the “Win­dows Live” moniker back in May.

Outlook.com

It turns out, the UI is refresh­ing and seems to be a new front-end for what was Hot­mail and Live Mail.  It is a refresh­ing, min­i­mal­is­tic UI with a lot of white space.   Users of the pre­view releas­es of Win­dows 8 will notice many UI and usabil­i­ty sim­i­lar­i­ties.  I was expect­ing to get a ‘pre­view like’ expe­ri­ence but that has not been the case.  I have sev­er­al domains I use and have linked togeth­er.  The authen­ti­ca­tion worked like a charm and I was able to jump around my three dif­fer­ent accounts in Outlook.com with­out it revert­ing to the old Hot­mail inter­face (send-as work­ing as well).

 

Outlook.com - Service Ribbon

Then I went to check out the Contacts/People inter­face and the Cal­en­dar.  The Cal­en­dar nev­er loaded in Chrome so I had to revert to IE.  The Contacts/People inter­face had the oppo­site prob­lem; it loads in Chrome just fine but not IE 10.  The Contacts/People inter­face match­es the new UI but the Cal­en­dar has yet to be upgrad­ed.  I

‘m sure MS will sort out these issues fair­ly quick­ly as they have already sur­passed 1 mil­lion usersin the new UI.Try it now.  All it takes is a vis­it to Outlook.com.

Microsoft Account and PaymentHub

This is just spec­u­la­tion but I can see this real­ly fit­ting into sub­scrip­tion ser­vices for Microsoft Office, Xbox games, addi­tion­al e-mail and Sky­Drive stor­age, advanced fea­tures in future releas­es of WebApps and more.Some peo­ple have been report­ing run­ning in the new “Microsoft Account” when log­ging in but this hasn’t been my expe­ri­ence.  How­ev­er, after the switch, I went into the Outlook.com options/settings and saw a new billing tab.  I also noticed I was now at https://account.live.com/.  The link redi­rect­ed to https://commerce.microsoft.com/PaymentHub/.  It appears this will han­dle sub­scrip­tions down the road and also func­tion on a point sys­tem sim­i­lar to Xbox Live and Bing Rewards.  It also iden­ti­fies my account as a ‘US - Per­son­al Account’ lead­ing me to believe they may be using the same billing sys­tem used with the pre­view release of Office365.

Screenshots

What’s Next

With the release of Win­dows 8, Serv­er 2012, Exchange 2013, Sur­face Tablets, Office365 Next, Share­point 2013, Office 2013, advance­ments w/ Azure IaaS and more, it is an excit­ing time for Microsoft.

 

C# Express - Create a Dummy or Placeholder Windows Service for Monitoring

Cre­at­ing my cus­tom ser­vice in Visu­al Stu­dio

The IT ecosys­tem is rich with net­work mon­i­tor­ing sys­tems (NMS). Each NMS has dif­fer­ent capa­bil­i­ties, costs, and pur­pos­es in life. It is com­mon­place for me to come into a busi­ness that has invest­ed in an NMS that doesn’t fit all their needs. You might ask, “What does this have to do with cre­at­ing a Win­dows ser­vice?” Here is the sce­nario that brought this up.

A client has a mon­i­tor­ing solu­tion for their Win­dows servers and some basic net­work up/down stats. Their inter­net con­nec­tion had been flaky for a month or two. As we worked with their ISP, their con­nec­tion con­tin­ued to stay up but laten­cy would spike and often drop pack­ets. The mon­i­tor­ing nev­er sees the link as down but the lev­el of ser­vice is degrad­ed and most­ly unus­able. The ISP can quick­ly reset the ports and fix the issue, but we want to know right when this hap­pens to min­i­mize down­time.

I set­up a pow­er­shell script with the help of the team at Com­put­er­Per­for­mance.  This script is pret­ty straight for­ward. It uses the Test-Con­nec­tion cmdlet and aver­ages the laten­cy to a remote host.

# Gets the average latency between you and $Server
# Using IP Addresses is recommended
$Server = "8.8.8.8"
$PingServer = Test-Connection -count 20 $Server
$Avg = ($PingServer | Measure-Object ResponseTime -average)
$Calc = [System.Math]::Round($Avg.average)
If ($Calc -gt 100 -Or $Calc -eq 0) {stop-service MyService} Else {start-service MyService}

Now, for the tricky part. How do I cre­ate a ser­vice that I can start and stop with­out actu­al­ly impact­ing the under­ly­ing OS? I won’t go into the code too much but I have includ­ed the exam­ple C# source files in a zip at the bot­tom. I got this code from a MSDN social forum post.

To imple­ment this, first make sure you read the forum post. You will need Visu­al Stu­dio 2010 C# Express. Cre­ate a Win­dows Form Appli­ca­tion and include ref­er­ences (Project --> Add Ref­er­ences --> .NET) to System.Configuration.Install and System.ServiceProcess. You will need three files in your project: MyService.cs, MyServiceInstaller.cs and Program.cs. These are includ­ed in a zip at the end of this arti­cle (I also includ­ed the exe­cutable from the code if you want to test it out). You real­ly only need to edit the MyService.cs and MyServiceInstaller.cs to match the Service’s pur­pose in life (and write use­ful event log entries). Once that is done, build the pro­gram. You will get an error on build about a “Win­dows Ser­vice Start Fail­ure” as shown below. (Any devel­op­ers out there know how to make this build w/o throw­ing the obvi­ous error?) Just ignore the error and grab the exe­cutable from the Debug fold­er of the project. Place the exe­cutable some­where safe (I use %windir%SysWOW64 in my exam­ple below).

Next, we need to install the ser­vice. You can install the ser­vice using the SC com­mand in Win­dows. In this exam­ple, I used the name “lat­test” as the ser­vice name and defined the dis­play name as well. You can find more infor­ma­tion on the SC.exe com­mand here. Note: those spaces after the equals (=) sign are required when using the SC com­mand.  Here is the code I used to install this ser­vice on Serv­er 2008 R2:

sc create lattest binpath= "C:WindowsSysWOW64MyService.exe" displayname= "Latency Test" start= auto

At this point, your script can be set­up to run as a sched­uled task to start or stop the ser­vice depend­ing on the con­di­tions you set. You can point your NMS to mon­i­tor the ser­vice and you can sleep peace­ful­ly at night know­ing you are proac­tive­ly mon­i­tor­ing the issue.

If this is tem­po­rary in nature and you want to remove the ser­vice, just remove it from your NMS, delete the ser­vice and exe­cutable and remove your sched­uled task. The ser­vice can be removed by run­ning:

sc delete lattest

Here is the code from the Visu­al Stu­dio Project: MyService.zip

Retrieving Password from Application Pool

I came across an undoc­u­ment­ed app the oth­er day. For a num­ber of rea­sons, we need­ed to restore the pass­word but it wasn’t doc­u­ment­ed any­where. Luck­i­ly, the ser­vice account was set­up in an app pool. In IIS 7.0 or 7.5, APPCMD can be used to recov­er the pass­word. In 6.0, adsutil.vbs can be used.

cscript.exe /nologo adsutil.vbs GET W3SVC/AppPools/AppPoolName/WAMUserPass

How­ev­er, I want­ed to write my own lit­tle script. Hav­ing a lit­tle tid­bit makes it easy to reuse lat­er for oth­er clients. For exam­ple, I could search AD for SPNs start­ing with “HTTP”, loop through each of their app pools and doc­u­ment the user­name and pass­words for all ser­vice accounts used in this fash­ion. So, here is the lit­tle tid­bit I threw togeth­er.

Option Explicit

Call GetAppPoolUserAndPass("localhost", "ApplicationPoolName")

Private Sub GetAppPoolUserAndPass (byVal strComputer, byVal strAppPool)
	Dim appPool
	On Error Resume Next
	Set appPool = GetObject("IIS://" & strComputer & "/w3svc/AppPools/" & strAppPool)
	If Err Then
		wscript.echo "Error connecting to " & chr(34) & strAppPool & chr(34) & " on " & strComputer
	Else
		wscript.echo strAppPool & vbTab & appPool.WAMUserName & vbTab & appPool.WAMUserPass
	End If
	On Error GoTo 0
End Sub

Here is an exam­ple of just what I men­tioned above. YMMV but this should dis­cov­er IIS box­es and report all the accounts used in their app pools. Note: Pools using built-in accounts will show up with blank pass­words; this is nor­mal; the pass­word isn’t actu­al­ly blank.

Option Explicit

' Determine DNS domain name.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")

' Determine DNS domain name.
Dim objRootDSE, strDNSDomain
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")

' Use ADO to search Active Directory.
Dim adoCommand, adoConnection
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
adoCommand.ActiveConnection = adoConnection

' Build Query
Dim strBase, strFilter, strAttributes, strQuery
strBase = ""
strFilter = "(servicePrincipalName=HTTP*)" 'Search for SPN starting w/ HTTP (case insensitive)
strAttributes = "name"
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False

Dim adoRecordset
Set adoRecordset = adoCommand.Execute

If (adoRecordset.EOF = True) Then
    Wscript.Echo "No SPNs Found matching HTTP*"
    Wscript.Quit
End If

Wscript.Echo "Computer Name" & vbTab & "AppPool Name" & vbTab & "User Name" & vbTab & "User Password"

Do Until adoRecordset.EOF
    Call GetApplicationPools(adoRecordset.Fields("name").Value & "." & strDNSDomain)
    adoRecordset.MoveNext
Loop
adoRecordset.Close

' Clean up.
adoConnection.Close

Private Sub GetApplicationPools (byVal strComputer)
	Dim objWMIService, colItems, objItem
	
	On Error Resume Next
	Set objWMIService = GetObject("winmgmts:{authenticationLevel=pktPrivacy}\" & strComputer & "rootmicrosoftiisv2")
	Set colItems = objWMIService.ExecQuery("Select * from IIsApplicationPoolSetting")
	If Err Then
		wscript.echo "Error connecting to " & strComputer
	Else
		For Each objItem in colItems
			Wscript.Echo strComputer & vbTab & objItem.Name & vbTab & objItem.WAMUserName & vbTab & objItem.WAMUserPass
		Next
	End If
End Sub

The Power of Scripting: Finding Morto.A

Here I go on anoth­er vbScript tuto­r­i­al.  You might ask why I’m not doing this in pow­er­shell yet and it is sim­ple: I still run into 2003 and XP envi­ron­ments. Oh yeah, and this works. I don’t care what script­ing lan­guage I’m writ­ing in if it gets the job done; you shouldn’t either. My $0.02. If you want to down­load this script, click here: Morto.A Detec­tion Script.

A had to do a lit­tle cleanup on a net­work from the Morto.A worm.  The first thing I want­ed to do was find out how bad things were.  They were report­ing a DDOS across their LAN (most­ly 3389) and a lot of oth­er issues.  It as obvi­ous we were going to need to rebuild a few sys­tems but we want­ed to get a grasp out of what the dam­age was.  This were gen­er­al­ly work­ing: logons, shares, etc.

I’m not going to go over what we did on the fire­wall or local net­work but dis­cuss a quick script I threw togeth­er to scan the net­work for infect­ed sys­tems.  The trick was this net­work had mul­ti­ple domains and sev­er­al com­put­ers that weren’t even domain joined.

So, I put my automa­tion hat on and threw togeth­er a script I will out­line below.  I split this into sec­tions to help you see how you can use script­ing to piece togeth­er a com­pli­cat­ed job in sim­ple tasks.  It is pret­ty basic.  I start by defin­ing what I want to do:

Prob­lem state­ment: I need to check every com­put­er in each domain for infec­tion of the Morto.A worm.  I can split this into three dis­tinct steps:

  1. For Each Domain
  2. Get Each Com­put­er
  3. Check for Morto.A

For Each Domain

This is pret­ty sim­ple.  There are advanced tech­niques for find­ing all the domains in a for­est or read­ing from a text file or even a spread­sheet.  I like to keep it sim­ple and just cre­ate an array.

Dim arrDomains
arrDomains = Array("domain1.domain.local", "domain2.domain.local", "domain3.domain.local")
For Each Domain in arrDomains
	Call ComputersAll(Domain)
Next

Get Each Computer

Now, I need to build the “Com­put­er­sAll” sub-rou­tine.  I call this in the domain script by pass­ing each domain in DNS for­mat.  I used DNS domains in my exam­ple on pur­pose (you could use the Dis­tin­guished­Name for­mat “dc=domain1,dc=domain,dc=local” but I pre­fer DNS names for this pur­pose).  By default, each com­put­er in that domain is going to reg­is­ter itself in DNS (assum­ing you set it up prop­er­ly).  I want to get the com­put­er name out of AD and append the dns domain name.  Once that is done, I want to use my “IsCon­nectible” script to check and make sure it is online.  If it pings, I should be able to car­ry out my busi­ness and find out if it is infect­ed.

The real mag­ic is in the lines: str­Base, strAt­trs and str­Fil­ter.  str­Base sets the search base to the domain you sent the sub-rou­tine.  It isn’t going to go out­side this domain for its search but it will search the whole domain due to its use of sub­tree.  The search a spe­cif­ic OU, you have to use the DN for­mat and that is out of scope of this arti­cle.  The strAt­trs is pret­ty straight for­ward.  This is an array of attrib­ut­es you want returned.  You could do DNS­Do­main­Name but some clients set this improp­er­ly.  It is safe to assume (in most cas­es) that the name and the domain name com­prise the DNS domain name.  The str­Fil­ter isn’t doing much but may look com­plex.  Basi­cal­ly, it is look­ing for com­put­ers in AD that aren’t dis­abled.

The oth­er things to pay atten­tion to is the line after

Do Until ADORecordSet.EOF

.  This checks first if the com­put­er is on the net­work through my “IsCon­nectible” script.  It pass­es the FQDN by append­ing “.” and the domain name to the name attribute from the query.

Const adUseClient = 3
Private Sub ComputersAll(byVal strDomain)
	Set adoCommand = CreateObject("ADODB.Command")
	Set adoConnection = CreateObject("ADODB.Connection")
	adoConnection.Provider = "ADsDSOObject"
	adoConnection.cursorLocation = adUseClient
	adoConnection.Open "Active Directory Provider"
	adoCommand.ActiveConnection = adoConnection

	strBase   =  ";"
	strFilter = "(&(objectClass=computer)(!userAccountControl:1.2.840.113556.1.4.803:=2));"
	strAttrs  = "name;"
	strScope  = "subtree"
	strQuery = strBase & strFilter & strAttrs & strScope
	adoCommand.CommandText = strQuery
	adoCommand.Properties("Page Size") = 5000
	adoCommand.Properties("Timeout") = 30
	adoCommand.Properties("Cache Results") = False

	Set adoRecordset = adoCommand.Execute

	If adoRecordset.RecordCount > 0 Then
		' wscript.echo "Computers for " & strDomain & ": " & adoRecordset.RecordCount
		' Loop through every single computer in the domain
		adoRecordset.MoveFirst
		Do Until adoRecordset.EOF
			If IsConnectible(adoRecordset.Fields("name").Value & "." & strDomain) = "Online" Then Call DetectMorto(adoRecordset.Fields("name").Value & "." & strDomain)
			adoRecordset.MoveNext
		Loop
	End If
	adoRecordset.Close
	adoConnection.Close
End Sub

Check For Morto.A

This is the tricky part. I used sev­er­al sources and found two dis­tict char­ac­ter­isitcs of this work:

  1. C:windowssystem32sens32.dll
  2. HKLM­Sys­temW­PA
    1. Key: sr
    2. Val­ue: Sens

So, I need to check and see if a file and reg­istry key exists in order to detect if the machine is infect­ed.  There are a cou­ple of caveats with this: 1) when check­ing if a file exists, the default response is true on error, 2) you need local admin rights to query the c$ share, and 2) the reg­istry check relies on the remote reg­istry ser­vice.  To over­come these caveats, we put error check­ing in.  If an error occurs, it assumes a man­u­al check is need­ed.  We do this to err on the side of cau­tion.  Of course, on a large net­work, this isn’t desir­able.  Feel free to con­tact me if you need more advanced help.  Here is the sub-rou­tine I came up with to do all of the above.  It is mean and nasty and isn’t exact­ly the kind of finesse I pre­fer but, it works…

First, I try writ­ing a temp file (and delet­ing it if it suc­ceeds). If that works, I should be able to detect if the file exists and con­nect to the remote reg­istry. How­ev­er, per­haps you are an admin that is para­noid and dis­ables the remote reg­istry ser­vice. Well, it will still detect an error and tell you to check man­u­al­ly. Of course, if you don’t have admin rights, it will also tell you to check remote­ly.

Private Sub DetectMorto(byVal strComputer)
	' Detects morto via several methods...
	Dim blnInfected : blnInfected = False
	
	
	' Requires admin rights to properly detect. Check for rights
	Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
	On Error Resume Next
	Dim TempFile : Set TempFile = objFSO.CreateTextFile("\" & strComputer & "c$WINDOWStempfile.deleteme", True)
	TempFile.WriteLine("This is a test.")
	TempFile.Close
	Set TempFile = Nothing
	objFSO.DeleteFile("\" & strComputer & "c$WINDOWStempfile.deleteme")	
	If Err Then bnlInfected = "Error"
	Err.Clear
	On Error GoTo 0
	
	' Check for registry key placed by Morto...
	Dim strKeyPath, strEntryName, objReg, strValue
	strKeyPath = "SYSTEMWPA"
	strEntryName = "sr"
	On Error Resume Next
	Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\" & strComputer & "rootdefault:StdRegProv")
	objReg.GetStringValue HKEY_LOCAL_COMPUTER, strKeyPath, strEntryName, strValue

	If Err Then blnInfected = "Error"
	If strValue = "Sens" Then blnInfected = True
	
	' Check for file indicating morto infection
	Dim strMortoSens32
	strMortoSens32 = "\" & strComputer & "c$WINDOWSsystem32Sens32.dll"
	If objFSO.FileExists(strMortoSens32) Then blnInfected = True
	
	' If the Infected flag is set, it is infected...
	If blnInfected = True Then
		wscript.echo "*******MORTO INFECTION: " & strComputer
	ElseIf blnInfected = "Error" Then
		wscript.echo "Error (Check Manually): " & strComputer
	Else
		wscript.echo "Clean: " & strComputer
	End If
End Sub

Conclusion

So, I have tak­en sev­er­al scripts and thrown them togeth­er to find a solu­tion. I can reuse this for any­thing. Per­haps I want to use vbscript to find com­put­ers with a cer­tain file on their hard dri­ve. I can reuse this by just tweak­ing the Mor­to sub-rou­tine.

Microsoft Releases Windows 8 Developer Preview

Microsoft has released the Win­dows 8 Devel­op­er Pre­view.  This down­load is a full ver­sion of the pre-beta Win­dows 8 build and is chock full of dis­claimers regard­ing its sta­bil­i­ty.  Need­less to say, I had to down­load it and give it a shot.  The down­load (2.8GB to 4.8GB) can be found linked off the front page of the Win­dows Dev Cen­ter.  I decid­ed to down­load the full ver­sion with all the Metro devel­op­ment good­ness though there is a lighter ver­sion with­out all the devel­op­er tools.

The Win­dows 8 Pre­view Guide (PDF) is pret­ty impres­sive.  It is a nice, clean overview of Win­dows 8.  Of course, the net is going to be sat­u­rat­ed with info in just a few days now that it is pub­licly avail­able.  I also high­ly rec­om­mend check­ing out the Build Keynote which pro­vides some of the eye can­dy you can look for­ward to.

I wasn’t as sur­prised to see ARM sup­port as Microsoft has made it clear it was com­ing.  I was sur­prised to see a 32-bit ver­sion for down­load.  I sup­pose it might be a bit lighter weight (at .8GB < the x64 ver­sion) for those just want­i­ng to pull it up in a VM to give it test run.

I was excit­ed when I saw the Live Con­nect tech­ni­cal pre­view (site doesn’t work w/ Chrome) until I real­ized it is only the SDK.

Installing Exchange 2010 Service Pack 1 Fails At Mailbox Role: Database is mandatory on UserMailbox.

In a recent inci­dent, an Exchange serv­er had a com­plete vol­ume fail­ure dur­ing test­ing. Exchange 2010 was rein­stalled but when installing Ser­vice Pack 1, it failed upgrad­ing the Mail­box Role. Upon review­ing the log, I found the fol­low­ing line:

Database is mandatory on UserMailbox. Property Name: Database

The error doesn’t explain the prob­lem very well but it is basi­cal­ly say­ing that there is a User­Mail­box with­out a data­base, which should nev­er hap­pen. The fail­ure of the vol­ume and sub­se­quent rein­stall of 2010 left the arbi­tra­tion mail­box­es (and one or two user mail­box­es) orphaned. Most of the sug­ges­tions to resolve this prob­lem list doing things like delet­ing the sys­tem mail­box­es and run­ning “setup.com /PrepareAD”. After look­ing around, I was able to parse togeth­er a few oth­er options and find a fix.

First, do a search in AD for the Sys­tem mail­box­es and make sure they exist in AD. (If they do not exist, check out this blog.)The three mail­box­es are:

  • Dis­cov­ery - SystemMailbox{e0dc1c29-89c3-4034-b678-e6c29d823ed9}
  • Mes­sage Approval - SystemMailbox{1f05a927-xxxx-xxxx-xxxx-xxxxxxxxxxxx} (where x is a ran­dom num­ber)
  • Fed­er­at­ed E-mail - FederatedEmail.4c1f4d8b-8179-4148-93bf-00a95fa1e042

Next, check out the sta­tus of their mail­box­es:

Get-Mailbox –Arbitration

For this client, their Dis­cov­ery and Mes­sage Approval mail­box­es spat out error mes­sages:

WARNING: The object XXXXXXXX.XXXXX/Users/SystemMailbox{e0dc1c29-89c3-4034-b678-e6c29d823ed9} 
has been corrupted, and it's in an inconsistent state. The following validation errors happened:
WARNING: Database is mandatory on UserMailbox.

The fix is a love­ly, one-line pow­er­shell. It won’t do any­thing with­out prompt­ing you first. To ver­i­fy it fix­es the issue after you run it, take the first half of the com­mand (get-mail­box -arbi­tra­tion) and run that again to con­firm they are online and okay.

Get-Mailbox -Arbitration | Set-Mailbox -Arbitration –Database "Mailbox Database XXX"

Hope­ful­ly this saves some­body from caus­ing a big­ger mess than nec­es­sary. After run­ning this, I was able to install Ser­vice Pack 1 just fine. YMMV.

Edit: I found the DiscoverySearchMailbox{D919BA05-46A6-415f-80AD-7E09334BB852} was orphaned as well. To fix this mail­box, I just ran the fol­low­ing PoSH.

Get-Mailbox -Identity "DiscoverySearchMailbox{D919BA05-46A6-415f-80AD-7E09334BB852}" | Set-Mailbox –Database "Mailbox Database XXX"

Exchange 2007+: Aliases have invalid data

Twice in the past two weeks, I have come across Exchange 2003 to Exchange 2007 migra­tions which went uncom­plet­ed. In both cas­es, I received the fol­low­ing error(s) when try­ing to view the prop­er­ties of a recip­i­ent with spaces in its alias or when view­ing the prop­er­ties of the offline address book:

  • The prop­er­ties on have invalid data. If you click OK, default val­ues will be used instead and will be saved if you do not change them before hit­ting Apply or OK on the prop­er­ty page. If you click can­cel, the object will be dis­played read-only and cor­rupt­ed val­ues will be retained. The fol­low­ing val­ues have invalid data: Alias.
  • WARNING: Object has been cor­rupt­ed and it is in an incon­sis­tent state. The fol­low­ing val­i­da­tion errors have been encoun­tered: WARNING: is not valid for Alias.
  • Set- : is not valid for Alias.

Here is a screen­shot of the error:

Exchange 2003 would allow an admin­is­tra­tor to put spaces in the Alias attribute. That pos­es a prob­lem for 2007 which is strict about the char­ac­ters it allows in this attribute. In Exchange 2007 the fol­low­ing char­ac­ters are con­sid­ered valid: Strings formed with char­ac­ters from a to z (upper­case or low­er­case), dig­its from 0 to 9, !, #, $, %, &, ‘, *, +, -, /, =, ?, ^, _, ‘, {, |, } or ~. But, no spaces.

Going through you recip­i­ents one by one is a daunt­ing task. Here is some code to auto­mate this cleanup. Once you take care of this, you shouldn’t run into it again since the tools in Exchange 2007 won’t let you make the same mis­take.

Clean up mail­box­es:

Get-Mailbox | Where {$_.Alias -like "* *"} | ForEach-Object {Set-Mailbox $_.Name -Alias:($_.Alias -Replace " ","")}

Clean up pub­lic fold­ers:

Get-PublicFolder | Where {$_.Alias -like "* *"} | ForEach-Object {Set-PublicFolder $_.Name -Alias:($_.Alias -Replace " ","")}
Get-PublicFolder -Identity "" -Recurse -ResultSize Unlimited | Foreach { Set-PublicFolder -Identity $_.Identity -Name $_.Name.Trim()}

Clean up con­tact objects:

Get-MailContact -ResultSize unlimited | foreach {$_.alias = $_.alias -replace 's|,|.'; $_} | Set-MailContact
Get-Contact | Where {$_.Alias -like "* *"} | ForEach-Object {Set-Contact $_.Name -Alias:($_.Alias -Replace " ","")}

Clean up dis­tri­b­u­tion groups:

Get-DistributionGroup | Where {$_.Alias -like "* *"} | ForEach-Object {Set-DistributionGroup $_.Name -Alias:($_.Alias -Replace " ","")}

Check for any objects that still throw errors:

Get-PublicFolder | findstr "Warning"
Get-Contact -resultsize unlimited | findstr "Warning"
Get-Mailbox -resultsize unlimited | findstr "Warning"
Get-DistributionGroup -resultsize unlimited | findstr "Warning"

Rebuild your address lists:

Set-AddressList "All Users" -IncludedRecipients MailboxUsers
Set-AddressList "All Groups" -IncludedRecipients Mailgroups
Set-AddressList "All Contacts" -IncludedRecipients MailContacts
Set-AddressList "Public Folders" -RecipientFilter {RecipientType -eq "PublicFolder"}
Set-GlobalAddressList "Default Global Address List" -RecipientFilter {(Alias -ne $null -and (ObjectClass -eq 'user' -or ObjectClass -eq 'contact' -or ObjectClass -eq 'msExchSystemMailbox' -or ObjectClass -eq 'msExchDynamicDistributionList' -or ObjectClass -eq 'group' -or ObjectClass -eq 'publicFolder'))}

Microsoft IT Environment Health Scanner

It's essentially a server for business.
It’s essen­tial­ly a serv­er for busi­ness.
Most peo­ple have a fear of tak­ing their vehi­cle to the mechan­ic for even the sim­plest tasks just to find out they need their trans­func­tion­er adjust­ed because of wear to the driver’s side steer­ing wid­get.  For many in the SMB mar­ket, that same fear can be found in their tech­nol­o­gy invest­ments.  “Did that last IT guy wrap our SQL serv­er in duct tape and tie it to the web serv­er with shoe string?”  The real­i­ty is often not that bad, but it can be unset­tling not know­ing.

The first thing I want to check when prepar­ing any SMB (or large scale Enter­prise) for a project is the over­all health of their envi­ron­ment.  I typ­i­cal­ly use a few cus­tom scripts, the invalu­able tools from Joe­ware and Sys­in­ter­nals, plus a few oth­ers offered by var­i­ous ven­dors to col­lect the data for analy­sis.  The stan­dard ser­vices are checked, like DNS, DHCP, WINS (ugh), Exchange, AD, NTP, Group Pol­i­cy, CAs, etc. for over­all health and mis­con­fig­u­ra­tions.  Even with the rich ecosys­tem of tools, this process can be time con­sum­ing so I am always look­ing for ways to stream­line the process.

It seems a lot of oth­ers were look­ing for a quick method as well; at least one that can get a quick assess­ment of whether you are deal­ing with a dis­as­ter or lim­it­ed pieces to fix.  The Microsoft Essen­tial Busi­ness Serv­er runs a check on the envi­ron­ment to assess its health before instal­la­tion.  From this Microsoft Tech­net blog, “[the EBS team] noticed that Prepa­ra­tion Wiz­ard was wide­ly used, not just by cus­tomers who were deploy­ing EBS, but any­one with Active Direc­to­ry in their net­work who want­ed to ver­i­fy the health of their envi­ron­ment.” This gave birth to the Microsoft IT Envi­ron­ment Health Scan­ner in the sum­mer of 2009.

This free tool does the basic checks I’m going to do any­way but it gives that quick assess­ment that often tells me whether I need to dig fur­ther. Microsoft’s down­load page states:

When run from a com­put­er with the prop­er net­work access, the tool takes a few min­utes to scan your IT envi­ron­ment, per­form more than 100 sep­a­rate checks, and col­lect and ana­lyze infor­ma­tion about the fol­low­ing:

  • Con­fig­u­ra­tion of sites and sub­nets in Active Direc­to­ry
  • Repli­ca­tion of Active Direc­to­ry, the file sys­tem, and SYSVOL shared fold­ers
  • Name res­o­lu­tion by the Domain Name Sys­tem (DNS)
  • Con­fig­u­ra­tion of the net­work adapters of all domain con­trollers, DNS servers, and e-mail servers run­ning Microsoft Exchange Serv­er
  • Health of the domain con­trollers
  • Con­fig­u­ra­tion of the Net­work Time Pro­to­col (NTP) for all domain con­trollers

Whether you have a small Microsoft IT envi­ron­ment or are Enter­prise large, this tool is great for catch­ing those things often over­looked dur­ing set­up or changes or mis­con­fig­ured. Down­load link: Microsoft IT Envi­ron­ment Health Scan­ner.

All Your VoIP Are Belong To Us

Looks like Microsoft is adding to its VoIP offer­ings. Skype should make a nice addi­tion to their recent push with the com­bined ser­vices of OCS and Live Meet­ing in Lync. Should be an inter­est­ing day to watch the MSFT stock. The price tag keeps going up. First I heard $7 bil­lion. Then $8.5 bil­lion. Yikes! http://goo.gl/bhsn6

vbScript: Tweaking Power Settings (disabling hibernate and standby)

As is often the case in IT, when you need to push out that soft­ware pack­age or migrate that com­put­er to a new domain, it isn’t on the net­work.  This has come up sev­er­al times in the past year and I want­ed to share my solu­tion.  Now, this isn’t the “green­est” solu­tion because this will ensure your clients nev­er go into a pow­er sav­ing mode.  How­ev­er, it can be a tem­po­rary fix for a project.  It can also be adapt­ed to force stand­by or hiber­nate at spe­cif­ic thresh­olds.

While Win­dows 7 and Vista make this task sim­ple, XP is still a real­i­ty in most enter­pris­es and SMB’s and there­fore, must be tak­en into account.  The script below does just that.  Some addi­tion­al exam­ples can be found at the US Government’s Ener­gy Star web­site.

Note: Copy­ing the script from the web­page may cause for­mat­ting issues.  You can down­load the script here: tweak-power-settings.vbs
Read More