1 0
post icon

What tools to install on a SharePoint 2010 developer box

I’ve built out SharePoint development environments many times but I’ve never really sat down and made a list of the tools I use before.   A good friend emailed me today and asked what tools I have on my SharePoint development box and it prompted me to put a list together.   I thought I’d share what tools fit into my day to day usage.

First a bit about the infrastructure and topology of my development environment.   I’ve got a dedicated VMWare ESXi 5.0 box in my basement with an i7-920, 24GB of ram, and 4x2TB hard drives in Raid 1+0.  I’m using an Adaptec hardware raid controller all inside of  a Super Micro tower.

With that box I’m able to run quite a number of virtual machines for a lot of different tasks beyond SharePoint development.   I’ve got a combination of Linux and Windows servers and clients setup for building and testing various applications.   A couple boxes are mainstays however and provide resources that are shared across the rest.   These are my domain controller and SQL box.   Both are running server 2008R2.   The SQL box has multiple SQL instances on it (2008R2 and 2012).   I have a couple of different SharePoint VMs and fire them up depending on what I’m working on.

When setting up the development box I always turn to AutoSPInstaller to actually install the SharePoint bits.   It automates the process and makes it repeatable.   It can handle installing the prequisites, configuring the farm, configuring service applications, creating web applications, creating site applications, etc.   It is really very powerful and saves a ton of time in setting up a new environment.   You can get it at http://autospinstaller.codeplex.com/.

 

For my primary 2010 development box I also have the following tools installed:

And while I hesitate to admit it given how much I hate the headache it can cause, I do also use SharePoint Designer from time to time.   While I’m a firm believer that you shouldn’t do SharePoint customizations with it (everything should be done via Visual Studio and packaged into a WSP) the truth is that SharePoint Designer is really good for working on masterpages.   If you’re doing branding work then I’d recommend it be included into your tool arsenal.

Leave a Comment
post icon

Comparing Office 365 and Google Apps

I’ve used Google Apps for many years given that it is a reliable way for me to host my personal email for free.   I own my own domain (obviously) and I enjoy having the address jason@vallery.net.    Since the surname Vallery isn’t terribly common I’ve also had the occasion to setup email addresses for close and distant family members who wanted the novelty of name@vallery.net.    With the free version of Google Apps you can create up to 10 accounts which was more than enough for my limited needs.

Given my role in technology I’ve also had the occasion to help friends and family with their own personal web needs.  Over the last few years I’ve helped several folks get off the ground with a basic website and email on their own domain for either personal or small business use.   Every single time I’ve turned to Google Apps as the solution for them to host their email, calendar, etc.

Now that Office 365 has been available for a while I decided to evaluate both my own usage of Google Apps as well as what tool I’m recommended to people who ask me.   What I’ve found has redefined the problem a bit and changed the way I approach the answer.

For my own use I migrated my domain over to Office 365 last fall (around November 2011 I think).   I was pleased with the tools that Microsoft offered to accomplish this.   It was a pretty simple task for me to import the users, migrate their email, and then send them their new login credentials.   I had a little bit of effort in walking the family members through configuring Outlook and/or their Phones but it generally went well.

There were a few things that I immediately noticed were missing however:

  • No custom CNAME for the login page.   Everyone had got used to logging in at https://mail.vallery.net/.   Now I have to have them go to https://portal.microsoftonline.com?   What is that about?   It would have made the transition quite a bit simpler if I could have just remapped the CNAME so the URL wouldn’t have changed for the users.

 

  • DNS management is tricky.   Microsoft has the expectation that I’m going to just hand them over my domain and use their DNS servers.   No way Microsoft!!   I use my domain for a lot more than email and instant messaging.   I’ve got a number of complex records that need to be maintained.  I want the ability to dynamically update those records via an API.   That is why I turned to paying for the premium service from dyndns.org to host my DNS.   With the limited capability that Microsoft is offering for DNS management there was no way I was going to switch to their name server.   As a result I had to “trick” their system by looking up all of the records that they would have inserted on my zone had they been hosting it and then create them on dyndns.org’s server.   This wasn’t a big deal but shortly after I setup my account those records changed and my service stopped working.   I had to go and repeat the process.   I understand why from a stability perspective Microsoft wants to be able to handle the DNS for the domain but that just isn’t practical until their tools are as robust as other offerings.

 

  • Of course the biggest difference is cost.   For free with Google Apps you get 10 mailboxes, calendar, cloud storage for documents, instant messaging,  SAML claims support (ADFS),  and a marketplace full of additional capabilities.  For free from Microsoft you get….  nothing.    The cheapest Office 365 plan is $4/month/user and that only gets you exchange.   For $6/month/user you can include Lync and a SharePoint site collection.   You still don’t get full enterprise features like sync with AD, true SharePoint (mysites, multiple site collections, etc).   That doesn’t kick in until you get up the E1 plan.  Current Office 365 pricing and plans: www.microsoft.com/en-us/office365/compare-plans.aspx

 

