Expanding my horizons and the Microsoft Cloud Show

 

I’ve known for a long time that in order to be successful in the music industry, especially for someone who doesn’t tour right now, that I needed to expand my horizons in order to get my music heard.

That’s why I’ve been working with other people to collaborate on music as well as offering my music for use in projects etc. that I have great interest in.

I thought I would share some of those collaborations and tidbits with you that you may have missed.

Smoking Land

First comes a student short film created by Axel Henneberg.  .

Axel is a film student of the Prague film school, and he has used some of the music from my award winning album “Ambient Highways” for his short film titled Smoking Land.

Smoking Land – A Noir Short Film by Axel Henneberg

 

A Room I Once Entered

Next up is a collaboration I did with David Gerard who goes by the name Ambientism.

David releases a collaboration album annually called “The Electronic Consortium” consisting of various artists he has collaborated with over the previous year.  David reached out to me to see if I would be interested, and I certainly was.

Here is A Room I Once Entered in which David and I collaborated

VR – Outward

As I’ve mentioned before, I’ve started working with Geoff Varosky on a collaboration project we’re calling “VR”.

Geoff currently produces and releases experimental ambient music, ranging from long slowing soundscapes to beat and heavily sampled ambient house via Musical Nature which is an ambient project in experimental sound.

Together, we are “VR”.

VR is obviously a combination of the initials of our last names (Varosky and Richie), but as most know, it is also the abbreviation for “Virtual Reality”.

Virtual Reality typically refers to computer technologies that use software to generate realistic images, and considering that we are both individuals who have been involved in software development and software architecture, it seemed a good fit for us as well.
VR (us) will bring you music that will immerse you in a virtual world of the mind, where our musical stories will be the backdrop for your imagination.

Here is a sample of the type of music you can hear from us in the not too distant future.

 

 

The Microsoft Cloud Show and Mastering the SharePoint Framework

Last, but certainly NOT least, I’ve been working with Andrew Connell and Chris Johnson on a couple of things over the past few months.

First, you were probably first introduced to me on this blog via my various SharePoint related posts I’ve made in the past.  Even though this site has morphed more into supporting my music, I hope you’ve decided to stick around 🙂 .

BTW, if your interested on where I’ll be placing more technical/SharePoint related content in the future…. be sure to check out code.krichie.com as that’s where I’ll be placing those things in the future.

I’ve known Andrew and Chris for many, many years and I’m super excited to inform you that they’ve chosen my music as the new theme music for their weekly podcast The Microsoft Cloud Show. I absolutely loved working on the piece of music they chose for the shows new theme, and upon listening to the first podcast using it myself, it was really cool to hear the specific sections of the piece they incorporated into the show. So go check out episode 186 right now and listen to them rip on me a bit and then geek out about home automation! :).

Secondly, Andrew recently started a new business venture called Voitanos. Voitanos is your host for on-demand technical training and educational resources for Microsoft’s Office 365, Microsoft Azure and cloud-related technologies. Whether you are looking to learn something new for a project, get up-to-speed on a new technology or level up your skill set, Voitanos is for you

The first set of deliverables Andrew is producing it is called Mastering the SharePoint Framework.  And guess what, it utilizes some of my music here and there for the background music!

I myself will be going through the Mastering the SharePoint Framework course, and I’m truly excited not only to be participating, but being a small part of the course material :).

Many thanks Andrew and Chris!

16 years

Lastly, this bit of news couldn’t come at a better time. Want to know how long I’ve been involved with SharePoint? Oh, just over 16 years.  Yep, 16 years ago today we announced Release to Manufacturing of SharePoint Portal Server 2001.

I remember taking a quick ramp up course on a product code named Tahoe in early 2000/2001 during my first tenure with Microsoft back in the day as it utilized the Web Storage System from Exchange.  At the time I was an Escalation Engineer for Outlook and Exchange.  Little did I know just how dramatic my life would change after that moment.

Happy Birthday SharePoint Portal server!

Be sure to also read Bill Baer’s post on the history of SharePoint right here.

That’s all for now! Back to a dedicated study day for myself.  I’ll be finishing up chapter 3 of the Mastering the SharePoint Framework course today as well!

