OpenXML Password Protection

In diesem Post möchte ich Quelltext vorstellen mit dessen Hilfe ein Word-Dokument per OpenXML mit einem Passwort-Schutz versehen werden kann. Die statische Methode “ApplyDocumentProtection” setzt ein per Zufall ausgewähltes Passwort (Hash und Salt) und liefert das Passwort im Klartext (Pass) zurück. Die Liste der vordefinierten Passworte kann beliebig erweitert werden. Siehe dazu auch die Kommentare im Quelltext.
using System;
using System.Linq;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

namespace OpenXMLTools
{
  // Diese Klasse enthält eine statische Methode zum Setzen eines Forms-Dokumentschutzes.
  // Das Passwort wird zufällig aus einer Liste ausgewählt.
  // Die Liste der Passworte kann erweitert werden.
  // Dazu einfach ein Passwort in Word setzen. Dokument anschließend mit dem OpenXML SDK Productiviy-Tool öffnen und Hash- und Salt-Wert
  // bei der Initialisierung der Passworte ergänzen.
  //
  // Außerdem muss anschließend in der Zeile
  // index = Convert.ToInt32(Math.Floor((3 * new Random().NextDouble())));
  // der Wert "3" entsprechend erhöht werden.
  public static class Tools
  {
    private static Protection[] protection = new Protection[3];

    static Tools()
    {
      // Initialisierung von Passworten
      protection[0].Pass = "Passwort1";
      protection[0].Hash = "gmfbcju55A0DSckelTAvyaHnbn0=";
      protection[0].Salt = "1IcXKEEmed1hRQQUnhX2zg==";

      protection[1].Pass = "Passwort2";
      protection[1].Hash = "i1WC8gI6AkPJSDfZK1ELMYG/anU=";
      protection[1].Salt = "q96ar2VXAk/LuO2glF+u4w==";

      protection[2].Pass = "Passwort3";
      protection[2].Hash = "ycHxPRqF4IE4iZKXIW4RzZKAeyo=";
      protection[2].Salt = "bC2+DsLquk3QnKg7rA5eug==";
    }

    // Dokumentschutz setzen. Es wird per Zufall eins von 3 vordefinierten Passworten verwendet.
    public static string ApplyDocumentProtection(WordprocessingDocument document, bool setPassword = true)
    {
      int index = 0;

      // Setzen des Dokumentschutzes
      DocumentProtection documentProtection = new DocumentProtection();
      documentProtection.Edit = DocumentProtectionValues.Forms;
      documentProtection.Enforcement = new OnOffValue(true);

      if (setPassword)
      {
        // Auswahl des Passworts
        index = Convert.ToInt32(Math.Floor((3 * new Random().NextDouble())));

        documentProtection.CryptographicAlgorithmClass = CryptAlgorithmClassValues.Hash;
        documentProtection.CryptographicProviderType = CryptProviderValues.RsaFull;
        documentProtection.CryptographicAlgorithmType = CryptAlgorithmValues.TypeAny;
        documentProtection.CryptographicAlgorithmSid = 4; // SHA1
        documentProtection.CryptographicSpinCount = 50000;
        documentProtection.Hash = Tools.protection[index].Hash;
        documentProtection.Salt = Tools.protection[index].Salt;
      }

      // Fall DocumentProtection bereits vorhanden, vorher löschen.
      DocumentProtection existingDocumentProtection = document.MainDocumentPart.DocumentSettingsPart.Settings.Descendants<DocumentProtection>().FirstOrDefault();
      if (existingDocumentProtection != null)
      {
        existingDocumentProtection.Remove();
      }

      // DocumentProtection muss vor DefaultTabStop stehen. Ansonsten gibt es einen Validation-Error!
      DefaultTabStop defaultTabStop = document.MainDocumentPart.DocumentSettingsPart.Settings.Descendants<DefaultTabStop>().FirstOrDefault();
      defaultTabStop.InsertBeforeSelf(documentProtection);

      document.MainDocumentPart.DocumentSettingsPart.Settings.Save();

      if (setPassword)
      {
        // Rückgabe des unverschlüsselten Passworts
        return protection[index].Pass;
      }
      else
      {
        return string.Empty;
      }
    }

    // Struktur wird von ApplyDocumentProtection benötigt
    private struct Protection
    {
      // Unverschlüsseltes Password
      public string Pass { get; set; }

      // Hash-Wert mit dem der Passwortschutz gesetzt wird.
      public string Hash { get; set; }

      // Salt-Wert mit dem der Passwortschutz gesetzt wird.
      public string Salt { get; set; }
    }
  }
}

App design wall clock

