Generate a random strong password in PowerShell

I’ve created this PowerShell function that allows you generate any random strong password.

With this method, the caller is able to specify:

  1. The desired password length (minimum = 4)
  2. Whether or not to use lowercase characters
  3. Whether or not to use uppercase characters
  4. Whether or not to use numbers
  5. Whether or not to use special characters
  6. Whether or not to avoid using similar characters ( e.g. i, l, o, 1, 0, I)

The function ensures that each type of character (lowercase, uppercase, number and/or special) is included at least once in the password.

Examples of how to use this:

  • GeneratePassword
    Generates a password using the default settings (length of 8, using a combination of lowercase, uppercase and numbers, while avoiding similar characters), e.g. YeM2B98r
  • GeneratePassword 16
    Generates a longer password using the default settings (length of 16, using a combination of lowercase, uppercase and numbers, while avoiding similar characters), e.g. 89p4758unWt2HDnp
  • GeneratePassword 4 $false $false
    Generates a 4 digit numeric PIN code, e.g. 8298
  • GeneratePassword 8 $true $true $true $true
    Generates an extra strong password, (length of 8, using a combination of lowercase, uppercase, numbers and special characters, while avoiding similar characters), e.g. 9c+9P=#z
  • GeneratePassword 20 $true $true $true $true $false
    Generates an extra strong password, (length of 20, using a combination of lowercase, uppercase, numbers and special characters with possible similar characters), e.g. YCi+R8?vVl1H!B+5hZU8

You can grab the script here (double-click it to copy):

function GeneratePassword() {
    Param (
    [int]$length = 8,    
    [bool] $includeLowercaseLetters = $true,
    [bool] $includeUppercaseLetters = $true,
    [bool] $includeNumbers = $true,
    [bool] $includeSpecialChars = $false,
    [bool] $noSimilarCharacters = $true
    )

    <#
    (c) Morgan de Jonge CC BY SA
    Generates a random password. you're able to specify:
    - The desired password length (minimum = 4)
    - Whether or not to use lowercase characters
    - Whether or not to use uppercase characters
    - Whether or not to use numbers
    - Whether or not to use special characters
    - Whether or not to avoid using similar characters ( e.g. i, l, o, 1, 0, I)
    #>

    # Validate params
    if($length -lt 4) {
        $exception = New-Object Exception "The minimum password length is 4"
        Throw $exception
    }
    if ($includeLowercaseLetters -eq $false -and 
            $includeUppercaseLetters -eq $false -and
            $includeNumbers -eq $false -and
            $includeSpecialChars -eq $false) {
        $exception = New-Object Exception "At least one set of included characters must be specified"
        Throw $exception
    }

    #Available characters
    $CharsToSkip = [char]"i", [char]"l", [char]"o", [char]"1", [char]"0", [char]"I" 
    $AvailableCharsForPassword = $null;
    $uppercaseChars = $null 
    for($a = 65; $a -le 90; $a++) { if($noSimilarCharacters -eq $false -or [char][byte]$a -notin $CharsToSkip) {$uppercaseChars += ,[char][byte]$a }}
    $lowercaseChars = $null
    for($a = 97; $a -le 122; $a++) { if($noSimilarCharacters -eq $false -or [char][byte]$a -notin $CharsToSkip) {$lowercaseChars += ,[char][byte]$a }}
    $digitChars = $null
    for($a = 48; $a -le 57; $a++) { if($noSimilarCharacters -eq $false -or [char][byte]$a -notin $CharsToSkip) {$digitChars += ,[char][byte]$a }}
    $specialChars = $null
    $specialChars += [char]"=", [char]"+", [char]"_", [char]"?", [char]"!", [char]"-", [char]"#", [char]"$", [char]"*", [char]"&", [char]"@"

    $TemplateLetters = $null
    if($includeLowercaseLetters) { $TemplateLetters += "L" }
    if($includeUppercaseLetters) { $TemplateLetters += "U" }
    if($includeNumbers) { $TemplateLetters += "N" }
    if($includeSpecialChars) { $TemplateLetters += "S" }
    $PasswordTemplate = @()
    # Set password template, to ensure that required chars are included
    do {   
        $PasswordTemplate.Clear()
        for($loop = 1; $loop -le $length; $loop++) {
            $PasswordTemplate += $TemplateLetters.Substring((Get-Random -Maximum $TemplateLetters.Length),1)
        }
    }
    while ((
        (($includeLowercaseLetters -eq $false) -or ($PasswordTemplate -contains "L")) -and
        (($includeUppercaseLetters -eq $false) -or ($PasswordTemplate -contains "U")) -and
        (($includeNumbers -eq $false) -or ($PasswordTemplate -contains "N")) -and
        (($includeSpecialChars -eq $false) -or ($PasswordTemplate -contains "S"))) -eq $false
    )
    #$PasswordTemplate now contains an array with at least one of each included character type (uppercase, lowercase, number and/or special)

    foreach($char in $PasswordTemplate) {
        switch ($char) {
            L { $Password += $lowercaseChars | Get-Random }
            U { $Password += $uppercaseChars | Get-Random }
            N { $Password += $digitChars | Get-Random }
            S { $Password += $specialChars | Get-Random }
        }
    }

    return $Password
}

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Compare two SharePoint person fields in XSLT using SharePoint Designer

