Microsoft
Filtering Exchange PowerShell Locally
As an Exchange developer, it’s quite possible you’ve run across this error message:
Assignment statements are not allowed in restricted language mode or a Data section.
Or you’ve possibly seen this one:
Script block literals are not allowed in restricted language mode or a Data section.
While it’s quite easy to change the PSLanguageMode to FullLanguage instead of RestrictedLanguage it may be that you can’t do that for one reason or another. Here’s a small method I put together for filtering the results locally. Use your discretion about the size of your resultsets to bring back.
public IEnumerable<PSObject> ApplyPSFilter(IEnumerable psData, ScriptBlock scriptBlock) { using (var ps = System.Management.Automation.PowerShell.Create()) { ps.AddCommand("Where-Object"); ps.AddParameter("FilterScript", scriptBlock); return ps.Invoke(psData); } }
Using Credentials to Get Remote PowerShell Connection to Exchange Connection
Saw this come across the search logs so I figured I’d detail the steps needed to supply credentials to a remote PowerShell connection to Exchange. Since we’re connecting to another system to run the Exchange PS cmdlets, and we are not loading a PSSnapin, the remote system needs to have those cmdlets available. I’m also separating this out into individual methods for easy re-use.
To setup a remote connection, we need to create a new WSManConnectionInfo object. We’re specifically going to use the constructor that takes a Uri for the connection endpoint, a string value for the Uri of the shell and the credentials we want to use.
WSManConnectionInfo Constructor (Uri, String, PSCredential)
The Uri will be specific to your situation and will look something like this : http://myexchangeserver.domain.corp/powershellThe shell is pretty simple. In this case it is : http://scemas.microsoft.com/powershell/Microsoft.Exchange
And last but not least it the PSCredential needed for the connection. PSCredential takes a string for the Username and a SecureString for the password. Here’s an small method to pass in a string and get a SecureString back :
SecureString GetSecurePassword(string password) { var securePassword = new SecureString(); foreach (var c in password) { securePassword.AppendChar(c); } return securePassword; }
With that out of the way, let’s take a look at a snippet for getting the connection info :
WSManConnectionInfo GetConnectionInfo() { var securePassword = GetSecurePassword(password); var cred = new PSCredential(username, securePassword); var connectionInfo = new WSManConnectionInfo(new Uri("http://superserver.corp/powershell), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", cred); connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Credssp; //or Basic, Digest, Kerberos etc. return connectionInfo; }
Now let’s put it all together to make a remote connection :
using (var runspace = RunspaceFactory.CreateRunspace(connectionInfo)) { using (var ps = System.Management.Automation.PowerShell.Create()) { //psCommand was created above ps.Commands = psCommand; runspace.Open(); ps.Runspace = runspace; try { var results = ps.Invoke(); if (!ps.HadErrors) { runspace.Close(); //Yay! no errors. Do something else? } catch (RemoteException ex) { //error handling here } } }
So, a couple of things to mention here. First, psCommand was created like this. You could also create a Pipeline if you have more than one command to run or even use it to create a PS script to run. Also, if you need to do something with the results of the command, well, you’ll have to either make this return the results ((FavoriteCollectionType) or modify this to suit your needs. Second, we verify that the command had no errors (no exception but didn’t run successfully for whatever reason) but that’s it. Might want to expand here or in the calling method.
I hope this has been informative. 😀
Creating Exchange 2013 Mailbox in C#
Holy moly it’s been a long time since I posted. Here’s a quick code snippet on using C# to create a mailbox to hopefully kick a string of posts off. This creates an AD account for the user unlike my previous article on creating a mailbox in Exchange 2010. And since I listed a gotcha in that article, I’ll leave a tip in this one after the code. 😀
var psc = new PSCommand(); psc.AddCommand("New-Mailbox"); psc.AddParameter("Name", newUser.UserName); psc.AddParameter("UserPrincipalName", upn); psc.AddParameter("Alias", upn); psc.AddParameter("PrimarySmtpAddress", string.Format("{0}@{1}", newUser.UserName, domainName).ToLower()); psc.AddParameter("OrganizationalUnit", domainDn); psc.AddParameter("SamAccountName", samAccount); psc.AddParameter("Password", _ps.CreateSecurePassword("mysupersecretpassword")); psc.AddParameter("DomainController", domainController); PowerShell ps = PowerShell.Create(); ps.Commands = psc; try { var result = ps.Invoke(); if (!ps.HadErrors) { Console.WriteLine("Congrats! User created successfully"); } } catch (RemoteException ex) { //Error conditions here... }
Easy enough. Now for the tip. If you specify the PrimarySmtpAddress it will automatically set the EmailAddressPolicyEnabled value to false. So leave that parameter out if it’s important for your org.
Creating Exchange 2010 Mailboxes in C#
Wow, it’s been a while! I had full intentions of creating regular posts but that kind of slipped away. So I’ll make this one fairly short and just highlight the basics of creating an Exchange 2010 mailbox via remote code. Nothing fancy, but I will highlight one gotcha that I encountered when updating our user creation code after we migrated from Exchange 2003. Keep in mind that Exchange 2010 is built on Powershell and as such, all of connections and manipulation must be done through it.
First, we want to add our usings…
using System.Management.Automation; using System.Management.Automation.Remoting; using System.Management.Automation.Runspaces;
Next, we’re going to create the PSCredential, the WSManConnectionInfo, and the Runspace. We’ll then create a powershell command, invoke the powershell with the command and cross our fingers. 😀
PSCredential newCred = (PSCredential)null; WSManConnectionInfo connectionInfo = new WSManConnectionInfo(new Uri("http://exchangeserver01.my.domain/powershell?serializationLevel=Full"), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", newCred); connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Kerberos; Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo); PowerShell powershell = PowerShell.Create(); PSCommand command = new PSCommand(); command.AddCommand("Enable-Mailbox"); command.AddParameter("Identity", user.Guid.ToString()); command.AddParameter("Alias", user.UserName); command.AddParameter("DomainController", ConnectingServer); powershell.Commands = command; try { runspace.Open(); powershell.Runspace = runspace; Collectionresults = powershell.Invoke(); } catch (Exception ex) { string er = ex.InnerException.ToString(); } finally { runspace.Dispose(); runspace = null; powershell.Dispose(); powershell = null; }
Now, a couple of things to note…
1) My gotcha…You don’t find a lot of information about creating a PSCredential using the credentials of the currently logged in user. Even the MSDN documentation only shows one constructor where you pass in a username and password. After searching around, some trial and error, I finally found this post detailing creating the PSCredential using Windows Authentication with no username or password supplied. Supplying credentials isn’t a problem, but as we log the account creations, and we didn’t have this issue when creating boxes in 2003, I wanted as seamless transition as possible. So this code just replaced the old code and my other Admins had no idea anything was different.
2) Accounts for my users need to be created at one of many different sites, and many times it’s not a site I’m currently at. So, the account is created on the ‘local to them’ server so they can immediately login and not need to wait for replication. Because of this, Exchange needs to know what server holds the account. If you don’t need this functionality, you can remove the DomainController command parameter above.
3) It is important to properly dispose of the runspace and powershell objects. Make sure this is done.
webOS and the Early Adopting Windows Phone Developer
Last week, HP announced it was killing off production of hardware devices for it’s mobile operating system webOS. This was just a few days after it was reported that Best Buy had 250k+ devices that it wanted to send back to HP because they couldn’t sell them. Always willing to jump on an opportunity to push the Windows Phone platform, Brandon Watson tweeted the following:
As of yesterday (and my last look for a count), Brandon had received responses from over 1k webOS developers looking for more information. Not a bad response to his offer, although I’m also not sure how many active webOS developers there are. But the point of this post is this…
What about the current/early entry Windows Phone developers?
Microsoft’s app store has seen great growth through it’s first year of existence. Developers are creating apps for it, partly due to Microsoft’s tremendous development tools and partly due to easily transitioning existing skill sets with Silverlight and XAML developers. Many ‘expected’ (Words with Friends I’m looking at you) apps are missing, however the addition of things like Sockets support in the upcoming Mango release should bring some of these apps about. But where are the free phones, free dev tools and free training for us?
Take a peek at Brandon’s email to webOS developers. Quick summary — free phones, dev tools and training. 😉
Well, they’re already there…
Microsoft knows it needs developers and since the beginning has been actively pushing to get them what they need to succeed. Charles Petzold released a free (and paid if you desire) book. Videos were produced for absolute beginners. More videos were produced for “Jump Starts”. Hands on labs were created for introductory training and with each release more have been created to expand on new features. And of course the always spectacular MSDN site is loaded with info (1, 2). Are you getting the feeling that MS is serious about developers?
So what about training. Well, there’s one today and tomorrow (continuation of today’s). They’ve also held “Windows Phone App Garages” where you train for a day with the whole intent to get an app published in the app store by the time you leave. These have been held in Birmingham, Tampa, Atlanta, New York, Charlotte etc. etc. Free, live, in-person events. And I’m sure there have been plenty more.
Oh yeah, there’s the free phone thing. Everyone would like a free phone. Free is good, but how come I’ve been developing for Windows Phone for 6 months and this new guy gets a free phone? That’s not fair!! Well, let me quote from Brandon’s email…
Ahem… “We have phones for developers committed to building apps and games for Windows Phone. This isn’t a free ride program where we just hand out phones to people because they say they want one.”
Wait, what? That sounds like it’ll take more than just an email to get Brandon’s team to send off a phone. But more to the point, Microsoft has been offering free phones to developers for a while. I attended one of the App Garage events and was given a code to enter to get a free phone. What did I have to do to enter? Submit an app. My understanding is that these codes were given out to developers everywhere. Different codes for different events, possibly as a way to track the viability of these training sessions and provide feedback for the presenters MS sent out to do the trainings. Phones are given out to student developers as well. A recent #WPAppItUp promotion on twitter did just that.
But the best part about these training sessions wasn’t the possibility of a free phone and might not have even been the training provided. It was the connections. Meeting people that are looking at the same road ahead as you, whether that be full time WP7 development, just taking a gander to see if it makes sense to develop for this platform or even just starting out. People willing to share knowledge and help each other. At least that’s what I took away from my experience.
My point here is that MS loves developers. And it doesn’t matter if you are exclusive to them or not. Developers, developers, developers. 😉
Exchange Free/Busy Problems
After searching for a few hours and feeling seriously inadequate in my Google-Fu, I finally found a fix for a problem that doesn’t seem to have happened to anyone else. So, if you have run across this issue, I feel your pain…
The boss lady called yesterday to let me know that she could not email her calendar with ONLY Free/Busy information.
Now, her error showed a date range for a month, not a single day. Changing the options to include Limited data worked fine. But this isn’t always acceptable. If you’re sending this info to a vendor to help with scheduling a meeting, the vendor doesn’t need to know you have lunch plans with a competitor or an interview scheduled for next Friday. They just need to know you aren’t available.
As I mentioned earlier, I searched for at least an hour and a half for this error. After verifying that this occurred on my machine as well, I ruled out Outlook and started looking for solutions regarding Exchange. I came across this great Technet article. I downloaded the MAPI Editor tool and proceeded to follow the instructions in the Removing Free/Busy Information from the Schedule+ Free/Busy Folder section.
To remove Free/Busy information from the Schedule+ Free/Busy folder
- Log on as an account that has Exchange Full Administrative permissions. For more information about permissions, see Microsoft Knowledge Base article 823018, “Overview of Exchange administrative role permissions in Exchange 2003” at http://go.microsoft.com/fwlink/?linkid=3052&kbid=823018.
- Start MAPI Editor.
- On the Session menu, click Logon and Display Store Table.
Note: If the Choose Profile dialog box does not appear, you are probably already logged on to a profile. Log off the client and profile, and try step 3 again. - Select the profile that you created for the directory service mailbox, and then click OK.
- On the MDB menu, click Open Public Folder Store, select Use Admin Privileges, and then click OK.
- In the Public Folders window, expand Public Root, and then expand NON_IPM_SUBTREE. The SCHEDULE+ FREE BUSY folder is displayed.
- Expand the SCHEDULE+ FREE BUSY folder.
The subfolders of the Schedule + Free/Busy folder will be of the form EX:/o=Organization/ou=domain.
- Double-click the appropriate folder to open it.
Note: The folder could have several messages in it. Press Escape (ESC) to stop loading messages. - Table/Create and Apply Content Restriction can be used to restrict the table to show only messages you are looking for. For example, because the subjects of free/busy messages take the form USER-/CN=container/CN=username, a restriction on PR_SUBJECT (0x0037001E) for the value “username” with the flags 0x00010001 (FL_SUBSTRING | FL_IGNORECASE) could be used to locate one specific message. Note that on large folders, restrictions may take time to apply.
- When the problem message is located, if you want to delete it, right-click the message, and then click Delete Message.
- When you are prompted, select Permanent Deletion (deletes to deleted item retention…) from the drop-down list, and then click OK.
- Using Outlook, create a new appointment for this user to force re-creation of the Free/Busy message.
Voila! Emailing the calendar with only Free/Busy status works as expected. 😀
Programmatically Throttling IIS
Ran across an issue where I needed to throttle WSUS bandwidth coming back to a server. While WUS uses BITS, each machine knows of it’s network availability and utilization but has no knowledge of the network congestion to the server. So, throttling IIS allows us to keep update traffic low and allows other traffic in and out of the site. Here’s some VBScript
'Connect to local default website Set IISConn = GetObject("IIS://localhost/W3SVC/1") 'Define kilobits for easier number manipulation kBits = 1024 'Define the maximum bandwidth when throttled minBandwidth = 10240 * kBits minConnections = 300 'Define the unthrottled bandwidth value maxBandwidth = -1 maxConnections = -1 'WScript.Echo IISConn.MaxBandwidth 'WScript.Echo IISConn.MaxConnections 'Detect current bandwidth setting and change appropriately If IISConn.MaxBandwidth = minBandwidth Then IISConn.Put "MaxBandwidth", maxBandwith Else IISConn.Put "MaxBandwidth", minBandwidth End If 'Write the value to the metadata IISConn.SetInfo
Two things of note…
1) Change the IISConn path to which ever service is running the website you want to throttle.
2) The values of the bandwidth entered to be multiplied should already be by 1024 (10 Mbps x 1024 = 10240 as listed above).
Manually uninstalling Office 2007
Ran across an issue where the setup for Office 2007 would not complete. It installed itself enough to show in Add/Remove Programs yet the programs wouldn’t start. To resolve this I followed part of the steps in this article.
Specifically just Step 1…
Step 1: Remove any remaining Windows Installer packages of the 2007 Microsoft Office system:
- Click Start, click Run, type installer, and then click OK.This process opens the %windir%\Installer folder.
- On the View menu, click Details.
Important To use the View menu in Windows Vista, you must press the ALT key first to display the menu bar, and then click the View menu. - On the View menu, click Choose Details.
- Click to select the Subject check box, type 340 in the Width of selected column (in pixels) box, and then click OK.
Note It may take several minutes for the subjects to appear next to each .msi file. - For Windows XP or Windows Server 2003, on the View menu, point to Arrange icons by, and then click Subject. For Windows Vista, on the View menu, point to Sort By, and then click Subject. In Windows Vista, a User Account Control dialog box may be displayed with the following warning:
An unidentified program wants access to your computer
Click Allow when you see this warning message.
- For each .msi file where the subject is “Microsoft Office Product_Name 2007,” right-click the .msi file, and then click Uninstall.
Note Product_Name is a placeholder for the name of the 2007 Microsoft Office product.
After that I used the Windows Installer CleanUp Utility (download here) to remove the instance in Add/Remove Programs. Installation completed successfully afterwards. 🙂