in

SharePoint Blogs

The Best Place for SharePoint-related Blogs

Meine SharePoint-Notizen

SharePoint-Notizen aus meiner täglichen Projektarbeit mit dem Microsoft Office SharePoint Server 2007
  • Desktop-Icons / Layout speichern und Wiederherstellen

    Wenn ich für einen Vortrag oder eine Präsentation zu einem Kunden fahre, nehme ich gern mein Präsentations-Notebook mit und schließe es vor Ort an einen Beamer an. Mein Notebook paßt dann aber die Auflösung an die maximale Auflösung des angeschlossenen Beamers an und zerwürfelt mir dabei jedesmal die Sortierung der Icons auf meinem Desktop. Da ich meist einige Icons auf meinem Desktop habe, ist ein Punkt der üblichen Nachbereitung das manuelle (und lästige) Wiederherstellen meines gewohnten Desktop-Icon Layouts.

    Ich denke, jeder der schon einmal eine Präsentation mit seinem Notebook und einem Beamer gehalten hat, kennt dieses Problem.

    Bei meiner letzten Kundenpräsentation hatte ein Mitarbeiter im Anschluß an meinen Vortrag einen guten Tipp für mich: es gibt ein kleines Tool, mit dem man das aktuelle Icon-Layout auf dem Desktop speichern und später bei Bedarf wieder herstellen kann. Dieses praktische Tool kann man sich hier herunterladen.

    Leider klappt die Installation nur für Systeme, auf denen Windows XP läuft. Wer Vista oder -wie ich- Vista 64-Bit einsetzt, findet eine erweiterte Version hier.

    So eine Funktion sollte es direkt in Windows Vista geben ...

     

    Add to Technorati Favorites
  • HowTo: Sharepoint-Liste als eigenen Suchbereich einrichten

    Die Suche von SharePoint ist ein sehr mächtiges Instrument und mit ein wenig Konfigurationsarbeit kann man sehr mächtige Suchcenter einrichten. Allerdings gibt es ein Manko: man kann keine einzelne SharePoint-Liste direkt als eigenen Suchbereich definieren. Als Basis für einen Suchbereich läßt SharePoint nur die folgende Inhaltsquellen zu: SharePoint-Websites, allg. Websites, Dateifreigaben, öffentliche Exchange-Ordner und Geschäftsdaten zu (siehe folgendes Bild).

     

    In unserem eigenen Intranet (natürlich basiered auf einem SharePoint Server 2007) existiert eine Bücherliste, die mittlerweile beachtliche Ausmaße angenommen hat. Bisher wurde diese Bücherliste in den allgemeinen Suchindex aufgenommen. Leider bedeutet dies aber auch, dass Mitarbeiter u.U. eine größere Suchergebnisliste angezeigt bekommen, selbst wenn sie nur nach einem Buch gesucht haben. Aus diesem Grund habe ich mir Gedanken darüber gemacht, wie man unsere Bücherliste als eigenständigen Suchbereich einrichten kann. Mein Ziel ist: ich möchte in unserem Intranet-Suchcenter einen eigenen Suchbereich Bücherliste einrichten und die Ergebnisliste soll nur aus Einträgen aus dieser Bücherliste bestehen.

    In diesem Post möchte ich eine auf Metadaten basierte Lösung vorstellen.

    Zuerst habe ich in unserer Bücherliste eine neue Spalte eingefügt. Diese Spalte bekommt den Namen MetaTagBookList und ist vom Typ Text. Da hier niemand Daten eingeben soll (bzw. darf), wird diese Spalte fest auf den Defaultwert Bücherliste gesetzt. Diese Spalte soll nur dazu dienen, jeden Eintrag in der Bücherliste mit einem festen MetaTag zu kennzeichnen. Um sicherzustellen, dass hier niemand einen anderen Wert eingibt oder verändert, empfiehlt es sich, diese Spalte aus den Ansichten auszublenden. Wer dies gründlich machen möchte, kann dazu mein SharePoint-Tool "List Field Form Properties" aus diesem Post benutzen. Etwas unschön ist nur die Tatsache, dass man nun alle Einträge in dieser Liste nochmals öffnen und speichern muss, damit jeder Eintrag in der Bücherliste einen gesetzten MetaTag Bücherliste hat. (Dieses Problem läßt sich aber zum Glück mit ein paar Zeilen Code und einem kleinen Entwicklertool lösen.)

    So - nun ist die Bücherliste vorbereitet. Als nächstes muss unsere neu-hinzugefügte Spalte MetaTagBookList in die Liste der SharePoint-Metadaten aufgenommen werden. Hierzu startet man einen Crawl der betreffenden Inhaltsquelle. Eigentlich sollte ein inkrementelles Crawling ausreichend sein. Dies hat bei mir aber nicht immer geklappt, weswegen ich dazu übergegangen bin, einen vollständigen Crawl zu starten.

    Nachdem das Crawling erfolgreich abgeschlossen wurde, sollten wir unseren neuen Metadaten-Tag MetaTagBookList in der Liste der Metadaten wiederfinden. Dazu öffnen wir die Zentraladministration, klicken auf den SharedService und danach unter der Rubrik Suchen auf den Link Sucheinstellungen. Es öffnet sich eine neue Seite mit den Crawleinstellungen. Ein paar Zeilen tiefer findet sich der Link Eigenschaftenzuordnung für Metadaten, auf den wir jetzt klicken. Es öffnet sich nun eine Liste mit den Eigenschaftenzuordnungen für Metadaten. Hier klicken wir auf Neue verwaltete Eigenschaft und fügen im folgenden Dialog eine neue verwaltete Eigenschaft mit dem Namen Bücherliste hinzu und wählen aus, dass wir diese Eigenschaft in Suchbereichen verwenden möchten! (siehe folgendes Bild).

    Nun haben wir eine neue verwaltete Eigenschaft mit dem Namen Bücherliste erzeugt - und diese können wir benutzen, um einen entsprechenden Suchbereich zu definieren. Hierzu gehen wir zurück zu den SharedService-Einstellungen in der Zentraladministration und klicken wieder auf den Link Sucheinstellungen im Bereich Suchen. Wir lassen uns alle Bereiche anzeigen und klicken oben auf Neuer Bereich. Es öffnet sich ein Dialog und wir geben dort unserem neuen Bereich den Namen Bücherliste und wählen aus, dass wir die Standardseite für Suchergebnisse verwenden wollen (siehe folgendes Bild).

    Als nächstes müssen wir noch eine Regel für diesen neuen Bereich hinzufügen - schließlich wollen wir nur Ergebnisse aus der Bücherliste als Ergebnis einer Suche in diesem neuen Bereich sehen. Wir klicken also auf Regel hinzufügen und wählen Eigenschaftsabfrage aus. Darunter wählen wir in der Dropdownbox Suchkriterien unsere Bücherliste aus und im darunterliegenden Textfeld geben wir "Bücherliste" ein. Bedeutet: wir wollen nur Ergebnisse, bei denen die Eigenschaft Bücherliste den Wert "Bücherliste" hat. Damit sichergestellt ist, nur Ergebnisse aus der Bücherliste zu bekommen, müssen wir unter Verhalten noch "Erforderlich - Jedes Element muss mit dieser Regel übereinstimmen"  auswählen. (siehe folgendes Bild).

    Nach einer Aktualisierung der Bereiche (kann automatisch erfolgen oder manuell angestoßen werden) sollte unser neuer Bereich existieren. Nun können wir diesen Bereich als weiteren Bereich für die Suche definieren. Dazu öffnen wir die Websiteeinstellungen der obersten Ebene und klicken auf Suchbereich unter der Rubrik Websitesammlungsverwaltung. In der Anzeigegruppe Suchdropdown fügen wir unseren neuen Bereich Bücherliste hinzu (siehe Bild).

    Sollte in der Spalte Einträge 0 angezeigt werden, ist u.U. ein weiterer Crawl-Durchlauf erforderlich. Nun können wir unser Suchcenter aufrufen und sollten im Bereichsdropdown unseren neuen Bereich Bücherliste vorfinden. Zeit für einen ersten Probelauf: Bereich Bücherliste auswählen und einen Suchbegriff eingeben, der in der Bücherliste vorkommt. Im Suchergebnis sollten jetzt nur Ergbnisse aus unserer Bücherliste auftauchen. Für diesen Post habe ich mir eine kleine Demo erstellt (aus der auch die Screenshots stammen) und da sieht das Ergebnis nun so aus, wie im folgenden Bild dargestellt.

    Diese Metadaten kann man auch verwenden, um ein Suchcenter zu erstellen, welches z.B. nur und ausschließlich in unserer Bücherliste sucht. Dies ist dann interessant, wenn man ein Suchcenter mit mehreren spezialisierten Suchfeldern auf unterschiedlichen Seiten haben möchte. Eine kleine Modifikation am Suchfeld-Webpart macht dies möglich. Dazu öffnet man die Webpart-Eigenschaften des Suchfeld-Webparts und trägt in der Rubrik Abfragetextfeld in das Textfeld Zusätzliche Abfrageausdrücke "Bücherliste:Bücherliste" ein - bedeutet auch hier wieder: Bücherliste muss den Wert "Bücherliste" haben. Nun kann man das Bereichsdropdownfeld noch ausblenden und fertig ist ein Suchfeld, dass ausschließlich in unserer Bücherliste sucht (siehe folgendes Bild).


     

    Zusammenfassung: Auf diese Weise kann man Benutzern eines Suchcenters sehr anwenderfreundliche Suchbereiche zur Verfügung stellen und es ermöglichen, Suchergebnisse auf eine SharePoint-Liste zu beschränken. Wer die Ausgabe des Suchergebnisses noch anpassen möchte (z.B. das Buchcover einblenden), der findet bei Tobias Zimmergren einen guten Artikel über dieses Thema.

     

    Add to Technorati Favorites
  • Interessantes über das "! Neu" Tag in SharePoint-Listen

    Ehrlich gesagt - meine Kollegen haben mich das schon einige Male gefragt, aber ich konnte Ihnen keine kompetente Antwort auf die Frage "Wie lange wird eigentlich dieser grüne ! Neu-Schriftzug angezeigt?" geben. Nun habe ich die Antwort darauf in einem Blogpost von Asif Rehmani gefunden. Hier der Link zum Post.

    Zusammengefasst: man kann mit STSADM steuern, ob und wie lange dieses Tag angezeigt wird. Dies geht mit diesem Aufruf:

    stsadm.exe –o setproperty –pn days-to-show-new-icon –pv (number of days) –url (Virtual server address) 

    Um das Tag ganz abzuschalten, kann man diesen Aufruf verwenden:

    stsadm.exe –o setproperty –pn days-to-show-new-icon –pv 0 –url http://(your server name)

    Wenn ich in Zukunft wieder nach diesem grünen ! Neu-Schriftzug gefragt werde, kann ich jetzt endlich auch darauf eine Antwort geben. Wink

     

    Add to Technorati Favorites
  • Benutzerdefinierte TimerJobs - die Basics

    Vor kurzem wurde ich mit einem Sharepoint-Problem eines Kunden konfrontiert, für das ich nur einen selbstdefinierten TimerJob als sinnvolle Lösungsmöglichkeit sah. Da ich mich aber bisher noch nicht mit SharePoint TimerJobs auseinandergesetzt habe, war dies ein willkommene Gelegenheit, dies nachzuholen. Zwar findet man im Internet einige interessante Posts über SharePoint TimerJobs, aber ich wollte mir zunächst selbst die Basics erarbeiten.

    Und genau über diese Basics möchte ich hier berichten:

    Ein SharePoint TimerJob besteht aus einer Klasse, die von der Basisklasse SPJobDefinition abgeleitet ist. In der Ableitung wird im Wesentlichen die Methode Execute() mit der gewünschten Funktionalität überschrieben und der eigentliche TimerJob ist bereits fertig. Zusätzlich kann man auch noch die Konstruktoren überschreiben, um z.B. dem eigenen TimerJob einen aussagekräftigen Titel zu geben.

    Ein TimerJob kann dann z.B. folgendermaßen aussehen:

    using System;
    using Microsoft.SharePoint.Administration;

    namespace TimerJobNotifyExpiredPassword
    {
        public class NotifyExpiredPasswordTimerJob : SPJobDefinition
        {
            public NotifyExpiredPasswordTimerJob()
                : base()
            {
            }

            public NotifyExpiredPasswordTimerJob(string strJobName, SPService oService, SPServer oServer, SPJobLockType oTargetType)
                : base(strJobName, oService, oServer, oTargetType)
            {
            }

            public NotifyExpiredPasswordTimerJob(string strJobName, SPWebApplication oWebApp)
                : base(strJobName, oWebApp, null, SPJobLockType.ContentDatabase)
            {
                this.Title = "NotifyExpiredPasswordTimerJob";
            }

            public override void Execute(Guid oContentDBId)
            {
                // Hier den auszuführenden Timer-Code einfügen
            }
        }
    }
     

    An der grün markierten Stelle würde man den eigenen Code einfügen, der vom SharePoint TimerDienst zyklisch aufgerufen werden soll. OK, nun haben wir bereits die Klasse, die vom SharePoint TimerDienst aufgerufen werden könnte - wenn es uns nun noch gelingen würde, die obige Klasse als SharePoint TimerJob auf einem SharePoint-Server zu installieren. Dies ist leider nur mit ein wenig zusätzlicher Programmierarbeit möglich. Das Verfahren ist ähnlich, wie es z.B. auch bei einem benutzerdefiniertem EventHandler angewendet werden kann. Wir werden unseren TimerJob über ein SharePoint Feature installieren und uns an den Event hängen, der beim Installieren bzw. beim Deinstallieren eines Features ausgelöst wird. Beim Installieren fügen wir unsere neue TimerJob-Klasse als neuen TimerJob der entsprechenden SharePoint-Liste hinzu, beim Deinstallieren entfernen wir unsere Klasse aus der Liste der SharePoint-TimerJobs. Im Folgenden möchte ich zeigen, wie man das genau macht:

    Zuerst benötigen wir eine zweite Klasse, die aber diesmal von der Basisklasse SPFeatureReceiver abgeleitet wird. Wir erstellen uns also einen eigenen EventReceiver und überschreiben hier z.B. die Methoden FeatureActivated() und FeatureDeactivating(). Beim Aktivieren unseres Features wird unsere Methode FeatureActivated() aufgerufen und hier fügen wir nun den Code ein, um unseren TimerJob zu installieren. Beim Deaktivieren unseres Features wird dann die Methode FeatureDeactivating() aufgerufen und wir fügen hier den Code ein, um unseren TimerJob wieder zu deinstallieren.

    Dies kann dann z.B. folgendermaßen aussehen:

    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;

    namespace TimerJobNotifyExpiredPassword
    {
        class FeatureReceiver : SPFeatureReceiver
        {
            public override void FeatureActivated(SPFeatureReceiverProperties oProperties)
            {
                SPSite oSite = oProperties.Feature.Parent as SPSite;

                // Falls ältere Instanz vorhanden, diese zuvor löschen
                foreach (SPJobDefinition oJob in oSite.WebApplication.JobDefinitions)
                {
                    if (oJob.Name == "TimerJobNotifyExpiredPassword")
                    {
                        oJob.Delete();
                    }
                }

                // Timer-Job installieren
                TimerJobNotifyExpiredPassword.NotifyExpiredPasswordTimerJob oTimerJob = new TimerJobNotifyExpiredPassword.NotifyExpiredPasswordTimerJob("TimerJobNotifyExpiredPassword", oSite.WebApplication);

                SPMinuteSchedule oSchedule = new SPMinuteSchedule();
                oSchedule.BeginSecond = 0;
                oSchedule.EndSecond = 59;
                oSchedule.Interval = 1;  // <- diesen Job jede Minute starten

                oTimerJob.Schedule = oSchedule;

                oTimerJob.Update();
            }
           
            public override void FeatureDeactivating(SPFeatureReceiverProperties oProperties)
            {
                SPSite oSite = oProperties.Feature.Parent as SPSite;
               
                // Job suchen und löschen
                foreach (SPJobDefinition oJob in oSite.WebApplication.JobDefinitions)
                {
                    if (oJob.Name == "TimerJobNotifyExpiredPassword")
                    {
                        oJob.Delete();
                    }
                }
            }

            public override void FeatureInstalled(SPFeatureReceiverProperties oProperties)
            {
            }

            public override void FeatureUninstalling(SPFeatureReceiverProperties oProperties)
            {
            }
        }
    }

     

    Das Ganze - also unsere beiden Klassen habe ich in einem einfachen VisualStudio 2008 Projekt für eine Klassenbibliothek verpackt und übersetzt. Um dies jetzt als SharePoint Feature installieren zu können, benötigen wir nur noch eine einzige Datei. Diese Datei trägt den Namen feature.xml und enthält eine XML-Beschreibung unsers Features. Für mein einfaches Beispiel reicht diese feature.xml völlig aus:

    <?xml version="1.0" encoding="utf-8" ?>
    <Feature xmlns="
    http://schemas.microsoft.com/sharepoint/
        Id="04496CA0-316D-11DD-BD11-0800200C9A66" 
        Title="TimerJobNotifyExpiredPassword" 
        Description="TimerJobNotifyExpiredPassword" 
        Version="1.0.0.0" 
        Scope="Site" 
        ReceiverAssembly="TimerJobNotifyExpiredPassword, Version=1.0.0.0, Culture=neutral, PublicKeyToken=639ff2c7cd9696b7" 
        ReceiverClass="TimerJobNotifyExpiredPassword.FeatureReceiver">
    </Feature>

    So einfach diese Datei auch aussieht, es gibt hier einiges, was man beachten muss:

    • unser Feature muss über eine eindeutige GUID identifizierbar sein. Die GUID in der Zeile "Id=" muss deswegen ausgetauscht werden
    • gleiches gilt für die Zeilen Title und Description. Hier gibt man dem Feature einen Namen und eine Beschreibung
    • ausgetauscht bzw. angepasst werden müssen auch die letzten beiden Zeilen, die die Assembly und die Klasse angeben, die als Receiver für die oben beschreibenen Feature-Events verwendet werden soll. Übrigens: den PublicKeyToken bekommt man recht einfach mit dem .NET Reflector von Lutz Roeder heraus.
    • wichtig ist auch die Zeile "Scope=". Hier gibt man den Gültigkeitsbereich des Features an. Wichtig zu beachten: der hier eingetragene Scope muss mit dem Scope übereinstimmen, den wir beim Installieren bzw. Deinstallieren unseres TimerJobs verwendet haben!

    So - das waren alle Dateien, die man unbedingt benötigt, um einen eigenen TimerJob auf einem SharePoint-Server zu installieren. Stellt sich die Frage: wie geht es nun weiter?

    Zuerst übersetzten wir unsere beiden Klassen. Sofern beide in einem Projekt zusammengefasst wurden, sollte dabei eine DLL erstellt werden. Diese DLL kopieren wird in den Global Assembly Cache. Als nächstes erzeugen wird im sogenannten 12-Hive unter ../TEMPLATE/FEATUES ein neues Verzeichnis mit dem Namen, dem wir dem Feature in der Datei feature.xml gegeben haben und kopieren die Datei feature.xml dort hin. Jetzt sind wir bereit, unser Feature zu installieren.

    Dies geschieht mit folgendem Auruf:

    stsadm -o installfeature -name TimerJobNotifyExpiredPassword 

    Nun müssen wir das Feature nur noch Aktivieren, damit unser EventReceiver aufgerufen wird und unseren TimerJob installieren kann:

    stsadm -o activatefeature -name TimerJobNotifyExpiredPassword -url http://mossbasis

    Die URL muss natürlich durch die URL des jeweiligen Ziels ersetzt werden.

    Beide Aufrufe kann man auch in einer kleinen Batch-Datei zusammenfassen. Für meine Testinstallationen verwende ich gern diese Batch-Datei:

    REM TO BE SAFE FIRST DEACTIVATE and UNINSTALL FEATURE
    stsadm -o deactivatefeature -name TimerJobNotifyExpiredPassword -url
    http://mossbasis
    stsadm -o uninstallfeature -name TimerJobNotifyExpiredPassword -force
    PAUSE

    REM NOW INSTALL FEATURE
    stsadm -o installfeature -name TimerJobNotifyExpiredPassword
    PAUSE

    REM FINALLY ACTIVATE FEATURE
    stsadm -o activatefeature -name TimerJobNotifyExpiredPassword -url
    http://mossbasis 

    Der beispielhafte TimerJob führt zwar keine Aktion aus, dennoch können wir mit dem Debugger schnell überprüfen, ob alles wie gewünscht funktioniert. Dazu setzten wir einen Breakpoint auf die Methode Execute() und verbinden uns mit dem Prozess OWSTIMER.EXE. Es kann notwendig sein, einen Haken neben "Prozesse aller Benutzer anzeigen" im Fenster "An den Prozess anhängen" des Debuggers zu setzen. Nach maximal einer Minute sollte der Debugger beim Aufruf der Methode Execute() anhalten - sofern am obigen Aktivierungsintervall (SPMinuteSchedule) nichts geändert wurde!

    Auf ähnliche Weise kann man übrigens auch Testen, ob unser Feature-EventReceiver funktioniert. Einfach je einen Breakpoint auf die überschriebenen Methoden setzen und diesmal an den Prozess W3WP.EXE anhängen. Möglicherweise gibt es den Prozess in mehreren Instanzen. Sofern man die richtige Instanz nicht kennt, kann man sich auch einfach -zu Testzwecken- an alle Instanzen hängen.

    Unser Feature läßt sich natürlich auch über die Zentraladministration aktivieren bzw. deaktiviren - in der Websitesammlungsverwaltung klickt man auf Websiteauflistungsfeatures. In der Liste Websitesammlungs-Features sollte sich unser TimerJob-Feature finden.

    Ich habe hier das grundsätzliche Vorgehen beim Erstellen und Installieren eines benutzerdefinierten SharePoint TimerJobs beschrieben. Auf diese Weise funktioniert es zwar, aber für das Deployment auf ein produktives System ist diese Vorgehensweise natürlich nicht geeignet. Hierfür bietet es sich an, aus unserem SharePoint-Feature eine SharePoint-Solution zu machen

     

    Add to Technorati Favorites
  • Design-Tipp: Formatierung des Web-Title durch Änderungen an der Masterpage

    Eine der Arbeiten der letzten Wochen war die Design-Änderung unseres eigenen Intranets - natürlich auf SharePoint-Basis! Ziel war, das Design moderner zu gestalten und besser an das CI unserer Firma anzupassen. Eine kleine Herausforderung dabei war die Startseite, denn der Titel sollte farblich hervorgehoben werden. Bisher lautete der Titel der Startseite "MITARBEITER-PORTAL" - dieser sollte in "MITARBEITER-PORTAL" geändert werden.

    Der Titel der Startseite entspricht normalerweise dem Titel des Webs zu dem die Startseite gehört. Dieser Titel wird als Text eingegeben und über die Masterpage auf jeder Seite des Webs eingeblendet. Die Frage, die sich für uns nun stellte war: wie kann man diese Texteinblendung manipulieren? Da dieser Mechanismus über die Masterpage gesteuert wird, ergab sich eine weitere Frage: wenn Änderungen an der Masterpage nötig sind, wie kann man diese Änderungen auf die Startseite bzw. das Root-Web begrenzen?

    Wie immer gibt es mehrere Lösungsmöglichkeiten. Wir haben uns für die folgende Lösung entschieden:

    Wir haben auf der Masterpage ein kleines Script hinterlegt:

     public void CheckForRoot()
     {
         SPWeb oWeb = SPControl.GetContextWeb(Context);
         if(false == String.IsNullOrEmpty(oWeb.Name))
         {
             Response.Write("<div id=\"OWNTITLE\" class=\"style2\"><strong>" + oWeb.Title.ToString() + "</strong></div>");
         }
         else
         {
          Response.Write("<div id=OWNTITLE class=style3><strong><span class=ms-menuitemdescription>M</span><span class=style4>IT</span><span class=ms-menuitemdescription>ARBEITER-PORTAL</span></strong></div>");
         }
     }

    Dieses Script macht sich eine Eigenschaft des SharePoint-Objektmodels zu Nutze: Zitat aus dem MSDN Developer Network:"The Name property returns an empty string if the site is a top-level site.". Man kann also ein Root-Web u.a. daran erkennen, dass die Name-Eigenschaft leer ist. Erkennt das Script, dass es gerade im Context des Root-Webs läuft, gibt es einen HTML-String zurück, der die Ausgabe "MITARBEITER-PORTAL" erzeugt. Ansonsten wird einfach die Title-Eigenschaft des aktuellen Webs zurückgegeben.

    Damit dieses Script aber auch wirklich das gewünschte Resultat bringt, müssen noch weitere Änderungen vorgenommen werden. In der Masterpage muss der Code, der normalerweise für die Ausgabe der Title-Eigenschaft zuständig ist, durch einen Aufruf des obigen Scripts ersetzt werden.

    Das sieht dann z.B. folgendermaßen aus:

     <asp:ContentPlaceHolder id="PlaceHolderSiteName" runat="server">
        <h1 class="ms-sitetitle">
        <br><% CheckForRoot(); %></h1>
     </asp:ContentPlaceHolder>

    Die interessante Zeile ist in roter Fettschrift dargestellt.

    Weiterhin muss in der web.config noch eingestellt werden, dass Scripte in der Masterpage erlaubt sind. Das sieht dann aus wie folgt:

    <configuration>

      <SharePoint>

        <SafeMode MaxControls="200" CallStack="false" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">

          <PageParserPaths>

             <PageParserPath VirtualPath="/_catalogs/masterpage/*" CompilationMode="Always" AllowServerSideScript="true" IncludeSubFolders="true" />

          </PageParserPaths>

        </SafeMode>

      </SharePoint>

    </configuration>

    Die in roter Fettschrift dargestellte Zeile muss einfach eingefügt werden. Damit werden Scripte in der Masterpage erlaubt.

    Auf diese Weise läßt sich durch ein wenig Scripting in der Masterpage eine einfache Dynamik in der Darstellung von Seiten bzw. Webs erzeugen.

     

    Add to Technorati Favorites
  • Bug in der SharePoint Benutzerverwaltung

    In unserem Kundenportal ist vor einigen Tagen ein bemerkenswerter Fehler aufgetreten. Nachdem wir Probleme mit einem Account bzw. dessen Profildaten hatten, haben wir diesen Account aus dem ActiveDirectory und aus der SharePoint-internen Benutzerverwaltung gelöscht und wieder unter dem gleichen Namen neu angelegt. Um zu probieren, ob dieser neu-angelegte Account wieder einwandfrei funktioniert, habe ich mich mit diesem Account an unserem Kundenportal angemeldet. Ich war verwundert, dass ich eine Fehlermeldung von unserem SharePoint Server bekam, die sinngemäß besagte, dieser Account hätte keine Rechte für die aktuelle Seite. Ich habe mich dann als Administrator angemeldet um nachzusehen, was mit dem Account nicht stimmt. In der SharePoint-Benutzerverwaltung wurde dieser Account aus allen Gruppen entfernt, in denen er zuvor Mitglied war.

    Dieses Problem mußten wir genauer untersuchen. Ich habe deswegen in einer virtuellen Umgebung mit lokalen Benutzerkonten versucht, dieses Problem nachzuvollziehen. Folgendermaßen bin ich dabei vorgegangen:

    • in der lokalen Benutzerverwaltung des Betriebssystems habe ich einen neuen Account angelegt.
    • in der SharePoint-Benutzerverwaltung habe ich diesen Account der SharePoint-Gruppe 'Mitglieder' hinzugefügt.
    • ich habe nun versucht, mich mit diesem neuen Account bei SharePoint anzumelden. Wie erwartet klappte dies problemlos!
    • zur Sicherheit habe ich mich wieder abgemeldet und das Browserfenster geschlossen.
    • in der lokalen Benutzerverwaltung habe ich nun den eben angelegten Account gelöscht
    • in der SharePoint-Benutzerverwaltung habe ich diesen Account auch gelöscht.
    • ein Anmelden mit diesem gelöschten Account schlägt nun -wie erwartet- fehl.
    • nun habe ich in der lokalen Benutzerverwaltung des Betriebssystems den zuvor gelöschten Account mit exakt den gleichen Daten wieder angelegt.
    • in SharePoint habe ich diesen neu angelegten Account wieder der SharePoint-Gruppe 'Mitglieder' hinzugefügt.
    • beim Anmelden an SharePoint mit diesem neu-angelegten Account kommt es nun wieder zu der genannten Fehlermeldung "Sie haben keine Berechtigung ...."
    • als ich mich wieder als Administrator angemeldet habe, stellt ich fest, dass der neu-angelegte Account aus der SharePoint-Gruppe 'Mitglieder' verschwunden war.

    Dies erklärt zwar die Fehlermeldung, aber warum verschwindet ein gelöschter Account, der mit den gleichen Daten wieder neu angelegt wurde, nach dem ersten Anmelden an SharePoint aus allen SharePoint-Gruppen?

    SharePoint speichert alle Accounts in einer Tabelle in der Content Database und weist diesen Accounts eine eigene ID zu. Diese ID wird sichtbar, wenn man mit der Maus auf einen Benutzernamen in der SharePoint-internen Benutzerverwaltung zeigt (also Mauszeigen nur auf den Benutzernamen schieben, nicht klicken!).

    Nachdem ein Account in SharePoint gelöscht wird, wird dieser nicht aus der User-Tabelle entfernt, sondern dort nur als gelöscht markiert. Erzeugt man nun einen neuen Account, der einem gelöschten Account exakt entspricht und fügt diesen Account einer SharePoint-Gruppe hinzu, tauchen in der User-Tabelle zwei Accounts mit dem gleichen Namen, aber unterschiedlichen IDs auf. Einer (der mit der kleineren ID) ist als gelöscht markiert, der andere mit der größeren ID ist der neu-angelegte Account. Loggt man sich nun mit einem solchen gelöscht-und-neu-angelegt Account bei SharePoint ein, kommt SharePoint offensichtlich durcheinander und verwendet die ID des gelöschten Accounts. Dies kann man sehen, wenn man sich die IDs wie oben beschrieben ansieht.

    Bevor ich mich mit diesem Fehler an den Microsoft-Support wenden wollte, wollte ich erst sichergehen, dass es sich wirklich um einen Fehler handelte. Fabian Moritz war so freundlich, mich ein wenig zu unterstützen. Er konnte mir das geschilderte Verhalten bestätigen, denn in seinem Blog-Artikel hatte er bereits Untersuchungen zur SharePoint-internen Benutzerverwaltung angestellt.

    Grundsätzlich gibt zwei Lösungsmöglichkeiten für dieses Problem - diese beiden Möglichkeiten konnte mir der Microsoft-Support im Nachhinein auch bestätigen:

    • der Person Synchronization Timer Service startet normalerweise ungefähr 1 Mal pro Stunde und sollte die Unstimmigkeiten in der Benutzerverwaltung wieder korrigieren. Bedeutet: man muß mindestens einen Timerzyklus abwarten. Der Microsoft-Support erwähnte aber auch noch, dass manchmal auch ein manueller vollständiger Profilimport nötig sei. In Ausnahmefälle müsse der vollständige Profilimport auch mehrmals durchgeführt werden. Diese Aussagen des Microsoft-Supports habe ich nicht weiter überprüft.
    • es gibt ein STSADM-Kommando, mit welchem man die Unstimmigkeiten in der SharePoint-internen Benutzerverwaltung manuell korrigieren kann: STSADM -o migrateuser <oldlogin> <newlogin> -ignoresidhistory

    Mit diesem STSADM-Kommando konnten wir unser Problem lösen. Wichtig ist aber, dass man hier den Parameter -ignoresidhistory nicht vergisst! Übrigens tritt das geschilderte Problem mit lokalen Benutzerkonten und mit Benutzerkonten in einem ActiveDirectory auf (Stichwort: Windows-Authentifizierung). Auf einer Testinstallation, die mit Forms Authication arbeitet, trat das Problem nicht auf.

    Wer sich noch ein wenig über die interne SharePoint-Benutzerverwaltung informieren möchte, findet entsprechende Informationen im Blog von Fabian Moritz in seinem Artikel über die UserInfo-Tabelle.

     

    Add to Technorati Favorites
  • Kleiner 'Bug' im Data View Webpart bei der Formatierung von Währungsangaben

    Vor ein paar Tagen sind wir auf einen Bug im Data View Webpart (bzw. auf deutsch: Datenansichtswebpart) gestossen, als wir den Inhalt einer SharePoint-Liste in einem anderen Web mithilfe des SharePoint-Designers anzeigen wollten. Ausgangsbasis war eine deutschsprachige SharePoint-Installation.

    In der ursprünglichen Liste gab es u.a. eine Spalte mit dem Namen 'Preis', die als Währung in € definiert war. Der Inhalt dieser Liste sollte mit dem Data View-Webpart auf einer Seite in einem anderen Web angezeigt werden. Dies klappte auch anfangs problemlos, nur als in der ursprünglichen Liste Preise mit Nachkommastellen (also z.B. 49,95€) auftauchten, wurde dieser Preis im Data View-Webpart nicht mehr angezeigt. An der Stelle, an der wir eigentlich 49,95€ erwartet haben, wurde nichts mehr angezeigt. Bei Preisen ohne Nachkommastellen klappt die Anzeige hingegen wie erwartet.

    Nach einigem Recherchieren und Ausprobieren sind wir zu der Erkenntnis gekommen, dass das Data View-Webpart offensichtlich ein Problem mit Punkt und Komma und länderspezifischen Einstellungen hat. Zwar wird im entsprechenden XSLT-String die deutsche LCID mit angegeben, aber trotzdem klappt die korrekte Formatierung von Währungsspalten nicht.

    Im Original sieht dieser XSLT-String folgendermaßen aus:

    <xsl:value-of select="format-number(@Preis, '€#.##0,00;-€#.##0,00', 'lcid1031')" />

    Eigentlich ist diese Formatierung richtig, denn in Deutschland werden die Nachkommastellen mit einem Komma abgetrennt. Das Problem kommt daher, dass wir auch einen deutschen SQLServer installiert haben - SharePoint aber wohl insgeheim von einem englischen SQLServer und damit von einem englischen Zahlenformat ausgeht.

    Zum Glück kann man über den XSLT-Editor des Data View-Webparts diesen String ein wenig verändern - und über diesen Weg läßt sich der beschriebene Fehler im Data View-Webpart dann auch korrigieren.

    Wir haben den XSLT-String ein wenig modifiziert:

    <xsl:value-of select="format-number(translate(@Preis,',','.'), '#.##0,00 €;-#.##0,00 €', 'lcid1031')" />

    Mit diesem String ersetzen wir vor der eigentlichen Formatierung ein Komma durch einen Punkt - und haben damit eine englischsprachige Zahlenformatierung erreicht. Dieses englischsprachige Zahlenformat kann das Data View-Webpart jetzt problemlos als deutsche Währung formatieren und ausgeben.

    Weitere Informationen zu diesem Thema finden sich in diesem MSDN-Artikel zu KB293469.

     

    Add to Technorati Favorites
  • Veranstaltungshinweis: „Die Brücke zwischen MS Office und SAP"

    Das Thema "SAP und SharePoint" wird immer interessanter - Ende letzten Jahres wurde mir dies zum ersten Mal durch die positive Resonanz auf meinen Vortrag beim "Shared Solution Day" bewußt. Auch die diesjährige SharePoint Konferenz in Frankfurt zeigte deutlich, dass die Anbindung von SharePoint an SAP ein wichtiges und interessantes Thema ist.

    Nicht zuletzt die zumehmenden Anfragen bei uns zu diesem Thema haben mir gezeigt, dass es bei unseren Kunden ein zunehmendes Interesse bzw. einen Informationsbedarf gibt. Aus diesem Grund habe ich bei uns einen Vortragstag zum Thema "SAP und SharePoint" initiiert. Wir möchten an diesem Tag (24.4.2008) über einige Möglichkeiten informieren, wie man einen SharePoint-Server mit einem SAP-System verbinden kann. Wir sehen diesen Tag weniger als Firmenpräsentation, sondern eher als Informationsveranstaltung für Kunden und interessierte SharePoint-Benutzer. Aus diesem Grund haben wir bei den Vorträgen auf einen guten Mix aus Information und Entwicklung geachtet.

    Ich freue mich besonders, dass es uns gelungen ist, Jan-Peter Wunderlich (Field Solution Manager bei SAP) als Gastredner gewinnen zu können. Er wird über die Informationworker Strategie bei SAP und die DUET-Roadmap berichten.

    Genauere Informationen über den Tagesablauf bietet diese Agenda bzw. dieser Link.

    Ich freue mich auf interessante Gespräche und natürlich auch darauf, über ein -wie ich finde- spannendes und interessantes Thema im SharePoint-Umfeld berichten zu dürfen.

     

    Nachtrag:

    Unsere Veranstaltung verlief sehr erfolgreich. Bedingt durch eine kleine Änderung an der Agenda konnte Herr Wunderlich den ganzen Vormittag nutzen, um ausführlich über neue Produkte bei SAP zu berichten und sich danach ganz auf eine sehr informative und anschauliche Duet-Präsentation konzentrieren - ich konnte mich so ganz auf meinen Vortrag am Nachmittag und die Live-Programmierung eines WebParts mit Zugriff auf SAP konzentrieren. Mir hat die Live-Programmierung viel Spaß gemacht und das Feedback unserer Gäste zeigte mir, dass ich einiges an KnowHow rüberbringen konnte.

     

    Add to Technorati Favorites
  • SAP .NET Connector / Visual Studio 2003 / Absturz beim Browsen der BAPIs

    Momentan arbeite ich an einer Demo-Umgebung für einen Vortrag zum Thema SAP-Anbindung an SharePoint. Ich möchte u.a. zeigen, wie man mit dem SAP .NET Connector auf ein SAP-System zugreifen kann. Offensichtlich ist beim Installieren aber etwas schief gegangen, denn jedesmal wenn ich den Server-Explorer im Visual Studio 2003 nutze, um mich mit unserem SAP-Server im Unternehmen zu verbinden und durch die BAPIs zu browsen, kommt es zu einem Absturz. Visual Studio 2003 wird recht unsanft beendet!

    Zuerst habe ich an einen Fehler beim Installieren der Komponenten gedacht, aber als der Fehler nach einer Neuinstallation immer noch auftrat, habe ich mich auf die Suche gemacht und bin in einigen SAP-Foren auf ähnliche Problemschilderungen gestoßen. Auch hier wurde auf der Suche nach einer Lösung sehr viel ausprobiert - ohne leider zu einer Lösung zu finden.

    Um es kurz zu machen:  nach intensiver Fehlersuche konnten wir das Problem in meiner virtuellen Umgebung lösen. Zwar kann auch ich nicht genau sagen, worin die Absturzursache letztendlich begründet war, aber immerhin läuft meine Demo-Umgebung wieder.

    • als Java Runtime verwende ich eine ältere Version V1.3 - eine zuvor verwendete aktuelle Version habe ich wieder deinstalliert.
    • in SAP-Foren habe ich immer wieder einen Hinweis auf die SAP.Connector.Design.DLL gefunden. Ich habe die ursprünglichen Version gegen eine DLL mit der Versionskennung 2.0.0.23 ausgetauscht.

    Nach diesen beiden Maßnahmen und einem Neustart traten die Abstürze im Visual Studio 2003 beim Browsen durch die BAPIs nicht mehr auf. Zwar kann ich nicht sagen, dass mit diesen beiden Änderungen das Problem grundsätzlich behoben ist, aber einen Versuch ist es wert.


    Add to Technorati Favorites
  • Tipp für Admins - 'MySite' ausgeschiedener Mitarbeiter löschen

    Bei einem SharePoint-Gespräch kam eine interessante Frage auf: was passiert eigentlich mit der 'MySite' eines Mitarbeiters, der das Unternehmen verlassen hat? Interessante Frage - ehrlich gesagt habe ich darüber bisher kaum nachgedacht und deswegen heute ein wenig recherchiert.

    Zum einen hat ein Mitarbeiter natürlich die Möglichkeit, seine eigene 'MySite' wieder zu löschen. Dazu klickt er auf seiner eigenen 'MySite' auf <Websiteaktionen> und danach auf <Websiteeinstellungen>. In der Spalte 'Websiteverwaltung' findet sich dann der Eintrag <Diese Website löschen>.

    Nur was macht man, wenn der ausscheidende Mitarbeiter nicht so ordentlich ist und nicht nur seinen Schreibtisch aufräumt, sondern auch selbst seine MySite löscht? Hier kommt dann der Admin ins Spiel. Ein Admin kann nämlich über die Zentraladministration auch eine 'MySite' löschen. Jede 'MySite' ist als eine Websitesammlung gespeichert. Um eine 'MySite' über die Zentraladministration zu löschen, wechselt man in die Anwendungsverwaltung und findet dort unter der Rubrik <SharePoint - Websiteverwaltung> den Eintrag <Websitesammlung löschen>. In dem neuen Fenster kann man jetzt die Websitesammlung (also auch die MySite) auswählen, die gelöscht werden soll.

     

    Noch einfacher geht es natürlich über die Kommandozeile und das SharePoint-Tool STSADM. Die Syntax zum Löschen einer MySite sieht dann so aus:

    stsadm.exe -o deleteWeb -url http://server/personal/username

    Hierbei muss 'server' durch den Namen des verwendeten Servers und 'username' durch den Loginnamen des betreffenden Users ersetzt werden.

    Natürlich sollte ein Admin vor dem Löschen der MySite eines Mitarbeiters die Datenschutzrichtlinien des Unternehmens beachten!

     

     

  • Best Practice - Upgrading älterer (Beta2 / TR) MOSS-Installationen

    Einer unserer Kunden kam Mitte 2006 zu uns, um den Aufbau eines Kundenportals auf Sharepoint-Basis zu besprechen. Nach intensiver Durchsprache der Anforderungen haben wir uns für SharePoint 2007 als Basis entschieden, obwohl zu diesem Zeitpunkt erst die Beta2-Version von SharePoint 2007 verfügbar war.

    Wir haben also die Portal-Entwicklung mit der Beta2-Version gestartet - wohlwissend, dass wir mit einer Beta-Version arbeiten und später auf die finale Version updaten müssen. Während der Entwicklungszeit haben wir dann mit einigen Mühen und manueller Nacharbeit ein erstes Upgrade vollzogen. Die ursprüngliche MOSS-Beta2-Installation wurde auf den Stand "Technical Refresh" gebracht.

    Als dann die finale SharePoint-Version verfügbar war, haben wir ein weiteres Upgrade durchgeführt. Diesmal haben wir ein Upgrade vom Stand "Technical Refresh" auf die finale Sharepoint-Version durchgeführt. Auch hierbei gab es das eine oder andere Problem, welches sich nur mit viel manueller Nacharbeit lösen lies.

    Die SharePoint-Installation war jetzt zwar auf dem finalen Stand, aber ein ungutes Gefühl blieb. Schließlich waren beide Upgrade-Vorgänge nicht problemlos durchgelaufen und hatten jedesmal einige manuelle Nacharbeit erfordert. Als dann auch noch ein paar seltsame Probleme auftauchten (z.B. verschwand mehrmals der Inhalt der Startseite, ohne dass jemand daran gearbeitet hätte), haben wir uns entschlossen, den Server neu auzusetzen.

    Um die Downtime möglichst gering zu halten, haben wir uns zuerst überlegt, wie wir am sinnvollsten vorgehen sollten. Einerseits sollte möglichst viel 'alter Ballast' entfernt werden, andererseits sollte die Downtime des produktiven Portals möglichst gering gehalten werden. Wir haben uns dann in Absprache mit unserem Kunden dazu entschlossen, den Server neu zu installieren und das Portal durch einen Transfer der Content-Database auf den neu-installierten Server zu übertragen. Da diese Aktion nicht ganz risikolos ist, haben wir das Vorgehen zuerst mit einem 1:1-Image des Servers in einer Testumgebung durchgeführt.

    So sind wir vorgegangen:

    • wir haben als Rettungsanker ein Komplett-Image des ursprünglichen Servers erstellt. Falls es zu größeren Problemen gekommen wäre, hätten wir so rechtzeit abbrechen und den alten Stand wiederherstellen können.
    • danach haben wir eine Sicherung der Content-Database erstellt. Wie man das am besten macht, habe ich vor einiger Zeit bereits hier beschrieben.
    • da nun alle wichtigen Daten mehrfach gesichert waren, konnte unser Rechenzentrum den Server nach unseren Vorgaben neu installieren. Wir haben uns dafür entschieden, den kompletten Server (also inkl. Betriebssystem) neu zu installieren.
    • nach der Installation des Servers und der nötigen Software (u.a. SQL-Server 2005 und .NET-Frameworks 2/3/3.5) haben wir SharePoint neu installiert und bei dieser Gelegenheit gleich ein Update auf SP1 durchgeführt.
    • der Server war nun komplett neu installiert und die SharePoint-Installation (inkl. SP1) lief problemlos durch. Auf dieser Basis konnten wir nun die Inhaltsdatenbank (Content-Database) zurückspielen und ein paar manuelle Umkonfigurationen vornehmen.
    • zum Abschluß haben wir noch die Daten aus der zurückgespielten Content-Database auf den SP1-Stand gebracht. Dazu reicht folgender Aufruf: stsadm -o upgrade -inplace -forceupgrade

    Serverinstallation und Transfer des Portals haben auf diese Art problemlos geklappt. Zwar war auch auf diesem Weg ein wenig manuelle Nachkonfiguration nötig, aber diese Arbeiten blieben im normalen und erwarteten Rahmen. Nach einem gründlichen Abschlußtest, der keine Probleme zeigte, konnten wir das Portal sehr zügig wieder online bringen. Bisher läuft dieses Portal ohne Probleme, die seltsamen Fehler, die wir immer auf die früheren Upgradevorgänge geschoben haben, sind nicht mehr aufgetreten und alles in allem läuft das ganze Portal jetzt sogar ein wenig flotter. Wir werden diese Vorgehensweise bei uns intern als "Best Practice" aufnehmen.

  • "Meine Website" durch Rechte-Entzug deaktivieren

    In Unternehmen ist das Sharepoint-Feature "Meine Website" nicht immer gern gesehen. Zwar bietet "Meine Website" viele Vorteile, aber in manchen Unternehmen befürchtet man, dass diese Vorteile von einigen Mitarbeitern auch missbraucht werden könnten - beispielsweise zum Horten von privaten Bildern oder ganzen MP3-Sammlungen. Momentan installiere ich für einen Kunden einen SharePoint-Server, der in der ersten Ausbaustufe als reines Suchcenter arbeiten soll, später aber Schritt für Schritt zu einem Intranet-Portal erweitert werden soll. Dieser Kunde möchte, dass "Meine Website" seinen Mitarbeitern nicht angeboten werden soll.

    Zuerst dachte ich, dass das eigentlich kein Problem sein könnte und startete die Zentraladministration um in den Einstellungen für den SharedService nach der Option zum Abschalten des Features "Meine Website" zu suchen. Was soll ich sagen - fündig wurde ich so leider nicht. Außerdem wollte ich ehrlich gesagt "Meine Website" nicht komplett abschalten - es wäre ja immerhin möglich, dass in einer späteren Ausbaustufe mein Kunde doch wieder "Meine Website" aktivieren und seinen Mitarbeitern anbieten möchte.

    Nach einiger Recherche habe ich dann aber doch eine verblüffend einfache Lösung gefunden - man muß nur wissen, wo man nach ihr suchen muss.

    Der Weg in die Zentraladministration und in die Einstellungen für den SharedService war schon richtig, nur muss man dort unter "Benutzerprofile und Meine Websites" auf "Berechtigungen für Personalisierungsdienste" klicken.

    Hier werden jetzt einige Benutzer- und Gruppennamen aufgelistet. Als Beispiel möchte ich hier mit der Gruppe "Authentifitzierte Benutzer" weitermachen. Nachdem man auf diese Gruppe geklickt hat, erscheinen erweiterte Berechtigungen - und so auch die Berechtigung zum Erstellen persönlicher Websites.

    Entzieht man nun z.B. der Gruppe "Authentifizierte Benutzer" das Recht zum Erstellen persönlicher Websites und klickt anschließend auf "Speichern", verschwindet der Link "Meine Website" - Benutzer dieser Gruppe können ab sofort keine "Meine Website" mehr anlegen.

    Sobald sich der Kunde umentscheidet und seinen Mitarbeitern doch persönliche Websites zur Verfügung stellen möchte, aktiviert man diese Berechtigung wieder und der Link "Meine Website" erscheint wieder wie gewohnt.

    Ich finde, dieses Beispiel zeigt wieder einmal, wie einfach SharePoint sein kann - wenn man weiß, wo man nach Einstellungen suchen muss.

  • Erste Erfahrungen mit Windows Vista SP1

    Das langerwartete (oder ersehnte) Service Pack 1 für Windows Vista ist nun doch schon u.a. für MSDN-Abonnenten verfügbar. Neugierig wie ich bin habe ich es auf einem meiner Entwicklungsnotebooks installiert. Die Installation von einer zuvor gebrannten DVD verlief problemlos und unspektakulär ab. Es dauerte ca. 30 Minuten bis das SP1 nach einigen Reboots installiert war.

    Meine ersten Erfahrungen:

    • trotz der Hinweise auch von Microsoft gab es bei meiner Installation keine Probleme mit Treibern. Nach der Installation zeigte der Gerätemanager keine Besonderheiten.
    • auch bei den installierten Applikationen gab es nach der SP1-Installation keine Auffälligkeiten. Alles läuft so, wie es auch vor der SP1-Installation lief.
    • subjektiv kann ich sagen, dass das System ein wenig schneller auf Befehle und Mausklicks reagiert. Vista mit SP1 wirkt ein wenig flotter und reagiert ein wenig schneller.
    • einige Tester berichteten von einer teilweise deutlichen Steigerung der Akkulaufzeit bei Notebooks. Dies kann ich leider nicht nachvollziehen.

    Wer wie ich beruflich viel mit seinen Notebooks arbeitet, der wird sicher von Vista SP1 profitieren. Am deutlichsten zeigen sich die Verbesserungen durch das SP1 in einem System, dass etwas flotter auf Befehle und Mausklicks reagiert und insgesamt etwas agiler wirkt. Zu hohe Erwartungen möchte ich an dieser Stelle aber gleich etwas dämpfen: Wunder sollte man sich von Vista SP1 nicht erhoffen!

  • SharePoint Workflows mit Visual Studio - E-Mail als 'plain text' verschicken

    In meinem letzten Blogpost habe ich mich postiv über das neue Visual Studio 2008 und den grafischen Workflow-Editor geäußert. Seitdem habe ich ein paar ältere Workflows mit Visual Studio 2008 neu erstellt - und dabei bin ich auf ein kleines Problem gestoßen.

    Um in einem Workflow eine Benachrichtigungsmail zu verschicken, zieht man im grafischen Editor das Icon SendEMail aus der Toolbox auf die gewünschte Stelle im Ablaufplan. Anschließend konfiguriert man die wichtigesten Parameter (Adresse, Betreff, Mailtext) und schon kann der Workflow eine Benachrichtigungsmail erzeugen und verschicken (vorausgesetzt, man hat in der Zentraladministration die Parameter für ausgehende Mails richtig eingestellt). Dies klappt auch, aber mit der Formatierung der abgeschickten Mail war ich nicht zufrieden, denn offenbar verschickt SendEMail Mails im HTML-Format. Ich habe nun nach einer Möglichkeit gesucht, statt in HTML die Mails als Text (plain text) zu verschicken. Leider gibt gibt es dafür bei SendEMail keinen Parameter - aber man kann sich mit dem Property Headers behelfen.

    Hinter dem Property Headers verbirgt sich ein StringDictionary - das ist eine Liste, die aus Key / Value - Paaren besteht.

    Mit folgendem Snippet kann man in einem Workflow Mails als 'plan text' verschicken:

     

    public StringProperty oHeaders;

    oHeaders = new StringDictionary();

    oHeaders.Add(„Content-Type“, „plain/text“);

     

    Anschließend weißt man dem betreffenden SendEMail-Objekt bzw. dessen Headers-Property die Variable oHeaders zu. Ab sofort werden Mails dieses SendEMail-Objekts als reine Textmails verschickt.

     

  • Workflows mit Visual Studio 2008 erstellen

    Das Erstellen von Workflows mit dem 'alten' Visual Studio 2005 war keine leichte Sache und ehrlich gesagt habe ich mich damit immer etwas schwer getan. Mit dem neuen Visual Studio 2008 ist das Erstellen von Workflows jetzt viel einfacher geworden.

    Dies beginnt bereits bei der Installation: einfach Visual Studio 2008 in einer Entwicklungsumgebung mit MOSS oder WSS installieren und darauf achten, dass die Visual Studio Tools for Office mitinstalliert werden. Empfehlenswert, aber nicht zwingend notwendig ist noch die Installation des .NET-Frameworks 3.5. Warum - dazu später mehr.

    Nachdem die Installation fehlerfrei durchgelaufen ist, kann man bereits damit beginnen, einen ersten Workflow mit Visual Studio 2008 zu erstellen. Dazu geht man wie folgt vor:

    1) Anlegen eines neuen Projekts vom Typ Sequentieller Sharepoint-Workflow. Dabei sollte darauf geachtet werden, dass oben rechts in dem Projektauswahlfenster .NET Framework 3.5 ausgewählt ist.

     

    2. Nachdem man einen Namen und einen Speicherort für das Projekt ausgewählt hat, startet der Wizzard mit seiner ersten Frage: wie soll der neue Workflow heißen und auf welcher lokalen Webseite soll der Workflow später getestet (Debugging) werden. An diesem Wizzard-Schritt sieht man schon, dass der Wizzard nicht für Remote-Debugging ausgelegt ist.

     

    3) Im nächsten Schritt fragt der Wizzard nach der Liste, mit der der neue Workflow verknüpft werden soll und welche Verlaufs- und Aufgabenlisten verwendet werden sollen. Der Wizzard befüllt die Auswahlliste bereits mit den Listen, die er auf der Webseite aus dem 2. Schritt gefunden hat.

     

    4) Im letzten Schritt fragt der Wizzard dann noch ab, wann der neue Workflow getriggert werden soll. Zur Auswahl stehen die bekannten manuellen und automatischen Trigger.

     

    5) Wenn man im letzten Schritt auf den Button Fertig stellen klickt, dauert es nur kurz, bis der Wizzard ein erstes und lauffähiges (!) Grundgerüst für einen sequentiellen Sharepoint-Workflow erstellt hat.

     

    Das dieses Grundgerüst bereits lauffähig ist, kann man ganz einfach ausprobieren: einfach F5 drücken und gespannt zusehen: Visual Studio 2008 wird zuerst den Code erstellen und danach das Deployment starten. Anschließend wird im Hintergrund ein IISRESET ausgeführt und danach wird der IE gestartet. Nach einer kurzen Wartezeit zeigt der IE die zuvor im Wizzard (Schritt 1) angegebene Webseite an. Nun kann man in der im zweiten Wizzard-Schritt angegebenen Liste einen neuen Eintrag hinzufügen. Hat man im letzten Wizzard-Schritt ein automatisches Triggern ausgewählt, wird der neue Workflow gestartet. Ansonsten muss man den neuen Workflow manuell durch das Kontextmenü des neuen Listeneintrags starten. Passieren wird natürlich noch nicht viel, aber man sollte bereits jetzt erkennen, dass der neue Workflow abgelaufen ist und erfolgreich beenndet wurde.

    Nun kann man damit beginnen, eigene Logik in den neuen Workflow zu integrieren.

    Nachdem ich jetzt schon ein paar Workflows mit dem neuen Visual Studio 2008 erstellt habe, muss ich zugeben, dass ich ziemlich begeistert bin. Das Erstellen eines Sharepoint-Workflows mit dem neuen Visual Studio 2008 ist jetzt fast so einfach geworden, wie das Erstellen eines Sharepoint-Workflows mit dem Sharepoint-Designer.

    Nachtrag: die Integration der Projekttypen für Workflows ist Microsoft gut gelungen. Schade finde ich aber, dass Microsoft keine Unterstützung für Sharepoint Webparts in das neue Visual Studio 2008 integriert hat. Hier wünsche ich mir, dass Microsoft bald Projekttypen für Sharepoint Webparts zur Verfügung stellt, die genauso einfach zu benutzen sind, wie die Projekttypen für die Sharepoint Workflows!

    Nachtrag 2: auf der deutschen SharePoint-Konferenz in Frankfurt hat Martin Vollmer einen inoffiziellen Workaround vorgestellt. Alles weitere dazu in seinem Blog.

  • Webpartwartungsseite - Hilfreich bei Problemlösungen

    Meist geschieht es, wenn man sehr viel an einer Seite gearbeitet hat. Man hat vielleicht hier und da ein Webpart hinzugefügt, es konfiguriert, es in eine andere Zone verschoben, gelöscht, wieder hinzugefügt und neu konfiguriert, ein anderes Webpart ausprobiert ... und irgendwann passiert es dann: die Seite läßt sich z.B. im Sharepoint-Designer nicht mehr öffnen. Stattdessen erscheint eine Fehlermeldung, die meist sinngemäß besagt, dass Probleme mit einem Webpart das Öffnen der Seite verhindern.

    Für solche Probleme ist die Webpartwartungsseite hilfreich. Hier werden alle Webparts aufgelistet, die jemals auf einer Seite eingebunden waren. Allerdings ist der Zugang zu dieser Wartungsseite gut versteckt.

    Ich möchte hier einen Weg aufzeigen, wie man an diese Wartungsseite für eine spezielle Seite kommt:

    • zuerst läßt man sich die betroffene Seite im Browser anzeigen
    • nun klickt man auf Websiteaktionen -> Alle Websiteinhalte einblenden
    • es wird nun eine Seite angezeigt, in der alle Website-Inhalte (Biliotheken, Listen, ...) angezeigt werden. Hier klickt man nun auf Seiten.
    • nun wird eine Bibliothek mit alle Seiten der aktuellen Website angezeigt. In dieser Bibliothek sucht man sich die problembehaftete Seite aus und wählt in deren Kontextmenü Eigenschaften bearbeiten.
    • nun wird eine ausführliche Ansicht aller Parameter der aktuellen Seite angezeigt. Ganz unten auf der Seite findet man den gesuchten Link: Webpartseite in Wartungsansicht öffnen. Klickt man auf diesen Link, bekommt man die gewünschte Übersicht aller jemals auf dieser Seite verwendeten Webparts.

    Oftmals ist es so, dass ein früher eingefügtes, aber mittlerweile von der Seite entferntes Webpart Grund für die Fehlermeldung ist. Diese nicht mehr benutzten Webparts erkennt man daran, dass sie in der Spalte Geöffnet auf Seite? ein Nein stehen haben. Sofern man diese Webparts nicht mehr benötigt, kann man sie markieren und anschließend löschen. Meist löst das Löschen von alten, nicht mehr benötigten Webparts die Probleme beim Anzeigen der Seite im SharePoint-Designer.

    Hier ein Beispiel einer Webpartwartungsseite:

  • Ereignisanzeige / DCOM-Fehler mit ID 10016 / Win2k3 SP1

    Ich habe gerade eine neue virtuelle SharePoint-Umgebung für eine Vorführung erstellt. Nach Fertigstellung der virtuellen Umgebung habe ich als Test die SharePoint-Zentraladministration geöffnet. Es dauerte zwar ein wenig, aber schließlich öffnete sich diese Anwendung.

    Danach habe ich einen Blick in die Ereignisanzeige gewofen und dort einen Hinweis auf einen Fehler gefunden. Es handelte sich um einen DCOM Fehler mit der ID 10016.

    Offensichtlich ist dieser Fehler schon länger bekannt und hängt mit dem SP1 vom Windows Server 2003 zusammen.

    Es gibt aber eine einfache Vorgehensweise, wie man diesen Fehler wieder korrigieren kann. Hier der Link zum entsprechenden Artikel bei Admin's Tipps.

    Nachtrag: Link zu den Admin's Tipps wurde aktualisiert!

  • Großes Zeitfenster beim Ändern des Passworts in einem ActiveDirectory

    Ein Mitarbeiter eines unserer Kunden rief mich vor kurzem an, um mir ein ungewöhnliches Verhalten beim Ändern seines Passwortes zu schildern. Nachdem er sein Passwort mit Hilfe eines unserer WebParts geändert hatte, konnte er sich dennoch weiterhin mit seinem alten Passwort anmelden. Eine Fehlermeldung beim Ändern seines Passworts habe es nicht gegeben. Daraufhin habe er versucht, sich mit seinem neuen (also dem geänderten) Passwort anzumelden und auch mit diesem konnte er sich anmelden. Da er sich sowohl mit altem, als auch mit neuem Passwort anmelden konnte, vermutete er nun einen Fehler in unserem Passwort-Ändern-WebPart.

    Unser WebPart zum Ändern von Passwörtern greift auf ein ActiveDirectory zu. Und genau hier liegt die Erklärung zu diesem ungewöhnlichen Verhalten. Nach dem Einspielen des SP1 für Windows Server 2003 verlängert sich das Zeitfenster in dem sowohl das alte, als auch das neue Passwort gültig sind, auf 1 Stunde. Dies bedeutet, dass das alte Passwort unter Umständen noch eine Stunde gültig bleibt, nachdem es bereits vom Benutzer geändert wurde.

    Dieses Zeitfenster läßt sich aber durch Änderungen an einem Registry-Key auf 1 Minute verkürzen. Microsoft hat die nötigen Änderungen hier beschrieben: http://support.microsoft.com/kb/906305/en-us

    Dieses Problem lies sich also schnell lösen - auch deswegen, weil diese Änderung keinen Neustart des Servers erfordert!