PowerShell “here” strings

I’m using verbatim strings in C# quite a lot. Even when I have no explicit need, for example because there’s no escape sequence nor line break and I could just avoid typing the extra @ at the beginning.

I definitely like the fact that there’s a similar syntactic behavior in PowerShell too.

These are called “here” strings (more information here).

Although these two features have much in common, you have to pay some more attention when using here-strings in PowerShell, since the behavior is not *exactly* the same you get when you write C# code.

For example, line breaks are mandatory.

The “start sequence” tokens are indeed @”+CRLF or @’+CRLF.

And the same applies to “end sequence” tokens as well (CRLF+@” or CRLF+@’ respectively).

And in case you are wondering what’s the difference between the single quote vs. double quote syntax, well… the single quote version disables escape sequences, whereas the double quote version does not.

Strings have always been tricky.

When I started writing C/C++ code against the Windows API I was struggling with LPSTR, LPTSTR, LPCSTR, LPCTSTR to name a few (probably any combination of characters here would be a valid name, I’m sure there’s a typedef or a MACRO definition somewhere even for LPABCSTR :) ).

Then came COM and BSTR and smart pointers and… and that was real pain!!

0  

How to quickly identify large lists with PowerShell

It’s easy, and it’s just one line (without word wrapping J).

Get-SPWebApplication http://webappurl | Get-SPSite | Get-SPWeb |% { $_.Lists | select @{n=“Url”;e={$_.RootFolder.ServerRelativeUrl} }, Title, ItemCount } | sort ItemCount -Descending

Here I’m traversing the contents of a Web Application in order to iterate over each List (in each Web, in each Site of the Web Application):

Get-SPWebApplication http://webappurl | Get-SPSite | Get-SPWeb |% { $_.Lists | … }

Then, I’m using the Select-Object command-let to add a custom object to the pipeline, built from the list data using both standard properties (Title, ItemCount) and a calculated property for the list url:

{ $_.Lists | select @{n=“Url”;e={$_.RootFolder.ServerRelativeUrl} }, Title, ItemCount }

Finally, it’s just a matter of manipulating the custom objects collections, applying sorting, filtering, grouping or any other set operations according to your specific needs.

Here’s the output you may receive:

In addition, you may choose to bring these data into Excel for further analysis, which is extremely easy to achieve adding the Export-CSV command-let at the end of the pipeline.

Here’s a sample Excel spreadsheet generated from the data above, where I’ve applied a custom number filter to the data set and I have created a line chart on the data series:

0  

Grouping by a multi-value Managed Metadata Field using XSLT and a DataFormWebPart

First and foremost, I think that there’s a reason why grouping (generally speaking) is usually disabled when the group-by criteria is on a multi-value field.

Performance is probably the key point here: especially when you are dealing with semi-structured data (i.e. SharePoint list items), you need to extract a set of unique values first, on which, in a second pass, you apply your filtering logics.

Also, but this is just my personal opinion, having a result set where a single item may appear more than once (if it “belongs” to more than one group) is far from optimal. I would definitely prefer to rely on refiners, rather than on pre-pupulated item groups.

And finally… where, it’s a little bit tricky J

Here’s what I have done.

Scenario.

A document library with a Managed Metadata field which allows multiple values, named “OU” (which stands for, guess what, Organizational Unit J).

A DataFormWebPart fetching all items from that library.

And, of course, XSLT!

Implementation.

I started implementing a recursive template that parses the value of the taxonomy field and produces an XML tree.

<xsl:template
name=extractOU>

<xsl:param
name=list />