Seit Dezember 2012 hängt nun diese schicke Wanduhr in unserem Büro. Wenn man einmal davon absieht, dass man die Zeit ab einer gewissen Entfernung praktisch nicht mehr ablesen kann, weil die schwarzen Zeiger auf dem relativ dunklen Hintergrund verschwinden, ist das Design doch sehr gelungen. Allerdings funktioniert der “Touchscreen” 🙂 nicht! Das kann man aber auch für den Preis von 14,99€ nicht wirklich erwarten!

clock

(Uhr findet man z.B. bei Amazon)

Ansicht kann nicht angezeigt werden (SharePoint 2010)

Sharepoint-2010

In einem SharePoint 2010-Projekt bin ich bei einem Kunden kürzlich auf den folgenden Fehler gestoßen:

“Diese Ansicht kann nicht angezeigt werden, weil die Anzahl der darin enthaltenen Nachschlage- und Worflowstatusspalten den durch den Administrator durchgesetzten Schwellenwert (8) übersteigt.”

oder auf Englisch:

“This view cannot be displayed because the number of lookup and workflow status columns it contains exceeds the threshold enforced by the administrator.”

Ja ich muss zugeben, es waren tatsächlich eine Menge Nachschlagespalten in der Liste vorhanden. Erstaunlich war allerdings, dass ich -als Besitzer dieser Liste- diese trotzdem ohne Probleme anzeigen lassen konnte. Die Fehlermeldung kam, wenn ein Benutzer mit “Mitwirken”-Rechten darauf zugreifen wollte. Das Limit beträgt standardmäßig übrigens “8”. Glücklicherweise lässt sich dieses mit Hilfe der SharePoint-Zentraladministration ohne Probleme anheben.

Dazu einfach die Zentraladministration aufrufen. Dann unter “Anwendungsverwaltung” den Punkt “Webanwendungen verwalten” aufrufen. Anschließend die passende Webanwendung auswählen. Im Ribbon unter “Allgemeine Einstellungen” den Menüpunkt “Ressourcensteuerung” aufrufen und unter “Schwellenwert für den Listenansicht-Nachschlagevorgang” den Wert nach Bedarf erhöhen.

Ressourcensteuerung

Details dazu findet man hier: http://sharepointmalarkey.wordpress.com/2012/03/05/this-view-cannot-be-displayed-because-the-number-of-lookup-and-workflow-status-columns-it-contains-exceeds-the-threshold-enforced-by-the-administrator/

你好中国 (Hello China)

Chinesischer_Drache

我想借此机会,对我的中国读者说声“您好”。这太棒了,您能够找到并阅览我的博文。我很感谢您的每一个评论。如果必要的话,这将是非常有益的。如果你您用德语或英语就太好了,当然也可以写法语。但不幸的是,我不会说中文。您能阅读我的博客,是对我最良好的祝愿和我最大乐趣之所在。

此外,这是我的中国同事的博客链接(鎏金天涯)http://blog.myyicity.com

Setting word document variables via OpenXML

Word2007Document variables in Microsoft Word can be valuable for storing any kind of additional information within a document. Document variables are (in contrast to document properties) not visible to the end user. But, serendipitously one can get their values via source code (e.g. from a Word AddIn). These characteristic properties might be very useful in multiple situations.

Setting and getting document variable values via Office automation is a simple and straightforward task. See http://support.microsoft.com/kb/306281.

