Guide Book to Sitecore Reporting

Taking a journey without a good guidebook can be exciting and scary all at the same time. Having looked at the journey our data moves through from collection, squeezing through formatting to arrive at reporting, I thought we should have some more detailed guiding points (the cheap man’s guide book) as to what we can ‘do’ on the journey.

My first guide book takes a detailed look into the built-in reporting of Sitecore, http://www.paragon-inc.com/resources/blogs-posts/guide_book_to_built_in_reporting.

Advertisements

Journey Into the Aggregation Process Part 2

hope you are not feeling to weary just yet, as we embark on the second leg of the Sitecore Experience Platform data journey. In this leg of the journey we will see how the data points go from living in tables into bright, colorful, and insightful tables and charts. Understanding how these tables and charts populate will allow you to take control of your organizations data and make meaningful decisions to further engage customers. http://www.paragon-inc.com/resources/blogs-posts/journey_into_the_aggregation_process_part_2

 

Journey Into the Aggregation Process

Pack your bags and get ready for an exhilarating trip through Sitecore Experience Platform’s data aggregation process. This introductory post will help you and your team get on board with the basics of data movement as a site visitor becomes an important data point in understanding customer engagement with your brand. http://www.paragon-inc.com/resources/blogs-posts/journey_into_the_aggregation_process

 

Sitecore Experience Analytics Part 2

