Learn to Love, Love to Learn

I’ve been in the technology field now for over 15 years.  I must say that I’ve been extremely fortunate and believe that while I’ve only had a handful of jobs, I’ve made the right decision to move on when the opportunity has presented itself.  But my story could be very different.

At this point in my life, finally, I love learning.  Well, I love it again.  Most of that probably has to do with my wife (and children) but I realize that I’ve loved it for a while and at some point just lost my way.  I did well in high school without really applying myself.  But when I got ready to graduate and decide on what I wanted to go to college for I wasn’t really sure.  I had been tinkering with computers for a while, owned a few Java 1.0 and HTML books and had been ‘the guy’ for friends and family PC issues.  I enjoyed technology.  I enjoyed learning about what was next.  But for a career?  I just wasn’t sure.

That’s when my dad gave me the worst advice ever:

You don’t want to go to school for computers.  You’ll always have to be learning and studying.

Looking back on this, it stings a little (okay, a lot).   I took this advice and said, you know what, you’re right.  Who wants to have to be in school all the time learning new things.  Or constantly reading books (even though I was an avid reader) to learn how to do something new.  So I went to school and floundered.  The truly engaging classes I excelled in.  The ho-hum classes I tried not to sleep through.  Three major changes later, I was in the Comp-Sci program and burnt out on college.  So I quit.  But college isn’t the issue or my lack of focus the first time around.

You see, we are teaching our kids to love learning.  To enjoy what they don’t yet know.  And we certainly live in an age where information is right at their fingertips.  They don’t fathom having to go to the library to look up something in an encyclopedia.  They don’t know what it’s like to not have information instantly available, to have an inquiry and be able to search out info from multiple sources.  But my dad took that away.  With one sentence, he made me think that learning was one and done.  Like sitting in math class and thinking you’ll never use this in ‘the real world’. 😉

At this point in my life I have found the love again.  I read as much as possible and watch all the lovely videos on Pluralsight that I can.  I model this for my children and when they ask questions I don’t know the answers to, we look them up.  But I will never tell my children to bypass what they love to do what’s easier, especially if it involves learning.

Saturday, May 3rd, 2014 Uncategorized No Comments

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

 

Tuesday, March 25th, 2014 C#, Code, Exchange No Comments

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

Saturday, February 22nd, 2014 C#, Code, Exchange, Uncategorized No Comments

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.

 

Tuesday, February 11th, 2014 C#, Code, Exchange 6 Comments

Moving WSUS Databases

Most important piece of information….SQL Server name:

\\.\pipe\MSSQL$MICROSOFT##SSEE\sql\query

Detach database, move files, re-attach database.

Moving WSUS content:

C:\Program Files\Update Services\Tools\wsusutil.exe movecontent “Content destination” “logfile destination”

Ex.
C:\Program Files\Update Services\Tools\wsusutil.exe movecontent W:\WSUS W:\MoveContent.log

Friday, February 24th, 2012 Uncategorized No Comments

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;
    Collection results = 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.

Wednesday, February 15th, 2012 C#, Code, Exchange 10 Comments

User and Group Information in AD

Continuing our Active Directory theme from the last post, I wanted to follow up on locating the groups that users belong to or groups you’d like to add to a user account.  These examples will also continue with using the .Net 3.5 DirectoryServices.AccountManagement namespace since there is quite a bit less code than using the methods for .Net 2.0.

So, the first example deals with getting all of the groups of a user account. Some of the code you might have already seen.

UserPrincipal user = null;
//Create a PrincipleContext that will search the full domain
//ie not just the site's user OU
//FQDC = Fully Qualified Domain Controller
string userName = "MyUserToSearch";
using (var context = new PrincipalContext(ContextType.Domain, FQDC))
{
    try
    {
        if ((user = UserPrincipal.FindByIdentity(context, userName)) != null)
        {
            // Search for current groups
            PrincipalSearchResult<Principal> groups = user.GetGroups();

            // Iterate group membership
            foreach (GroupPrincipal g in groups)
            {
                Console.WriteLine(g.Name);
            }
        }
    }
}

Now we know how to grab the group information for a user, but what if we want to remove a group?

UserPrincipal user = null;
//Create a PrincipleContext that will search the full domain
//ie not just the site's user OU
//FQDC = Fully Qualified Domain Controller
string userName = "MyUserToSearch";
using (var context = new PrincipalContext(ContextType.Domain, FQDC))
{
    try
    {
        if ((user = UserPrincipal.FindByIdentity(context, userName)) != null)
        {
            // Search for current groups
            PrincipalSearchResult<Principal> groups = user.GetGroups();

            // Iterate group membership and remove IT_Dept group
            foreach (GroupPrincipal g in groups)
            {
                if (g.Name == "IT_Dept")
                {
                    g.Members.Remove(user);
                    g.Save();
                }
            }
        }
    }
}

Finally, adding a new group is a little different.

UserPrincipal user = null;
//Create a PrincipleContext that will search the full domain
//ie not just the site's user OU
//FQDC = Fully Qualified Domain Controller

string userName = "MyUserToSearch";
using (var context = new PrincipalContext(ContextType.Domain, FQDC))
{
    try
    {
        if ((user = UserPrincipal.FindByIdentity(context, userName)) != null)
        {
            // Add user to new group
            string groupName = "GroupToAddUser";
            using (var group = GroupPrincipal.FindByIdentity(context, IdentityType.Name, groupName))
            {
                // Verify user is not currently a member and save
                if (!group.Members.Contains(user))
                {
                    group.Members.Add(user);
                    group.Save();
                }
            }
        }
    }
}

Here we search for the group name explicitly, check that the user isn’t already in it and then add the user.  Pretty simple stuff.

Tags: Active Directory, C#