If you want to compare two columns, a simple way would be to create a calculated column. However, SharePoint doesn’t let you use Person fields (columns) in calculated column.

With a little XSLT, you can compare two person columns in a DataFormWebPart.

Say you add an extra column to a task list, called “OriginallyAssignedTo” and you want to check if the “AssignedTo” column matches the “OriginallyAssignedTo” column.

Within the DataFormWebPart’s dvt_1 template, you add the following code:

<xsl:variable name="CurrentlyAssignedTo" select="@AssignedTo" />
<xsl:variable name="OriginallyAssignedTo" select="@OriginallyAssignedTo" />
<xsl:variable name="TaskDelegated" select=substring-before(substring-after($CurrentlyAssignedTo, 'userdisp.aspx?ID='), '"') != substring-before(substring-after($OriginallyAssignedTo, 'userdisp.aspx?ID='), '"')" />

The variable $TaskDelegated will be false if the two person fields are the same and true if they are different. Comparison is being made based on the ID parameter which is used in the /_layouts/userdisp.aspx page.

So you could show the task’s original owner if it differs from the current owner like this:

<xsl:value-of select="@AssignedTo" disable-output-escaping="yes"/>
<xsl:if test="$TaskDelegated">
	(on behalf of <xsl:value-of select="@OriginallyAssignedTo" disable-output-escaping="yes" />)
</xsl:if>

Remove Timeline from a task view using PowerShell

If you create a new view for a SharePoint 2013 task list, you’ll get a timeline above the task items table.

Should you want to remove this timeline from the view using PowerShell, you should alter the ViewData property for the view.

Initially, this property contains the following data:

<FieldRef Name="PercentComplete" Type="StrikeThroughPercentComplete" /><FieldRef Name="DueDate" Type="TimelineDueDate" />

Simply remove the second FieldRef element from the view’s ViewData to remove the Timeline from the view:

