Discover unpublished files within a SharePoint web site

Here’s another small script that traverses a web hierarchy, seeking for files that are in a checked-out or unpublished (not approved) status.

function CheckPublishedFiles([Microsoft.SharePoint.SPFolder]$folder)

{

    foreach ($file in $folder.Files)

{

        $name = $file.Url

        try

        {

            $ok = (($file.Exists) -and ($file.OpenBinary() -ne $null));

            if ($ok)

           {

                $checkOutType = $file.CheckOutType

                if ($checkOutType -ne “None”)

                {

                    write-host “Checked Out: $name”

                }

                else

                {

                    $level = $file.Level                   

                    if ($level -ne “Published”)                   

                    {

                        write-host “Unpublished: $name”

                    }

                }

            }

        }

        catch

        {

            write-host “INVALID: $name”

        }

    }

    foreach ($subFolder in $folder.SubFolders)

    {

        CheckPublishedFiles $subFolder

    }

}

$web = get-spweb http://yourwebsite

$fld = $web.RootFolder

CheckPublishedFiles $fld

Discover corrupted files within a SharePoint web site

Although this is not exhaustive at all, since it uses a very simple mechanism to deem a file as corrupted (i.e. it tries to open it :-)), I found myself writing this little script and use it quite a lot of times.

Here it is:

Add-PSSnapin microsoft.sharepoint.powershell -ErrorAction SilentlyContinue

function CheckFiles([Microsoft.SharePoint.SPFolder]$folder)

{

    foreach ($file in $folder.Files)

    {

        $name = $file.Url

        try

        {

            $ok = (($file.Exists) -and ($file.OpenBinary() -ne $null));

            if (!$ok)

            {

                write-host “$name”

            }

        }

        catch

        {

            write-host “$name”

        }

    }

    foreach ($subFolder in $folder.SubFolders)

    {

        CheckFiles $subFolder

    }

}

$web = get-spweb http://yourweburl 

$fld = $web.RootFolder

CheckFiles $fld

Developer Dashboard settings

Yes, you can find this almost everywhere (even within sites that talk about food or cars :-)), but anyway, I’m writingt here just for reference.

Here’s some line of PowerShell code that set how the Developer Dashboard is displayed:

Add-PSSnapin microsoft.sharepoint.powershell -ErrorAction SilentlyContinue

$DevDashboardSettings = [Microsoft.SharePoint.Administration.SPWebService]::ContentService.DeveloperDashboardSettings;

$DevDashboardSettings.DisplayLevel = ‘***’;

$DevDashboardsettings.Update();

As a final note, remember that:

  • These settings are farm-wide
  • Having the Developer Dashboard “on demand” causes, at least in OOTB master pages, a small control to appear on the right upper corner of your pages. Which is fine (how would you launch the dashboard without some visual aid?) but sometimes can be painful: if you do not take care about this control beinig possibly there, you may end-up with a broken layout (imagine you have developed some custom master pages in an environment where the dashboard wasa off, then move everything into another environent where it is on-demand, and suddenly portions of your markup overflow… believe me, this may happen!!)

Measuring HTTP requests response time

Needless to say, this topic is complex, first of all because the total response time varies due to network congestion, server load, amount of bytes transfered just to name a few.

Anyway, if you just need to get a raw indication, you could just try out this small script:

function GetRequestTime([string]$url)

{

  $wc = new-object System.Net.WebClient

  $wc.Credentials = [System.Net.CredentialCache]::DefaultCredentials

  $start = get-date

  $output = $wc.DownloadString($url)

  $span = (get-date).Subtract($start)

  return $span.TotalMilliseconds

}

function ShootRequests([string]$url, [int]$count)

{

  $totalTime = 0

  1..$count |% { $totalTime += GetRequestTime($url)}

  return $totalTime / $count

}

What it does is firing for a request a configurable number of times and return the average response time. Here’s how you may invoke this function:

ShootRequests http://blog.claudiobrotto.com 50

Just a few notes, though:

  • It does not consider any client-side caching (you could easily overcome this issue by passing some query string parameter that makes the client consider it a brand new resource)
  • It does not download automatically any resource defined in the HTML of the page (i.e. if a page contains img tags that force the browser to download 10MB of content… this script just ignores that)
  • The rendering time is completely transparent too (you may have pages with a small network footprint but with a lot of JS code that slows doen the browser rendering)

