High Class PowerShell: Objects and Classes in PowerShell

My presentation to the SQL PASS PowerShell Virtual Users Group is now online. To see it you can go to the PowerShell Virtual User Group page on YouTube:

https://www.youtube.com/channel/UCFX97evt_7Akx_R9ovfiSwQ

Or watch the embedded video below:

Presentation for the SQL PASS PowerShell Virtual User Group

Today (April 6, 2016) I was pleased to present “High Class PowerShell” to the SQL PASS PowerShell Virtual User Group. In it I covered the creation of custom objects and classes in PowerShell.

The first question everyone asks is “where’s the code”. I’ve pasted the code samples for the main demo at the bottom of this post. You can review it here, or copy – paste into your own ISE.

The closing code on calling classes created in PowerShell was discussed in these two blog posts, so I won’t repeat it here.

During the presentation, I mentioned this code is a small subset of my larger Pluralsight course, Beginning PowerShell Scripting for Developers. You’ll find it and my other courses here:

https://www.pluralsight.com/authors/robert-cain

Don’t have a Pluralsight subscription? No problem, Pluralsight has graciously provided me some trial codes I can share with you. These will allow you a one month, no obligation trial with which you can watch any of my courses, or indeed any course found on Pluralsight. Just email free@arcanetc.com to request your code. (If you didn’t get to see the presentation, no worries, you can still email us for the Pluralsight trial code!)

When the video of the presentation goes live I will have a follow up blog post, meanwhile, and without further ado, here is the code sample.

<#-----------------------------------------------------------------------------
  High Class PowerShell

  Author: Robert C. Cain | @ArcaneCode | arcanecode@gmail.com
          http://arcanecode.com
 
  This module is Copyright (c) 2016 Robert C. Cain. All rights reserved.
  The code herein is for demonstration purposes. No warranty or guarentee
  is implied or expressly granted. 
  This module may not be reproduced in whole or in part without the express
  written consent of the author. 
-----------------------------------------------------------------------------#>

#-----------------------------------------------------------------------------#
# Demo 0 -- Object Oriented Terminology
#-----------------------------------------------------------------------------#
<#
                                  class = blueprints
                             properties = describe
                    methods (functions) = actions
                                 object = house
             instantiating a new object = building a new house
each object is an instance of the class = each house is a copy of the blueprint


#>

#-----------------------------------------------------------------------------#
# Demo 1 -- Create a new object 
# This is the most common method of creating objects
#-----------------------------------------------------------------------------#

# The most basic way to create a custom object is to build a hash table with 
# the properties. Using [ordered] will ensure the properties remain in the
# desired order. 
$properties = [ordered]@{ Schema = $Schema
                          Table = $Table
                          Comment = $Comment
                        }

# Start by creating an object of type PSObject
$object = New-Object –TypeName PSObject -Property $properties

# Now you can access it's properties
$object.Schema = 'MySchema'
$object.Table = 'MyTable'
$object.Comment = 'MyComment'
$object


# Much of the time, the process of creating a custom object is wrapped in a 
# function to make it easier. 
function Create-Object ($Schema, $Table, $Comment)
{
  # Build a hash table with the properties
  $properties = [ordered]@{ Schema = $Schema
                            Table = $Table
                            Comment = $Comment
                          }

  # Start by creating an object of type PSObject
  $object = New-Object –TypeName PSObject -Property $properties

  # Return the newly created object
  return $object
}

$myObject = Create-Object -Schema "MySchema" -Table "MyTable" -Comment "MyComment"
$myObject

# Display in text. If you try to reference a property in text, it doesn't
# work quite right.
"My Schema = $myObject.Schema"

# Instead, wrap it in $() to access a property. This will force PowerShell to
# evaluate the object.property call as an expression, and return that to the
# string
"My Schema = $($myObject.Schema)"

# Changing properties is easy
$myObject.Schema = "New Schema"
$myObject.Comment = "New Comment"
$myObject