$web = Get-SPWeb <insert web URL>
$view = $web.GetViewFromUrl(<insert view URL>
$view.ViewData = "<FieldRef Name=`"PercentComplete`" Type=`"StrikeThroughPercentComplete`" />"
$view.Update()
$web.Dispose()

Where has the Else-If branch gone to in SharePoint Designer 2013?

In SharePoint 2010, you could create conditional trees with OR statements, like so:

IF <value> equals <value> THEN
    Action(s)
OR IF <value> equals <value> THEN
    Action(s)
ELSE
    Action(s)

In SharePoint 2013, this has changed. The OR condition, is now moved within the ELSE branch:

IF <value> equals <value> THEN
    Action(s)
ELSE 
    IF <value> equals <value> THEN
        Action(s)
    ELSE
        Action(s)

While this makes it slightly less apealing in the Text-Based designer, it does make sense when you understand how Microsoft tries to promote Visio 2013, for designing SharePoint 2013 workflows visually, which can be done if you have Visio 2013 Professional installed on your client:

Click for bigger version

Above shows the if then else branch (without any actions) with 3 possible outcomes.

Extract the parent foldername of a document in a SharePoint Designer 2013 workflow

Using the LastIndexOf Algorithm for SharePoint 2013 workflows described in my previous post, you can now extract the parent folder of a document in a SharePoint 2013 workflow using SharePoint Designer.

The following example retrieves the parent folder for any document. The variable FolderName is empty for documents that are created in the root of the site collection. Handy for custom (drop-off) libraries that require action or routing based on the folder in which the document is placed. (Of course, normally you’d use metadata columns for this, but in some cases, columns are not really an option, i.e. when dealing with documents coming from SharePoint-unaware scanners).

Click for the full version

 

LastIndexOf in a SharePoint 2013 workflow using SharePoint Designer 2013

Unfortunately, there is no out-of-the-box Workflow action for String.LastIndexOf() in SharePoint 2013 workflows when working with SharePoint Designer 2013, but using the new Loop condition, you can get the last index of any character or string:

Use the following actions to retrieve the last index:

Click for a bigger version

This algorithm uses the following local variables:

This can come in handy, when you want to dissect a filename or URL in a workflow.

Create headers in the Quick Launch without links.

When you’re working with site templates in SharePoint Foundation, you might want to group the links to lists and libraries under different headings, than their type. By default, SharePoint will create a heading link “Libraries” and list the libraries under it. But when you’ve got a lot of libraries, you might want to group them under different labels.

But any header link in the quick launch requires that you specify a URL from the web application’s domain root, i.e. “/sitename”. You do not always want this, if you’re simply grouping links in the quick launch, having a link there is not always wanted, especially if you want to create a site template from the site.

An easy way to “deactivate” the link is by replacing the URL with the following JavaScript: javascript:window.goback(0)

This link will still be valid for SharePoint (it requires that you enter a URL), but won’t cause any navigation to happen for the user.

Overcoming the “Content type is still in use” message when deleting unused workflow task content types

When you’re working on a workflow that contains task items or task processes from SharePoint Designer, SharePoint will create content types for these tasks. If you’ve been experimenting with several variations, you could end up with some left over content types for tasks that you’re no longer using. Of course, we’d want to keep this list clean. However, when you try to delete these unused content types, you’ll receive a “Content type is still in use” message.

This message indicates that a list or library is still using the content type. This will be the task list assigned to your workflow (usually “Workflow Tasks”). To remove the content type from the SharePoint site, you should first remove the content type (assignment) from all task-based lists. Go to the list settings and remove the content type.

You can now remove the content type from the content types gallery.

Get file extention in XSLT

When working with data view web parts or data form web parts in SharePoint, you might want to use some conditional formatting or branching logic, based on the file extention of your SharePoint item.

This xsl template returns the file extention from an URL:

<!-- Determine File Extention template -->
<xsl:template name="get-file-extension">
    <xsl:param name="path"/>
    <xsl:choose>
        <xsl:when test="contains($path, '/')">
            <xsl:call-template name="get-file-extension">
                <xsl:with-param name="path" select="substring-after($path, '/')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:when test="contains($path, '.')">
            <xsl:call-template name="get-file-extension">
                <xsl:with-param name="path" select="substring-after($path, '.')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$path"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

It runs recursively through the parameter “path” and returns the extention.

You can call and use it like this:

<xsl:variable name="extension">
	<xsl:call-template name="get-file-extension">
		<xsl:with-param name="path" select="@yourcolumnname" />
	</xsl:call-template>
</xsl:variable>
<!-- example use in branching logic -->
<xsl:choose>
	<xsl:when test="$extension = 'pdf'">
		<!-- add your logic -->
	</xsl:when>
</xsl:choose>

 

Different ways of scanning a document into SharePoint

SharePoint offers excellent ways to manage scanned documents, i.e. in PDF or XPS formats. Most scanners nowadays include software that automatically scans multiple page-documents and creates searchable PDF docs using OCR (text recognition).

When you’re scanning documents often, you’d want to minimize time and (manual) actions to get the documents into SharePoint. Luckily, SharePoint offers an array of possibilities to achive this. Furthermore, SharePoint is becoming more and more widespread in organizations, so many scanner manufacturers already support SharePoint connectivity out-of-the-box with their scanners and scanner-software. These are the most common methods:

SharePoint-ready scanners

The easiest way of scanning a document into SharePoint is achieved if the scanner-software manufacturer already prepared the scanner to work with SharePoint. This is already the case with many suppliers, such as Epson and Canon. Usually, this involves specifying the SharePoint address and port number and the user credentials to connect to this SharePoint site. These SharePoint-ready scanners usually work using the SharePoint Web Services and support WSS 3.0 / MOSS 2007, SharePoint 2010 and higher.

WebDAV

Web-based Distributed Authoring and Versioning (WebDAV) is an extension to the HTTP protocol, which makes it possible to manage files on a SharePoint document library from Windows Explorer. Some printer manufacturers support WebDAV out-of-the-box. When this is not the case, you could map a network drive letter to a WebDAV location, and treat the WebDAV location as a network share. There are different ways of doing this, depending on the Operation System. Use Google or Bing to find the one that works for you.

Email enabled libraries

If your scanner (software) does not support SharePoint or WebDAV directly, you could also specify an incoming email address for a library and send scanned documents to this address. Most scanners support scan-to-mail functionality. Be aware though, that this will impact your email infrastructure and keep email size limits in mind.

Alternate solutions

There are many more possible solutions, that may require (custom) development to some extend, depending on the flexibility of your scanner software. Examples include  using RESTful services within SharePoint 2010, PowerShell, the SharePoint Client Object Model, SharePoint Workspace, using File Classification Infrastructure (FCI) and more. Which one works best in your solution, depends primarily on the scanner and scanning software used, as well as the network infrastructure your users will be working in.