Wednesday, November 13, 2013

Read XML with PowerShell

I have found that the ability to define and read an xml file with PowerShell is very useful. Often times I will generate XML from an Excel spreadsheet to drive a PowerShell script.

For example, what if we wanted to read this xml file using PowerShell? Let’s say it was in a file named “sample.xml”
<?xml version="1.0" encoding="utf-8"?>
<albums>
  <album name="Time Out">
    <artist>The Dave Brubeck Quartet</artist>
    <released>12/14/1959</released>
  </album>
  <album name="Red Headed Stranger">
    <artist>Willie Nelson</artist>
    <released>5/1/1975</released>
  </album>
</albums>

Here’s how I access all the attributes and nodes.
    # path/file name of xml file
    $xmlfile = "sample.xml";
   
    # Read an xml file
    [xml]$musiccatalog = get-content $xmlfile;
    foreach ($album in $musiccatalog.albums.album) {
        # Display what we've read
        write-host;
        write-host -f green "   Album Name: " -nonewline;
        write-host -f yellow $album.name;
        write-host -f green "   Artist    : " -nonewline;
        write-host -f yellow $album.artist;
        write-host -f green "   Released  : " -nonewline;
        write-host -f yellow $album.released;
    }


And here is the output

   Album Name: Time Out
   Artist    : The Dave Brubeck Quartet
   Released  : 12/14/1959

   Album Name: Red Headed Stranger
   Artist    : Willie Nelson
   Released  : 5/1/1975


Wednesday, November 6, 2013

Send Email from SharePoint

Although in general I believe that SharePoint should contribute to reducing email rather than adding to it, there are circumstances and user requirements that call for SharePoint to produce emails. I have used code similar to the following function to create and send emails from SharePoint as needed.

// Abbreviated namespace imports
using System.Collections.Specialized; // For StringDictionary
using System.Text;                    // For StringBuilder
using Microsoft.SharePoint.Utilities; // For SPUtility

/// <summary>
/// Email a message to a user
/// </summary>
/// <param name=”emailSubject”>string: the subject for the email</param>
/// <param name=”emailAddr”>string: the target email address</param>
/// <param name=”emailMsg”>string: the message to include in the email</param>
private void EmailUser(string emailSubject, string emailAddr, string emailMsg)
{
    try
    {
        // Define a dictionary for the email parameters
        StringDictionary headers = new StringDictionary();
       
        // Set the email content type (I am using text format in this example)
        // Use "text/html" if you want to format/send email as HTML
        headers.Add("content-type", "text/plain");

        // Set the from address (does not need to be a valid email address)
        headers.Add("from", "donotreply@yourdomain.local");

        // Set the to address
        headers.add("to", emailAddr);

        // Set the cc address (in this case we will cc the current SharePoint user)
        headers.add("cc", SPContext.Current.Web.CurrentUser.Email);

        // Set the bcc address (if desired)
        headers.add("bcc", "someaddr@yourdomain.local");

        // Set the email subject
        headers.add("subject", emailSubject);

        // Build the message body (just a sample with text line feeds and tabs)
        StringBuilder emailBody = new StringBuilder();
        emailBody.AppendFormat("*** SharePoint Notification ***\n\n");
        emailBody.AppendFormat("Site:\t{0}\n", SPContext.Current.Web.Url);
        emailBody.AppendFormat("Message:\t{0}\n", emailMsg);
        emailBody.AppendFormat("\n*** End of SharePoint Notification ***");

        // Send the email
        SPUtility.SendEmail(SPContext.Current.Web, headers, emailBody.ToString());

    } // end try

    catch (exception ex)
    {

        // Log exception to event and/or uls logs (code omitted)
        // Handle exception (code omitted)

   } // end catch

} // end EmailUser

PowerShell Pause for Yes/No

Sometimes you need to ask a simple Yes or No question in a PowerShell script, I use the following function:
<#
    Function   : PauseForYesNo
    Description: Prompt for user input of "Y" or "N"
    Note       : Will not run from ISE, must run from command prompt
    Parameters :
       -question  : Question text to display to user
    Returns    :     Key pressed ("Y" or "N")
#>
function PauseForYesNo
{
    param(
        [Parameter(Mandatory=$true)][System.String]$question)

        # Setup the question
        write-host -f Yellow ("{0}? " -f $question) -nonewline;
        write-host -f Green "(Y or N): " -nonewline;
       
        # Read key input until "Y" or "N" pressed
        do {
            $key = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown");
        }
        until (($key.Character -eq "Y") -or ($key.Character -eq "N"))
       
        # Echo the key pressed
        write-host -f White $key.Character;
       
        # Return the key pressed
        return $key.Character.ToString();
}

# Main

# Ask user if they are ready to do something
$Reply = PauseForYesNo -question "Are you ready to do something";

# Based on user key pressed, do something or not
if ($Reply -eq "Y") {
    write-host -f Green "   Do something!";
}
else {
    write-host -f Red "   Do nothing!";
}

Tuesday, November 5, 2013

JavaScript Date Compare


I quite often need to compare a date selected on a form to the current date. Usually because I wish to prohibit the form user from selecting a due date in the past. I came up with this JavaScript function to accomplish this check:
/*
Function:     DateGEToday
Parameters:   dateToCompare, a date string to compare against
Returns:      True, if dateToCompare is greater than or equal to today
*/
function DateGEToday(dateToCompare) {
    // By default, set our compare result to false
    var result = false;
    // Convert the passed date to a date data type
    var comp = new Date(dateToCompare);
    // Create a data data type for the current date/time
    var now = new Date();
    // Create a new due date that does not include the time
    var dueDate = new Date(comp.getFullYear(), comp.getMonth(), comp.getDate());
    // Create a new current date that does not include the time
    var today = new Date(now.getFullYear(), now.GetMonth(), now.getDate());
    // Compare the two date only variables
    if (dueDate >= today) {
        result = true;
    }
    // Return the boolean result
    return result;
}

Caveat: I am a JavaScript novice, so I welcome constructive comments. I don't doubt this code could be reduced and/or simplified, but it works and it makes sense to me.

The call to this script in a form validation checker might look like this...
var dueDate = document.getElementById('<%= dtcDateTime.Controls[0].ClientID %>');
if (!DateGEToday(dueDate.value)) {
    document.getElementById('<%= dtcDateTime.Controls[0].ClientID %>').focus();
    alert('Due date must be today or future date!');
}