Sitecore Experience Platform comes with a plethora of colorful tables and charts. I have found that the default names don’t always provide enough context as to the slice of data I am looking at. To help myself out and all those in your organization that get excited about data crunching my Quick Start to Engagement Analytics Part 2 (http://www.paragon-inc.com/resources/blogs-posts/engagement-analytics-quickstart-part-2) is go to reference guide.

Collapse and Expand the Accordion

One click, two click, three click, where is that field? Once a day, I get so lost expanding and collapsing field sections when working in Sitecore’s Content Editor interface, that my poor mouse almost takes a unplanned trip across the office. As the industrious Sitecore developer I am, I decided enough was enough. My decision lead to the creation of Custom Content Editor Buttons.

Requires Qualified Assembly Name, ugh!

You are plugging away at writing this super sweet class, to be used in your latest application, and then you hit the wall! Nothing builds because the configuration file requires a reference to the fully qualified assembly name…ugh!!!

The first thing you do is scratch your inner mind trying to recall what makes up this name. (At least that is what I end up doing every time.) It seems depending on what you are working on you will either need a four-part name or a ‘five-part name’.

The four-part fully qualified name consists of the following in the following order:

Assembly Name, Version= 0.0.0.0, Culture=culture code, PublicKeyToken=public key

(It is common for culture to be set to ‘neutral’ if there is nothing contained that is specific to a cultural style.)

What I consider the to be the five-part name is the four-part name with the namespace and class name that is being referenced prefixed.

Namespace.Class Name, Assembly Name, Version=0.0.0.0, Culture=culture code, PublicKeyToken= public key

With the background details explained, how as a lazy programmer can we retrieve the fully qualified name without a lot of clicks? The old stand by use to be to fire up reflector, throw your assembly in and poof there was the four part assembly name, but any more finding a really good reflector is much more difficult (and there is a lot of extra clicking involved by using a second program.)

Visual Studio 2010 has a great feature in allowing you to set up single clicks from the menu bar and via hotkeys to external tools…which means a perfect fit for a simple PowerShell command.

  1. Go to Tools -> External Tools.
  2. The External Tools dialog box should open for you. Click Add.
    image
  3. This will then generate a new value labeled [New Tool 1] and have it selected for you.
    image
  4. In the lower half, provide a Tittle for the new tool such as "4-Part Name".
  5. In the Command, textbox you will enter the following
    powerhell.exe
  6. In the Arguments, textbox enter the following
    -command "[System.Reflection.AssemblyName]::GetAssemblyName(\"$(TargetPath)\").FullName
  7. Select Use Output window to force the assembly name into the output window of Visual Studio.
  8. The completed dialog should resemble the following
    image
  9. Click OK.
  10. Your command should now display under Tools.
    image
  11. To get the four part name,
    1. Select the project or any file in the project from Solution Explorer or Solution Navigator
    2. Go to Tools –> 4-Part Name
    3. See the four part name displayed in the Output window
      image

References:
MSDN AssemblyName.GetAssemblyName()
MSDN Type.FullName
MSDN Details on Assemnly Names

All Together Now

This is the final part in my series on how to load users and groups into Active Directory (AD) using the magical powers found in PowerShell. ‘All Together Now’ is combining the different commands that have been reviewed in the earlier parts and how to load the users and group details from an XML file. There are a number of post out in the vast inter-webs which explain how to insert groups and users via a comma delimited file, but I have a slight bias towards the nice hierarchal form of XML, hence this final piece to the puzzle.

I am going to presume you understand the ins and outs of the other commands which were explained and demoed in the first series of post. If you haven’t read the first three parts here are the links to them for reference:

    The first step is to generate the XML. Here is the XML I will be referencing.

    1 <NewUserManagement> 2 <User> 3 <givenname></givenname> 4 <surname></surname> 5 <fullname></fullname> 6 <login></login> 7 <description></description> 8 <password></password> 9 <group></group> 10 <group></group> 11 </User> 12 <User> 13 <givenname></givenname> 14 <surname></surname> 15 <fullname></fullname> 16 <login></login> 17 <description></description> 18 <password></password> 19 <group></group> 20 <group></group> 21 </User> 22 </NewUserManagement>

You will need one ‘User’ node for each user that you will want to generate. Within this node, the ‘group’ node can be repeated for any number of groups that this user will be a member of. One thing that caused me a slight headache was specifically listing the Users domain group. What I learned is that users are automatically added to this group upon add, so no need to list it out.

Here is the definition f the other fields for reference:

     givenname – First Name

     surname – Last Name

     login – User login name for the domain

     description – Description of the user

     password – password in plain text for the user

     group – Name of an existing or new group the user should be a member

Hint 1: When writing multiple functions for a script, these functions must be defined before they are called.

Now that we have our XML written, let’s begin the script.

  1. For this script to be as flexible as possible, we will need to generate a single required parameter for the path to the XML file.

    1 param( 2 [Parameter(Mandatory=$true)] 3 [string] $pathToFile 4 )

  2. The first function that will be written will be the adding of new users to Active Directory.

    1 function addNewUser{ 2 param($uXML) 3 $loginName = $uXML.login; 4 $user = Get-ADUser -Filter {samAccountName -eq $loginName}; 5 if(!$user) 6 { 7 $securePassword = ConvertTo-SecureString $uXML.password -AsPlainText -Force; 8 $user = New-ADUser -SamAccountName $uXML.login -Name $uXML.login -AccountPassword $securePassword -CannotChangePassword $true -PasswordNeverExpires $true -Description $uXML.description -DisplayName $uXML.login -Enabled $true -EmailAddress ($uXML.login + "@rainfly.com") -Server "rainfly.com" -GivenName $uXml.givename -Surname $uXML.surname -PassThru; 9 Write-Host "User $user.SamAccountName was created."; 10 } 11 Sleep -Seconds 5; 12 return $user; 13 }

    The function has a single parameter, uXML, which is the XML object of the entire user node from the file. Line 4, performs a get on the user login name. If the user exists, then an AD user object is returned else it will be empty.

    Hint 2: Objects in PowerShell can be tested for null or nothing, by a simple if statement.

    i.e.

    1 if($obj) 2 { # $obj has a value; } 3 else 4 { # $obj is null or nothing; }

    The not version of this test is performed in Line 5 to determine if the user already exists. If the user does not exist they are added via the New-ADUser command. (When adding new users with a password the ConvertTo-SecureString is required.)

    Finally, the method returns the AD User object to the main script.

  3. The second function is to add the new users to groups.

    1 function addUserToGroup 2 { 3 param($uObj, $groupSamName) 4 $gObj = Get-ADGroup -Filter {samAccountName -eq $groupSamName}; 5 if(!$gObj)#check for null, true is null 6 { 7 $gObj = New-ADGroup -Name $groupSamName -GroupScope DomainLocal -DisplayName $groupSamName -SamAccountName $groupSamName -PassThru; 8 Write-Host "Group $groupSamName was created"; 9 } 10 if($gObj) 11 { 12 try{ 13 Add-ADGroupMember -Identity $gObj -Member $uObj; 14 Write-Host "Added user, $uObj.SamAccountName, to group $gObj.SamAccountName"; 15 }catch 16 { 17 Write-Host "Failed to add user, $uObj.SamAccountName , to $gObj.SamAccountName "; 18 } 19 } 20 else 21 { 22 Write-Host "User was not added to Group $groupSamName." 23 } 24 }

    This method accepts two parameters. The first, $uObj, is the AD user object that is either retrieved or returned after creation from addNewUser method. The second parameter, $groupSamName, is the name of the group as taken from the XML user node’s group element.

    Line 4 performs a retrieval from AD of the group, just as with the addNewUser method, a check is done for null/nothing to determine if the group already exists.

    Hint 3: Version 2.0 of PowerShell introduced try…catch blocks, that you can see beginning on line 12. Here it is used if to catch any issues that occur when adding the user to the group.

  4. Now that the basic methods we will be needing are in place, let’s begin to write the main script. The first line will be

    1 Import-Module active*;

    This line will automatically load the active directory modules for the PowerShell prompt being ran. This saves you the hassle of trying to remember to load the active directory modules, or run the script from the Active Directory PowerShell prompt.

  5. Finally, here is the heavy lifting portion of the script.

    1 if(Test-Path $pathToFile) 2 { 3 [xml]$xmlObj = Get-Content $pathToFile; 4 $allUsers = $xmlObj.NewUserManagement.ChildNodes; 5 if($allUsers) 6 { 7 foreach($userXML in $allUsers) 8 { 9 if($userXML.Name -ne "#comment") 10 { 11 $theUser = addNewUser -uXML $userXML; 12 foreach($userGroup in $userXML.group) 13 { 14 Write-Host "Procsessing Group: $userGroup"; 15 addUserToGroup -groupSamName $userGroup -uObj $theUser; 16 } 17 } 18 } 19 } 20 } 21 Else 22 { 23 Write-Host "The path to the XML file of users and groups is not valid."; 24 Write-Host $pathToFile; 25 }

    Line 1 kicks things off with a simple check to make sure the user XML file does exist. From there the file is parsed via a loop, to load each user and group. One of the great parts about using PowerShell to parse XML is that once the XML file has been loaded, you can use simple dot notation to get at each node, attribute, and element.

There you have it. The final piece to the puzzle, a script that will generate users and groups based on an XML file. I will note that there may be even more efficient ways to perform this task that I haven’t thought of, so please let me and everyone else know in the comments.