<xsl:variable
name=thisId
select=substring-before($list, ‘;#’) />

<xsl:variable
name=thisName
select=substring-before(substring-after($list, ‘;#’),’;#’) />

<xsl:variable
name=left
select=substring-after(substring-after($list, ‘;#’),’;#’) />

<ou
id={$thisId}
name={normalize-space($thisName)} />

<xsl:if
test=$left>

<xsl:call-template
name=extractOU>

<xsl:with-param
name=list
select=$left />

</xsl:call-template>

</xsl:if>

</xsl:template>

When applied to a field value such as:

1;#HR;#2;#Finance;#3;#Marketing;#

It would eventually produce an XML fragment similar to this one:

<ou
id=1
name=HR />

<ou
id=2
name=Finance />

<ou
id=3
name=Marketing />

 

I applied this template to the overall result set which is returned by the list query, saving the output into a variable:

<xsl:variable
name=items
select=/dsQueryResponse/Rows/Row />

<xsl:variable
name=groupsTree>

<xsl:for-each
select=$items>

<xsl:call-template
name=extractOU>

<xsl:with-param
name=list
select=concat(normalize-space(@OU.), ‘;#’) />

</xsl:call-template>

</xsl:for-each>

</xsl:variable>

This would generate an XML fragment with duplicate elements:

<ou
id=1
name=HR />

<ou
id=2
name=Finance />

<ou
id=3
name=Marketing />

<ou
id=2
name=Finance />

<ou
id=3
name=Marketing />

<ou
id=1
name=HR />

<ou
id=2
name=Finance />

 

In order to extract a set of unique rows (a “distinct” operation) and to iterate over its output, I had to first load the XML tree into a nodeset:

<xsl:variable
name=groups
select=msxsl:node-set($groupsTree)/* />

 

I used the MSXML node-set function, which is not necessarily the best way to achieve this goal, but unfortunately I could not use XSLT extensions (without extending the DataFormWebPart, which was out of scope here) nor I could use XSLT 2.0, which is not supported as well.

On that node set I could finally apply standard XSLT grouping techniques.

In this case I chose the Muenchian method (here you can find an excellent reference).

I defined a key based on the name attribute of my ou element:

<xsl:key
name=organizational-units
match=ou
use=@name />

And I finally used that key to filter the items within the overall set:

<xsl:for-each
select=$groups[count(. | key('organizational-units', @name)[1]) = 1]>

<xsl:sort
select=@name />

<xsl:variable
name=id
select=@id />

<xsl:variable
name=ou
select=@name />

<div
class=certification well>

<h2
class=subtitle text-center>

<xsl:value-of
select=$ou />

</h2>

<ul
class=unstyled inline>

<xsl:for-each
select=$items[contains(@OU., concat($id,';#',$ou))]>

<xsl:sort
select=@Title
order=descending />

<li
style=width:170px>

<div
class=wrapper
style=position:relative; text-align:center>

<xsl:value-of
select=@CertificationIcon0
disable-output-escaping=yes />

<div>

<a
title=@Title
href={@FileRef}
target=_blank>View</a>

</div>

</div>

</li>

</xsl:for-each>

</ul>

<div
style=clear:both></div>

</div>

</xsl:for-each>

 

As a final note, performance implications are quite noticeable here.

I have n+1 operations on the result set (1 to get the groups, n to extract values for the specific group I’m processing).

And I use a contains criteria to get the items back.

I could accept this since this library will only have a bunch of items (a few dozens), but this may not always be the case :P

 

0  

Moving SharePoint 2013 databases – Issue with different SQL Server Editions

If you are a SharePoint Administrator it’s possible that sometimes you need to move all SharePoint database (i.e. the configuration database, the content databases, the service application databases, etc.) to a completely different SQL Server box.

Well, it’s not something that you do on a daily basis, but you may need to perform this task in at least a couple of circumstances:

  • You are revamping the infrastructure and you have a super-powerful, brand new SQL Server cluster
  • You are performing a SQL Server consolidation (reducing the number of servers/instances)
  • You need to replicate a production environment back into the staging farm (sometimes the opposite is possible as well)

The technique is definitely feasible and is well documented in a number of places (see, for example, this page on Technet: http://technet.microsoft.com/en-us/library/cc512725.aspx).

In a nutshell, you use SQL aliases as a way of indirection.

SharePoint does not resolve the SQL instance by IP address or servername/port, but through a generic name (the alias).

You can modify the alias so that the connection is redirected to another instance, without affecting the SharePoint configuration (a part from the service interruption, of course).

That said (and coming back to the reason for this post) pay a lot of attention to the Edition of your SQL Server Box, even if you have the very same level of upgrades at the source and the target (for example, you move the databases from a SQL Server 2008 R2 + sp1 box to another SQL Server 2008 R2 + sp1 box).

SharePoint does not require the Enteprise Edition of SQL Server, but it leverages Enterpise features if these features are available!!

So if you are trying to move a database from Enterprise to Standard, you may be lucky or not according to whether any enterprise specific configuration has been applied.

Just to make an example, SQL Server Enterprise supports data compression for tables and indexes.

Some SharePoint databases make use of data compression, if it is available (for example, I verified this on the Links Store db used by the Search Service Application on a SP2013 farm).

You can revert to an uncompressed database (table/index), but I guess you will end up completely out of support (you are modifying a database directly).

So… be careful and always perform all verifications beforehand J

0  

Deleting a Site Collection that cannot be deleted

Today I stumbled upon a strange issue on a production SharePoint 2013 Farm.

I had a bunch of site collections created using a batch script, and one of those was unreachable.

It’s quite common (well, at least… it happens sometimes J) that a site creation process may fail, resulting in resources not provisioned correctly.

Since file provisioning is one of the last operation that is performed during site creation, you may get a 404 accessing the site home page.

But this was not the case. I got a 400 response (i.e. Bad Request). I could not even navigate to application pages (which are not “provisioned” as ghosted resources).

The symptoms of something gone wrong were quite evident in several places.

The Central Administration displayed the site in the sites list, but without any reference to the Content Database where it should have been created. No way to remove it using the web interface (all pages displaying information about the site had no content at all).

Ok, let’s clean it up and remove via script.

A simple Get-SPSite returned a valid object. But a subsequent Remove-SPSite failed with the dreaded “Unknown SPRequest error.occurred”.

I had not time to investigate, so I had to find a quick solution, sort of a “force delete” where the site cannot be deleted.

Therefore I used a not-so-well-know operation on the Content Database object: Microsoft.SharePoint.Administration.SPContentDatabase::ForceDeleteSite (see http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.spcontentdatabase.forcedeletesite.aspx).

The PowerShell code is definitely simple:

$site = Get-SPSite http://siteurl

$siteId = $site.Id

$siteDatabase = $site.ContentDatabase 

$siteDatabase.ForceDeleteSite($siteId, $false, $false)

As the documentation clearly states:

This way I managed to remove the corrupt site collection (and recreate it again with the same command I had used for the batch script, which completed successfully).

Hope useful J

0  

Italian SharePoint and Office Conference 2013 – What’s new in SharePoint Designer 2013 Workflows

(again, for my non-Italian readers, I’m switching to Italian language here)

What’s new in SharePoint Designer 2013 Workflows è la terza ed ultima sessione del “trittico” sui workflow che presenteremo alla SharePoint and Office Conference 2013.

Il titolo lascia immaginare quale sarà lo strumento che io e Riccardo useremo durante la sessione.

Uno strumento con cui si realizzano workflow dichiarativi – è sempre stato così, solamente che ora sono dichiarativi anche quelli sviluppati in Visual Studio J – in modo flessibile ed espressivo.

E questa è invece un’enorme novità, se pensate che su piattaforma 2010 non c’era verso (se non con forzature non prive di difetti) di definire loop e tantomeno blocchi di esecuzione non sequenziali.

Anche flussi semplice come quello rappresentato qui sotto diventavano “scomodi” per ragioni di struttura, ancor prima che di complessità nella logica.


Per inciso, questo qui su è un diagramma Visio, che si presenta così *nella* design surface di SPD, perfettamente modificabile quanto ad azioni e relative proprietà.

Insomma, persa(*) una Design View, ecco che ne spunta un’altra :P

 

(*) Design view and Split view (MSDN)

Description of the change.

SharePoint Designer 2010 has three views for editing HTML and ASPX pages: Code view, Design view, and Split view. Design view and Split view are removed from SharePoint Designer 2013. The removal of Design view and Split view affects the features of SharePoint Designer 2013 that are used for editing Web Parts and master pages. If you edit pages in SharePoint Designer 2013, you must use Code view.

Reason for the change.

Compared to current versions of Internet Explorer, Design view is an older technology that does not support many new HTML5 and CSS tags.

Migration path.

If you edit pages in Code view, you can press F12 to preview the page in the browser. Alternatively, you can use Visual Studio to edit pages.

If you want to visually design or brand your site, and you want a WYSIWYG (“what you see is what you get”) page-editing experience, you can use any professional HTML editor, such as Microsoft Expression Web. Then you can import your HTML files into SharePoint Server 2013 by using the new Design Manager, which is a feature included in publishing sites, such as the Publishing Portal Site Collection site template.

0  

Italian SharePoint and Office Conference 2013 – What’s new with Workflow in SharePoint 2013

(for my non-Italian readers, I’m swithcing to Italian language here, but you can use some online translation service to have this post translated… and have fun with the results J)

Credo che tutti sappiate che il 5-6-7 marzo si terrà a Milano la SharePoint and Office Conference.

Sul sito dell’evento trovate ogni tipo di informazione, dai contenuti alla logistica.

E ovviamente potete (dovete J) registrarvi, sfruttando, se siete veloci J, l’early bird ancora valido per alcuni giorni dal momento in cui scrivo.

Quest’anno terrò quattro sessioni, in coppia con Paolo Pialorsi, Riccardo Celesti ed Elisabetta Sasselli (in rigoroso ordine di agenda J).

Sempre nello stesso rigoroso ordine di cui sopra, inizio quindi a parlarvi della prima: What’s new with Workflow in SharePoint 2013.

La prima in cui sono coinvolto io, ma la seconda di un filotto di tre, tutte incentrate sul tema Workflow, affrontato da prospettive e con premesse diverse.

Paolo inizierà le danze ed introdurrà Workflow Foundation 4.x: chi ha utilizzato (configurato, sviluppato o… troubleshootato, se si può dire) workflow su SharePoint 2010 potrebbe non aver mai avuto modo di giocare con WF4, che è invece alla base di quanto Paolo ed io illustreremo nella sessione successiva.

Le novità legate all’ambito Workflow su SP2013 sono rilevanti (e forse dire rilevanti è poco).

Se mi aveste chiesto, un annetto fa, la mia previsione su questo tema, avrei scommesso in un’introduzione di WF4 (era scontato) su un’architettura analoga all’attuale, in cui SharePoint fa da host del nuovo workflow runtime, sfruttandone ovviamente le novità e i miglioramenti.

Avrei sbagliato!

Perché i workflow in SharePoint 2010 erano così:

E con qualche *lieve* facelifting sono diventati circa così:

Per i più attenti… spot the difference J

Dedicheremo un po’ di tempo a queste slide, nella nostra sessione.

E vedremo insieme che cosa si porta dietro la nuova architettura, sia dal punto di vista dell’infrastruttura (deployment, monitoring, governance) e soprattutto (visto che Paolo è un dev e io, nonostante i miei continui sforzi, un pochettino ancora J) dal punto di vista dello sviluppatore: nuovo framework, nuove API, nuovi tool, nuove modalità.

Ci si vede a Milano!

0  

SharePoint MVP 2013

Yesterday I received an email from my MVP Lead.
I have been renewed as a SharePoint Server MVP for the fifth year in a row :-)
It’s a great honor and a huge pleasure for me.

I wish to congratulate with all new and renewed MVPs.

And special compliments to Igor (my friend, colleague and boss @ Green Team) and Robi Voncina, whom I met in Slovenia during the local SharePoint Events and who has been awarded for the first time.
Thank you!

1  

SharePoint Future 2012

SharePoint Future 2012

SharePoint Future 2012

We launched the SharePoint Future brand back in 2009, during the very early days of the SharePoint 2010 beta timeframe.

It was the first event in Italy (and probably the first or the second one in Europe) about SharePoint 2010, just a week after the public disclosure, which took place during the SharePoint Conference in Vegas.

Three years after, the new “15″ wave is the new “future”: SharePoint 2013 reached RTM some weeks ago, bringing to the masses a plethora of new and exciting features in most, if not all, of the pillars that constitute the SharePoint platform.

It’s time for a new edition of the SharePoint Future event!

SharePoint Future 2012 will take place in Milan on November 27.

On the event website, you can find all the information you need: content, logistics, registration.

I will be presenting 2 sessions about Search and Web Content Management and about the new Developer stuff, with special emphasis on the new Workflow platform.

And… well, this is just a small prelude of what we’ll be talking about during the SharePoint and Office Conference 2013.

See you in Milan!

 

 

0  

It’s new, it’s green

And it’s finally live: the new Green Team web site!

It’s been rebuilt from scratch, using SharePoint 2010 as the CMS publishing infrastructure.

The web design was created independently from the SharePoint-isms using a Responsive Layout pattern based on plain HTML5/CSS3. Then it was “applied”, i.e. converted into SharePoint master pages and page layouts.

Most of the content targeting is driven by Managed Metadata terms and rollup techniques leveraging CQWP and Search.

There’s some multimedia content also, produced internally by our multimedia gurus Smile… they have almost succeeded in making myself an actor (take a look at the video from the home page).

Hope you like it!

0