Friday, August 26th, 2011 C# 3 Comments

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:

Brandon Watson's tweet to webOS developers

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) bookVideos 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.  😉

Tags: Microsoft, WP7, WP7Dev

Tuesday, August 23rd, 2011 Microsoft No Comments

Active Directory UserPrincipals in .Net

Continuing our Active Directory theme from the last post, I wanted to step back for a second and discuss UserPrincipal objects a little more as I have a few posts relating more to accounts following this one.

The UserPrincipal class has two constructors.  One takes a PrincipalContext and the other one takes the PrincipalContext, SAM account name, password, and enabled value.  In general, I use the constructor with just the PrincipalContext when searching for an existing AD account and the ‘expanded’ constructor when I am creating a new AD user object.  As most Active Directory environments need passwords, and I generally make it a point to not know user passwords (after I create them) I think this makes sense.  So, now I’ll detail these two uses below.

First, let’s take a look at finding a user and mapping it to a UserPrincipal object.  What I’m really focused on here is the UserPrincipal itself and I’ll cover searching more in other articles.  Here’s some code:

using (var context = new PrincipalContext(ContextType.Domain, FQDC))
{
   UserPrincipal user = null;
   do
   {
      // We don't create accounts with '1' so we need to increment again.
      if (count == 1) { count++; }
      // Similar to the ADID we need to determine the identifier for the username
      string filter = count > 0 ? this.UserName + count.ToString() : this.UserName;
      user = UserPrincipal.FindByIdentity(context, filter);
      count++;
   } while (user != null);
}

This is a somewhat expanded example of a routine I use to determine AD usernames but I didn’t want to just throw in three lines and call it a day.  My primary AD domain has 18000+ user accounts so we’re bound to have duplicate names using our standard naming scheme.  In case of a duplicate, I need to append a number on it so that’s what you see here, me determining the number.  What’s truly important here is that by using the FindByIdentity method, we return a UserPrincipal object from AD that contains common AD attributes that we may be interested in and once we have this object we can manipulate these values quite easily.  As a bonus, we can extend this object with custom code and map properties such as the EmployeeID field (which is not exposed by UserPrincipal).  I’ll save that for a later post though.

Now, the second scenario involves us wanting to create a new user.  Finding and connecting to a current user is easy and so is creating a new one.

using (PrincipalContext adPC = new PrincipalContext(ContextType.Domain, FQDC))
{
    using (UserPrincipal user = new UserPrincipal(adPC, this.CommonName, this.Pass, true))
    {
        user.SamAccountName = UserName;
        user.UserName = UserName;
        user.UserPrincipalName = UserName + "@some.domain";
        user.GivenName = FirstName;
        if (this.mName != "") { user.Initials = MiddleName; }
        user.Surname = LastName;
        user.DisplayName = this.CommonName;
        user.EmailAddress = UserName + "@mydomain.com";
        user.SetPassword(this.Pass);
        user.Department = "Rocking IT Department";
        user.Company = "My Fake Company";
        user.PhysicalDeliveryOfficeName = officeLocation;
        user.ExpirePasswordNow();
        user.Enabled = true;
        user.PasswordNotRequired = false;
        user.Save();
    }
}

So creating an account is pretty simple too.  Using a PrincipalContext attached to the DC that you want to create the object on, you create a new UserPrincipal passing in the values for the context, the name as it’ll appear in AD (First Last or Last, First — however your procedures require it)  the temporary password and true to say it’s enabled (although we do set that below).  The rest are fairly standard properties that you may be setting in your schema.  Once you’ve set all of your properties save the object and you have a new Active Directory user.

Tags: Active Directory, C#

Monday, August 22nd, 2011 C#, Code No Comments

Querying AD from C# using DirectoryServices.AccountManagement

I ran across a need  to query AD and make bulk changes to a subset of AD user accounts.  When creating an account in Active Directory using a UserPrincipal object you must specify certain properties on the account.  The ones I was interested in are as follows:

PasswordNotRequired
UserCannotChangePassword
PasswordNeverExpires

During my initial creation, I forgot to set PasswordNotRequired to false and needed to go back and set this on a group of accounts.  My initial attempt had a problem…it only returns the first 1000 results:

using (var context = new PrincipalContext(ContextType.Domain, FQDC))
{
     UserPrincipal up = new UserPrincipal(context);

     up.EmployeeId = "*";
     up.Enabled = true;

     PrincipalSearcher ps = new PrincipalSearcher();
     ps.QueryFilter = up;

     PrincipalSearchResult<Principal> results = ps.FindAll();

     if (results != null) ...

Here we setup a PrincipalContext and create a new UserPrincipal with it. We then set the search criteria (some value entered in the EmployeeID field and an Enabled account).  After creating a PrincipalSearcher we set a QueryFilter and then return the results.  Again, this works great but it only returns 1000 results.  As I was expecting closer to 15000, this was a slight problem. 😉

So, how do we return all of the results?  The solution is actually quite simple and I’ll highlight the one-line code change below.

...
PrincipalSearcher ps = new PrincipalSearcher(up);
...

When creating the PrincipalSearcher, we need to pass in the UserPrincipal object to get the desired result.  According to MSDN, the QueryFilter must be set (we set it in the example above) before passing it into the PS object.  Also, you can go the long route and set the PageSize in the underlying DirectorySearchwe object, but I find this way to be much easier.

One other side note. Don’t forget how it easy it is to “parallelise” your operations.

if (results != null)
{
     int count = 0;
     Parallel.ForEach (results, s =>
     {
           code to do stuff....
      });
}

.Net makes it very easy to make your operations parallel.

Tags: Active Directory, C#

Sunday, August 21st, 2011 C#, Code 1 Comment

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

WordPress SEO fine-tune by Meta SEO Pack from Poradnik Webmastera