#-----------------------------------------------------------------------------#
# Demo 2 -- Create a new object by adding properties one at a time
# In the previous demo a property hash table was used to generate the object
# Behind the scenes it does the equivalent of what this function does
#-----------------------------------------------------------------------------#
function Create-Object ($Schema, $Table, $Comment)
{
  # Start by creating an object of type PSObject
  $object = New-Object –TypeName PSObject

  # Add-Member by passing in input object
  Add-Member -InputObject $object `
             –MemberType NoteProperty `
             –Name Schema `
             –Value $Schema

  # Alternate syntax, pipe the object as an input to Add-Member
  $object | Add-Member –MemberType NoteProperty `
                       –Name Table `
                       –Value $Table
  
  $object | Add-Member -MemberType NoteProperty `
                       -Name Comment `
                       -Value $Comment

  return $object
}

$myObject = Create-Object -Schema "MySchema" -Table "MyTable" -Comment "MyComment"
$myObject

# No difference in the way we display values or assign them
"My Schema = $($myObject.Schema)"

$myObject.Schema = "New Schema"
$myObject

# Show this is a PSCustomObject
$myObject.GetType()

# Each property has it's own .NET Data Type. 
# Note this is different from the Member Type
$myObject.Comment.GetType()

# To see the Member Types, pipe to Get-Member
$myObject | Get-Member 


#-----------------------------------------------------------------------------#
# Demo 3 -- Add alias for one of the properties
#-----------------------------------------------------------------------------#
Clear-Host

# Demo 3 -- Add alias so both Comment and Description reference the same thing
Add-Member -InputObject $myObject `
           -MemberType AliasProperty `
           -Name 'Description' `
           -Value 'Comment' `
           -PassThru  # Use passthru to see the new object

"Comment......: $($myObject.Comment)"
"Description..: $($myObject.Description)"

# Change the value
$myObject.Description = 'This is now a description'
"Comment......: $($myObject.Comment)"
"Description..: $($myObject.Description)"

# Demo 3 -- Add script block to object
Clear-Host
$block = { 
           $fqn = $this.Schema + '.' + $this.Table 
           return $fqn
         }

Add-Member -InputObject $myObject `
           -MemberType ScriptMethod `
           -Name 'FullyQualifiedName' `
           -Value $block `
           -PassThru

# Using Get-Member we can see the newly added script method
$myObject | Get-Member 

# When calling our new function, parens are very important, without them 
# PowerShell will just display the function
$myObject.FullyQualifiedName()  


#-----------------------------------------------------------------------------#
# Demo 4 -- Script block with parameters
#-----------------------------------------------------------------------------#
Clear-Host
$block = { 
           param ($DatabaseName)
           $fqn = "$DatabaseName.$($this.Schema).$($this.Table)"
           return $fqn
         }

Add-Member -InputObject $myObject `
           -MemberType ScriptMethod `
           -Name 'DatabaseQualifiedName' `
           -Value $block 

# Place any parameters within the parens
$myObject.DatabaseQualifiedName('MyDBName')  


#-----------------------------------------------------------------------------#
# Demo 5 -- Script Property
#-----------------------------------------------------------------------------#
# These are analogues to properties in C#, with a Getter and Setter function
Clear-Host

# Add a property we can work with
Add-Member -InputObject $myObject `
           –MemberType NoteProperty `
           –Name AuthorName `
           –Value 'No Author Name'

$myObject # Show the added property

# This defines the GET for this property
$getBlock = { return $this.AuthorName }

# This defines the SET. Adding a simple check for the name
$setBlock = { 
              param ( [string]$author )
                            
              if($author.Length -eq 0)
              { $author = 'Robert C. Cain, MVP' }
              
              $this.AuthorName = $author
            }

# Now add the custom Get/Set ScriptProperty to the member
Add-Member -InputObject $myObject `
           -MemberType ScriptProperty `
           -Name Author `
           -Value $getBlock `
           -SecondValue $setBlock

# Demo its use when passing as value
$myObject.Author = 'ArcaneCode'
"`$myObject.Author now equals $($myObject.Author )"

# Now pass in nothing to see the setter functionality kicking in
$myObject.Author = ''
$myObject.Author

# Unfortunately the original property is still available, and thus
# the custom get/set can be bypassed
$myObject.AuthorName = ''
$myObject.Author                       # Author reflects value of AuthorName

$myObject.Author = ''                  # Going thru scriptproperty sets correctly
$myObject.Author


#-----------------------------------------------------------------------------#
# Demo 6 -- Set default properties
# Note: Thanks to Poshoholic for his cool code sample, see it at:
# http://poshoholic.com/2008/07/05/essential-powershell-define-default-properties-for-custom-objects/
#-----------------------------------------------------------------------------#
Clear-Host

# When just running the object, it displays all properties
$myObject

# If you have a lot, this can get overwhelming. Instead you can define a
# default set to display.

# Define the property names in an array
$defaultProperties = 'Schema', 'Table', 'Comment', 'Author'

# Create a property set object and pass in the array 
$defaultPropertiesSet `
  = New-Object System.Management.Automation.PSPropertySet(`
      ‘DefaultDisplayPropertySet’ `
      ,[string[]]$defaultProperties `
      )

