Kategorien
IT SharePoint

SharePoint (On-Premise) Blob-Cache löschen

Da sich der Markt in den letzten Jahren sehr in Richtung Office 365 bewegt hat, habe ich nur noch selten mit On-Premise SharePoint-Installationen zu tun.

Heute jedoch, musste ich eine (SharePoint 2016) Test-Farm neu aufbauen, zumindest ab Stufe Web-Applikation/Inhaltsdatenbank, welche neu von der Produktion übernommen werden musste und dann als neues Test-System konfiguriert werden sollte, da die alte Test-Farm nach einem missglückten Update korrupt und nicht mehr lauffähig war.

Um zu erkennen, ob man sich auf der produktiven Seite oder auf der Test-Umgebung befindet, hatten wir unteranderem früher via Composed Looks in der Test-Umgebung einen eigenen Look definiert, der im Farbton von der produktiven Seite abwich.

Im Prinzip also ein Look, mit der selben Masterpage, aber einem anderen *.spcolor-File, welches für das Test-System andere Farbtöne enthielt.

Nach dem Einspielen der neuen *.spcolor-Datei und aktivieren des gewünschten Composed Looks stellte sich jedoch Ernüchterung ein, die Seite sah genau so aus wie vorher. In der Preview des Composed Looks war schon zu erkennen, dass sich nichts ändern würde.

Gut, an was könnte das liegen? SPColor-Datei eingecheckt und veröffentlicht? Ja. Composed Look nochmals wegwechseln und dann erneut probieren – brachte nichts. IISReset durchführen – brachte auch nichts? Vielleicht den Object-Cache auf allen Servern (hier gab es nur einen) leeren? Hat auch nichts gebracht.

Eine Überprüfung der SPColor-Datei zeigte, dass sie die richtigen Werte enthielt, sie war auch veröffentlicht. Mit den Developer Tools im Browser wurde dann geprüft, durch welche CSS-Regel dieser Style appliziert wurde.

Der (falsche) Style entstammte von einer Themed-CSS-Datei. Beim Anwenden eines Composed Looks, werden die Werte aus der SPColor-Datei in eine zum Theme zugehörige CSS-Datei geschrieben (/Catalog-Bibliothek), die Datei hatte auch den richtigen Namen, aber die falschen Werte die nicht mit denen aus der SPColor-Datei übereinstimmten.

Ich erinnerte ich mich daran, dass ich so ein Problem schon einmal hatte und es daran lag, dass im Blob-Cache noch alte Versionen der CSS-Dateien (und anderer Dateien) vorhanden waren und diese dann an den Browser gesendet wurden, anstelle der aktuellen/korrekten.

Zuerst habe ich versucht, den Blob-Cache mittels PowerShell (SharePoint Management Shell) zu leeren:

$webApp = Get-SPWebApplication "<WebApplicationURL>"
 [Microsoft.SharePoint.Publishing.PublishingCache]::FlushBlobCache($webApp)

Leider hatte auch das nichts gebracht, nach einem erneuten aktivieren des gewünschten Looks, war immer noch alles beim Alten. Auch nach einem erneuten IISReset.

Ich wusste, dass man den Cache auch manuell löschen kann. Um auf Nummer sicher zu gehen, dass es wirklich nicht an diesem Cache liegt, beschloss ich auch dies auszuprobieren.