– Keith

 

 

 

Back at Microsoft, and the Music won’t stop.

There’s been an awakening, have you felt it?

A long time ago, in a cubicle far, far away… Ok, maybe not so long ago, and not so far away, but nearly a decade ago I decided to leave Microsoft on a bit of a walkabout in search of my passion.

I entered the world as a professional software developer somewhere around 1993 – 1995. I always had a passion for it, and it allowed me to express my creativity in more than one way or another.  In 2000, I joined Microsoft as an Escalation Engineer. Though not a development position, I was honored to join the Microsoft family and the position still allowed me to use my development skills in my role when working on some of the most challenging issues the company faced. I initially debugged and supported Outlook and Exchange.

In 2001, I attended some training for a product code named “Tahoe” and became instantly intrigued.  As you may or may not know, SharePoint evolved from projects codenamed “Office Server” and “Tahoe” during the Office XP development cycle.

“Office Server” evolved out of the FrontPage and Office Server Extensions and “Team Pages”. It targeted simple, bottom-up collaboration.

“Tahoe”, built on shared technology with Exchange and the “Digital Dashboard”, targeted top-down portals, search and document management. The searching and indexing capabilities of SharePoint came from the “Tahoe” feature set. The search and indexing features were a combination of the index and crawling features from the Microsoft Site Server family of products and from the query language of Microsoft Index Server.

SharePoint Portal Server 2001 needed a place with the support organization, and since it utilized the Web Storage System that Exchange used, various engineers within the Exchange group were elected to help support this emerging product. After discussions with my manager, we determined I that I would join the very select few (Maybe only 3 Escalation Engineers in the US) to help debug and support customer issues with SharePoint. And the rest is history.

At the beginning of 2007, I decided to leave Microsoft and pursue some of my other passions. Since then, I have missed my Microsoft family and the work I performed debugging, tracing, and helping our customers.

SharePoint has grown and matured into an amazing product.

I am delighted and extremely happy to be returning to my Microsoft family as a Senior SharePoint Escalation Engineer.

The music will NOT stop.  My music is an essential part of me, and I will continue driving this passion of mine as well. Expect some exciting news on this forefront in the next couple of months or so. Many great things are in the works.

Always follow your dreams.  You will always have your ups and downs, that’s just part of life. But never give up, and align yourself with people and environments that respect you; embrace your skills; and challenge you to be the very best you can be.

I’m just Keeping the Dream Alive

Have an awesome day!

– Keith

 

 

SPUserCollection.Remove() throws misleading exception “Cannot complete this action”

 

Over the weekend we performed a User Migration of our primary SharePoint 2010 farm.  In our case, which is probably a quite common scenario, we had users from both the source and target domain that we were migrating actively using the system.  In our scenario, the “TARGET” domain is the company that acquired us and our portals in the “SOURCE” domain.  New users from the target domain needed to access our portals in the source domain, and our source domain users needed to continue business as usual until we were prepared to migrate source users into the target domain.

Of course, with any company acquisition, there are many levels of migration steps, and one of those for us was the users actual AD accounts were migrated months ago, so they use TARGET\user as their primary logon, but when accessing the SharePoint sites, they re-log in with their current SOURCE\user until those accounts in SharePoint are migrated, but this left a problem we had to work around, and that problem being that the users had hit SharePoint with their TARGET domain account, and thus had both a reference to their SOURCE domain account and their TARGET domain account in SharePoint.  You can’t call the SharePoint Migrate commands to migrate a user from the source to the target, if the target already exists.  It will fail since the target user already exists.

Therefore, what we needed to do delete the target domain instances of their account in SharePoint before migrating their source account. 

Doing that from the object model is a very simple process. You just enumerate over every site collection, and call SPUserCollection.Remove() using the SiteUsers collection of the RootWeb in the site collection.  The only problem that we ran in to, was something I’ve actually seen a long long time ago, but never thought to actually document the problem before.

 

