SharePoint 2013 Quick Edit ausgegraut

Der absolute Klassiker zum Thema Quick Edit und dennoch immer wieder gern gesucht bzw. nspmql1achgefragt: Was tun, wenn trotz aller Bemühungen die Datenblattansicht sich nicht zur Mitarbeit überreden lassen möchte?

Die Symptome: Die Schaltfläche „QuickEdit“ im Ribbon-Menü ist ausgegraut, ein wenig sagender Hinweis im Tool-Tip verweist eher auf fehlende Berechtigungen und die Ansicht sieht mehr nach SharePoint 2010 als nach 2013 aus. Gerne tritt das Verhalten auch nach der Migration von Seiten aus der Vorgängerversion auf.

Eine Checkliste zur Lösung des Problems:

  1. Prüfen, ob die Verwendung der Funktion in den Listeneinstellungen unter „Erweiterte Einstellungen“ zugelassen ist. Sind die Einstellungen nicht erreichbar, so wie es für einige wenige Listen-Typen im Standard vorgesehen ist, so kann mittels PowerShell auf dem Listen-Objekt die Property „DisableGridEditing“ auf false gesetzt werden (Update-Methode nicht vergessen auszuführen!)
  2. Prüfen, ob sich eine neue Ansicht nach Vorlage der Datenblattansicht erstellen lässt
  3. Einstellungen der Ansicht…
    1. Entfernen eventuell vorhandener Gruppierungen auf der Ansicht
      (bei Verwendung der Gruppierung steht Quick-Edit nicht zur Verfügung)
    2. Evtl. gesetzte Formatierungen des Views wie „Magazin“, „Schattiert“ etc. entfernen
      (zurück auf Standard stellen)
    3. Verwendung von Kontrollkästchen zulassen
  4. Ergänzen der möglicherweise fehlenden JavaScript-Bibliothek unter <JSLink> in den Quellen (.aspx) der Ansicht…
    1. SharePoint Designer öffnen
    2. Defekte Ansicht öffnen
      spmql2
    3. JSLink mit clienttemplates.js ergänzen
      spmql3

In 99% aller Fälle sollte damit die größte Not vorüber sein. Falls nicht, immer her damit!

Lync Server 2013 & Skype for Business 2015 Protocol Workloads

Ein Muss für jeden Lync- bzw. Skype for Business-Admin, der noch ein Stückchen Tapete in seinem Büro sehen kann!

lyncposter

Die Poster offenbaren keine großen Geheimnisse mehr – dennoch wurden beide Visualisierungen auf den aktuellen Stand gebracht und ganz frisch in den Microsoft Download-Bereich als PDF und Visio-Grafik entlassen. Die umfangreichen Darstellungen der Kommunikationsrichtungen und Verbindungen zwischen Clients und Serversystemen lassen kaum Wünsche offen.

Inhalte

  • Server/Client-Kommunikation und Protokolle für…
    • Instant Messaging & Presence
    • A/V & Web Conferencing
    • Application Sharing
    • Enterprise Voice
  • Notwendige/Optionale Zertifikat-Konfiguration
  • DNS-Konfiguration
  • CMS

Download

 

Benachrichtigung bei Änderung von Homematic-Systemvariablen

HomeMaticNotification_SysVar-NotifyDie aktualisierte Version des Homematic-Benachrichtigungsdienstes ist online. Bislang informierte der Dienst stets nur über geänderte Zustände von Homematic-Sensoren bzw. -Aktoren.

Mit dem neuen Release (RC-Version 1.1.10 bzw. Version 1.2) kann man sich nun auch über geänderte Systemvariablen informieren lassen, was beispielsweise die Alarm-Benachrichtigung oder Informationen zu von Homematic-Programmen gesetzten Systemzuständen vereinfacht.
Die bislang verfügbaren Benachrichtigungsprovider (PushOver, Pushalot, E-Mail und Telegram) funktionieren natürlich auch für die neue Funktion wie gehabt.

Konfiguration

Um für eine Systemvariable Benachrichtigungen zu erhalten, muss diese mit ihrer Homematic-internen ID (IseId) in der Konfigurationsdatei als notifyVariable-Element angelegt werden:

<notifyVariable Name="Anwesenheit" IseId="1234" IsImportant="false" />

Weitere Details zur Konfiguration gibt es in der Beispielkonfiguration ConfigTemplate.xml

Die IseId kann man mit Hilfe des für den Service ohnehin benötigten Addons XML-API herausfinden, indem man die Seite sysvarlist.cgi aufruft. In der XML-Struktur kann man die IseId als Attribut der einzelnen Variablen finden, die auf der CCU2 definiert sind.

Den aktuellen Build findet man an der üblichen Stelle im OneDrive (MD5: 5820d546af62c43ada0eaa3b517ea4dd). Alternativ dazu ist der jeweils aktuelle Quellcode im GitHub-Repo HomeMatic-Notification-Service zu finden.