Counting SharePoint list items

Well, this is a tipical situation when you may say “it’s easy”.

And it is, indeed, but you have to be aware of a couple of “small” issues.

First of all, you know that the SPListItemCollection class exposes a count property, you invoke it and voila, you get the total numebr of items contained within a SharePoint list.

But… be careful, because you are fetching *all* items, possibly causing a hige load on the server (SharePoint and SQL Server).

A better approach would be using the ItemCount property of the SPList class.

Which is what I would suggest, with a little gotcha: ItemCount returns exactlt what the name suggests, i.e. the count of all list items, and doing so it *does not* apply any sort of security trimming. In other words, if the code is run within the context of a user who has the rights to view only 5 out of a total of 10 list items, this property returns 10.

Pay a lot attention when you are looping or indexing an SPListItemCollection this way!

Managing IIS settings through PowerShell

Do you miss the IISAPP command line tool that was available with IIS6?

Do you feel that APPCMD is not enough?

Enter the WebAdministration PowerShell module!

Its usage is straightforward, as it it leverages the concept of providers and drives that the PowerShell engine uses to unify the way you access resources on your server. And it provides several commandlets that can help you automate most (if not all) of the web administration tasks.

In order to use the WebAdministration module, you need to launch PowerShell with elevated rights, then just import the module:

Import-Module WebAdministration

A quick Get-Command will show you that there’s something to try!

gcm -Module WebAdministration | Measure-Object

In my environment, this shows a total count of 74 items (71 commandlets, 2 aliases and one function).

I’ll let you explore the list of commandlets yourself, while I spend some other words about the function, whose name is “IIS:”.

Just like C:, D: etc, which are indeed just functions that set the current location to the root of the C or D drives, the IIS: function uses the Set-Location commandlet to “move” to the IIS: drive.

Which, of course, is not a drive based on the FileSystem provider, but is relies on the WebAdministration PowerShell provider that you get inside the WebAdministration module.

Thanks to this approach, you can easily “navigate” within IIS settings just by using “dir” or “cd” (which, btw, are aliases too). For examples, if you need to list the IIS Web Sites on the local server, just try with this syntax:

dir IIS:\Sites

Or if you need to get, say, the list of running w3wp.exe processes for a specific application pool, you can type something like this:

dir IIS:\AppPools\<NameOfTheAppPool>\WorkerProcesses

Nice, isn’t it?

PowerShell string escaping

Ok, this is probably a very very basic topic to tal about, but anyway…

String escaping has always been cumbersome and tricky in – I guess – most of the programming languages I have used. You need a way to represent special characters, most of the times you do this by defining them through an escape sequence, and most of the times the escape sequence is made up of an escape character followed by another character (or a character code). You know that \n stands for “newline” in ANSI C syntax, right?

PowerShell follows these widely adopted standards, with a couple of gotchas.

First off, the escape character is the backtick (`), which is 0x60 (96) ASCII code and the U+0060 Unicode code.

Which is fine, I mean, using a backslach or a backtick… it doesn’t matter.

Well, yes, it does’t matter, although I’m using the Italian keyboard layout and we have no grave accent (back tick) character anywhere. Sgrunf 🙁

Second: in PowerShell we can use both single quote and double quote characters to enclose string literals.

The difference stands in the way the string is interpreted before being used.

Consider, as an example, the MSSQL$SHAREPOINT string.

If you use single quotes (‘MSSQL$SHAREPOINT’), you get exactly what you have typed within the single quotes.

If you use double quotes, and try to print-out the string variable:

Write-Host “MSSQL$SHAREPOINT”

You get, guess what, just MSSQL on your output stream.

The reason for this behavior is due to the automatic variable substitution that the PowerShell intepreter performs and strings literals escaped by double quotes: variable names, in PowerShell, are prefixed by the $ char, which means that the previous string is resolved as MSSQL concatenated with the value of the SHAREPOINT variable, which in my case is just null.

Sometimes, even simple things get tricky!