So what does that mean?   For someone like my cousin who has a classic car restoration business (http://chclassics.com) it would make no sense for him to pay $6/month/user for email.   He has five employees and only two of those actually use email.   With Google Apps he can get free hosting for his email and calendar and it meets 100% of his needs for free.   I can’t help but recommend that he go that route.

For someone like myself who lives in his email it makes more sense for me to go Office 365.   I mentioned the things that Office 365 was missing above but I didn’t mention what it brings.   This is exchange.   The most powerful mail server that has ever existed.   I get to push my email down to Outlook.  No more IMAP.   I get 25GB of storage to archive and search my old messages.   I get a SharePoint site for hosting my family’s documents.   I have a shared One Note with my wife with all kinds of stuff in it (tasks, shopping list, recipes, finances, etc).

So – if you’re a small business with a technical savvy audience that can appreciate the real value that having a true exchange/SharePoint based solution can bring then obviously Office 365 is the way to go.   If you need the very basic functionality and are watching your expenses very closely than I’d say stick with Google Apps.   For me the $6/month/user I’m paying is a small price to pay for the functionality that I get.   I will certainly continue to recommend Google Apps though for people like my cousin who just want to get their email.

Obviously neither Google or Microsoft are making their money off customers like myself or my cousin.   That isn’t the market that either of them are after.   The under 10 user customer isn’t even on the Microsoft radar.   I think from a public relations perspective though it would benefit Microsoft to consider introducing a plan that would directly compete with the free Google Apps plan.  Who knows…  maybe some day my cousins 5 person business will turn into a 50 person business?  Wouldn’t it be easier for him to continue using Google Apps then switch to Office365 at that point?

Leave a Comment
post icon

Terrible customer service from Microsoft

I’m obviously a big proponent of Microsoft and the Windows Phone platform.   I’m not one to badmouth them usually but I’m very upset at the moment.   Since I’ve been developing WP7 applications I convinced my wife to help with testing by swapping her phone.  During the recent Smoked by Windows Phone Challenge she reluctantly exchanged her iPhone 4 for an HTC Titan.  She likes the phone but it turns out the specific device she received has a malfunctioning microphone.   When she is on the phone she sounds like she is under water or has a sock in her mouth.   As a phone it is pretty much unusable.   The problem is fairly well documented

http://pocketnow.com/windows-phone/htc-investigating-titan-voice-quality-problems

http://community.htc.com/na/htc-forums/windows-phone/f/174/t/14950.aspx

I assumed this would be a straightforward swap to get a replacement phone.  She took her phone over to the local Microsoft store and explained the problem.   They told her that they couldn’t do anything about it and she would need to contact AT&T.   I called AT&T and they explained because the issue happened within the first 30 days there is nothing that they can do.  It is the responsibility of the original point of purchase to exchange the device or refund the money (we didn’t pay anything).  If it was after 30 days the best they could do would be to give her a refurbished phone.  I called back Microsoft and begged with the store representative to give us a new phone or her old iPhone back.  The best he could offer me was if (and according to him it was a VERY big if) they managed to get more HTC Titans in he would give me a call and we could exchange it.   He said this could be weeks or may never happen at all.  He suggested I contact HTC for warranty repair.  I called HTC and they explained that the best they could do is have us ship them the device and they would repair it and ship it back.   This could take up to 6-8 weeks.

So – my choices are either my wife goes without a phone for several weeks or I drop $500+ on an out of contract replacement phone.   She is furious because she didn’t want to switch in the first place and just 2 weeks ago she had a perfectly functioning iPhone 4.

Microsoft – If you want to be successful in the consumer space you need to work on your customer service skills. I would have NEVER had this experience in an Apple store.

Update 5/16/2012 — Derek, the store manager at the Park Meadows location, called me yesterday.   It sounded like he had probably read my blog article based on what he was saying.   He offered to swap my wife’s Titan for a Samsung Focus S.  I gladly took him up on the offer.  I went and picked it up today without incident.   I’ve had a Focus S since it launched last fall and I’ve been very happy with it.

Leave a Comment
post icon

Organizing your music with Powershell

So my wife just swapped her iPhone 4 for a new HTC Titan Windows Phone thanks to the recent Smoked by Windows Phone challenge.   The first thing she asked me about is how to get all of her music over to the new phone.  I’ve been using Zune Pass quite happily for a while however she has still continued to buy music from iTunes.   Her library, combined with the one that I had been amassing over the last several yeas before Zune Pass, meant that we have quite a bit of owned music.  Unfortunately like my pictures in the previous blog post thanks to multiple system backups, multiple computers, and the general fact that most of my files are in a sad state of unorganized I’m left with no consolidated music library.

Powershell to the rescue!!

I took the basic idea from the picture script I posted earlier and combined it with an open source DLL I found online which can query the metadata from a music file.  Grab the latest Windows package from http://download.banshee.fm/taglib-sharp/ and extract the taglib-sharp.dll file into the same folder as your powershell script.  

Here is the script –  it will remove duplicates and create a new folder with all of your music across multiple locations containing the unique files in the directory hierarchy ARTIST\ALBUM\TITLE.

#This is really divided into two scripts.   The first one searches for our audio files and creates and MD5 hash of each one. 
#Merging them all into the same folder allows us to eleminate duplicates.
#The second script reads the audio tags and puts them back out into folders based on artist, album, and title.


#Function to calculate the MD5 hash of a file
function Get-MD5([System.IO.FileInfo] $file = $(throw 'Usage: Get-MD5 [System.IO.FileInfo]'))
{
    # This Get-MD5 function sourced from:
    # http://blogs.msdn.com/powershell/archive/2006/04/25/583225.aspx
    $stream = $null;
    $cryptoServiceProvider = [System.Security.Cryptography.MD5CryptoServiceProvider];
    $hashAlgorithm = new-object $cryptoServiceProvider
    $stream = $file.OpenRead();
    $hashByteArray = $hashAlgorithm.ComputeHash($stream);
    $stream.Close();

    ## We have to be sure that we close the file stream if any exceptions are thrown.
    trap
    {
        if ($stream -ne $null) { $stream.Close(); }
        break;
    }

    $md5 = ""
    foreach ($byte in $hashByteArray)
      {
        $md5 = $md5 + $byte.ToString("X2");
      }
return $md5;
}

#Figure out where we are at and if there is a subfolder called output.  If not we will create one.   This is where we will put all of our images.
$currdir =  split-path -parent $MyInvocation.MyCommand.Definition
$outputdir = $currdir + "\output\"
if (!(Test-Path -path $outputdir))
{
    New-Item $outputdir -type directory
}

$tmpdir = $currdir + "\tmp\"
if (!(Test-Path -path $tmpdir))
{
    New-Item $tmpdir -type directory
}

#Using Get-ChildItem we search for all files matching our extension recurisvley from the location of the script down.
$files = Get-ChildItem -Exclude $outputdir -Recurse -Include *.m4a,*.mp3,*.wma

#We're going to keep track of how many files we process and put a unique number in the file for each one (eliminates all possibility of duplicate filename)
$i = 0;
foreach($f in $files) {
    #Increment our counter
    $i++;

    #Calcualte the MD5 of the original file so that we can look for duplicates later
    $md5 = Get-MD5($f);

    #The target filename will be the output directory with the MD5 hash as the filename and the original file extension
    $targetname = $tmpdir + $md5 + $f.extension;

    #Write the file to the output folder, if there are duplicate files Copy-Item's default behavior is to overwrite.   This eleminates the dupes.
    Copy-Item  $f.fullname $targetname

    #Could delete the old version, I'm leaving it as a backup so I've commented this out.
    #Remove-Item $f.fullname;    

    Write-Output $targetname

    #Write percent compelted of current operation
    $percent = [System.Math]::Round((($i / $files.Count)  * 100), 2)
    Write-Progress -Activity "Calculating hashes..."  -PercentComplete $percent -CurrentOperation "$percent% complete" -Status "Please wait."
}

#Now that we've zapped our duplicates we can move the files out to their target locations
#We loop through them again extracting the important bits from the audio tags
#Format will be /$artist/$album/$title.Extension

#Load the taglib library assuming the DLL is in the same folder (be sure to Unblock it).  
#You can get the DLL from http://download.banshee.fm/taglib-sharp/ -- I'm using 2.0.4.0 which was latest at time of writing this
[Reflection.Assembly]::LoadFile( (Resolve-Path ".\taglib-sharp.dll") )

#List of characters that we can't use
$invalid_characters = "[{0}]" -f ([Regex]::Escape([String][System.IO.Path]::GetInvalidPathChars()) + "/", "\", "*", "?", ":")  

$files = Get-ChildItem $tmpdir -Recurse
$i = 0;
foreach($f in $files) {
    $i++;

    #Load up the audio file into TagLib
    $audiofile = [TagLib.File]::Create($f.fullname);                

    if($audiofile.Tag.AlbumArtists) {
        $artist = [string] $audiofile.Tag.AlbumArtists
    } elseif ($audiofile.Tag.FirstArtist) {
        $artist = [string] $audiofile.Tag.FirstArtist
        $audiofile.Tag.AlbumArtists = $artist
        $audiofile.Save()
    } else {
        $artist = "Unknown"
    }

    if($audiofile.Tag.Album) {
        $album = [string] $audiofile.Tag.Album
    } else {
        $album = "Unknown"
    }

    if ($audiofile.Tag.Title) {
        $title = [string] $audiofile.Tag.Title
    } else {
        $title = "Unknown"
    }

    $artist = [string][Regex]::Replace($artist, $invalid_characters, '')
    $album = [string][Regex]::Replace($album, $invalid_characters, '')
    $title = [string][Regex]::Replace($title, $invalid_characters, '')

    #Where are we putting the new file?
    $targetname = $outputdir  + $artist + "\" + $album + "\" + $title  

    #Make sure that our folders exist (one for each month under the year) and if not create them
        if (!(Test-Path -path ($outputdir + $artist)))
        {
          $output =  New-Item ($outputdir + $artist) -type directory
        }

        if (!(Test-Path -path ($outputdir + $artist + "\" + $album)))
        {
          $output =  New-Item ($outputdir + $artist + "\" + $album) -type directory
        }

        $dupe = $true
        $x = 1
        While($dupe) {
            $x++
            if (!(Test-Path -Path ($targetname + $f.extension)))
            {
                $targetname = $targetname + $f.extension
                $dupe = $false
            } elseif (!(Test-Path -Path ($targetname + "-" + $x + $f.extension)))
            {
                $targetname = $targetname + "-" + $x + $f.extension
                $dupe = $false
            }
        }

        #Move the source file to it's new home. 
        Move-Item -Path $f.fullname -Destination $targetname
        Write-Output $targetname

        #Write percent compelted of current operation
        $percent = (($i / $files.Count)  * 100)
        Write-Progress -Activity "Moving files..."  -PercentComplete $percent -CurrentOperation "$percent% complete" -Status "Please wait."
    }
Leave a Comment
post icon

Organizing lots of pictures

If you’re anything like me you’ve been taking digital pictures for a long time now.   You’ve used various strategies and tools for organizing them over the years.   You’ve gone through several computers and moved the files around countless times.   Where does that leave you?  With an unorganized mess.

With library software like Picasa you can import all of those pictures and you can have some semblance of organization by way of the user interface but it doesn’t really solve the problem at the core.   The files are a mess.

I wanted to find a way to give a consistent filename to all of my pictures, organize them into folders based on the month and year they were taken, and remove duplicates.   At first it sounded like a tall order as I couldn’t find any off the shelf tools to do this.  Thankfully with just a little bit of time in Powershell I was able to put together a script that accomplished this for me.

 

The script does the following:

    • Identify all of the existing pictures
    • Query the EXIF data
    • Calculate an MD5 has of the file
    • Create a new copy based on the data in a “staging” folder
    • Parse the new file name to get the MD5 and look for duplicates
    • Delete the duplicate version
    • Move the files to the YYYY\MM folders

 

The first task of querying the EXIF data of files was actually the hardest.   I found a couple of blog articles that touched on this.   The synopsis is that you have to use the .NET System.Drawing DLL.   We can use Get-ChildItem to recurse a directory structure looking for files of a specific type.   For each file that we find we instantiate a new Bitmap object which contains the EXIF properties.   We can extract and update these.   I thought it might be useful to store the original path as a “Comment” in the EXIF in case it contained some relevant information that I later want to turn into a tag.

Below is the complete script.

#Load the .net System.Drawing assembly for examining the EXIF data of the pictures.
[reflection.assembly]::loadfile( "C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll")

#Function to calculate the MD5 hash of a file
function Get-MD5([System.IO.FileInfo] $file = $(throw 'Usage: Get-MD5 [System.IO.FileInfo]'))
{
    # This Get-MD5 function sourced from:
    # http://blogs.msdn.com/powershell/archive/2006/04/25/583225.aspx
    $stream = $null;
    $cryptoServiceProvider = [System.Security.Cryptography.MD5CryptoServiceProvider];
    $hashAlgorithm = new-object $cryptoServiceProvider
    $stream = $file.OpenRead();
    $hashByteArray = $hashAlgorithm.ComputeHash($stream);
    $stream.Close();

    ## We have to be sure that we close the file stream if any exceptions are thrown.
    trap
    {
        if ($stream -ne $null) { $stream.Close(); }
        break;
    }

    $md5 = ""
    foreach ($byte in $hashByteArray)
      {
        $md5 = $md5 + $byte.ToString("X2");
      }
return $md5;
}

#Figure out where we are at and if there is a subfolder called output.  If not we will create one.   This is where we will put all of our images.
$currdir =  split-path -parent $MyInvocation.MyCommand.Definition
$outputdir = $currdir + "\output\"

if (!(Test-Path -path $outputdir))
{
    New-Item $outputdir -type directory
}

#What files should we look for?   Typically this would be *.jpg.
$ext = "*.jpg"

#Using Get-ChildItem we search for all files matching our extension recurisvley from the location of the script down.
$files = Get-ChildItem -r -Include $ext

#We're going to keep track of how many files we process and put a unique number in the file for each one (eliminates all possibility of duplicate filename)
$i = 0;
foreach($f in $files) {
    #Increment our counter
    $i++;

    #Load up the .net system.drawing.bitmap object for the current file.  We will use this to access and update the exif data.
    $img=New-Object -TypeName system.drawing.bitmap -ArgumentList $f.fullname;

    #We grab up the camera date, height, and width.  We use try catch in case the property isn't availabe and set a default value.
    #For more details on properties available check:
    #http://blogs.technet.com/b/jamesone/archive/2007/07/13/exploring-photographic-exif-data-using-powershell-of-course.aspx

    Try
     {
        #The value is a byte array which we need to convert (assuming ASCII character set)
        $date = [System.Text.Encoding]::ASCII.GetString($img.GetPropertyItem(36867).Value);
     }
    Catch [system.exception]
     {
        #Default value in case we can't access the EXIF
        $date = "0000:00:00 00:00:00";
      }

    #Grab the height and width of our object
    $height = $img.Height;
    $width = $img.Width; 

    #The date is returned as a null terminated string with spaces and colons in it.   We replace all of these with dashes to make it filename friendly.
    $date = (($date.Replace("`0", "")).Replace(" ","-")).Replace(":","-");

    #Calcualte the MD5 of the original file so that we can look for duplicates later
    $md5 = Get-MD5($f);

    #The target filename will be the output directory with the variables concatnated in the below format.
    #Format will be YYYY-MM-DD-HH-MM-SS-WIDTHxHEIGHT-MD5-ID.Extension
    $filename = $outputdir + [string]::Format("{0}-{1}x{2}-{3}-{4}{5}", $date, $width, $height, $md5, $i, $f.extension);

    #We want to save the current path as a comment so we create a new property of type 40092 (comment)
    $property = $img.PropertyItems[0];
    $property.Id = 40092;
    $property.Type = 1;

    #It needs a string array so we pass in the current path ($f.fullname) and convert it to an array
    $property.Value = [system.text.encoding]::Unicode.GetBytes($f.fullname + ":" + $md5);
    $property.Len = $property.Value.Count;
    $img.SetPropertyItem($property);

    #We will save our image from memory in the path of our new file.
    $img.Save($filename);
    $img.Dispose();

    #Could delete the old version, I'm leaving it as a backup so I've commented this out.
    #Remove-Item $f.fullname;

    #Let the user know what the current status is and which files are being moved.    
    Write-Output "Copying $f to $filename";
}

#This is a one liner to split on filename, find the duplicates by MD5, ignore the first result and then delete the rest
#The 7th item in the filename format is the MD5 hence the hard coded index
$o = Get-ChildItem $outputdir `
| Select-Object @{Name="MD5";Expression={($_.Name).Split("-")[7]}}, @{Name="Filename";Expression={$_.Fullname}} `
| Group-Object md5 `
| ?{ $_.Count -gt 1 } `
| % {($null, $rest) = $_.Group; $rest;} `
| Select-Object Filename  `
| % { Write-Output "Removing duplicate $_"; Remove-Item $_.Filename }

Write-Output $o

#Now that we've zapped our duplicates we can move the files out to their target locations
#We loop through them again extracting the important bits from the filename
#Format will be YYYY-MM-DD-HH-MM-SS-WIDTHxHEIGHT-ID.Extension
$files = Get-ChildItem $outputdir
$i = 0;
foreach($f in $files) {
    $i++;

    #split string on dash and create an array of attributes
    $name = ($f.name).split("-");
    $year = $name[0];
    $month  = $name[1];
    $day = $name[2];
    $hour = $name[3];
    $min = $name[4];
    $sec = $name[5];
    $size = $name[6];
    $md5 = $name[7];

    #Where are we putting the new file?
    $targetname = $outputdir  + $year + "\" + $month + "\" + [string]::Format("{0}-{1}-{2}-{3}-{4}-{5}-{6}-{7}{8}", $year, $month, $day, $hour, $min, $sec, $size, $i, $f.extension);

    #Make sure that our folders exist (one for each month under the year) and if not create them
    if (!(Test-Path -path ($outputdir + $year)))
    {
        New-Item ($outputdir + $year) -type directory
    }

    if (!(Test-Path -path ($outputdir + $year + "\" + $month)))
    {
        New-Item ($outputdir + $year + "\" + $month) -type directory
    }

    #Move the source file to it's new home.  -Force tells it to overwrite if the file already exists.
    Write-Output "Moving $f to $targetname";
    Move-Item -Path $f.fullname -Destination $targetname -Force
}

 

 

Here are a couple of references that I found helpful in building this script:

 

http://blogs.technet.com/b/jamesone/archive/2007/07/13/exploring-photographic-exif-data-using-powershell-of-course.aspx

http://blog.codeassassin.com/2007/10/13/find-duplicate-files-with-powershell/

Leave a Comment
post icon

Building a near silent PC

I spend 12 to 14 hours a day in my office on any given weekday.   My productivity on my PC is vital and as a result I’m not afraid to invest in good equipment.   For the last several desktop workstations that I’ve used I’ve assembled the computer myself from various components.  One of my challenges with this approach is the amount of noise produced.   The DIY computer market is targeted at the 19 year old gamer who cares more about how many neon lights his computer has than how quiet it is.

As a software developer and power user I demand a very performant machine.  I’m constantly running virtual machines, visual studio, graphics design applications, etc.  I needed a PC that can deliver while also looking good and remaining silent (or near silent).

I don’t have a decibel meter at hand so I can’t give you empirical measurements on exactly how loud my old computer was.   Anecdotally though it was enough to upset my wife because when she would call for my attention I wouldn’t hear her.  It really had become a problem and the noise was impacting my mood and productivity.  

I decided to set out on solving my noise challenges and spend as little money as possible while doing it.   One of my main concerns was ensuring that I would continue to have 4 DVI ports that can uniquely configure each monitor.   I’m a firm believer that the more screen real-estate you have the more productive you are.   I’m on the fence about the value of the 4th monitor but I really do think that 3 is the minimum I could ever be happy with.   I typically use the 4th display for my music app or I hook it up to my laptop when it is on my desk.  In order to drive 4 separate displays however there aren’t many single card solutions available.   In the past I’ve always had to have 2 separate video cards and I expected that would continue.

What I started with:

  • i7-920 processor
  • 12GB of Corsair DDR3 memory
  • Crucial 256GB C300 SSD (6Gbs)
  • Asus P6X58D Premium Motherboard
  • 2 x Nvidia GTS 240 video cards (2 monitors on each)
  • Antec Lanboy Air case
  • Antec 850w power supply

The computer itself was actually fairly powerful.   I reviewed benchmark sites and realized that the cost of upgrading to a Sandy Bridge i7 isn’t really justified given the minimal performance increase.   I found this conclusion interesting given that I’ve had the i7-920 for over 2 years.   Previously I had a general rule of thumb to replace my processor and supporting components every 2 – 3 years.   I generally feel the pace of processor innovation has slowed.   I decided that I would retain the motherboard, processor, memory, and hard drive.   All of which would continue to work fine in my new silent PC.  I will need to replace the case, CPU cooler, power supply, and video cards.

Looking at the above starting point the first and obvious place to start is the Antec Lanboy case.   That thing is completely open and offers zero noise isolation.  I bought it without thinking because it was on sale at Micro Center.   In reality it was a very poor choice for my scenario.  

 

When selecting a new case my primary criteria were:

  • Clean looking and professional design -  no cut outs, neon lights, plexiglass panels, giant fans, etc

 

  • As small as possible – Even though I have a full size ATX board I don’t need water cooling, 15 hard drives, 4 fans, and 3 optical. I just want the ability to mount my SSD, one optical drive, and maybe an additional 3.5” SATA drive for backups.

 

  • Either powder coated or aluminum -  I don’t think the raw insides of a steel case look very good. I wanted a very high quality case and to me that meant attention to detail both on the inside and out.

 

  • Quiet! -  Ideally the case would have built in noise shielding or padding to help me on my mission

 

  • Top mounted power supply – Given that I intended to use a fanless power supply I wanted the opening at the top of the case to allow for passive heat dissemination.

 

  • Good cable management to allow for airflow and to keep everything organized

 

I spent a significant amount of time going over the reviews of a number of cases from Lian Li, Antec, Fractal Design, Thermaltake, etc.  Cost wasn’t a significant concern although I couldn’t ignore it completely.   I short listed the following cases:

 

 

Fractal Design Define XL Titanium Grey w/USB 3.0  – $149


image

Pros:

Clean style
Noise reduction built in
Cable management

Cons:

Size (very large at 22.10" x 9.13" x 22.05" or
4,150 cu in.)
Bottom mounted power supply
Inside not powder coated

 

LIAN LI PC-90 Black Aluminum ATX Full Tower – $199

 

image

Pros:

Aluminum body
Lian Li (great reputation)
Very professional looking

Cons:

Size (still large at 19.25" x 9.06" x 20.16" or
3,516 cu in.)
Bottom mounted power supply
No explicit noise insulation, large grate in front might allow sound to escape.

 

 

Antec Sonata Series SOLO II Black Steel  – $129

 

image

Pros:

Top mounted power supply
Fully powder coated inside and out
Very professional looking
Built-in noise absorption panels
TrueQuiet fan included

Cons:

Size (still large at 18.5" x 8.1" x 17.3" or 
2,592 cu in. but by far the best of the 3)
I would prefer aluminum
USB 3.0 header doesn’t work with my motherboard

 

Given the choices available it was a pretty easy decision to go with the Antec Sonata Solo II.   I really wanted to find a Lian Li case that I would fall in love with.  I just couldn’t find one that had everything important to me.  The general state of computer cases bothers me in that so many of them are targeted to the gaming market.   These high end professional cases are rare especially one that can accommodate a full size ATX motherboard.

 

With the biggest decision out of the way I still needed to get power supply, CPU fan, case fan, and most importantly video cards sorted.

I settled on the following components in addition to what I already had:

    Product

    Comments

    Qty

    Cost

    Antec Sonata Series SOLO II Black Steel See above 1 $129.99
    PowerColor Go! Green HD 6750 passive cooled video card The most significant causes of noise in my current configuration was the fans on the GPU I wanted to find a DirectX 11 capable card that was also fanless. I have no need to play games but I also didn’t want to sacrifice significantly on video performance. This card was a good best of both worlds solution. 2 $139.99
    Antec TrueQuiet 120mm case fans I was concerned about the heat in the case with the two fanless GPUs next to each other. I decided to put in these extra fans in the slots provided by the Antec Solo II. They are super quiet and controlled by my motherboard so the majority of the time they aren’t even running. 2 $14.99
    Cooler Master V8 RR-UV8-XBU1-GP CPU Cooler This thing looks cheesy but it sits inside the case and isn’t visible. The cooler is massive but very effective and quiet. I went with it based on the many positive reviews. I’m not disappointed. My processor sits at around 50 degrees Celsius the majority of the time. 1 $49.99
    Seasonic SS-460FL Active PFC F3 460W Fanless power supply This is a great passive cooled powersupply. My only complaint was the packaging. Why the heck do I need a felt bag to carry it? I can’t imagine a case where I would want to do that. It seems like a waste and could have shaved a few dollars off the price. 1 $109.99
    Total:     $599.93

 

 

Summary:

 

So after all of that what did I end up with?   A nearly silent PC with a WEI score of 7.3.  The PC is pretty much completely silent.   The only time I hear anything is when I’m running at very high CPU load and the fans kick up their RPM.   I do have my CPU fan and all 3 case fans hooked up to my motherboard to allow it to control the speed.   In the Asus bios you can choose a fan profile for each fan.   All of mine are set to “silent”.    Typically I’m running in the mid 50 degree Celsius range on the CPU and the low 70s on the GPU.   I’m sure if I cranked up the fan speed a bit I could bring these down further but it hasn’t been enough of an issue to justify it.

 

WEI Score:

 

image

 

Real Temp:

 

image

 

imageimage

Leave a Comment
post icon

And we’re back…. On wordpress

So my fairly short lived experiment with migrating my Blog to SharePoint is over.   As much as I love SharePoint it really isn’t a great platform for public blogging, at least using the out of the box blog template.

There are some major limitations that caused me to switch back:

 

  • Because the solution runs in the sandbox I can’t make any outbound HTTP requests from my custom code.  This means that even if I wanted to write a custom comment handler to use a spam filter like Akismet, I can’t.   The result was that I was getting hundreds of spam comments on my blog. 
  • There is no URL rewrite support so all of the URLs on the new blog were simply “Post.aspx?ID=XX”.   This is crap for search engine optimization.
  • The comment capability doesn’t allow for anonymous users to specify their name and email address.   This meant that all comments were anonymous.

Overall it was a fun experiment and I learned a lot about sandbox solutions and online hosting.   I think I’ll stick to wordpress at least for now though as I have considerably more flexibility with it.

For historical purposes though I still have the Visual Studio project available that I used to create the sandbox solution here:  http://vallery.net/wp-content/uploads/2012/01/ValleryBlog.zip

Leave a Comment
post icon

Blog migration to SharePoint

 

You can find the source code for this entry at:  http://vallery.net/wp-content/uploads/2012/01/ValleryBlog.zip

So I decided to migrate my blog from WordPress to SharePoint.   The motivation was driven primarily out of wanting to “eat my own dogfood”.    Given that most of the work I do and the posts on my blog all have to do with SharePoint I thought it would be appropriate to actually host my blog with SharePoint.  

I decided to seek out a hosting provider which specializes in “SharePoint in the cloud” given that my blog is high enough traffic and important enough to me that hosting at my house isn’t an option.   I first turned to Microsoft’s Office 365 service given that I’m already hosting my personal email with them.    I was disappointed to learn that you currently cannot host a public facing website with anonymous access.   They require the site to be secured which wouldn’t work for a blog.

I emailed a couple of the other community hosting options and got a very nice reply from FPWeb.   One of the services they offer gives you a single site collection on SharePoint Foundation which you can optionally give anonymous access to.   The site is limited in terms of which SharePoint features are available but they did offer the blog template.  If you’re not familiar with the differences check out this great guide which details the plans that are available.   The site provided uses SharePoint hostname site collections which allows me to have a fully qualified domain name (http://blog.vallery.net/) point to a single site collection on their web application.  

For my use case there were a few limitations that bit me:

  • Deployed custom solutions must fit into a “Sandboxed Solution”.    This is true for any of the non-dedicated online SharePoint option though so not an issue with FPWeb specifically.    This means that many of the things I’m used to doing for my customer’s on-premise installations are not possible in the cloud.   Microsoft has a good list of the limitations of SandBoxed solutions worth reading.  The things I missed the most are:
    • Ability to create custom delegate controls.    This made doing a custom searchbox a bit more difficult and less flexible than I’d like.
    • Ability to integrate with external systems.   My current WordPress based blog will post to twitter automatically when I write a new article but given that no external HTTP requests are allowed I can’t write an event receiver to do that for me.
    • I have to deploy all style assets to the SharePoint “Style Library” because I can’t write to the file system.    This could potentially have a negative impact on performance because now they live in the database.
    • I wanted to create a few custom controls to handle some of the style elements.   For example the banner on the site isn’t as flexible as I’d like.   It should really pull the title, url, and description from SPContext.current.web.   I had to hardcode them into the masterpage which means my solution isn’t portable.
  • Since FPWeb only provides SharePoint Foundation it makes branding more difficult.   There are a number of capabilities found in the enterprise publishing features that I typically use with my customers which were unavailable to me. 
    • In a custom masterpage you can use the SPUrl object to find a the URL of the site collection or site in order to reference your style library (to include CSS, JS, and images on the page).   This is not available if you don’t have enterprise so I had to hard code the path to the Style Library into the masterpage.   On my development box I created a blog site collection in a managed path off the root which made the path different than my site here at FPWeb (which is the root site collection).   This caused me to have to make a quick change every time I switched from my dev box to pushing out the solution to FPWeb.
  • Search is limited given that it is only SharePoint Foundation.  This is fine because I only need a site scoped search anyways.   The trouble of course is that it turns out the control that is used is very different.   I styled the Enterprise version since that is what I had on my dev box.   Once I deployed to FPWeb I discovered that none of my styles worked.   I had to go back and refactor for the foundation search box.   It wasn’t a huge issue but it took me a while to figure out why my styles weren’t working!

Once I got my solution done with my custom style I needed to get all my old content off my WordPress blog and onto SharePoint.   I had some good conversations with Metalogix at their booth during the SharePoint conference in Anaheim so I was already familiar their "Migration Manager for Blogs and Wikis" product.   They were kind enough to give me a trial key which was enough to migrate my posts and comments from wordpress across.   The process was painless and just required confirming the source and destination.   It was able to capture metadata as well like category which was handy.  

I did discover a few issues with the way the data was migrated though.  I realized that the blog author for all of the posts and comments was listed as me.   I guess this make sense since the author field is tied to a people picker and needs to be a person.   None of the comment authors in wordpress are users in my SharePoint environment obviously.    Metalogix handles this by creating a couple of extra columns on the comments list which store the original comment author, name, and email address.   I plan on writing a custom XSLT file and view to parse this at some point to place this information onto the page.  I’ve also included these fields on the new comment dialogue so I can capture it for future comments.  For now though I’m listed as the comment author for all of the comments.

The only issue I had with the Metalogix tool is the moving of images.   This could easily have been my fault as well so I don’t want to blame the tool.   My posts had a number of embedded images which WordPress stored in the wp-content folder.   My expectation would have been that Metalogix would have grabbed those files and put them into SharePoint and updated the references.   It even looked like it attempted to do that however I received a bunch of error messages which indicated failure.   My images are still linking to their original source on my WordPress site (which is still up) so they are not broken.   One of my todo items is to migrate those across by hand and then update my old posts that reference them.     This will give me an opportunity to clean up my old posts anyways which I’ve been meaning to do for a while.

With everything up and running I put 301 redirects into the .htaccess file on my WordPress server for each post.   I pulled out a list of all the posts from the SharePoint list and matched them up to their original URL (which thankfully Metalogix stores in an additional column for me).   With all of these URLs known I’m able to redirect the deeplinks to their specific posts.   WordPress has the handy SEO optimized permalinks which SharePoint does not.

Overall I’m very satisfied with both FPWeb and Metalogix.  Without either of them this project would have been significantly more difficult.   If you can accept the limitations of hosting your SharePoint site in a shared environment then I highly recommend FPWeb.

In case anyone is interested in the actual development work that was involved with the branding in all this I’ve posted my Visual Studio project.  In total I spent about 15 hours on the entire project over my Thanksgiving weekend. You can download the project at http://vallery.net/wp-content/uploads/2012/01/ValleryBlog.zip.

Leave a Comment
post icon

Disable email notifications in SharePoint 2010

Out of the box in SharePoint 2010 all users who have a profile are also defaulted to having email notifications set to “on”.   This might make sense in a small scale implementation but for my customer that was unacceptable.  I created a powershell script that iterates through the user profiles and turns the notifications off.  This script is similar to ones I’ve posted before for working with the user profile however it uses different fields.  The SharePoint field is called SPS-EmailOptin. This field disables both SharePoint and NewsGator emails.

Of course in future releases these field names might change so you should verify before using this script.  In my case this was SharePoint 2010 October CU and NewsGator Social Sites 1.2.2419.

#Load the SharePoint snap-in
Add-PsSnapin Microsoft.SharePoint.PowerShell;

#Load the SharePoint assemblies
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server");
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server.UserProfiles");

#Specify the MySite URL
$MySiteUrl = "http://sharepoint.vallery.net/";

#Get the server context for the profile manager
$site = Get-SPSite $MySiteUrl;
$ServerContext = Get-SPServiceContext $site;
$UPManager = new-object Microsoft.Office.Server.UserProfiles.UserProfileManager($ServerContext);

#Count variables
$ucount = 0;

$enumProfiles = $UPManager.GetEnumerator();
"Total User Profiles available:" + $UPManager.Count
$count=0;

#Loop through the profile entries and update the property
#Recieve Instant Notifications - NGAllowMetaEmail (bool)
#24 Hour Digest Email - NGReceiveDigestEmail (bool)
#RSS NewsFeed Email - NGAllowRssEmail (bool)
#SharePoint Notification emails - SPS-EmailOptin (int)
#This field has 3 values one for each email type

foreach ($oUser in $enumProfiles)
{
    $count = $count + 1;
    $u = $oUser.Item("Accountname");
    Write-Output "($count):  Setting values for $u";

    $oUser["NGAllowMetaEmail"].Value = $false;
    $oUser["NGReceiveDigestEmail"].Value = $false;
    $oUser["NGAllowRssEmail"].Value = $false;
    $oUser["SPS-EmailOptin"].Value = 111; 

    $oUser.Commit();
} 

#Dispose of site object
$site.Dispose();
Leave a Comment
post icon

My 2010 travel statistics

Now that the year has drawn to a close I took a few minutes to tally up all of my nights away from home.  I was surprised to learn that I actually spent LESS time away than I initially would have assumed.  It certainly was a grueling year of back and forth across the country (and the world!).

After all was said and done I spent 38.63% of the nights last year away from home.  Here are the numbers as they break down by city visited:

Location Nights Away
Stockholm, Sweden 37
Rahway, NJ 33
Springfield, VA 32
Whitehouse Station, NJ 17
New York City 5
Wailea, HI 5
30,000 feet 3
Portland, OR 3
Toronto, Canada 2
Chicago, IL 1
Colorado Springs, CO 1
Newark, DE 1
Williamsburg, VA 1
Total 141
%age of year 38.63%
Leave a Comment