Workflow: __SharePoint 2010 Output Variablen löschen

Wenn man in einem SharePoint Designer 2013 Workflow die Aktion zum Starten eines (2010) Workflows verwendet, wird im Hintergrund eine völlig überflüssige Variable angelegt. Ebenso jedes Mal wenn man an der Aktion etwas ändert. Diese Variablen sind über die normale SharePoint Designer Oberfläche nicht zugänglich, außer in den Nachschlagedialogen. Dort findet man sie mit solchen Namen:
__SharePoint 2010 Output: <Name des zu startenden Workflows>.

Die Variablen an sich sind ja kein Problem, aber ein Workflow darf nur maximal 50 Variablen haben und selbstverständlich zählen diese „unsichtbaren“ Variablen da mit. Auch wenn man sie auf normalem Weg nicht wieder entfernen kann. Danke Microsoft für diesen Blödsinn!

Man muß also schon etwas tiefer in die Trickkiste greifen, wenn man nicht den ganzen Workflow neu machen möchte:

  • Man öffnet die Website mit dem Windows Explorer. Am einfachsten geht das, wenn man in eine Dokumentbibliothek navigiert und dort den Button „Mit Explorer öffnen“ klickt.
  • Im Root der Website findet man einen Ordner wfsvc, den man öffnet.
  • Darin findet man für jeden 2013 Workflow der Website einen Ordner mit einer GUID als Namen. Zum Identifizieren des richtigen Ordners bleibt also nur das Änderungsdatum. Im Zweifel macht man in SharePoint Designer eine Änderung am Workflow und schaut dann nach dem Ordner mit aktuellem Datum.
  • Im Ordner findet man eine Datei workflow.xaml, die man mit einem geeigneten Editor öffnet. Es ist eine XML-Datei, aber Vorsicht: der Editor darf keinerlei Formatierungen, Whitespace, Zeilenumbrüche oder ähnliches einfügen. Microsoft nimmt einem das übel.
  • In der Datei sucht man jetzt nach „__SharePoint 2010 Output“ und löscht alle
    <x:Property Name=“__SharePoint 2010 Output: …“. Dabei darauf achten, daß immer das ganze XML-Element gelöscht wird. Und natürlich nur das und nicht mehr.
  • Der Workflow muß danach noch in SharePoint Designer geöffnet werden und alle Aktionen zum Starten eines Workflows müssen neu konfiguriert werden.

Für den Fall des Falles macht man sich natürlich vorher ein Backup dieser Datei…

Mein Blog ist umgezogen

Nachdem mein Blog seit mittlerweile einigen Jahren auf einem eigenen SharePoint 2010 mit CKS:EBE lief, mußte ich mir doch langsam Gedanken um eine Migration machen. Mit einigem Gewürge bekommt man dieses Konstrukt auch auf SharePoint 2013 zum Laufen, aber ich wollte das dann doch nicht ewig so weiter treiben. Praktischerweise hatte René Hézser vor einiger Zeit genau dasselbe Problem und auch gleich die Lösung: er entwickelte ein Tool, das SharePoint-Blogs mit allem drum und dran nach WordPress migriert. Die Beschreibung und den Download findet man hier in Renés Blog. Ich habe es getestet und es hat auf Anhieb funktioniert – ich hätte aber auch nichts anderes erwartet🙂

Und damit werden meine Beiträge zukünftig hier erscheinen. An der alten Stelle ist eine Weiterleitung eingerichtet. Leider ist es mir dabei nicht gelungen, die einzelnen Beiträge auf sich selbst weiterzuleiten. D.h. alle alten Links werden jetzt auf die neue Startseite geleitet. Ich kann das leider nicht ändern. Ich werde versuchen im Laufe der Zeit alle mir bekannten Links anzupassen.

Und noch die Bitte: wenn jemand falsche Links innerhalb der Seiten oder auch sonstwo findet, sendet mir bitte eine kurze Nachricht oder hinterlaßt einen Kommentar.