Unfortunately Office automation has several drawbacks. For example it isn’t advisable to use Office automation in a pure server process scenario(see https://knabben.wordpress.com/2013/01/04/problemfall-office-automation/). Hence, I want to reveal a different approach.

With the present article I would like to provide you C# source code for adding document variables to an existing word document via OpenXML. In order to use the code you’ll need to install the OpenXML SDK 2.5 and add references to “WindowsBase” and “DocumentFormat.OpenXML” (see https://knabben.wordpress.com/2013/01/08/hello-world-mit-openxml-sdk/).


    /// <summary>
    /// add a document variable
    /// </summary>
    /// <param name="document">word document where document variable should be added</param>
    /// <param name="name">variable name</param>
    /// <param name="value">variable value</param>
    /// <returns>'true' on success and 'false' otherwise</returns>
    public static bool AddDocumentVariable(WordprocessingDocument document, string name, string value)
    {
      try
      {
        DocumentVariables documentVariables;
        documentVariables = document.MainDocumentPart.DocumentSettingsPart.Settings.Descendants<DocumentVariables>().FirstOrDefault();

        if (documentVariables == null)
        {
          documentVariables = new DocumentVariables();
          Compatibility compatibility = document.MainDocumentPart.DocumentSettingsPart.Settings.Descendants<Compatibility>().FirstOrDefault();
          compatibility.InsertAfterSelf(documentVariables);
        }

        DocumentVariable documentVariable = new DocumentVariable() { Name = name, Val = value };
        documentVariables.Append(documentVariable);

        return true;
      }
      catch
      {
        return false;
      }
    }

Feel free to use it or adapt it to your necessities. In case you have any kind of optimization, please let me know! Any comment will also be appreciated!

Microsoft TechDay Office 2013

Im Februar bietet Microsoft den TechDay Office 2013 in München, Stuttgart, Berlin und Köln an.

TechDay

Agenda findet man hier: http://www.techday.ms/office2013/Agenda.aspx

Zur Anmeldung geht es hier: https://www.event-team.com/events/techday/office2013/Anmeldung.aspx

Ich habe mich für den TechDay am 19.02.2013 in Köln angemeldet.

Brother MFC-7820N and Windows 8

Brother7820NI’ve bought the All-In-One printer “Brother MFC-7820N” in 2007. By far the MFC-7820N is the best printer I’ve ever had. The device is an A+ with asterisks for home use and small business. Although I quite often use the printer, I still have in use the first toner cartridge. MFC-7820N is able to copy, fax, print and scan. Duplex functionality is the only thing I miss from time to time.

Brother provides a Windows 7/64bit – driver that supports printing and scanning via network. Now I discovered that unfortunatly scanning on Windows 8/64bit only works via USB. Printing still works via network. The driver comes out of the box with Windows 8. Requesting Brother gave the same result:

“Since we are not planning to develop a driver for Windows 8, scanning only works via local USB connection with the built-in Windows 8 driver.”

The printer is now approximately 5 years old. No eternity for a printer. Nevertheless, Brother doesn’t support this printer on the latest Microsoft OS professionally. I’ve heard that other manufacturers provide drivers significantly longer. I think that one should definitely take that into account for future purchase decisions.

Test Logitech T650 cordless rechargeable Touchpad USB

Touchpad_Logitech

Wer auf seinem Desktop PC bereits mit Windows 8 arbeitet, wird festgestellt haben, dass die Bedienung der Modern UI – Oberfläche (früher “Metro” genannt) mittels Maus wenig Spass macht! Eine Alternative wäre zum Beispiel die Verwendung eines Touchscreens. Bei einem großen auf dem Schreibtisch stehenden Bildschirm bekommt man allerdings nach kurzer Zeit einen relativ langen Arm. Außerdem sind große Touchscreens momentan noch relativ teuer. Daher ist es durchaus sinnvoll, sich nach anderen Möglichkeiten umzusehen.

Ich teste seit einigen Tagen das “T650 cordless rechargeable Touchpads” von Logitech. Das Touchpad macht auf mich einen hochwertigen Eindruck. Das kann man allerdings für den Preis von ca. 80 € auch erwarten. Eigentlich musste nur der Dongle eingesteckt werden. Danach funktionierte nach kurzer automatischer Installation der Treiber sowohl unter Windows 7 als auch unter Windows 8 alles direkt. Alle Windows 8 typischen Gesten werden zuverlässig erkannt. Nach einer kurzen Eingewöhnungszeit macht es sogar richtig Spass. Unter Windows 7 und zur Bedienung von Desktop-Anwendungungen macht es allerdings weniger Sinn. Hier bevorzuge ich nach wie vor die Verwendung einer Maus. Das Touchpad wird über USB aufgeladen und arbeitet dann nach Angaben des Herstellers ca. 1 Monat autark bis es wieder geladen werden muss. Das konnte ich allerdings bislang noch nicht verifizieren. Um den Akku zu schonen, gibt es einen Ein-/Aus-Schalter auf der rechten vorderen Seite. Bis jetzt kann ich das Touchpad empfehlen. Allerdings finde ich, dass der Preis noch ein bißchen zu hoch ist.

Als Alternative zum Touchpad bietet Logitech auch noch sogenannte Touchmäuse, z.B. das “T620“. Dieses hat allerdings in den Bewertungen der User bislang nicht ganz so gut abgeschnitten (siehe z.B. bei Amazon).

BASTA! .Net, Windows, Visual Studio

Im letzten Jahr habe ich die BASTA Spring in Darmstadt besucht. Es war eine sehr interessante Veranstaltung rund um das Thema .Net, Windows und Visual Studio mit vielen spannenden und auch lehrreichen Vorträgen von zum größten Teil bekannten Speakern. Es gab unter anderem Beiträge zu den Themen Visual Studio 2012, TFS, ALM, SharePoint, MS Office und Mobile Development. Die Veranstaltung war sehr gut besucht. Das führte allerdings dazu, dass einige Räume fast zu klein waren. Trotzdem kann ich diese Veranstaltung allen .Net-Entwicklern sehr empfehlen, so dass ich hiermit auf die BASTA Spring 2013  vom 25.02. – 01.03.2013 hinweisen möchte: http://basta.net/2013spring/