Viel Spaß beim Ausprobieren. Über Feedback, Anregungen und Ideen freue ich mich!

Push Notification via Telegram

Bis vor ca. zwei Wochen hatte ich mit dem Benachrichtigungsdienst Pushalot von Maciej Olesiński eine wirklich gute und verlässliche Plattform, um mir allerlei Statusmeldungen an zentraler Stelle zukommen zu lassen. Dann wurde es plötzlich ruhig auf meinen mobilen Endgeräten. Kein Server mehr, der mir seinem Gemütszustand mitteilte, keine Wohnungstür mehr, die mich über ihren Status informiert…
Inzwischen bin ich auch nicht mehr gänzlich allein mit dem Thema, wie man beispielsweise auf Reddit lesen kann. Das beruhigt ein wenig, da es nicht an mir zu liegen scheint, andererseits löst es aber auch das Problem nicht.

TelegramPushNotificationsWie dem auch sei – diesem Umstand geschuldet habe ich mich kurzerhand mit der API des Messenger-Dienstes Telegram befasst und entschieden, den Messenger für meine Zwecke und damit als Ersatz für die ausbleibenden Benachrichtigungen von Pushalot zu verwenden.
Die API ist überaus funktional, reich an Funktionen und durchgehend gut dokumentiert. Der Service lässt sich unkompliziert über die heute gängigen Wege ansprechen.
Spannend ist das Konzept der Telegram-Bots als unpersonalisierte Service-Accounts, mit denen man in seiner Rolle als Nutzer interagieren kann. Dabei können vorhandene genutzt oder individuelle, neue Bots angelegt werden. Telegram geht diesen Weg sehr konsequent, so dass ebenfalls die Bedienung der Plattform auf Ebene des Entwicklers über einen solchen Bot läuft. Will man einen Bot erstellen und konfigurieren, so chattet man mit dem @BotFather, dem man über definierte Kommandos die entsprechenden Einstellungen übergibt bis hin zum Profilfoto des eigenen Bots.

Mit relativ geringem Aufwand haben in den letzten Tagen die beiden im vergangenen Jahr veröffentlichten Tools – der Homematic Notification Service sowie das PushMonitoring – einen zusätzlichen Benachrichtigungskanal für die Nutzung von Telegram erhalten.

Das Setup…

…der beiden Tools für die Verwendung der Telegram-Bots funktioniert wie folgt:

  1. Telegram installieren
  2. Als Empfänger die eigene Chat-ID herausbekommen
    (z.B. dem Bot @get_id_bot eine Nachricht mit /my_id senden)
  3. Die Chat-ID in der Konfiguration des Service/Tools ( <notifyBy /> bzw. <sendTo />) hinterlegen
  4. Den jeweiligen Bot – „Homematic Alert“ bzw. „PushMonitoring“ – aufrufen und mit der Nachricht /start aktivieren

Homematic Notification Service

<notifyBy NotifyProvider="Telegram">123456789</notifyBy>

PushMonitoring

  <sendInterfaces>
    <sendTo Type="Telegram" ApiKey="123456789" />
  </sendInterfaces>

Alternativ können statt der eigenen Chat-ID noch Gruppen-IDs öffentlicher Gruppen verwendet werden, wenn der Bot in der Gruppe Mitglied ist.

Die Push-Messages, die über die beiden Tools versendet werden verhalten sich wie normale Chat-Nachrichten, die man vom Kontakt des jeweiligen Bots erhält:

TelegramPushWindowsPhone

Es ist ein wenig schade, dass Pushalot so ganz ohne weitere Informationen abgetaucht ist. An dieser Stelle vielen Dank an die Plattform und ihren Betreiber für die lange Zeit an Zuverlässigkeit sowie das kostenfreie Angebot!

Die beiden Tools (Homematic Notification Service + PushMonitoring) gibt es in aktualisierter Version an der üblichen Stelle im OneDrive oder den Quellcode unter GitHub.

Win32 oder .NET in UWP-App konvertieren

Bestehende Windows Desktop-Anwendungen mit nur wenig Kenntnis der UWP-Apps in eine vollwertige Windows 10 App konvertieren. Dieses Ziel hat man sich bei Microsoft mit dem Projekt Centennial gesetzt.
Der auf der Build 2016 vorgestellte Desktop App Converter war bereits vor einigen Monaten als Preview zum Download zu haben.

Der Konverter führt die Desktop-Anwendung bzw. deren Installer in einer isolierten Windows-Umgebung aus, welche dem Konverter als Windows Basis-Image beiliegt. Dabei werden alle Aktionen in Registry und Dateisystem erfasst und als Grundlage für ein neues AppX-Package verwendet. Diese UWP-App verfügt über ihre eigene Identität, was für die Verwendung der WinRT-APIs sowie die Integration von Features wie Live-Toasts, -Kacheln, Hintergrundaufgaben und Ähnliches erforderlich ist.