Sollte ich mal etwas Zeit übrig haben (also wahrscheinlich nie🙂 ), kümmere ich noch etwas um das Design.

SharePoint Multiclient Anwenderstudie 2016

Die Hochschule der Medien Stuttgart führt wieder eine Online-Befragung durch und auch dieses Mal auch von mir der Aufruf mitzumachen. Es gibt wieder etwas zu gewinnen!

Auf der Seite heißt es dazu:

die Verbreitung der Portalsoftware Microsoft SharePoint ist in den letzten Jahren enorm gestiegen.

Die Frage ist: Wie zufrieden sind die Kunden? Dieser Thematik geht die Hochschule der Medien unter der Leitung von Prof. Dr. Thorsten Riemke-Gurzki und Prof. Dr. Arno Hitzges in der vorliegenden Befragung nach.

Ziel ist es, die Meinung der tatsächlichen Anwender zu erfragen, um auf Grundlage der Aussagen Rückschlüsse auf den Prozess der Nutzung von Intranet und Unternehmensportalen und der Integration von Microsoft SharePoint vornehmen zu können.

SharePoint 2013: „Mehr anzeigen“ Link auf Formularen entfernen

Und hier gleich noch ein Beitrag zum Thema Anpassung von Aufgabenformularen in SharePoint 2013. Hier ging es darum, die Verwandten Elemente auch auf dem EditForm anzuzeigen. Jetzt soll noch gezeigt werden, wie man den meiner Meinung nach völlig überflüssigen „Mehr anzeigen“ Link von den Aufgabenformularen entfernen und gleich alle Felder darstellen kann.

Der Link selbst ruft nur eine JavaScript-Funktion rlfiShowMore auf. Das machen wir uns zunutze, indem wir diese Funktion einfach selbst aufrufen, sobald die Seite geladen ist. Auf dem Formular muß dazu nur diese Zeile Script eingefügt werden:

_spBodyOnLoadFunctionNames.push(„rlfiShowMore“);

SharePoint 2013: Verwandte Elemente auf dem EditForm anzeigen

Bei SharePoint 2013 haben Workflowaufgaben standardmäßig eine Spalte Verwandte Elemente (Related Items). Leider ist diese Spalte ohne weiteres Zutun nur auf dem Formular zur Anzeige (DispForm) vorhanden und auch nur dort pflegbar.

SharePoint 2013 Workflows fügen beim Erstellen einer Aufgabe dort einen Link zum Element ein, auf dem Workflow läuft. Wenn man also einen Workflow hat, der z.B. Aufgaben erstellt, mit deren Hilfe etwas genehmigt werden soll, hat es durchaus Sinn diesen Link auch auf dem Änderungsformular (EditForm) darzustellen. Die genehmigende Person hat dann direkt auf dem Formular, mit dem sie arbeitet, auch einen Link zum Element, das genehmigt werden soll.

Das ist mal wieder ein typischer Fall für JavaScript. Das notwendige Script dazu kann man, wie fast immer, entweder in einem Script Editor Webpart oder per SharePoint Designer direkt im Code der Seite unterbringen.

SharePoint stellt zum Zugriff auf die Verwandten Elemente das Objekt SP.RelatedItemManager zur Verfügung. Es befindet sich in der Datei sp.js und kann erst verwendet werden, wenn diese geladen ist. Wir beginnen das Script also so:

ExecuteOrDelayUntilScriptLoaded(function() {
    // hier der Code
}, "sp.js");

Wir benötigen den ClientContext, den man auf die bekannte Art bekommt. Außerdem die ID der Aufgabenliste, die man aus dem _spPageContextInfo-Objekt bekommt. Und schließlich die ID der Aufgabe, die man aus der URL holen kann. Wir bedienen uns hierzu der altbekannten Methode getQueryStringParameter:

function getQueryStringParameter(paramToRetrieve) {
  if (document.URL.indexOf("?") > 0) {
    var params = document.URL.split("?")[1].split("&"),
        i,
        singleParam;
         
    for (i = 0; i < params.length; i++) {
      singleParam = params[i].split("=");
      if (singleParam[0] == paramToRetrieve)
        return singleParam[1];
    }
  }
  return "";
}

Mit diesen Werten liefert uns SP.RelatedItemManager direkt die Verwandten Elemente zur aktuellen Aufgabe:

var ctx = SP.ClientContext.get_current(),
    itemId = getQueryStringParameter("ID"),
    relItems = SP.RelatedItemManager.getRelatedItems(ctx, _spPageContextInfo.pageListId, itemId);

Jetzt braucht es nur ein executeQueryAsync und die Verwandten Elemente können benutzt werden. Es handelt sich dabei um ein Array, das Objekte enthält. Die Objekte haben eine get_url() Methode, die die URL des Elements liefert. Sie kann direkt z.B. in einen Link eingebaut werden. Und es gibt eine get_title() Methode, die den Anzeigenamen liefert, der z.B. als Text für den Link verwendet werden kann.

Hier nur ein kleines Beispiel, wie damit per jQuery ein Link in einem vorher bereitgestellten Container mit der ID myContainer erzeugt werden kann. Dazu nochmal das gesamte Script zum Kopieren und Einfügen:

ExecuteOrDelayUntilScriptLoaded(function() {
    var ctx = SP.ClientContext.get_current(),
        itemId = getQueryStringParameter("ID"),
        relItems = SP.RelatedItemManager.getRelatedItems(ctx, _spPageContextInfo.pageListId, itemId);
    ctx.executeQueryAsync(function() {
        var html;
        if (relItems.length > 0) {
            html = "<a href=’" + relItems[0].get_url() + "‘ target=’_top‘>" + relItems[0].get_title() + "</a>";
            $("#myContainer").append(html);
        }
        }, function() {}
    );

    function getQueryStringParameter(paramToRetrieve) {
        if (document.URL.indexOf("?") > 0) {
            var params = document.URL.split("?")[1].split("&"),
                i,
                singleParam;
         
            for (i = 0; i < params.length; i++) {
                singleParam = params[i].split("=");
                if (singleParam[0] == paramToRetrieve)
                    return singleParam[1];
            }
        }
        return "";
    }
}, "sp.js");

SPWeb.EnsureUser und Claims

Jeder SharePoint-Entwickler kennt wahrscheinlich die EnsureUser-Methode der SPWeb-Klasse (Beschreibung bei MSDN). Der Methode übergibt man einen Benutzer in der Form Domäne\Login und bekommt eine gültige SPUser-Instanz und zwar unabhängig davon, ob der Benutzer in der Website bereits bekannt ist oder nicht.

Das war jedenfalls "früher" der Fall, d.h. vor der Benutzung von Claims-Authentifizierung. Wird die betreffende Webanwendung mit Claims betrieben, was bei SharePoint 2013 Standard ist, muß man etwas anders vorgehen. Dasselbe gilt für SharePoint 2010 wenn Claims benutzt wird.

Die Angabe von Domäne\Login reicht alleine nicht mehr aus und man muß zusätzlich angeben um welche Art von Benutzer es sich handelt. Mit Claims-Authentifizierung können schließlich auch andere Arten von Benutzerquellen als nur Active Directory verwendet werden. Hier die grundsätzliche Vorgehensweise:

string account = @"domain\login";
SPClaimProviderManager cpm = SPClaimProviderManager.Local;
SPClaim userClaim = cpm.ConvertIdentifierToClaim(account, SPIdentifierTypes.WindowsSamAccountName);
SPUser user = web.EnsureUser(userClaim.ToEncodedString());

Der Code benötigt folgendes using-Statement:

using Microsoft.SharePoint.Administration.Claims;

Der gezeigte SPIdentifierTypes.WindowsSamAccountName gilt für AD-Benutzer. Je nach Herkunft des gesuchten Benutzers muß hier ein anderer Typ angegeben werden.

SharePoint 2013: Distributed Cache aktuell halten

Der Distributed Cache Dienst (AppFabric) spielt in SharePoint 2013 eine sehr wichtige Rolle und entgegen früherer Aussagen von Microsoft, er würde zusammen mit SharePoint aktuell gehalten, ist man selbst für die Aktualität verantwortlich.

Ich beziehe mich hier auf diesen Beitrag von Wictor Wilén. Er beschreibt dort sehr ausführlich die genauen Schritte und auch warum etwas wie gemacht werden sollte. Als persönliche Referenz fasse ich hier nur in aller Kürze die notwendigen Schritte zusammen. Dabei beziehe ich mich auf das derzeit aktuelle CU5, das hier heruntergeladen werden kann.

Schritt 1: Distributed Cache anhalten. Das geht in der SharePoint Management Shell so:

Stop-SPDistributedCacheServiceInstance -Graceful

Schritt2: Das Update installieren. Dazu einfach die heruntergeladene Datei durch Doppelklick starten.

Schritt 3: Eine kleine Anpassung in der Konfigurationsdatei. Dazu Notepad (oder einen anderen Editor) als Administrator starten und diese Datei öffnen:

Program Files/AppFabric 1.1 for Windows Server/DistributedCacheService.exe.config

In diese Datei fügt man irgendwo innerhalb von <configuration> … </configuration> folgendes ein:

<appSettings>
  <add key="backgroundGC" value="true" />
</appSettings>

Schritt 4: Distributed Cache wieder starten. Das geht ebenfalls in der SharePoint Management Shell:

$svc = Get-SPServiceInstance | ? { $_.TypeName -eq "Distributed Cache" -and $_.Server.Name -eq $env:computername }
$svc.Provision()

Diese Schritte müssen nacheinander auf allen Servern der SharePoint Farm ausgeführt werden, auf denen der Distributed Cache läuft.

Eine Assembly in den GAC bringen beim Windows Server

Da ich mich immer wieder darüber ärgere, daß es seit einigen Versionen von Windows Server nicht mehr so einfach ist, eine Assembly (.dll) in den GAC zu bringen, hier eine kurze Notiz wie man das mit PowerShell erledigen kann. Früher ging das mal ganz einfach per Drag&Drop im Windows Explorer…

Eine Assembly dem GAC hinzufügen:

[System.Reflection.Assembly]::LoadWithPartialName("System.EnterpriseServices")
$publ = New-Object System.EnterpriseServices.Internal.Publish
$publ.GacInstall("C:\temp\MyAssembly.dll")

Wenn die Assembly im IIS benütigt wird, z.B. weil man es mit SharePoint zu tun hat, braucht es noch einen iisreset.

Wenn man eine Assembly wieder aus dem GAC entfernen möchte:

[System.Reflection.Assembly]::LoadWithPartialName("System.EnterpriseServices")
$publ = New-Object System.EnterpriseServices.Internal.Publish
$publ.GacRemove("C:\temp\MyAssembly.dll")

Zum Entfernen braucht es also tatsächlich die Assembly im Dateisystem. Wenn man sie dort nicht hat, kann man sie mit dieser Zeile aus dem GAC kopieren:

dir C:\Windows\Assembly –Recurse –Filter "MyAssembly.dll" | foreach { copy $_.FullName C:\temp }

Anwenderstudie SharePoint 2014/2015

Die Hochschule der Medien in Stuttgart führt eine Online-Befragung zur Kundenzufriedenheit durch und hat mich gebeten, mit zur Verbreitung beizutragen. Deshalb hier der Aufruf: bitte nehmt an der Befragung teil! Es gibt auch etwas zu gewinnen!