# Create a PS Member Info object from the previous property set object
$members `
  = [System.Management.Automation.PSMemberInfo[]]@($defaultPropertiesSet)

# Now add to the object
$myObject | Add-Member MemberSet PSStandardMembers $members

# Now the object will just display the default list in standard output
$myObject

# Little easier to read in a list
$myObject | Format-List

# To display all properties, pipe through format-list with wild card for property
$myObject | Format-List -Property *


#-----------------------------------------------------------------------------#
# Demo 7 - Create a class from .Net Code and call a static method
#-----------------------------------------------------------------------------#

# Load the contents of the file into a variable
$code = @"
using System;

public class MyObjectStatic
{   public static string composeFullName(string pSchema, string pTable)   {     string retVal = "";  // Using retVal for Write-Verbose purposes     retVal = pSchema + "." + pTable;     return retVal;   } // public static void composeFullName
} // class MyObjectStatic

"@

# Add a new type definition based on the code
Add-Type -TypeDefinition $code `
         -Language CSharpVersion3 

# Call the static method of the object
$mySchema = "dbo"
$myTable = "ArcaneCode"
$result = [MyObjectStatic]::composeFullName($mySchema, $myTable)
$result


#-----------------------------------------------------------------------------#
# Demo 8 - Instantiate an object from .Net Code in embedded code
#-----------------------------------------------------------------------------#

$code = @"
using System;