Microsoft sieht für Entwickler, die sich mit dem Schwenk auf die neue Plattform schwer tun, einen fließenden Migrationsprozess vor. Zuerst soll die Portierung auf die UWP-App per Konverter erfolgen. Nach dem Bereitstellen und Testen der App könne man UWP-Features ergänzen und die Anwendung Schritt für Schritt optimieren. Zu guter Letzt soll die UWP-App dann für alle Windows-Zielplattformen portiert werden können.

Vor ein paar Tagen gab es eine neue Version v0.1.21 im Downloadbereich inklusive der Windows Base Images 14371 und 14372. Einen guten Einstieg ins Thema bietet die Dokumentation des Konverters.

Ich wage zu bezweifeln, dass dies den mit großer Wahrscheinlichkeit erhofften Durchbruch für die Windows Apps bringen wird, bin aber gespannt, ob der Konverter eine echte Alternative gegenüber dem manuellen Portieren ist und einen entsprechenden Mehrwert bietet. Sollte dem so sein, werde ich ganz sicher ein wenig ausführlicher darüber berichten.

ListItem-Update führt zu „Catastrophic failure“

In einer SharePoint Liste ohne EventReceiver mit einem nicht angepassten Standardformular meldet das System beim Versuch ein Listenelement zu aktualisieren Folgendes:

Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))

Neben der doch sehr drastischen Wortwahl deutet bereits das HRESULT auf eine durchgereichte COM-Exeption hin. Gerade bei solch vermeintlich tiefgreifenden Offenbarungen erhält man üblicherweise den bekannten, ganzseitigen Dialog mit der beschwichtigenden Entschuldigung, etwas hätte leider nicht geklappt. Nicht so hier. Die Meldung erscheint ohne viel Drumherum und ohne Korrelationsid in roten Lettern direkt unterhalb der Angaben zu Erstellt/Geändert und dem Speichern-Button.
Das Anlegen von Listenelementen in besagter Liste funktioniert weiterhin problemlos – nur unangenehmerweise das Update nicht mehr.

Ein Blick ins ULS (Methodensignaturen auf das Wesentliche gekürzt) gibt ein wenig mehr Informationen preis:

Original error: Microsoft.SharePoint.SPException: Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED)) 
---> System.Runtime.InteropServices.COMException: Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))    
 at Microsoft.SharePoint.Library.SPRequestInternalClass.AddOrUpdateItem( /* --- snip --- */ )    
 at Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem( /* --- snip --- */ )     -
-- End of inner exception stack trace ---    
 at Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx)    
 at Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem( /* --- snip --- */ )    
 at Microsoft.SharePoint.SPListItem.AddOrUpdateItem( /* --- snip --- */ )    
 at Microsoft.SharePoint.SPListItem.UpdateInternal( /* --- snip --- */ )    
 at Microsoft.SharePoint.SPListItem.Update()    
 at Microsoft.SharePoint.SPListItem.ValidateUpdateListItem_Client( /* --- snip --- */ )    
 at Microsoft.SharePoint.ServerStub.SPListItemServerStub.InvokeMethod( /* --- snip --- */ )    
 at Microsoft.SharePoint.Client.ServerStub.InvokeMethodWithMonitoredScope( /* --- snip --- */ )

Hier erfährt man, wo die Exception geworfen wurde. Leider führt auch mit diesen detaillierteren Angaben eine Suche im Netz schnell in die Irre, was mir Grund und Anlass für diesen kurzen Post sein soll.
Gut gemeinte Tipps wie „iisreset“ oder „Liste löschen und neu anlegen“ über „Entfernen von Inhaltstypen lowlevel in der Config-DB“ bis hin zu „ein ernstzunehmendes Problem mit möglicherweise korrupten DLLs und man möge den 0x8000FFFF bitte nicht auf die leichte Schulter nehmen“ waren dabei nicht ernsthaft vielversprechend. Lediglich ein Hinweis auf einen Schreibfehler einer Feldbezeichnung in der Schema.xml hatte Potential.

Was ich noch erwähnen sollte: Die Liste ist Teil einer per WSP im SharePoint ausgerollten Solution mit deklarativ definierten Listen.

Die Lösung

Da es recht sicher war, dass der Fehler im Zusammenhang mit der Listendefinition stehen musste, schien die Eingrenzung des Fehlers sinnvoll. Durch das Löschen aller benutzerdefinierten Felder der Liste, bis ein Update wieder möglich war, konnte als Übeltäter ein Auswahlfeld (Choice-Field) identifiziert werden. Mit einem von Hand auf der Liste angelegten Feld gleichen Namens und Typs bestand das Problem nicht länger.

