Creating a Custom PowerShell Function for SharePoint

In previous articles I showed you how to develop custom PowerShell cmdlets using Visual Studio. In this article we will cover how one can go about creating custom function using native PowerShell scripts. The method we will create will accept piping parameters to it in order to fully leverage the power of PowerShell. To demonstrate this, we will go and create a new PowerShell function name Get-SPListItemCount that will receive and SPList object as an input parameter, and will output a custom PowerShelll object containing two parameters: the list title, and the number of items contained within it.

To begin our example, let’s have a look at what our code will look like for the function. The following block of PowerShell script represent the logic of our function (very basic logic):

Function Get-SPListItemCount

{

param(

[Parameter(Mandatory=$true,

ValueFromPipeline=$True)]

$list

)

[PSCustomObject]@{‘List’ = $list.Title; ‘Item Count’ = $list.ItemCount}

}

From the code above, we start off by declaring function Get-SPListItemCount. Then to start off the function declaration, we specify what parameters our method will be accepting, in our case a single parameter, named $list which represents the received SPList object for which we wish to obtain the item count. Using the Parameter, we specify three very important settings. First, that the parameter is mandatory, meaning we require the user the pass in at least one parameter, second that the parameter can be received by the pipeline (using the PowerShell ‘|’ operator), and third that the parameter received will be assigned to the $list variable within the function.

Then using the [PSCustomObject] operator, we ensure that our function returns a custom PowerShell object that will contain two properties: the Title of the list received as a parameter, and the ItemCount property of that same list which represents the total number of SPList item contained within the list.

Putting it all together, we can then call into our custom function throughout our script in the following manner:

$web = Get-SPWeb http://localhost

$web.Lists[“Documents”] | Get-SPListItemCount