public class MyObjectEmbedded
{   public string SomeStringName;   public string composeFullName(string pSchema, string pTable)   {     string retVal = "";  // Using retVal for Write-Verbose purposes     retVal = pSchema + "." + pTable;     return retVal;   } // public string composeFullName
} // class MyObjectEmbedded

"@

# Add a new type definition based on the code
Add-Type -TypeDefinition $code `
         -Language CSharpVersion3 

# Instantiate a new version of the object
$result = New-Object -TypeName MyObjectEmbedded

# Set and display the property
$result.SomeStringName = "Temp"
$result.SomeStringName

# Call the method
$result.composeFullName($mySchema, $myTable)


#-----------------------------------------------------------------------------#
# Demo 9 - Create object from .Net Code in an external file
#-----------------------------------------------------------------------------#

# Path and File Name
$file = 'C:\PS\Classes and Modules\HighClassPowerShell.cs'

# Open the file in the ise to look at it
psedit $file

# Load the contents of the file into a variable
$code = Get-Content $file | Out-String

# Add a new type definition based on the code
Add-Type -TypeDefinition $code `
         -Language CSharpVersion3 

# Call the static method of the object
$mySchema = "dbo"
$myTable = "ArcaneCode"
$result = [MyObjectExternal]::composeFullName($mySchema, $myTable)
$result


#-----------------------------------------------------------------------------#
# Demo 10 - Add to an existing object
#-----------------------------------------------------------------------------#

# Going to add a script method and note property to the System.IO.FileInfo 
# objects returned by Get-ChildItem

# Define the custom script method
$script = { 
            $retValue = 'Unknown'

            switch ($this.Extension)
            {
              '.ps1'  { $retValue = 'Script' }
              '.psm1' { $retValue = 'Module' }
              '.psd1' { $retValue = 'Module Declration' }
              '.cs'   { $retValue = 'C# File'}
              default { $retValue = 'No Clue. Seriously stumped here.'}
            }

            return $retValue
          }

# Load a variable with a collection of file objects
Set-Location 'C:\PS\Classes and Modules'
$items = Get-ChildItem

$itemCount = 0
foreach($item in $items)
{
  # Add a note property, setting it to the current item counter
  $itemCount++
  $item | Add-Member –MemberType NoteProperty `
                     –Name ItemNumber `
                     –Value $itemCount

  # Add script property to the individual file object
  Add-Member -InputObject $item `
             -MemberType ScriptMethod `
             -Name 'ScriptType' `
             -Value $script 

  "$($item.ItemNumber): $($item.Name) = $($item.ScriptType())"
}

# Show our new note and script having been added to the FileInfo type
$items[0] | Get-Member


#-----------------------------------------------------------------------------#
# Demo 11 - Serializing an Object
#-----------------------------------------------------------------------------#

  # Create a simple object
  $mySiteProperties = [ordered]@{ 
                                  WebSite = 'ArcaneCode'
                                  URL = 'http://arcanecode.com'
                                  Twitter = '@ArcaneCode'
                                }

  # Convert it to an object
  $mySite = New-Object –TypeName PSObject -Property $mySiteProperties
  
  # Show the object
  $mySite
  
  # Save the object to a file and 
  $savedDataFile = 'C:\PS\Classes and Modules\mySite.xml'
  $mySite | Export-Clixml $savedDataFile
  psedit $savedDataFile 

  # Now grab the saved object and recreate in a different variable
  $newMySite = Import-Clixml $savedDataFile
  $newMySite


#region Enum

#-----------------------------------------------------------------------------#
# Show Enums in PS
#-----------------------------------------------------------------------------#

# Define the valid values for the enum
Enum MyTwitters
{
  ArcaneTC
  ArcaneCode
  N4IXT
}

# Note when typing the last : will trigger intellisense!
$tweet = [MyTwitters]::ArcaneCode 
$tweet

# See if they picked something valid
[enum]::IsDefined(([MyTwitters]), $tweet)

# Set it to something invalid and see if it passes as an enum
$tweet = 'Invalid'
[enum]::IsDefined(([MyTwitters]), $tweet)

#endregion Enum


#region Basic Class

#-----------------------------------------------------------------------------#
# Basic Class
#-----------------------------------------------------------------------------#
  
Class Twitterer
{
  # Create a property
  [string]$TwitterHandle
  
  # Create a property and set a default value
  [string]$Name = 'Robert C. Cain'

  # Function that returns a string
  [string] TwitterURL()
  {
    $url = "http://twitter.com/$($this.TwitterHandle)"
    return $url
  }

  # Function that has no return value
  [void] OpenTwitter()
  {
    Start-Process $this.TwitterURL()
  }

}

$twit = [Twitterer]::new()
$twit.GetType()

$twit.TwitterHandle = 'ArcaneCode'
$twit.TwitterHandle
  
# See default property value
$twit.Name

# Override default value
$twit.Name = 'Robert Cain'
$twit.Name

$myTwitter = $twit.TwitterURL()
$myTwitter

$twit.OpenTwitter()

#endregion Basic Class


#region Advanced Class

#-----------------------------------------------------------------------------#
# Advanced Class
#   Constructors
#   Overloaded Methods
#-----------------------------------------------------------------------------#

Class TwittererRedux
{
  # Default Constructor
  TwittererRedux ()
  {
  }

  # Constructor passing in Twitter Handle
  TwittererRedux ([string]$TwitterHandle)
  {
    $this.TwitterHandle = $TwitterHandle
  }

  # Constructor passing in Twitter Handle and Name
  TwittererRedux ([string]$TwitterHandle, [string]$Name)
  {
    $this.TwitterHandle = $TwitterHandle
    $this.Name = $Name
  }

  # Create a property
  [string]$TwitterHandle
  
  # Create a property and set a default value
  [string]$Name = 'Robert C. Cain'

  # Static Properties
  static [string] $Version = "2016.04.06.001"

  # Function that returns a string
  [string] TwitterURL()
  {
    $url = "http://twitter.com/$($this.TwitterHandle)"
    return $url
  }

  # Overloaded Function that returns a string
  [string] TwitterURL($twitterHandle)
  {
    $url = "http://twitter.com/$($twitterHandle)"
    return $url
  }

  # Function that has no return value
  [void] OpenTwitter()
  {
    Start-Process $this.TwitterURL()
  }

  # Can launch a twitter page without instantiating the class
  static [void] OpenTwitterPage([string] $TwitterHandle)
  {
    $url = "http://twitter.com/$($TwitterHandle)"
    Start-Process $url
  }

}

# Create a class using default constructor
$twitDefault = [TwittererRedux]::new()

# Display without assigning
"TwitterHandle = $($twitDefault.TwitterHandle)"

# Now assign and display again
$twitDefault.TwitterHandle = 'ArcaneTC'
"TwitterHandle = $($twitDefault.TwitterHandle)"

# Show version one of TwitterURL
"URL = $($twitDefault.TwitterURL())"

# Show overloaded version
"URL = $($twitDefault.TwitterURL('ArcaneCode'))"

# Create a new instance using the second constructor
$twitAdvanced = [TwittererRedux]::new('N4IXT')

# Display without assigning - Should have what was passed in constructor
"TwitterHandle = $($twitAdvanced.TwitterHandle)"

# Create yet another instance using the third constructor
$twitAdvanced2 = [TwittererRedux]::new('ArcaneCode', 'R Cain')
$twitAdvanced2.TwitterHandle
$twitAdvanced2.Name

# Static Value - Can be called without initializing the class
[TwittererRedux]::Version

# Use the static method
[TwittererRedux]::OpenTwitterPage('ArcaneTC')


#endregion Advanced Class

Resolving Ambiguous Class Names Across PowerShell Modules

Right after my last post, I got to wondering what would happen if I had two modules with the same class named defined?

The dictionary defines ambiguous as “unclear or inexact because a choice between alternatives has not been made”. In context of this discussion, it means we have two different PowerShell modules that both have definitions for a class that is named the same (but may not necessarily look the same).

To quote one of the most often used phrases in technical blogging, “Let’s look at an example!”.

Here is our first module, which defines a class MyAmbiguousClass. As you can see it has one property and one method.

# MyAmbiguousModule1.psm1
class MyAmbiguousClass
{
  [string] $MyString = 'Ambigouous String 1'

  [string] GetSomeValue()
  {
    return 'Ambigouous Value 1'
  } 
}

Pretty simple. Now let’s look at a second module. This also has a class defined of MyAmbiguousClass, but it has two properties and one method, all with different names from the previous modules definition.

# MyAmbiguousModule2.psm1
class MyAmbiguousClass
{
  [int] $MyInteger = 2

  [string] $MyName = 'ArcaneCode'

  [string] DidILeaveTheStoveOn()
  {
    return 'Probably not'
  } 
}

You would then declare these at the top of your script thusly:

using module 'C:\PS\Classes and Modules\MyAmbiguousModule1.psm1'
using module 'C:\PS\Classes and Modules\MyAmbiguousModule2.psm1'

As described in my previous post, you would instantiate a new instace with this command:

$myClass = [MyAmbiguousClass]::new()

Now of course you can see the issue, it is not clear which version of the MyAmbiguousClass is being instantiated. What’s even scarier is PowerShell will execute this command without producing an error!

When PowerShell creates the new variable it looks through its memory to find the first time this class is defined, then it uses that definition. In this example, since the MyAmbiguousModule1.psm1 was loaded first, it is that definition that gets used.

If, however, the ‘using module’ statements had been reversed, and MyAmbiguousModule2.psm1 was first, then it is the definition for MyAmbiguousClass found in MyAmbiguousModule2.psm1 that would have been used.

Yikes!

So how to resolve? Well it turns out to be quite simple. All you have to do is prefix the class name with the module name, like so:

$myClass1 = [MyAmbiguousModule1.MyAmbiguousClass]::new()

Now intellisense will list the correct methods and properties, and we can access them in code.

$myClass1.MyString
$myClass1.GetSomeValue()

Will produce

Ambigouous String 1
Ambigouous Value 1

Likewise, we’ll prefix the second version with its module name, MyAmbiguousModule2:

$myClass2 = [MyAmbiguousModule2.MyAmbiguousClass]::new()
$myClass2.MyInteger
$myClass2.MyName
$myClass2.DidILeaveTheStoveOn()

Produces this output

2
ArcaneCode
Probably not

And there you go, resolving ambiguous class names across PowerShell modules is just that easy.

Accessing a PowerShell Class Defined In A Module From Outside A Module

PowerShell 5 introduced the concept of classes. This is an exciting new feature that will really help promote code reusability. It seems natural then, that you would want to organize your classes into PowerShell Modules.

It’s not obvious though, how to use a class defined inside a module from outside that module. There are, in fact, three methods available to you.

Let’s say you have a module, MyModule.psm1. In it you’ve defined a class:

class MyClass
{
  [string] $MyString = 'My String Value'

  [string] GetSomeValue()
  {
    return 'Some Value'
  } 

}

Simple enough. So how do we get to this masterpiece of class coding? The first technique has us creating a function inside the module. Within that function we return a new instance of the class.

function Get-NewMyClass()
{
  return [MyClass]::new()
}

# Export the function, which can generate a new instance of the class
Export-ModuleMember -Function Get-NewMyClass

Using it simply requires we import the module, then call the function. From there we can access the properties and methods of our function.

# Import our test module
Import-Module -Force 'C:\PS\Classes and Modules\mymodule.psm1'

# Use the function to generate a new instance of the 'MyClass' class
$myClassFunction = Get-NewMyClass

# Call a method from it
$myClassFunction.GetSomeValue()

# Get a property of the class
"MyString=$($myClassFunction.MyString)"

Pretty simple and straightforward. This can be a useful method if there are extra checks you wish to do inside the module prior to returning the new instance of the class.

The next method simply has us create a variable within the module, and export that as a module member.

$newClass = [MyClass]::new()
Export-ModuleMember -Variable newClass

You’d then use it in your script, just like any other variable:

# The module also has a variable exported from the function
# of type MyClass. 
"NewClass=$($newClass.MyString)"
$newClass.GetSomeValue()

With that shown I have to say I really don’t like this method. Primarily it is due to the issue of name collisions. If you have a variable also named $newClass in your script, it will block out the one from the class causing the collison.

The final option is the new using clause. I want to give a shout out to PowerShell MVP Dave Wyatt (blog | twitter) for pointing this one out to me.

As the first line of your script (except for comments, which are allowed before it) you use the syntax “using module” followed the module name, or path to the module.

using module 'C:\PS\Classes and Modules\mymodule.psm1'

Here I hard coded the path to the module since this is a simple demo. If the module had been installed in one of the default locations for modules, such as the WindowsPowerShell\Modules folder in the current users Documents area, you could have omitted the path and just put the name of the module.

After this, you would simply create a new variable from the class and use it normally.

$myClassUsing = [MyClass]::new()

# Setting / Getting property
$myClassUsing.MyString                  # Show default property
$myClassUsing.MyString = 'ArcaneCode'   # Change the value
$myClassUsing.MyString                  # Show the change

# Calling a method
$myClassUsing.GetSomeValue()

Note that if you had multiple modules you wanted to access the class definitions in, you would simply have multiple lines of “using module”, each line referencing the module you wanted.

using module 'C:\PS\Classes and Modules\mymodule.psm1'
using module 'C:\PS\Classes and Modules\anothermodule.psm1'

 

There you go. Three ways you can access a class definition stored inside a module, externally. Now not only can you create useful, reusable classes, you can also organize them into modules and use them outside the modules.

High Class PowerShell–Presenting for the SQL PASS PowerShell Virtual Chapter

I’m pleased to announce I’ll be presenting for the SQL PASS PowerShell Virtual Chapter this Wednesday April 6th, 2016, at 12 pm Eastern Time (GMT-5).

In this session I’ll focus on the ability to create custom objects in PowerShell, covering PowerShell versions 3 to 5. I’ll then dive into the use of the new Class and Enum types introduced in PowerShell 5.

To join me, simply go to https://attendee.gotowebinar.com/register/2277748661677465857 and register. It’s free, fast and easy. If you can’t make it live, don’t worry these sessions are recorded and will be posted for viewing later.

Hope to see everyone there!

Getting Music on your Windows Phone with Windows Media Player

I admit it. I have a Windows Phone. And I like it.

I’ve had an iPod, which is more than enough to tell me I don’t want an iPhone. Every time I switched PCs it was like starting over with a brand new device. Egad.

I also had an Android phone. It did a terrible job of letting me organize my apps, and often rearranged them after an update, leaving me once again to try and find where the heck everything is.

No, I like the simplicity of my Windows Phone. Easy to use, easy to setup. True, as critics say there’s not a lot of apps. But an awful lot of what I need I can do just via the web. Starbucks is a great example, they have an excellent mobile website through which I can check my card balance, see my current points (stars), and easily refill my card.

Truth be told, I actually have two Windows Phones. One is my large Samsung ATIV-SE, which I use daily. I also have a small inexpensive Nokia, only has 4 gig of ram but takes a 128 gig SD card. (The SD card cost twice as much as the phone.) When I travel I don’t want to run down the battery on my Samsung phone, so it works as a great device for playing my music, podcasts, and Audible audiobooks. Additionally, f something ever happened to the Samsung I can run and get a cheap SIM card and use it for a backup. I’ve nick named it ‘Zune’.

The one painful thing is getting music on my phones. One option is to simply open up File Explorer and copy things across. But that doesn’t let you really manage it well, and doesn’t help with playlists.

Another option is the Windows Phone desktop app. What a big pile of steaming poo that is. There’s a Windows 8 style app for it, which isn’t any better but is prettier. Of course there’s Groove / XBox Music. It does a great job of organizing music and playlists. But wait, it doesn’t talk to the Windows Phone. WTF Microsoft??? Come on, three different apps, none of which are worth a flip with the Windows Phone.

I’ve found the best app to be good old Windows Media Player. Yes, you heard me, the ancient but venerable Windows Media Player. It is easy to organize music and other types of media, as well as create playlists. Even better, when I plug in my phones it just recognizes them and shows up in the Sync tab. All I have to do is drag playlists or other media to it and click the start sync, and away it goes.

Unfortunately it’s a one way sync, it won’t retrieve things from the phone, but I can live with that.

I did have one frustrating moment last night. I was creating some new playlists, then when I went to sync them something happened. Not sure what, but everything went kablooie. Sync failed, and when I looked back many of my playlists had vanished.

I uttered a long string of explicatives involving the fleas of a thousand llamas and the armpits of most Microsoft Executives, then sighed and went to recreate one of them. When I did, it told me the list already existed! I went to look and of course didn’t see it, but I still had some glimmer of hope my lists were still there, like gold nuggets waiting to be found.

I put my Bingfu skills to work, and quickly found this question/answer in the Microsoft forums:

http://answers.microsoft.com/en-us/windows/forum/windows_7-pictures/missing-playlists-in-windows-media-player-12-for/176a2d8f-568a-4bce-8488-b6c640c2859b?auth=1

The solution came from one Afzal Taher, who appears to be a Microsoft employee. Or at least he was as of 2010 when the answer was posted.

His answer had multiple options you could try, but the first was all I needed. (If the below doesn’t work for you reference the above link).

1. Exit Windows Media Player.

2. Hold down the Windows Key and press R (for Run). Type %LOCALAPPDATA%\Microsoft\Media Player and click OK.

3. Select all the files in that folder, and delete them. NOTE! DO NOT DELETE THE FOLDERS! Only the files.

4. Restart Windows Media Player.

Of course any time you delete files, do it with caution, and you’re on your own, no warranties from me.

When you restart Windows Media Player, it will begin rebuilding its database. I have literally hundreds of gigs of music. My collection has records and/or CDs back to the late 70’s that I’ve digitized because I’m really old and we all know the last decade for original music was the 80’s. Except for ZZ Top. No matter when their stuff comes out, it rocks. (Also a shout-out to DJ Lobsterdust for his really innovative mash-ups.)

Anyway, this was an overnight process for me. But this morning, all my songs and playlists were back, even the ones that had vanished. I was able to sync my playlists to my phones with no problem, and am now happily rocking out while writing some PowerShell code.

Hmmm. PowerShell + Windows Phone + Windows Media Player. I wonder….

Encoding Strings to Base64 in C# – The Movie

Way back in 2007 I wrote a blog post entitled “Encoding Strings to Base64 in C#”. This continues to be my #1 referenced post.

The guys over at Webucator have turned my post into an instructional video, and I couldn’t be happier with the results. You can find the video on YouTube at:

https://www.youtube.com/watch?v=r94gKb-NzLM&feature=youtu.be

Make sure to give ‘em a like for all their hard work!