Die genaue Untersuchung der Feld-Definition in der Schema.xml der zugrundeliegenden Liste brachte die Ursache ans Licht.
Im Field-Element des Auswahlfelds war das optionale Attribut BaseType mit dem Wert  „Integer“ enthalten, mit welchem man explizit angeben kann, ob der Wert als Integer oder als Text persistiert werden soll.

In der Beschreibung des Attributs im Artikel der MSDN ist ersichtlich, dass die Verwendung des BaseTypes in Zusammenhang mit Choice- bzw. Auswahlfeldern nicht möglich ist:

BaseType | Optional. The BaseType attribute can be set to Integer, which stores values as integers, or to Text (default), which stores values as text. You cannot create integer base-type choice fields.

Dennoch spannend, dass sich ein dementsprechend definiertes Feld in einer Liste überhaupt anlegen und ein Listenelement damit erstellen lässt sowie dass dazu noch die eher spektakuläre, wenig sagende Fehlermeldung präsentiert wird.
Falls irgendjemand mal Lust hat herauszubekommen, warum ausgerechnet für Auswahlfelder die Option Integer nicht zulässig ist – ich würde mich über eine Antwort freuen.

SharePoint Bulk-Delete via PowerShell

1.000+ ListItems in einer SharePoint-Liste und die müssen alle weg – und zwar fix. Manchmal sind es Demo- oder Test-Daten und mal soll schlicht nur aufgeräumt werden. Was tun? Eine Art „TRUNCATE TABLE“ wäre schön. Wieder hilft hier die PowerShell mit wenigen Zeilen und geladenen SharePoint-Commandlets weiter.

DELETE ALL ListItems

$web = Get-SPWeb <URL zum Web>
$lst = $web.Lists[„<Name der Liste>“]
$lst.Items | % { $lst.GetItemById($_.ID).Delete(); }

Zwar muss man dediziert für jedes ListItem die Delete-Methode rufen doch dafür verschwinden so zügig und unkompliziert die nicht länger benötigten Elemente aus SharePoint-Listen oder Bibliotheken.

Noch etwas interessanter wird der auf den ersten Blick nicht übermäßig elegant anmutende Ansatz für ein selektives Massen-Löschen…

DELETE SOME ListItems

$web = Get-SPWeb <URL zum Web>
$lst = $web.Lists[„<Name der Liste>“]
$query = New-Object Microsoft.SharePoint.SPQuery
$query.Query = „<Where><Eq><FieldRef Name=’Project‘ LookupId=’TRUE‘ /><Value Type=’Lookup‘>23</Value></Eq></Where>“
$lst.GetItems($query) | % { $lst.GetItemById($_.ID).Delete(); }

Mit Hilfe einer CAML-Abfrage holt man sich nur die ListItems, die man löschen möchte. Auf dem SPList-Objekt findet man die Methode GetItems(), welches als Parameter ein SPQuery-Objekt entgegennimmt. Im Beispiel oben sind ListItems zu löschen, die mit einem Projekt-Datensatz in einer zweiten Liste verknüpft sind, welcher auf die ID 23 hört.

Wer nun Freude am Löschen per PowerShell findet, für den habe ich hier noch ein paar CAML-Query Beispiele zusammengetragen, welche vielleicht die ein oder andere Idee zur eigenen Adaption bringt…

# ** Query-Beispiel: ListItems, deren ID kleiner als 250 ist
$query.Query = „<Where><Lt><FieldRef Name=’ID‘ /><Value Type=’Counter‘>250</Value></Lt></Where>“

# ** Query-Beispiel: ListItems, die am oder nach dem 01.01.2016 angelegt wurden
$query.Query = „<Where><Geq><FieldRef Name=’Created‘ /><Value IncludeTimeValue=’FALSE‘ Type=’DateTime‘>2016-01-01</Value></Geq></Where>“

# ** Query-Beispiel: ListItems, die im Titelfeld mit ‚A‘ beginnen
$query.Query = „<Where><BeginsWith><FieldRef Name=’Title‘ /><Value Type=’Text‘>A</Value></BeginsWith></Where>“

# ** Query-Beispiel: ListItems, deren Beschreibungsfeld (‚Description‘) das Wort ‚Prozess‘ enthält
$query.Query = „<Where><Contains><FieldRef Name=’Description‘ /><Value Type=’Note‘>Prozess</Value></Contains></Where>“

# ** Query-Beispiel: ListItems, deren Aktiv-Flag auf FALSE gesetzt ist
$query.Query = „<Where><Eq><FieldRef Name=’Active‘ /><Value Type=’Boolean‘>0</Value></Eq></Where>“

Und wem das nicht weit genug geht – man kann nicht nur die Delete-Methode auf dem Objekt rufen…