The example above obtains a reference to the “Documents” library located at the rootweb (http://localhost), then passes it to our custom Get-SPListItemCount method using the pipeline operator. The following figure shows the result of executing our script using PowerShell:

20150416-01.png

Bridging the Gap Between IT Pros & Devs using PowerShell

The title of this article also happens to be the title of my PowerShell book. For a long tiem I’ve been wanting to go and write a non-technical article explaining how I envision the future of traditional IT shops with the rapid growth of PowerShell in the industry. When I first started working with SharePoint 2003 back in 2006, my role was to develop several webparts and application pages for my company. The environment I was maintaining had over 1,500 site collections with about 150 sites each. Whenever I created a new webpart, I had to go back and add it retro-actively to all sites (150 * 1,500 = 225,000 sites). Off course there was not way in hell I was going to do this manually. Instead, I started creating new console applications from within Visual Studio (VS 2005 at the time), and had to my application loop through all site collections, through all sites, and add the webpart to the main page of each one using the SharePoint Object Model and some C# code. Then my application was packaged as an .exe (a.k.a. total black box), and this executable file was sent off to the servers’ administrators for them to execute directly on the SharePoint servers (starting with the dev environment off course). I can just imagine being in their shoes, where some crazy developer just gave me a piece of executable, that I need to trust does20150415-01.png what the developers says it does, and then simply have to execute it on the server and wait for hours for it to complete. I used to be known as the “Dev cow-boy” back then due to my total lack of risk adversion 🙂 Depending on the timeframes I had, I would even threat the administrators with some verbose logging of what was really happening in the background…..if I had the time. Otherwise, they would be starting at a good old black MS-DOS style dialog for quite a while.

That is how I use to do it back in the days. The dev guys were doing the work, and then the admins had to trust them entirely, and only be invovled at the very end of the process, whenever the code was all finalized. They had no say really in the code’s logic, and had no exposure to the SharePoint object model. This very often initiated very interesting discussions between the dev teams and the administrators. “You need to activate the feature at the SPSite level!”……”Say what???”. On one end you had developers spending their times in C# and the SharePoint object model, and on the other end, you had the administrators trying to do everything using batch files and STSAdm.exlifelong-learning-skills-gap.jpge. Looking back at it, I think the worst part was that developers used to improvised them as being adminsitrators. I remember my team creating such a .exe console app to automate the creation of Shared Service Providers (SSPs), the ancestors of the SharePoint 2010 Service Application architecture. This is some scary stuff, since the devs at total control over components that could directly have a huge negative impact on the overall stability of the environment (god knows that th SSPs were shaky at best). Back then, the gap between IT Pros and the developers was incredibly hard to bridge.

Then towards the end of life of SharePoint 2007 (beginning of year 2009), a new technology emerged at Microsoft: PowerShell. This technology opened up a lot of possibilities for both the developers and the IT Pros. First off, it was for most scenario, faster to accomplish a task than the STSAdm. Secondly, it now allowed developers, who were willing to learn the language, to provide their servers admins with a clear text .ps1 file that they could open and read instead of the scealed box that was the console applications my team used to write. Even if the IT Pros didn’t want to learn the object model and understand exactly what each line of code was doing, it was at least giving them the false feeling that it was not only a Dev thing anomore, and that they had some little more control as to what was being execued on their servers. One problem remained however, in order for one to write an efficient script, they had to learn and understand the SharePoint Object model. Back then, with SharePoint 2007, you didn’t have any PowerShell cmdlets to help you out. So for example, if you wimage002.pngished to acquired the number of items contained in a specific SharePoint list, say “Fruits”, your code would have looked like the following:

[Void][System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint”)
$site = New-Object Microsoft.SharePoint.SPSite(“http://portal”)
$web = $site.RootWeb
$list = $web.Lists[“Fruits”]
$count = $list.Items.Count

Therefore, even if there was some light at the end of the tunnel, there was still a huge gap in that in the eyes of IT Pros, the lines of code above are dev specific and most of them had no interest in learning how to become a programmer.

Then at the end of year 2009, Microsoft revealed what was to become SharePoint 2010, and everything changed. Microsoft introduced over 400 SharePoint specific PowerShell cmdlets. These “shortcut” methods made the code required to accomplish a set of very powerful actions against a SharePoint environment extremely simple, and most of all, human readable to both IT Pros and Devs. I think that this is where the true power of PowerShell resides. Both developers and IT Pros were now given the tools to write their own scripts. Off course IT Pros still had to learn a bit about the Object Model if they wished to interact with what I consider to be lower level objects (lists, items, views, pages, etc), and developers still had to understand some SharePoint architecture concepts if they wished to interact with higher level objects (Shared services applications, Web Applications, etc.), but all in all, the gap between devs and admins was being bridged! Based on my example above, with the venue of SharePoint specific PowerShell cmdlets, one could now achieve the same result with the following lines of code:

$web = Get-SPWeb http://localhost

$list = $web.Lists[“Fruits”]

$count = $list.Items.Count

3 lines instead of 6, and the code if much more readable.  PowerShell is just that great. It completely changed the story for SharePoint as far as I am concerned. You guys just stay tuned for what is coming up with SharePoint 2016 🙂 !

Get a List SharePoint Sites Recently Modified using PowerShell

On many occasions, my team has been asked to produce a list of all SharePoint sites we had in our Web Application​, as well as the date there was any action on the site (list item or documents CRUD operations). The idea behind the following script is that a user would input a date, and that the PowerShell script will list all workspaces that have had some action after that date. Now, I understand that I most cases, you may wish to get the opposite information (sites that haven’t been touched since a specific date). This information can be obtained by making minor modifications to the script.

Let’s begin! The property that is key for achieving what we are trying to accomplish, is the .ItemLastModifiedDate property of the SPWeb object. This property returns a Date object that indicates the date at which any list item or document was last modified within the site. With that information in hand, all we have to do from there is to compare it against the date the user input in the script and make a decision whether the last modified date is newer or not. One big caveat here is that very often, Cummulative Updates or Service Packs will automatically set the last modified dates of all libraries and lists across all sites to the date they were installed. Please take this into consideration when doing your tests.

$dateInput = Read-Host “Please enter a Date”)

$date = (Get-Date $dateInput)

$url = Read-Host “Please enter the URL of your Web Application”

$webApp = Get-SPWebApplication $url

foreach($site in $webApp.Sites)

{

foreach($web in $site.AllWebs)

{

​if($web.ItemLastModifiedDate -lt $date)

{

​Write-Host “Site Found:” $web.Url

}

$web.Dispose()

}

$site.Dispose()

}