Auf der Seite heißt es dazu:

die Verbreitung der Portalsoftware Microsoft SharePoint ist in den letzten Jahren enorm gestiegen.

Die Frage ist – wie zufrieden sind die Kunden? Dieser Frage geht die Hochschule der Medien unter der Leitung von Prof. Dr. Thorsten Riemke-Gurzki und Prof. Dr. Arno Hitzges in der vorliegenden Befragung nach.

Ziel ist es, die Meinung der tatsächlichen Anwender zu erfragen, um auf Grundlage der Aussagen Rückschlüsse auf den Prozess der Nutzung von Intranet und Unternehmensportalen und der Integration von Microsoft SharePoint vornehmen zu können.

Und hier nochmal der Link zur Befragung.

Inhaltsdatenbank von SharePoint 2010 nach 2013 migrieren

Dieser Beitrag beschreibt, wie man eine Inhaltsdatenbank von SharePoint 2010 nach SharePoint 2013 migriert und welche Probleme dabei im Bezug auf die Authentifizierungsmethode auftreten können. Es geht dabei wirklich nur um die Vorgehensweise beim Migrieren einer Inhaltsdatenbank. Beim Planen und Durchführen einer kompletten Migration ist wesentlich mehr zu beachten! Hier finden sich dazu ausführliche Informationen bei TechNet.

Ich habe diesen Prozeß bereits einige Male gemacht, mußte aber immer wieder Kleinigkeiten z.B. zur genauen Syntax der PowerShell-Cmdlets nachschlagen. Es handelt sich hierbei also durchaus auch um eine Nachschlagemöglichkeit für mich selbst.

Datenbankbackup auf dem alten System

Zunächst wird die Inhaltsdatenbank vom alten zum neuen System verschoben. Es gibt dazu mehrere Möglichkeiten, aber die einfachste dürfte in den meisten Fällen Backup und Restore sein. Dazu verwendet man z.B. das SQL Management Studio. Weil es in diesem Blog in erster Linie um SharePoint und nicht um SQL Server geht, werden die einzelnen Schritte hier nur kurz erläutert.

Wenn man ein Backup einer Inhaltsdatenbank erstellen möchte, sollte man verhindern, daß ein SharePoint-Prozeß während des Backups in die Datenbank schreibt. Dazu kann man entweder die Verbindung zwischen SharePoint und SQL Server kappen oder den oder die SharePoint-Server herunterfahren oder ganz einfach die Datenbank auf read-only setzen. Natürlich kann in dieser Zeit kein SharePoint-Benutzer mit den Daten dieser Datenbank arbeiten.

Um eine Datenbank read-only zu machen, klickt man im SQL Management Studio mit der rechten Maustaste darauf und dann auf Properties. Die entsprechende Einstellung findet sich hier unter Options:

Jetzt kann man durch Rechtsklick > Tasks > Back Up… ein Backup der Datenbank erstellen. Dabei ist im Grunde nichts Besonderes zu beachten. Der Dialog kann z.B. so aussehen:

Falls die Benutzer mit dem alten System weiterarbeiten sollen, z.B. weil es sich nur um eine Testmigration handelt, kann jetzt die read-only Einstellung wieder von der Datenbank entfernt werden.

Datenbank auf dem neuen System wiederherstellen

Man kopiert sich jetzt die oben erstellte Backupdatei auf den neuen SQL Server (nur lokal abgelegte Dateien können wiederhergestellt werden). Über das SQL Management Studio legt man eine neue Datenbank an. Die Einstellungen sind dabei völlig egal. Über Rechtsklick auf die neue Datenbank und dann Tasks > Restore > Database stellt man jetzt das oben erstellte Backup auf dieser Datenbank wieder her.

Man wählt dazu unter Device die Datei aus und prüft unter Destination, daß die korrekte Datenbank überschrieben wird:

Unter Files kann man prüfen, daß die zugehörigen Datenbankdateien (mdf und ldf) auch an der gewünschten Stelle landen. Wichtig ist noch, daß unter Options der Haken bei Overwrite the existing database gesetzt wird:

 

Nach dem Wiederherstellen der Datenbank nicht vergessen, die read-only Einstellung wieder zu entfernen!

Datenbank prüfen

Zum Test, ob die Datenbank auf dem neuen System verwendet werden kann, gibt es ein PowerShell-Cmdlet. Man öffnet dazu eine SharePoint Management Shell als Administrator und gibt diesen Befehl ein:

Test-SPContentDatabase –Name <NameDerDatenbank> -WebApplication http://sharepoint

Das Cmdlet Test-SPContentDatabase ist hier beschrieben.

Falls das Cmdlet Warnungen betreffs fehlender Feature ausgibt, sollten die entsprechenden Solutions (WSPs) auf dem Zielsystem bereitgestellt werden. Man kann die Datenbank zwar trotzdem einbinden, aber die enthaltenen Sites werden dann höchstwahrscheinlich nicht (korrekt) funktionieren.

Classic und Claims Authentifizierung

Sehr häufig wird man bei einer Migration von 2010 nach 2013 von Test-SPContentDatabase aber folgende Meldung erhalten:

The web application is configured with claims authentication mode however the content database you are trying to attach is intended to be used against a windows classic authentication mode.

Bei SharePoint 2010 war die Verwendung der Claims Authentifizierung optional, während sie bei SharePoint 2013 Standard ist und genau das macht uns jetzt Probleme. Im Web findet man viele Anleitungen dazu, wie man mit der Problematik umgeht. Es werden jeweils zwei Möglichkeiten beschrieben:

Möglichkeit 1: Upgrade der Datenbank auf Claims im alten System vor dem Backup. Wie man das macht, ist hier beschrieben. Dabei werden allerdings Änderungen an einem bestehenden und eventuell produktiv genutzten System gemacht. Wenn z.B. die Migration erstmal nur getestet werden soll, ist das nicht unbedingt erwünscht.

Möglichkeit 2: Erstellen einer Classic Webanwendung in SharePoint 2013 per PowerShell, anhängen der Datenbank an diese Webanwendung und danach Upgrade auf Claims. Wie man das macht, ist hier beschrieben (weiter unten auf der Seite). Auch diese Vorgehensweise ist nicht immer praktikabel, well man dabei eine neue Webanwendung im Zielsystem benötigt. Wenn bereits eine Webanwendung mit Inhalt besteht und die Datenbank dort angehängt werden soll, ist dieser Weg nicht direkt gangbar.

Es gibt aber eine dritte Möglichkeit, bei der die Meldung ignoriert werden und die Datenbank trotzdem an die Webanwendung angehängt werden kann.

Datenbank anhängen

Die Datenbank wird mit Hilfe von PowerShell einer SharePoint-Webanwendung angehängt:

Mount-SPContentDatabase <NameDerDatenbank> -DatabaseServer <Servername> -WebApplication http://sharepoint

Das Cmdlet Mount-SPContentDatabase ist hier beschrieben.

Nach dem Anhängen der Datenbank kann ein Farmadministrator die in der Datenbank enthaltenen Websites im Browser aufrufen. Alle anderen Benutzer erhalten aber eine Zugriff verweigert Fehlermeldung. Um das zu reparieren, muß jetzt noch die Authentifizierung angepaßt und die Benutzer migriert werden. Das geht jetzt mit

Möglichkeit 3: per PowerShell nachträglich auf Claims umstellen. Dazu führt man in der SharePoint Management Shell folgendes aus:

$wa = Get-SPWebApplication http://sharepoint
$wa.MigrateUsers($true)
$wa.ProvisionGlobally()

Und schon sind alle Websitesammlungen der Datenbank migriert und können von allen Benutzern verwendet werden.