Consider the following section of code:

  
foreach (SPWebApplication wa in SPWebService.ContentService.WebApplications)
{
  WritePurgeOutput("Examining web application: " + wa.Name);
  // Enumerate all site collections in the web application
  foreach (SPSite sc in wa.Sites)
  {
  try
  {
    // Get the root web, so that we can get to SiteUsers.
    // SiteUsers represents all users in the site collection.
    using (SPWeb web = sc.RootWeb)
    {
      foreach (SharePointUser user in users)
      {
        WritePurgeOutput("Removing login: " + user.LoginName);
        try
        {
          web.SiteUsers.Remove(user.LoginName);
        }
        catch (Exception ex)
        {
          WritePurgeOutput(string.Format("ERROR - purging User '{0}' " +
           "from site collection '{1}': {2} ", 
           user.LoginName, sc.Url, ex.ToString()));
        }
      }
    }
  }
  catch (Exception ex)
  {
    WritePurgeOutput(string.Format("ERROR - purging Users " +
      "from site collection '{0}': {1} ", 
      sc.Url, ex.ToString()));
  }
  finally
  {
    sc.Dispose();
  }
}

 

The foreach(SharePointUser user in users) section is a collection of user objects containing the information for the users we want to purge from the system.  We had a prepared list of all the users that were AD migrated, and the user collection information was their  login name in the TARGET\user formation. WritePurgeOutput() is just a method that’s going to …we… write purge output.

In testing, this worked flawlessly.   I had some of my test members in the site, and deleted them, then ran this code while some were still permissioned.   For those that were still permissioned, they were removed, and for those that didn’t exist anymore, it still just called SiteUsers.Remove() without any problems.  In production though, we ran into an interesting exception.

We started noticing the following exception being thrown when the Remove() call was made:

"Cannot complete this action.\n\nPlease try again."

Our first thought was there there was something wrong in the access rights granted to the account we were using while logged onto the server to run our tool. (See http://blog.krichie.com/2008/09/11/unrestricted-access-via-sharepoint-object-model-from-console-applications/) But we did see successful executions as well, so that didn’t appear to be the problem.

It turns out, that Remove() only throws an exception if the user truly had NEVER visited the site collection (or was added) and therefore, there was NO record in the Users table.

YET, when a user DOES exist in the Users table, but was previous deleted (the tp_Deleted column has a positive value), the Remove() method just silently returns.  In other words, the user TRULY does not exist as an active user for the site collection, but that users information still exists in the database associated to the site collection.  He’s just marked deleted.  This made us think that SPUserCollection.Remove() would just silently return when called for a login that didn’t exist in the site.

Instead, our logs were filled with the exception message noted above, and leading us down a path of misguided troubleshooting.

 

In the end, we modified the code to look something similar to the following:

 

  
foreach (SPWebApplication wa in SPWebService.ContentService.WebApplications)
{
  WritePurgeOutput("Examining web application: " + wa.Name);
  // Enumerate all site collections in the web application
  foreach (SPSite sc in wa.Sites)
  {
  try
  {
    // Get the root web, so that we can get to SiteUsers.
    // SiteUsers represents all users in the site collection.
    using (SPWeb web = sc.RootWeb)
    {
      foreach (SharePointUser user in users)
      {
        WritePurgeOutput("Removing login: " + user.LoginName);
        try
        {
          SPUser userexists = null;
          userexists = web.SiteUsers[user.LoginName);
          if(userexists != null)
            web.SiteUsers.Remove(user.LoginName);
        }
        catch (Exception ex)
        {
          if(ex.Message != "User cannot be found.")
            WritePurgeOutput(string.Format("ERROR - purging User '{0}' " +
             "from site collection '{1}': {2} ", 
             user.LoginName, sc.Url, ex.ToString()));
        }
      }
    }
  }
  catch (Exception ex)
  {
    WritePurgeOutput(string.Format("ERROR - purging Users " +
      "from site collection '{0}': {1} ", 
      sc.Url, ex.ToString()));
  }
  finally
  {
    sc.Dispose();
  }
}

 

So we look for the user in the collection, and if it throws an exception with a message of “User cannot be found”, we just eat that and move on.   If we did find the user, then we make the call to Remove().

A nice exception message of “User cannot be found” on the call to Remove() in the first place, would have been really helpful.

 

– Keith