Dazu mus man wie folgt vorgehen:

  • web.config Datei der Web-Applikation ermitteln, öffnen und darin den Blob-Cache deaktivieren (Tag „BlobCache“ suchen und das Attribut „enabled“ auf „false“ stellen – dies muss auf jedem SharePoint-Server der Farm durchgeführt werden
  • Den Ordner des Blob-Caches im Dateisystem auf jedem Server löschen (den Pfad zum Ordner findet ihr auch in der web.config, im BlobCache-Tag)
  • IISReset durchführen
  • Nun den Blob-Cache wieder auf jedem Server der Farm aktivieren, dazu die web.config-Dateien erneut anpassen (BlobCache-Tag Attribut „enabled“ nun auf „true“ setzen)
  • Erneut einen IISReset durchführen (sollte durch das Speichern der web.config eigentlich automatisch geschehen)

Nachdem ich diese Schritte durchgeführt hatte, ging ich in den Websiteeinstellungen erneut auf „Aussehen ändern“ (Composed Looks) und wählte den gewünschten Look aus. Im Preview erschien immer noch der falsche Farbton. Ich habe den Look trotzdem angewendet und siehe da, auf der Webseite war dann nun doch der richtige Farbton endlich vorhanden.

Die (themed) CSS-Datei wurde nun korrekt neu erstellt, mit dem gewünschten, angepassten Farbton.

Hier noch weitere Informationen zum Thema Blob Cache, auf dem Blog von Karin Bosch, dort musste ich auch wieder einige der manuellen Schritte nachschlagen, da ich sie selber nicht mehr alle wusste 🙂 :
https://karinebosch.wordpress.com/my-articles/improving-performance-of-sharepoint-sites/part-3-blob-caching-in-sharepoint-2010/

Kategorien
IT SharePoint

SharePoint: client-seitiger Datei-Upload mit Metadaten

Vor ein paar Monaten bekam ich eine Anfrage, ein Skript zu entwickeln, um eine Datei mit Metadaten in eine SharePoint-Dokumentbibliothek hochzuladen.

Das Skript würde durch eine Workflow-Anwendung angestossen werden, welche unter anderem PowerShell-Skripts starten und an diese Parameter übergeben kann.

Diese Anwendung lief jedoch nicht auf einem SharePoint-Server, so war es mir nicht möglich das Server Side Object Model zu verwenden, welches ich im Normalfall für ein solches Szenario gewählt hätte und welches ich auch heute noch bevorzuge, da es noch immer mächtiger ist (als das Client Side Object Model) und man auf das ganze Async-„Gemurks“ verzichten kann.

Der eigentliche Datei-Upload gestalltet sich mit CSOM auch äusserst einfach. Was mir aber grosse Probleme bereitete, war die Übergabe von Benutzer-Logins an das Skript, respektive, dass diese dann korrekt verwendet wurden.

In den ersten Anläufen hatte ich das Phänomen, dass wenn ich Benutzer-Logins (via String-Array) übermittelte, nur die ungeraden übernommen wurden.

Initial hatte ich das sehr dirty (Schande über mich) gelöst, indem ich einfach alle Einträge im Array jeweils verdoppelte.
Da ich aber solche Hacks nicht sehr sauber finde und diese ja nicht gerade sehr wartungsfreundlich sind, da wenn jemand der in einem Jahr den Code anschaut sich denkt „Wtf?! Warum?“, beschloss ich der Sache etwas tiefer auf den Grund zu gehen und eine bessere Lösung zu finden.

Leider schien ich mit dieser Problematik alleine zu sein. Ich fand im Internet zwar einige Beispiele für das setzen von Metadaten via CSOM bei Datei-Uploads, jedoch nie eine Beispiel für das setzen eines „People Picker“-Feldes, welches mehrere Werte erlaubte (FieldUserValueCollection).

Nach etwas Debugging und Ausprobieren konnte ich das Problem aber dann doch noch eingrenzen und schlusssendlich lösen.
Das Problem lag daran, dass bei den Einträgen für die Benutzer auch ein Wert (LookupValue) vorhanden sein muss (welcher, wenn ich mich richtig erinnere, nicht gesetzt werden konnte, da der Setter read-only ist).
Der Feldwert darf dann nicht einfach als FieldUserValue-Array gesetzt werden, sondern muss folgendes Format haben, welches ihr vielleicht schon kennt, wenn ihr auf einem Lookup-Wert schon einmal „.ToString()“ ausgeführt habt („[User-ID];#[User-Anzeigename]“):

"32;#Peter Muster;#22;#Petra Meier;#31;#Hans Meister;#"

Hier der Auszug der relevanten Stelle, mit der Erstellung eines „FieldUserValue“-Objektes (gut könnte man strenggenommen auch weglassen und den $valueUsers-String direkt aufbauen) und der anschliessenden Umwandlung der Collection in einen String:

{
    ...
    $user = $web.EnsureUser($userLogin)
    # User must be loaded to pass a valid user ID as lookup ID
    $ctx.Load($user)
    $ctx.ExecuteQuery()
    if ($user.Id -ne $null)
    {
        $fieldUserValue = New-Object Microsoft.SharePoint.Client.FieldUserValue
        $fieldUserValue.LookupId = $user.Id
        $userFieldValueCollection += $fieldUserValue
    }
    else
    {
        throw "User for login '$userLogin' not found!"
    }
}

$valueUsers = ($userFieldValueCollection | % { $_.LookupId.ToString() + ";#DUMMY;#" }) -join "" 

Hier noch das komplette Beispiel-Skript:

param(
    [Parameter(mandatory=$true)]
    [string] $SourceFilePath, 
    [Parameter(mandatory=$true)]
    [string] $ValueTitle,
    [Parameter(mandatory=$true)]
    [string] $ValueChoice,
    [Parameter(mandatory=$false)]
    [string] $ValueComments,
    [Parameter(mandatory=$false)]
    [bool] $ValueSendNotification = $true,
    [Parameter(mandatory=$true)]
    [string[]] $ValueUserLogins
)

# Set target site collection URL
$siteUrl = "http://server.name"
$targetLibraryInternalName = "Documents"

# Get script directory
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path

# Load SharePoint Client Dlls
Add-Type -Path (Resolve-Path (Join-Path -Path $ScriptDir -ChildPath "Microsoft.SharePoint.Client.dll"))
Add-Type -Path (Resolve-Path (Join-Path -Path $ScriptDir -ChildPath "Microsoft.SharePoint.Client.Runtime.dll"))

# Create Client Context (connect to target site)
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
$web = $ctx.Web 
$ctx.Load($web) 
$ctx.ExecuteQuery()
Write-Host "Connected to web: $($web.Url)" -ForegroundColor Yellow

# Get target library
$targetLibrary = $ctx.Web.GetList($web.ServerRelativeUrl + "/" + $targetLibraryInternalName)

# Prepare 'Viewers' value
[Microsoft.SharePoint.Client.FieldUserValue[]]$userFieldValueCollection = @()
foreach ($userLogin in $ValueUserLogins)
{
    $user = $web.EnsureUser($userLogin)
    # User must be loaded to pass a valid user ID as lookup ID
    $ctx.Load($user)
    $ctx.ExecuteQuery()
    if ($user.Id -ne $null)
    {
        $fieldUserValue = New-Object Microsoft.SharePoint.Client.FieldUserValue
        $fieldUserValue.LookupId = $user.Id
        $userFieldValueCollection += $fieldUserValue
    }
    else
    {
        throw "User for login '$userLogin' not found!"
    }
}
# Needs beside the LookupId also a dummy LookupValue, otherwise only odd entries are stored!
$valueUsers = ($userFieldValueCollection | % { $_.LookupId.ToString() + ";#DUMMY;#" }) -join "" 

# Upload file
$fci = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$fci.Overwrite = $true
$fci.Content = [System.IO.File]::ReadAllBytes($SourceFilePath)
$fci.URL = [System.IO.Path]::GetFileName($SourceFilePath)
$uploadFile = $targetLibrary.RootFolder.Files.Add($fci)
Write-Host "File uploaded to target library"

# Set metadata properties on uploaded file (must be done on item of file)
Write-Host "Writing metadata to fields"
$listItem = $uploadFile.ListItemAllFields
$listItem["Title"] = $ValueTitle
$listItem["MyChoice"] = $ValueChoice
$listItem["Comments"] = $ValueComments
$listItem["SendNotification"] = $ValueSendNotification
$listItem["Readers"] = $valueUsers
$listItem.Update()
Write-Host "Executing pending queries (write metadata to file)"

$ctx.Load($uploadFile)
$ctx.Load($listItem)
$ctx.ExecuteQuery()

Write-Host "Uploaded file '$($uploadFile.Name)', received ID: $($listItem.Id)" -ForegroundColor Yellow

Das Skript kann wie folgt aufgerufen werden:

.\Skript.ps1 -SourceFilePath "X:\SourceFiles\Test Document.docx" -ValueTitle "Title Value" -ValueChoice "My Choice Value" -ValueComments "Test Comment" -ValueUserLogins @("Domain\username1", "Domain\username2") –ValueSendNotification $true 

Wichtig: damit ihr via PowerShell CSOM verwenden könnt, müsst ihr noch die SharePoint-Client-DLLs zur Verfügung haben (findet ihr im SharePoint-Installationsverzeichnis) und diese im Skript Verzeichnis ablegen, darum die beiden Aufrufe im Skript:

# Load SharePoint Client Dlls
Add-Type -Path (Resolve-Path (Join-Path -Path $ScriptDir -ChildPath "Microsoft.SharePoint.Client.dll"))
Add-Type -Path (Resolve-Path (Join-Path -Path $ScriptDir -ChildPath "Microsoft.SharePoint.Client.Runtime.dll"))

Kategorien
IT SharePoint SQL

Eine „suspect“ Datenbank reparieren

Es ist mir schon passiert, dass ich auf einmal keine SharePoint-Webseite meiner Virtual Machine mehr öffnen konnte. Auch die Central Administration funktionierte nicht mehr. Als Fehlermeldung erschien:

„This operation can be performed only on a computer that is joined to a server farm by users who have permissions in SQL Server to read from the configuration database. To connect this server to the server farm, use the SharePoint Products Configuration Wizard, located on the Start menu…“

Ein Ausführen des SharePoint Products Configuration Wizards war nicht möglich, der Wizard brach nach einigen Schritten ab, mit der Begründung, dass nicht auf die Configuration-Datenbank zugegriffen werden konnte.

Ein Blick in das MSSQL Management Studio zeigte dann, dass die SharePoint-Config-Datenbank im Status suspect, also verdächtig war.

Zum Glück gibt es einen Weg, die Datenbank wieder in einen gesunden Zustand zu bringen, oder zumindest es zu versuchen. Achtung: je nach Schweregrad der zu Grunde liegenden Störung kann es sein, dass bei diesem Vorgang Daten verloren gehen, da hier eine Reparatur der Datenbank mit „REPAIR_ALLOW_DATA_LOSS“ durchgeführt wird.

Via MSSQL Management Studio auf den Datenbankserver verbinden und ein neues Query-Fenster öffnen, danach folgende Zeilen ausführen („DatabaseName“ durch den Namen der „suspect“ Datenbank ersetzen):

EXEC sp_resetstatus [DatabaseName];
ALTER DATABASE [DatabaseName] SET EMERGENCY
DBCC checkdb([DatabaseName])
ALTER DATABASE [DatabaseName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DBCC CheckDB ([DatabaseName], REPAIR_ALLOW_DATA_LOSS)
ALTER DATABASE [DatabaseName] SET MULTI_USER

Je nach Grösse der Datenbank, Server-Leistung und Fehler-Anzahl kann der Vorgang zwischen wenigen Sekunden bis hin zu Stunden dauern. Bei mir brauchte es für eine 1 GB grosse Datenbank zum Beispiel ca. eine Minute. Im Ausgabefenster ist ersichtlich, was für Reparaturen vorgenommen wurden und ob diese zu Datenverlust führten.

Nachdem die Operation beendet wurde, kann man versuchen wieder auf die Datenbank zuzugreifen. In meinem Fall konnte ich wieder auf die SharePoint-Central-Administration und die Web-Applications zugreifen.

Kategorien
IT SQL

Microsoft SQL Server Management Studio – verbleibende Datenbank-Restore-Dauer anzeigen

Vielleicht habt ihr auch schon mal in einem Microsoft SQL Server einen Restore einer Datenbank durchgeführt und wolltet wissen, wie weit der Restore nach einigen Minuten/Stunden schon gekommen ist und wann der Restore ungefähr beendet sein wird.

Wird der Restore via „Management Studio“-GUI durchgeührt (Datenbank-Kontextmenü -> Tasks -> Restore), dann habt ihr im Restore-Dialog zumindest eine ungefähre Prozent-Anzeige. In der 2012er-Version wird diese oben rechts angezeigt:

Die Prozent-Anzeige erscheint aber erst nach einem Weilchen und wenn man den Restore via SQL-Skript gestartet hat und dabei „STATS“ nicht (oder mit einem ungünstigen Wert) verwendet hat, weiss man auch nicht bei wieviel Prozent der Restore aktuell steht und wie lange er noch dauert. Häufig bleibt die Prozentzahl auch lange unverändert und man ist sich nicht sicher, ob der Restore noch läuft oder sich aufgehängt hat.

Zum Glück gibt es jedoch eine Möglichkeit mit einem SQL-Befehl den aktuellen Fortschritt und die geschätzte Endzeit zu erhalten – egal ob  der Backup-Job via GUI, Skript oder sogar von einer anderen Maschine gestartet wurde. Voraussetzung ist ein MSSQL Server der Dynamic Management Views (DMVs) unterstützt, also ab MSSQL 2005. Ist das gegeben kann man folgenden Befehl als Query absetzen (es muss keine Datenbank dazu vorselektiert werden):

SELECT session_id as SPID, command, a.text AS Query, start_time, percent_complete, dateadd(second,estimated_completion_time/1000, getdate()) as estimated_completion_time
FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) a
WHERE r.command in ('BACKUP DATABASE','RESTORE DATABASE')

Das Resultat sieht dann zum Beispiel wie folgt aus (unterer Bereich, Spalten percent_complete und estimated_completion_time):

Im Beispiel sieht man also, dass bereits 96.16975 % des Restores durchlaufen ist und der Restore um 12:38 Uhr, des 7. Dezember 2016, fertig sein sollte – nach ungefähr 19 Stunden Laufzeit. Praktisch oder?

Gefunden auf: https://www.mssqltips.com/sqlservertip/2343/how-to-monitor-backup-and-restore-progress-in-sql-server/

Kategorien
IT SharePoint

SharePoint: relative Pfade in XSLT verwenden

Wenn man eine SharePoint-Listenansicht mittels XSLT anpasst, so möchte man häufig auch relative Pfade verwenden.

Besonders wichtig, wenn man eine XSL-Datei für ein Feature deployed, welches in verschiedenen Webs aufgerufen wird und folglich keine absoluten Pfade sondern relative enthalten sollte.

Dies lässt sich innerhalb einer SharePoint-Seite mit der Verwendung des globalen XSLT-Parameters „ServerRelativeUrl“ einfach lösen, wie nachfolgendes Beispiel (Auszug aus einer XSL-Datei) zeigt:

                  <a href="{$ServerRelativeUrl}/Lists/Customers/DispForm.aspx?ID={@ID}">
                    <xsl:value-of select="@Title"/>
                  </a>

Man hätte natürlich auch z.B. „../Lists“ oder „http://servername/…“ voranstellen können, jedoch verliert man dann Flexibilität. Sobald der Servername geändert wird (man denke auch an „Alternate Access Mappings“ und Extranet-Lösungen)  oder das XSL auf einer Listen-Ansicht statt auf einer Page verwendet wird, geht der Link nicht mehr, da der Verweis dann einen ungültigen Pfad hat.

Damit der globale Parameter verfügbar ist, muss innerhalb der XSL-Datei die „Main.xsl“-Datei von SharePoint referenziert werden:

<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">
  <xsl:import href="/_layouts/xsl/main.xsl"/>
  ...

Informationen über verfügbare globale Parameter findet ihr hier: http://msdn.microsoft.com/en-us/library/ff806158.aspx

Kategorien
IT personal

Minecraft

Vor einigen Monaten habe ich mir Minecraft gekauft, dass wohl schon seit einigen Jahren eigentlich verfügbar ist, aber immer irgendwie an mir vorbei gegangen ist.

Minecraft würde ich als eine Art Lego für Erwachsene.. oder jung gebliebene 😉 … bezeichnen. Die ganze Spielwelt, in den neueren Versionen praktisch unendlich gross, besteht aus kleinen Blöcken. Die Blöcke können aus verschiedenen Materialien bestehen, welche auch verschiedene Eigenschaften haben (fest, Wasser, Lava, Schienen, Stromkabel etc.). Im Prinzip haben alle Blöcke die gleiche Dimension, was  in etwa 1 Meter auf 1 Meter entspricht. Einige Spezialblöcke haben aber nur die Hälfte dieser grösse, eine Treppenform oder sind noch spezieller (z.B. Lampen, Schienen, Bilder, Schalter), haben aber auch dann immer im Standardblock (1m*1m) platz. Dadruch ergibt sich eine sehr spezielle Welt mit einer gewissen Lego-ästhetik.

Ein eigentliches Spielziel gibt es nicht wirklich. Es gibt einen Survival Modus, bei dem man eine Lebensenergie hat und Nahrung besorgen muss, da man ansonsten stribt. Man hat jedoch unendlich viele Leben und respawnt am ersten Spawn-Point im Spiel oder einem selber platzierten Bett. In der Nacht (es gibt einen Tag-/Nachtrythmus) und an dunklen Orten spawnen Monster, Mobs genannt, welche die eigene Spielfigur angreifen. Dort gibt es als grösseres Ziel eine Art Endboss, aber danach kann man in der freien Welt weiterspielen wie zuvor. In einem anderen Modus, „Creative“-Mode genannt, existieren keine Mobs und man hat alle Materialen unbegrenzt bereits im Inventar zur verfügung. Interessant um grössere Bauprojekte zu bewerkstelligen, aber auf die Dauer vermutlich öde. Der Survival-Modus ist sicher abwechslungsreicher und auch im Multiplayer dann nach meinem Empfinden die beliebteste Variante.

Das ganze ist dann leider auch sehr süchtig machend, so habe ich bedauerlicherweise 🙂 schon Stunden damit verbracht diese Blöcke irgendwie sinnvoll zusammen zubauen, wie z.B. das nachfolgende Video illustriert:

Zum Glück gibt es scheinbar noch Leute mit extrem viel mehr Freizeit und Zeit für diese Spiel, wie nachfolgendes Video einer Kathedrale mit über 2’000’000 Blöcken zeigt:

Für Bastler ganz interessant sind die Möglichkeiten, welche einem das Material „Redstone“ bietet, eine Art Stromleiter und Energiequelle. Man kann damit komplexeste Schaltungen bauen mit verschiedensten Logiken. Nachfolgendes Video zeigt als Beispiel einen wissenschaftlichen Taschenrechner, welcher in Minecraft umgesetzt wurde:

Ich nehme trotzdem nicht an, dass Intel/AMD etc. nun auf Minecraft umsteigen werden, um ihre zukünftigen Prozessor-Architekturen zu designen. 😉

 

Kategorien
IT SharePoint

SharePoint: Versionsnummer mit Hilfe von SharePoint Designer ermitteln

Um die Vesionsnummer des aktuell installierten SharePoint-Servers zu ermitteln gibt es viele Wege. Einige davon sind etwas umständlicher und liefern auch nicht immer leicht verständliche Ergebnise (mehere Versionsnummern z.B., wenn man in der SharePoint Central Administration unter Check product and patch installation status nachschaut).

Eine einfache Möglichkeit die aktuelle Versionsnummer der SharePoint-Installation zu ermitteln, bietet der SharePoint Designer. Einfach den Designer öffnen und auf eine Site auf dem gewünschten Server verbinden. Auf der Startseite findet man dann unter der Rubrik „Site Information“ die aktuelle Version:

SharePoint Designer Site Information
SharePoint Designer Site Information

Kategorien
IT SharePoint

SharePoint: Inhaltsdatenbank-Version an SharePoint-Version angleichen

Wenn man in einer SharePoint-Installation ein neues Cumulatives Update installiert um Programm-Fehler zu beheben, so wird die gesamte SharePoint-Version hochgehoben, also die Assemblies/Dlls etc. aktualisiert und haben dadurch höhere Versionsnummern.

Die Inhaltsdatenbank (Content Database) wird grundsätzlich aber nicht automatisch aktualisiert und behält das alte Schema und auch die alte Versionsnummer bei.

In der Regel ist dies nicht weiter tragisch, aber unter Umständen kann es trotzdem nötig werden, dass man die Inhaltsdatenbank aktualisiert und damit ihre Version an diejenige des SharePoint-Serves angleicht, so zum Beispiel, wenn man ein Backup einer Site-Collection einspielen möchte (Restore-SPSite), welches von einer Site/Datenbank mit der höheren Versionsnummer, die des Servers, entstammt.

Um manuell die Inhaltsdatenbank zu aktualisieren, kann man sich der SharePoint Management Shell bedienen.

Zuerst sollte man die gewünschte Content Database in eine Variable laden (wobei man „SQLServerName\WSS_Content_Database_Name“ durch den entsprechenden Datenbank-Server und Namen der Inhaltsdatenbank ersetzen muss):

$contentdb = Get-SPContentDatabase | Where-Object {$_.Name -match "SQLServerName\WSS_Content_Database_Name"}

Ist unklar, wie die Inhaltsdatenbank heisst, so kann man zuerst einfach nur Get-SPContentDatabase eingeben um eine Auflistung aller Inhaltsdatenbanken zu erhalten. Sollte die gewünschte Datenbank nicht aufgeführt sein, sollte sicher gestellt werden, dass diese in der Central Administration im Status „Ready“ ist.

Danach kann man mit folgendem PowerShell-Befehl die Aktualisierung starten:

Upgrade-SPContentDatabase -Identity $contentdb

In der PowerShell wird der Fortschritt in Prozent angezeigt. Bei grösseren Datenbanken kann die Aktualsierung mehrere Minute bis hin zu Stunden dauern.

Weitere Informationen findet ihr in diesem Technet-Artikel: http://technet.microsoft.com/en-us/library/ff607813.aspx

Kategorien
IT SharePoint

SharePoint: Alerts für Volltext-Suchresultate aktivieren

SharePoint 2010 bietet ja die Möglichkeit auf Listen Alerts einzurichten. Wenn Elemente geändert oder hinzugefügt werden, kann man sich so über Email oder auch SMS benachrichtigen lassen. Sehr praktisch wenn man etwas beobachten möchte, aber nicht die ganze Zeit manuell sich durch Listen wühlen möchte.

Solche Alerts kann man praktischerweise aber auch in der SharePoint-Suche aktivieren. So kann man sich benachrichtigen lassen, wenn die Volltextsuche zu einem bestimmten Suchbegriff ein neues oder geändertes Element findet.

SharePoint Search Alerts anlegen
SharePoint Search Alerts anlegen

Die Möglichkeit solche Alerts in der Volltext-Suche zu verwenden ist jedoch in der Grundeinstellung deaktiviert. Der Link dazu ist zwar vorhanden, doch möchte man einen neuen Alert hinzufügen, erscheint folgende Fehlermeldung:

Search alerts have been turned off for this Search Application. For assistance, contact your server administrator.

Über die „Central Administration“ von SharePoint kann dies einfach aktiviert werden:

  • In der „SharePoint 2010 Central Administration“ auf „Manage service applications“ gehen (in der Sektion „Application Management“)
  • In der Liste die „Search Service Application“ finden und den Link zum Öffnen anklicken
  • In der obersten Rubrik „System Status“ befindet sich ziemlich zu unter der Eintrag „Search alert status“
  • Bei „Search alert status“ auf der rechten Seite auf „Enable“ klicken um Alerts zu aktivieren

Alerts für Suchresultate in der Search Service Administration aktivieren
Alerts für Suchresultate in der Search Service Administration aktivieren

Grosse Nachteile, bei aktivierter Einstellung, sind mir nicht bekannt, aber ich vermute dass bei einigen 10’000 Alerts die Performance etwas leiden könnte, vermutlich in den meisten Szenarien vernachlässigbar. Die MSDN zu Thema Alerts für die Suche erwähnt jedenfalls nichts dazu.

Kategorien
IT SharePoint

SharePoint: TaxonomyHiddenList manuell aktualisieren

Unter gewissen Umständen und mit gewissen Cumulativen Updates für den SharePoint 2010 kann es vorkommen, dass die TaxonomyHiddenList nicht mehr auf dem aktuellsten Stand ist, da die Synchronisation mit dem Term-Store (Terminologiespeicher) nicht mehr fehlerfrei durchgeführt werden kann.

Abhilfe (wenn auch eventuell nur temporäre?)  schafft folgendes PowerShell-Skript:

$Assem = (
	"Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" ,
	"Microsoft.SharePoint.Taxonomy, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
)

$Source = @"
using Microsoft.SharePoint;
using Microsoft.SharePoint.Taxonomy;
using System;

namespace TaxonomyUpdater
{
	public static class TaxonomyHiddenList
	{
		public static void Update(string SiteUrl)
		{
			SPSite Site2Update = new SPSite(SiteUrl);
			TaxonomySession.SyncHiddenList(Site2Update);
			Site2Update.Dispose();
		}
	}
}
"@

Add-Type -ReferencedAssemblies $Assem -TypeDefinition $Source -Language CSharp

Das Skript muss man in einen Text-Editor einfügen und als „UpdateTaxonomyHiddenList.ps1“ abspeichern.

Danach das Skript in einer PowerShell einmal ausführen, damit die Klasse verfügbar wird. Zum Schluss mit folgendem Befehl die Synchronisation starten:

[TaxonomyUpdater.TaxonomyHiddenList]::Update(“http://SharePointServer”)

Siehe auch: http://blogs.msdn.com/b/joerg_sinemus/archive/2011/03/03/terms-and-how-to-update-taxonomyhiddenlist-when-the-timer-job-was-not-able-to-update.aspx