Quantcast
Channel: ppedv Team Blog
Viewing all 1198 articles
Browse latest View live

Normal, Klein, Nano – Der NanoServer

$
0
0

Mit Server 2016 hat Microsoft eine neue Art des Servers eingeführt. Bereits bekannt ist die Installation eines normalen Windows Servers mit GUI und die Installation der Core Variante.

Neu ist allerdings der NanoServer, welcher in der Standard und Datacenter Version enthalten ist.

Als extrem kompakter und ressourcenarmer Server übernimmt er die Aufgaben bei denen kein vollständiger Server nötigt ist. Er eignet sich z.B. als Host System für Hyper-V Virtualisierung oder als schlanke DNS-Server Lösung. Bei der Erstellung eines NanoServers werden nur die Rollen und Features installiert, welche er auch wirklich für seine Aufgaben braucht. Da jedoch nicht alle Funktionen zur Verfügung stehen, ist dies je nach gewünschter Einsatzart vorher zu prüfen.

In diesem Artikel wird die Erstellung eines NanoServerImages per PowerShell in minimaler Konfiguration und ohne Installation von weiteren Rollen und Features veranschaulicht.

Allem voran wird ein Installationsmedium eines Windows Server 2016 benötigt, da sich dort ein Order „NanoServer“ befindet, in dem unter „NanoServerImageGenerator“ die PowerShell Module liege. Diese sind für die Erstellung notwendig. Am besten erstellen Sie sich einen neuen Ordner auf einer Festplatte und kopiert sich den NanoServerImageGenerator-Ordner dorthin.

clip_image002clip_image004

Danach wird die PowerSell im Administratormodus geöffnet, zum Ordner C:\Nano\ navigiert und folgender Befehl für den Import des NanoServer-Moduls eingegeben.

Import-Module .\NanoServerImageGenerator\NanoServerImageGenerator.psm1

clip_image006

Wichtig hierbei ist die .psm1 und nicht die .psd1 auszuwählen.

Über diesen Befehl wird eine Nano1.vhdx im Ordner Nano erstellt:

New-NanoServerImage -DeploymentType Guest -Edition Standard -MediaPath D: -BasePath .\base -TargetPath .\nano1.vhdx -ComputerName Nano1 -Package Microsoft-NanoServer-Guest-Package -EnableRemoteManagementPort

clip_image008

Vor der Erstellung des Images muss noch ein Administratorpasswort hinterlegt werden. Hierbei ist zu beachten, dass es keine doppelte Abfrage gibt, so dass bei einem verschreiben der Vorgang wiederholt werden muss.

clip_image010

Im Ordner C:\Nano\ befindet sich jetzt eine „Nano1.vhdx“. Per Hyper-V kann jetzt ein neuer virtuellerer Computer erstellt und die VHDX Datei mit eingebunden werden.

Nach dem Starten des virtuellen Computers, kann man sich mit „Administrator“ und dem vorher vergebenem Passwort anmelden und sieht eine sehr rustikale Oberfläche

clip_image012

Innerhalb des NanoServers kann sich nur per Tastatur fortbewegt werden. Einstellbar ist in diesem Beispiel lediglich die Netzwerkkonfiguration, die Firewall und das Windows Remoting.

Mehr kann dieser NanoServer nicht, da wir ihm bei der Erstellung keine weiteren Funktionen, bis auf die Mindestvoraussetzungen, mitgegeben haben.

Alles was der Nanoserver können soll, muss bei der Erstellung der VHDX mitgegeben werden.

Die Erstellung eines NanoServers ist nicht sehr schwer und kann so für die verschiedenen Aufgaben im Unternehmen eingesetzt werden.

Weitere Informationen über den NanoServer erfahrt ihr in unserem Kurs Windows Server 2016.

Eine genaue Agenda und Buchungszeiträume dazu findet ihr hier.


Autofill Produktivitätsboost Web Formular

$
0
0

Amazon lebt davon, es dem Kunden so einfach wie möglich zu machen. Eine tägliche Qual ist das ausfüllen von Formularen im Web, Name, Strasse, PLZ usw. Das muss nicht sein, mit Autofill.

Zunächst kann der Benutzer (ja das bist Du) in seinem Browser der Wahl Daten hinterlegen.

Für Chrome Einstellungen – Erweitert (unten) –Passwörter und Formulare- Autofill. Dort hinterlegt man seine Adressdaten oder Kreditkarten.

image

Autovervollständigen bei Microsoft EDGE – Einstellungen. Erweiterte Einstellungen –Formulareinträge speichern. Edge lernt die Daten aus der Nutzung und bietet keine Möglichkeit diese manuell zu ändern.

image

Der Website Entwickler kann einfach die ID Name Werte der HTML Page passend eintragen oder besser er deklariert sie per Autocomplete Attribut. Das klappt auch mit ASP.NET Webforms, hier mit Bootstrap hervorragend.

   1:  <divclass="form-group">
   2:  <asp:Labelrunat="server"AssociatedControlID="email">Email</asp:Label>
   3:  <asp:TextBoxrunat="server"ClientIDMode="Static"ID="email"
TextMode="email"CssClass="form-control"AutoComplete="email"/>
   4:  <asp:RequiredFieldValidatorrunat="server"ControlToValidate="Password"
Display="Dynamic"
   5:  CssClass="text-danger"ErrorMessage="Email ist erforderlich."/>
   6:  </div>

 

Die dabei wichtigsten Werte sind für Name und Email

email tel name fname mname

Für Adressdaten

address city state zip country

und für mutige die Kreditkartendaten

cc-name  cc-number cc-csc cc-exp-month cc-exp-year cc-exp cc-type

Demosite für einen Test https://greenido.github.io/Product-Site-101/form-cc-example.html

Dabei kann man auch in eine beliebige Zeile des Formulars springen und Autfill entdeckt ob es einen passenden Datensatz gibt und fügt diese auf Benutzerwunsch ein. Die farbliche Markierung der automatischen gefüllten Felder in gelb ist dann noch Herausforderung für einen Designer.

autofill 

Der Unterschied zu Edge ist, das die ausgefüllten Felder blau hinterlegt werden.

C# 8.0 - Das Ende der NullReferenceException ?

$
0
0

Ach, was wäre doch nur Programmieren ohne dem Lieblingsbug der .NET Entwickler: die NullReferenceException. So gut wie jeder Programmierer hat sie mindestens einmal gesehen und sich gewundert, warum beispielsweise ein bestimmtes Objekt nicht initialisiert ist. Oder schlimmer: Warum eine Methode null anstelle einer Objektreferenz zurückgibt.

Der Wert null ist ein wichtiger Bestandteil des .NET Frameworks, da dies der Standardwert eines jeden Referenztypen ist. Solange man einer Variable eines Referenztypen keinen Wert zuweist, muss man auf irgendeine Art und Weise dessen Abwesenheit im Programmcode repräsentieren. Genau dies wird mit null erreicht.  Ein weiterer häufiger Anwendungsfall sind die sogenannten "Nullable Value Types", bei denen es möglich ist, einem Wertetypen null zuzuweisen. Dies ist insbesondere beim Arbeiten mit Datenbanktabellen praktisch, da in vielen Datenbanken die Abwesenheit eines Wertes in einer Tabelle mit null repräsentiert wird. Diese „Abwesenheit“ eines Wertes kann beispielsweise in einer normalen Int32 Variable nicht ohne weiteres abgebildet werden.
Beispiel: Die Spalte Alter in einer Tabelle hat für die Person X keinen Eintrag. Soll das Alter der Person auf „0“ gesetzt werden, um die Abwesenheit des Wertes in der Datenbank zu repräsentieren ? Wäre „-1“ ein geeigneter Wert, und wenn ja, hat man den Setter des Properties für diesen Sonderfall angepasst? Und wie würde das Problem bei dem Datentyp byte statt Int32 aussehen ? Fragen über Fragen…

Während das Setzen auf null für Wertetypen ein reines Opt-In ist, kommen wir bei Referenztypen oftmals nicht drum herum, null zu verwenden. Standardmäßig kann man in den meisten Fällen aber davon ausgehen, dass die zur Laufzeit verwendeten Objekte initialisiert sind und zur Verwendung zur Verfügung stehen. Ab und zu schleicht sich aber doch ein kleiner Implementierungsfehler ein, der im weiteren Programmablauf zu einer NullReferenceException führt.
Mein persönlicher Favorit ist das unabsichtlich vergessene Instanziieren von Objekten, viele kostbare Minuten sind bei mir schon auf der Suche nach diesem simplen Fehler draufgegangen.

Grundsätzlich kann man in sehr vielen Fällen davon ausgehen, dass ein Objekt zum Zeitpunkt der Verwendung initialisiert ist und uns zur Verfügung steht. Gelegentlich kann es aber auch vorkommen, dass wir das nicht-Vorhandensein eines Objektes durch den Wert null repräsentieren müssen. Ein (leider) beliebtes Antipattern: Eine Methode, die, aus welchem Grund auch immer, null anstelle der in der Signatur definierten Objektinstanz zurückliefert.
Wenn man sich bewusst auf dieses Antipattern einlässt, muss man im weiteren Programmablauf dauernd prüfen, ob die Rückgabe eine funktionierende Objektreferenz oder doch null ist. Der Code wird dann meist mit lauter Verzweigungen zugepflastert, die auf null prüfen. Die Einführung des "Null-Conditional-Operators" in C# 6.0 hat diese Situation glücklicherweise ein wenig verbessert.

Doch was kann man nun tun ? Gänzlich auf die Verwendung von Referenztypen verzichten ? Null komplett verbieten ? Die funktionale Programmiersprache F# hat hierfür einen interessanten Ansatz:
Alles ist per default Immutable und null ist als regulärer Wert nicht zugelassen.
Für den „Es ist kein Wert vorhanden“ – Fall kann man beispielsweise "Option-Types" verwenden:
Die Rückgabe einer Funktion kann für den Datentyp T „Some(T)“ oder „None“ sein. Mithilfe von Pattern-Matching ist der Programmierer dann in weiterer Folge dazu gezwungen, beide Fälle zu behandeln. Ein erzwungener Null-Check sozusagen. Schauen wir uns das einmal genauer an:

Der folgende C#-Code kann ohne Probleme kompilieren, wird aber zur Laufzeit eine NullReferenceException werfen. Das liegt daran, dass null ein gültiger Wert für einen String ist.


In F# hingegen können wir null nicht direkt übergeben. Um einen „fehlenden Wert“ zu repräsentieren, verwendet man sogenannte Option-Types. Die Möglichkeiten hierfür wären "Some" (= ein Wert ist vorhanden) und "None" (= kein Wert vorhanden). Pointer oder „nicht initialisierte Variablen“ gibt es in der funktionalen Sprache F# nicht.

Beim direkten Zuweisen von "None" merken wir sofort, dass der Compiler das Auslesen der Length-Eigenschaft nicht zulässt.

Wenn wir also mit dem String arbeiten wollen, müssen wir das sogenannte Pattern-Matching verwenden:

Hier sehen wir, dass wir den Wert des Option-Types durch das Pattern-Matching sauber herausbekommen: Wenn in der Variable "text2" ein Wert vorhanden ist, greift der „Some“ – Fall und die Länge des Strings wird ermittelt. Falls kein Wert vorhanden ist, greift der „None“ – Fall und es wird 0 zurückgegeben.

Wo liegt nun aber der Unterschied zu C# ? Dasselbe Problem können wir in C# auch mit folgendem Code lösen:

In C# ist ein „null String“ vom Datentyp her immer noch ein String. Zum Kompilierzeitpunkt kann daher nicht unterschieden werden, ob eine gültige Zeichenkette wie „Hallo Welt“ oder null drinnensteht. Erst zur Laufzeit bekommen wir im schlimmsten Fall eine NullReferenceException.
Wir können natürlich wie im obrigen Beispiel dauernd auf null prüfen und Alternativwerte angeben, doch das ist komplett optional. Wenn wir in unserer Businesslogik nur ein paar Nullchecks unabsichtlich vergessen, könnte es irgendwann einmal zu einer NullReferenceException kommen.

In F# hingegen würden man beispielsweise Option-Types nutzen. Mit denen hat man den Vorteil, dass man nicht direkt auf Properties wie Length oder Methoden des darunterliegenden Strings zugreifen kann. Somit muss man mithilfe des Pattern-Matchings den Wert sozusagen erst „auspacken“, ein erzwungener Null-Check. Alle potentiellen Fehler oder Versäumnisse bekommen wir also entweder in der IDE oder beim kompilieren mit.

 

C# 8.0

Wozu also nun die Gegenüberstellung von C# und F# ? Aktuell wird für die nächste große Sprachversion von C# an einem Feature gearbeitet, welches das Problem der ständigen NullChecks lösen könnte: „Nullable ReferenceTypes“
Hierbei wird das Konzept der NullableTypes, welches bei Wertetypen bereits existiert, auch auf Referenztypen ausgedehnt: Ein Referenztyp darf u.U nicht mehr null sein !

Eine möglicher Anwendungsfall könnte beispielsweise so aussehen:

Im Vergleich zu F# bekommt man hier aktuell nur Warnungen, wenn zum Zeitpunkt X eine Variable null sein könnte. Insbesondere in Großprojekten kann dieses Feature durchaus praktisch sein. Anfangs wird man sicher bei der Umstellung mit Warnungen überflutet, doch die eine oder andere Warnung könnte doch zu einer Stelle führen, wo man unerlaubterweise null als Wert verwendet hat.

Und jeder Bug weniger bringt uns alle einen großen Schritt weiter zu sauberem Code und fehlerfreien Projekten !


Für detailiertere Informationen und eine Preview des geplanten Features empfehle ich folgende GitHub - Seite: The C# Nullable Reference Types Preview

Windows 10: Überwachter Ordnerzugriff

$
0
0

In den letzten Jahren häuften sich Warnungen und Berichte über sogenannte Erpressungs-Trojanern (Ransomware), die persönliche Daten auf dem PC verschlüsseln und den zum Entschlüsseln benötigten Key nur gegen Bezahlung via Kryptowährung herausrügt. Das Setzen bzw. Einschränken von NTFS-Berechtigungen hilft hier nicht viel – hat ein Trojaner erst einmal Ausführungsrechte, dann hat dieser in der Regel auch Zugriff auf die Festplatte. Microsoft hat nun in der Version 1709 von Windows 10 (Fall Creators Update) dem Windows Defender ein neues Sicherheitsfeature spendiert: Der überwachte Ordnerzugriff.

Damit überwacht der Windows Defender Änderungen an Dateien, die von Anwendungen vorgenommen werden, und unterbindet dies. Der User kann die Ordner, die überwacht werden sollen, frei bestimmen – ebenso können Anwendungen hinzugefügt werden, die Zugriff auf diese Ordner bekommen sollen.

Als erstes muss dieses Feature aktiviert werden. Hierzu geht man in den Windows-Einstellungen in

1. “Update und Sicherheit” > “Windows Defender”
2. “Windows Defender Security Center öffnen”
3. “Viren- & Bedrohungsschutz” > “Einstellungen für Viren- & Bedrohungsschutz”

Hier kann man nun “Überwachter Ordnerzugriff” aktivieren.

Überwachter Ordnerzurgiff 01

Unter “Geschütze Ordner” kann man eigene Ordner mit wichtigen und sensiblen Daten hinzufügen, die geschützt werden sollen. In der Liste befinden sich bereits bekannte Windows Ordner wie Dokumente, Bilder und Desktop. Diese Standard-Ordner kann man auch nicht aus der Liste entfernen.

Überwachter Ordnerzurgiff 02

Unter “App durch überwachten Ordnerzugriff zulassen” fügt man die Programme hinzu, die auf die geschützten Ordner zugreifen sollen. Vertrauenswürdige Programme (“Apps die von Microsoft als unbedenklich eingestuft werden”) erhalten automatisch Zugriff.

Überwachter Ordnerzurgiff 03

Wird ein Programm durch dieses Feature daran gehindert eine Datei zu verändern, erhält der User im Info-Center eine entsprechende Benachrichtigung.

Automatisiertes Wechseln lokaler Kennwörter

$
0
0

Welche IT Abteilung , kennt das nicht das sie unterschiedliche Standard Kennwörter haben für die lokalen Administrations Konten. Oder sich diese unter den Usern herumsprechen. Doch welche Möglichkeiten gibt es jetzt für die Zukunft die uns dieses Problem in den Griff zu kriegen. Gerade aus dem Sicherheitsaspekt ist dieses Problem auch nicht zu unterschätzen. Anfangs habe ich überlegt das über Gruppenrichtlinien zu realisieren bis ich auf LAPS (Local Administrator Password Solution) gestoßen bin.

LAPS ist eine Client seitige Erweiterung die sich darum kümmert Clients und Servern in konfigurierten Abständen für die hinterlegten lokalen Benutzern die Passwörter durch Zufalls Passwörter zu ersetzen und diese anschließend in Active Directory Attributen zu hinterlegen. Ich werde euch heute zeigen wie diese Lösung zu implementieren ist. Doch erstmal zu den Anforderungen:

  • Active Directory Domänenstruktur: min. Windows Server 2003
  • Client OS: Ab Windows Vista
  • Server OS: Ab Windows Server 2003
  • Management Tools: .Net Framework 4.0 & PowerShell 2.0 or later

Als erstes muss der Client von Microsoft runtergeladen werde:

https://www.microsoft.com/en-us/download/details.aspx?id=46899

imageIn meiner Demo werde ich die Software auf dem Domänen Controller installieren sodass ich gleich die benötigten Administrativen Templates und das PowerShell Modul für die Schemaerweiterung parat habe. Wichtig ist bei der Installation die Management Tools hier mit zu installieren. Anschließend muss die Software auf die zu verwaltenden Geräte ausgerollt werden. Größere Umgebungen verfügen hier garantiert die Möglichkeit dies über eine Software Verwaltung zu tun. Andere Möglichkeiten wären zb Skript basierend die AdmPwd.dll aus dem Installationsverzeichnis auf die Geräte zu verteilen und anschließend über das Kommandozeilentool “regsvr32.exe” zu registrieren. In überschaubaren Größen wäre es auch noch Überlegenswert das Tool manuell auf den Geräten zu installieren. Ich werde das Tool über die Gruppenrichtlinien verteilen. Dazu lege ich erst die Installationsdatei auf ein Netzwerk Share um diese dann als Software Paket zu verteilen. Für die Gruppenrichtlinie wenden einen WMI Filter an der verhindert das diese Software auf Domänen Controllern installiert wird:

"SELECT * FROM WIN32_OperatingSystem WHERE Producttype != 2"

ProductType 1 = Clients

ProductType 2 = Domänen Controller

ProductType 3 = Server

Die zwei Attribute die LAPS nutzt um das Administrator Passwort und dessen Ablauf Datum zu speichern müssen im Active Directory Schema erst angelegt werden. Ich empfehle hierfür das mitgelieferte PowerShell Modul zu verwenden. Da eine falsche Änderung am Schema mal schnell eine Infrastruktur lahmlegen kann.

image

 

Im nächsten Schritt muss den betreffenden Computerkonten das Recht delegiert werden das sie im eigenen Konto die neuen zwei Attribute beschreiben dürfen. Das lässt sich manuell erledigen oder wieder über ein PowerShell cmdlet welches aus dem gleichen Modul wie der vorherige Befehl kommt. In meinem Fall setze ich es auf die Organisationseinheit “LAPS” die ich zum testen verwende.

image

Über den Befehl “Set-AdmPwdReadPasswordPermission” lässt sich jetzt konfigurieren welcher User oder welche Gruppe für die jeweilige OU das Recht hat die Passwörter anzuzeigen. Somit lässt es genau steuern wer für welche Computer die lokalen Admin Passwörter anzeigen darf. In meinem Fall delegiere ich das Recht an die globale Gruppe “g-ITSupport”.

image

Da ich Gruppenrichtlinien für LAPS von jedem meiner Domänencontroller aus erstellen können will habe ich noch die dazugehörigen Dateien “AdmPwd.admx und AdmPwd.adml” aus dem lokalen Store (C:\Windows\PolicyDefinitions) in den Central Store (C:\Windows\SYSVOL\domain\Policies\PolicyDefinitions) für Gruppenrichtlinien verschoben. Zu guter Letzt muss via GPO die lokale Passwort Verwaltung noch aktiviert werden. Die Einstellung ist in der Computerkonfiguration in den Administrativen Vorlagen zu finden.

image

imageOhne weitere Konfiguration würde LAPS jetzt die Passwörter für den lokalen Administrator ändern und in die Werte in das Active Directory speichern. Da aber gerade bei Clients der lokale Administrator deaktiviert ist und bei der Installation ein alternativer User wie zb. Admin verwendet wird müssen wir LAPS noch mitteilen welcher Benutzer verwaltet werden soll. Für eine OU die Server enthält darf diese Einstellung nicht gesetzt sein, diese Einstellung ist nur zu setzen wenn ein anderer Benutzer außer der “Administrator” verwendet wird. Des weiteren könnte man auch noch die Komplexität festlegen welcher das zufällig generierte Passwort entsprechen muss.

Nachdem ich jetzt mittels gpupdate /force und einem Reboot  sichergestellt habe das der Client die Änderungen übernommen und angewandt hat, kann ich jetzt die Möglichkeiten ansprechen um auf die Passwörter zuzugreifen. Es existieren  insgesamt 3 Möglichkeiten um auf die Passwörter zuzugreifen. Die erste Möglichkeit besteht dadrin die LAPS UI zu nutzen die über die Installation der Management Tools mit onboard ist. Mit dieser Oberfläche zudem auch noch gleich das Ablaufdatum gesetzt bw lässt sich setzen bei bedarf um jemand für eine begrenzte Zeit das Passwort mitzuteilen. Die zweite Möglichkeit die einem ebenfalls das Ablaufdatum mit anzeigt ist das cmdlet Get-AdmPwdPassword. Die dritte Möglichkeit die einem leider nur das Passwort in Klartext anzeigt ist über die Attribute des Computer Objekts zu gehen. Das entsprechende Attribut ist hier in der Sammlung grau markiert.

image

Ich hoffe ich konnte euch einen guten Überblick über dieses Tool geben mit dem man sich spätestens beschäftigen sollte wenn man eine "MCSE Prüfung anstrebt". 

IIS Administration API

$
0
0

Es gibt einige Möglichkeiten einen IIS-Server zu verwalten: Über das GUI-Verwaltungstool IIS-Manager, das klassische CMD-Tool appcmd.exe oder Powershell. Seit dem IIS 10 steht für Powershell sogar ein neues Modul zur Verfügung (“IISAdministration”), das schneller und flexibler sein soll – das bisherige Modul “WebAdministration” gibt es aber weiterhin. Jede dieser Möglichkeiten hat seine Vorzüge, aber auch Nachteile. Was es aber bisher nicht gab, ist eine offene und standardisierte Schnittstelle, die über eine Vielzahl an möglichen Technologien angesprochen werden kann – am Besten von jedem Client aus (und nicht nur auf Windows-Systeme beschränkt). Genau so eine Schnittstelle hat nun Microsoft in Form einer REST-API unter dem Namen “IIS Administration API” zur Verfügung gestellt.

Die “IIS Administration API” bietet damit neue Möglichkeiten einer Remote-Verwaltung von IIS-Servern. Sie läuft als Microservice auf dem Ziel-Server und kann letztendlich über alle Sprachen/Technologien, die HTTP-Verbindungen ermöglichen, ansprechen:

  • Powershell
  • JavaScript
  • .NET
  • PHP
  • Java
  • Python
  • Native Mobile-Apps (Windows, Android, iOS)
  • ect.

Darüber hinaus steht unter https://manage.iis.net der “Microsoft IIS Web Manager” zur Verfügung - eine webbasierte IIS-Admin-Oberfläche. Hierüber lassen sich die eigenen Webserver nicht nur verwalten, sondern auch monitoren. Es muss nur die API auf den Servern installiert sein!

IIS API 01IIS API 02

Installation

Die IIS Administration API kann ab Windows 7 bzw. Windows Server 2008R2 installiert werden (auch der Nano-Server wird unterstützt) und setzt die Runtime von Microsoft .NET Core voraus. Es sollte jedoch zuerst der IIS, dann .NET Core installiert werden.

Nach dem Download der IIS Administration API installiert man diese.

Konfiguration

Alle Konfigurationsmöglichkeiten der API sind in der Datei appsettings.json zu finden. Diese liegt unter:

%SystemDrive%\Program Files\IIS Administration\<version>\Microsoft.IIS.Administration\config\appsettings.json


Die gesamte Datei hat eine JSON-Struktur. Allerdings sind anfangs die NTFS-Berechtigungen dieser Datei so gesetzt, dass Administratoren nur Leseberechtigung haben. Schreib- bzw. Vollzugriff hat nur das System. Wenn man Änderungen oder Ergänzungen vornehmen möchte, muss man zuvor als Administrator den Besitz übernehmen und sich entsprechende Schreibberechtigungen geben.

Wichtig: Alle Änderungen an der Datei erfordern einen Neustart des Dienstes “Microsoft IIS Administration”, damit die Änderungen wirksam werden!

IIS API 04

Die wichtigsten Konfigurations-Punkte im Überblick:

Security: “require_windows_authentication”
Über true/false gibt man an, ob für jeden API-Request die Windows Authentifizierung verwendet werden soll. Diese Option ist standardmäßig aktiviert.

Security: “users”
Es gibt innerhalb der API 2 Benutzergruppen: “Administrators” und “Owners”. Jeder dieser API-Gruppen kann man Windows-Benutzer zuweisen (lokale oder AD-Benutzer), die dann Mitglied werden.

Security: access_policy
Es gibt insgesamt 3 Zugriffsregeln, über die man bestimmten Usern Berechtigungen geben kann.

  1. api: Wer bekommt Zugriff auf die API
  2. api_keys: Wer darf die API-Keys verwalten
  3. system: Wer darf API Aktionen ausführen, die höhere Berechtigungen benötigen (z.B. das Ändern der Identität eines Application Pools)

Innerhalb jeder Regel können insgesamt 4 Attribute konfiguriert werden:

  1. users: Angabe, für wen die Regel gelten soll. Anzugeben ist entweder eine API-Gruppe (siehe oben) oder “Everyone” (um jedem Zugriff zu ermöglichen).
  2. access_key: Steuert, ob für Requests ein Access Token notwendig ist.
  3. read_only: Erzwingt einen Nur-Lese-Modus. Dadurch können nur Anfragen über die HTTP-Methode “GET” geschickt werden.
  4. forbitten: Blockiert den gesamten Zugriff

CORS
Die sog. CORS-Richtlinien steuern welche Browser-basierten Anwendungen Requests an die API schicken dürfen. Standardmäßig ist nur https://manage.iis.net eingetragen. Wenn man eine eigene Web-Anwendung hat, die auf die API zugreifen soll, dann muss man für diese eine neue Regel anlegen.

Hinweis: Die Angabe keiner Regel führt nicht dazu, dass allen Web-Anwendungen Zugriff gewährt wird!

Zugriff auf die API

Standardmäßig kann auf die API via http bzw. https über den Port 55539 zugegriffen werden.

API-Explorer
Die einzelnen IIS-Komponenten, die man einsehen, hinzufügen, ändern oder löschen möchte, spricht man über URLs an. Um einen Gesamtüberblick über die einzelnen Komponenten und deren URLs zu bekommen, stellt Microsoft den API-Explorer zur Verfügung. Diesen erreicht man unter https://localhost:55539. Für den Zugriff ist ein Access-Token notwendig (siehe unten).

Microsoft IIS Web Manager
Hierbei handelt es sich um eine Web-Oberfläche, um einen IIS-Server via GUI zu verwalten. Stellt damit eine Alternative zum klassischen IIS Manager dar. Das Web Management Portal hat jedoch den Vorteil, dass dieses in jedem Browser auf jedem Endgerät (Dank Responsive Design auch auf mobilen Endgeräten) ausgeführt werden kann. Für den Zugriff ist ein Access-Token notwendig (siehe unten).

Access-Token
Egal, ob man via API-Explorer, IIS Web Manager oder Programmier-/Scriptsprache auf die API zugreifen möchte, man benötigt hierfür einen Access-Token. Um sich solch einen generieren zu lassen, öffnet man den API-Explorer (https://localhost:55539) oder IIS Web Manager (https://manage.iis.net) und klickt auf “Get Access-Token” oder geht direkt zu https://localhost:55539/security/tokens.

Dort gib man zu erst den Zweck des Access-Token an. Das ist ein frei wählbarer Name, der auch nur optional angegeben werden muss – macht später die Verwaltung mehrerer Token jedoch einfacher. Als nächstes wählt man die Gültigkeitsdauer aus (1 Tag, 1 Monat, 3 Monate, 1 Jahr, unendlich). Der Access-Token, der dann generiert und angezeigt wird, sollte man gut abspeichern, da man sich diesen im Nachhinein nicht noch einmal anzeigen lassen kann!

IIS API 03

Programm-/Scriptsprachen
Über diveres Programmier- oder Scriptsprachen kann ohne großen Aufwand auf die API zugegriffen werden. Voraussetzung ist nur, dass mit der Sprache eine HTTP-Verbindung aufgebaut werden kann. Damit können gängige Sprachen wie Powershell, JavaScript, C# (.NET) oder PHP verwendet werden.

Beispiel Powershell

Mit diesem Code-Beispiel kann man mit Powershell alle Webseiten eines IIS-Servers inkl. Status ausgeben lassen:

$token = "1-4b1BmGw00a6bjLDCkqJDHaszFM-lNNY1Zdz7ligTV0-F1t_9Jy6g"
$headers = @{ "Access-Token" = "Bearer $token"; "Accept" = "application/hal+json" }
$response = Invoke-RestMethod "https://localhost:55539/api/webserver/websites" -UseDefaultCredentials -Headers $headers
$response.websites

Für den Zugriff auf die API benötigt man auch hier einen Access-Token (siehen oben), den man als Header dem HTTP-Request mitgeben muss (dieser muss im Quellcode natürlich entsprechend ausgetauscht werden).

IIS API 05


Beispiel JavaScript

Mit JavaScript ist es auch nicht wesentlich komplizierter die Webseiten ausgeben zu lassen. Hier kommt für die HTTP-Verbindung ein AJAX-Request zum Einsatz. Für mehr Komfort bzw. weniger Schreibarbeit habe ich hierfür jQuery eingesetzt.

Zu erst einmal ein simples HTML-Dokument für den Script-Aufruf und die Ausgabe:

IIS API 06

Bei der Einbindung der JavaScript-Datei (api.js) das Attribut “defer” beachten – damit spare ich mir im JS-Code das jQuery-Event “ready”!

Und nun der JavaScript-Code:

$.ajax({
    method: "GET",
    url: "https://localhost:55539/api/webserver/websites",
    headers: {"Access-Token": "Bearer 8RFvwFK6KTeegT_WJVKJzu5xjSRdOKItbE8QaJXANmm2WD2v8qQOHg"
    },
    xhrFields:{
        withCredentials: true
    },
    complete: function(data)
    {
        var htmlString = "";

        data.responseJSON.websites.forEach(function(site)
        {
            htmlString += "<h3>"+  site.name +"</h3>";
            htmlString += "ID: " + site.id + "<br>";
            htmlString += "Status: " + site.status + "<br>";
        });

        $("#output").html(htmlString);
    }
});

 
Auch hier nicht vergessen den Access-Token gegen den Eigenen auszutauschen.

Für weitere Informationen und Beispiele empfehle ich die offizielle Dokumentation der Microsoft IIS Administration API.

Sharepoint 2016 Listenelement drucken

$
0
0

Da im Sharepoint das Drucken eines Listenelements auf direktem Wege nicht möglich ist, behelfen sich viele mit dem Drucken über den Browser. Mit ein wenig Arbeit kann man aber Abhilfe schaffen.

Um in einer Liste bzw. im Menü eines Listenelements einen „Druckbutton“ zu erstellen, ist etwas Code notwendig.

Zuerst muss in der jeweiligen Liste bei „Formularwebparts“ das „Standardanzeigeformular“ bzw. das „Standardformular bearbeiten“ editiert werden.

clip_image002

In beiden Formularen füge ich das „Inhalts-Editor“-Webpart hinzu und klicke in die Webpartzeile.

clip_image004clip_image006

Danach im Ribbon auf „Quelle bearbeiten“ klicken, damit sich das Codefenster öffnet.

clip_image008

Im Codefenster dann folgenden Code eingeben:

<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js" type="text/javascript"></script><script>

$(document).ready(function() {

$('.printList').click(function() {

window.print();

return false;

});

});</script>

<style>

.printList{

color:#666666;

font-weight:bold;

cursor:pointer;

}

.printList:hover{

color:#333333;

font-weight:bold;

cursor:pointer;

}

</style>

<button class="printList">Element drucken</button>

Im Inhalts-Editor-Webpart sollte nun der „Element drucken“ -Button angezeigt werden.

clip_image010

Seite speichern. Fertig!

Audio Recording UWP

$
0
0

Eigentlich ist es ganz einfach. Über das eingebaute Mikrofon schnell etwas aufnehmen. Wenn Carmen Geiss völlig talentfrei ein Album aufnimmt, dann sollte das meine UWP App doch auch. Erstens kommt es anders und zweites … Es fängt damit an, das die Beispiel aus dem Github Repository völlig overengineerd (schreibt man das so?) sind. Dann braucht eine UWP App spezielle Recht um auf das Mikro zugreifen zu können. Außerdem kann man nicht so einfach überall seine Dateien hin  speichern, wäre ja völlig unsicher.

Beides erlaubt der Entwickler im Visual Studio Projekt in der Manifest Datei

image

Der Benutzer muss beim ersten Start den Zugriff außerdem erlauben. Nur Siri oder Alexa dürfen dauerhaft lauschen.

Das UI wird einfach mit einem Kreis definiert der auf ein Tapped Event lauscht. Um den Nutzer nicht im unklaren zu lassen färbt er sich rot im Recording mode und grün, wenn fertig gespeichert.

 

Im Code wird dann der Stream für den Tonund ein Media Element benötigt, am besten als Eigenschaft der Klasse.

   1:  Dim capture As new MediaCapture
   2:  Dim buffer As new InMemoryRandomAccessStream

Da es ziemlich viele Möglichkeiten gibt Audio und auch Video Devices zu nutzen, muss man die gewünschten Einstellungen initialisieren.

   1:  Dim settings = New MediaCaptureInitializationSettings
   2:  settings.StreamingCaptureMode = StreamingCaptureMode.Audio
   3:  Await capture.InitializeAsync(settings)

Starten und Stoppen der Aufnahme ist beinahe schon intuitiv. Man gibt noch die gewünschte Tonqualität als Parameter an. Natürlich auch den armen Stream, der meinen Gesang entgegen nehmen darf.

   1:  await capture.StartRecordToStreamAsync(MediaEncodingProfile.CreateWav(AudioEncodingQuality.Low), buffer)
   2:  ....
   3:  Await capture.StopRecordAsync()

An dieser Stelle wärs für Carmen vorbei.

Ich möchte aber meinen neuen Hit “Hallo Welt” auch noch auf der lokalen Festplatte verewigen. Dazu muss ich den WinRT Stream in ein Byte Array umwandeln um ihn dann wieder einer WinRT API Funktion als Parameter zu übergeben. Wie vorher schon angeschnitten, mit einem StorageFile Objekt das in dem Fall auf meinen Ordner Musik zeigt.

   1:  Using dataReader = New DataReader(buffer.GetInputStreamAt(0))
   2:       Await dataReader.LoadAsync(buffer.Size)
   3:       Dim b(buffer.Size - 1) As Byte
   4:       dataReader.ReadBytes(b)
   5:       Dim saveFile = Await KnownFolders.MusicLibrary.CreateFileAsync(
   6:  "audio.wav", CreationCollisionOption.FailIfExists)
   7:        Await Windows.Storage.FileIO.WriteBytesAsync(saveFile, b)
   8:  End Using

So dann steht eurer Karriere nichts mehr im Wege.


Information Rights Management (IRM) mit Sharepoint 2016

$
0
0

Eine Erweiterung bzw. eine Ergänzung der Berechtigungen im Sharepoint, stellt die Verwendung der „Information Rights Management“ (IRM) zur Verfügung.

Wenn man Dokumente schützen möchte, wie z.B. das Drucken verbieten oder ein Dokument ablaufen lassen will etc. ist die Verwendung der IRM mit Hilfe eines z.B. RMS-Clusters innerhalb einer Domäne eine interessante Möglichkeit.

Für die Verwendung ist es erforderlich einen fertig konfigurierten RMS-Cluster in der Domäne zu betreiben und sicherzustellen, dass der Sharepoint den Serviceconnectionpoint (SCP) auffinden kann.

Fertig konfiguriert, ist es dann wenig Aufwand IRM in Verbindung mit Sharepoint zu nutzen.

In der Zentraladministration unter „Sicherheit“ wird der AD-RMS Dienst verbunden.

clip_image002

In Listen und Bibliotheken stehen dann in den Einstellungen die Konfigurationsmöglichkeiten zur Verfügung.

clip_image005

clip_image007

Alexa selbstgebaut -Bing Speech API

$
0
0

Spracheingabe ist der neueste Trend. Dabei geht es nicht nur um das erkennen eines Wortes oder Befehl, es geht um Sinn, Kontext, Stimmung, Übersetzung und sogar um Authentifizierung. Also weit über Diktierfunktion hinaus. Windows enthält schon sehr lange eine recht ausgefeilte API um Sprache zu erkennen. Das bedeutet es ist mit .net oder UWP dank dem Namensraum System.Speech oder Windows.Media.SpeechRecognition  offline möglich mit Sprache zu agieren.

Richtig nett wird Interaktion mit Sprache allerdings erst wenn AI zum Einsatz kommt. Die Produkt Familie von Microsoft nennt sich dazu Cognitive Services. Konkret die Bing Speech APi. Mit 20 gratis Anforderungen pro Minute für jedermann mit einer Microsoft ID nutzbar.

image

Man erhält einen API Key in der Form 1b877c4bbba24b26acb7019afbdb95af  und eine als Endpoint bezeichnet Url

https://api.cognitive.microsoft.com/sts/v1.0

 

Als Vorbereitung für die Aufzeichnung der Sprache empfehle ich meinen Blog Artikel. Es wird zwar die Audio Aufzeichnung als Wav File gespeichert, man kann aber in der Praxis auch über den Stream direkt gehen.

Als nächstes müssen wir vier Probleme lösen. Für die Nutzung des Bing Services muss ein Authentifizierungs Token erstellt werden. Dann muss das Wav File in Blöcken eingelesen werden. Diese Blöcke werden an den Bind Service per Chunk Post übermittelt. Das Ergebnis wird ausgelesen und in eine Objekt Struktur deserialisiert. Eine Menge zu tun. Legen wir los.

 

Um das Thema zu isolieren bekommt die UI im XAML einen Button und eine Textbox. Dem asynchronen Button Event fügt man den Code hinzu um den Bearer Token zu beziehen.

   1:  Using client = New HttpClient()
   2:      client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "ersetzen durch API Key")
   3:  Dim UriBuilder = New UriBuilder("https://api.cognitive.microsoft.com/sts/v1.0")
   4:      UriBuilder.Path += "/issueToken"
   5:  Dim result = Await client.PostAsync(UriBuilder.Uri.AbsoluteUri, Nothing)
   6:      text1.Text = Await result.Content.ReadAsStringAsync()
   7:  ...

 

Dieser soll 10 Minuten gelten. Es ist also überflüssig, bei jeder Spracherkennung diesen erst anzufordern. Um das Beispiel klein zu halten, mach ich es trotzdem so. In meiner Textbox lässt sich so gut ablesen ob das funktioniert.

Nun muss das Wav File gelesen und in 1KB große Blöcke zerlegt werden. Die API fordert das so. Streams bereiten mir in UWP wenig Freude weil anders implementiert wie in System.IO. Meine optimale Lösung unter Berücksichtigung der beschrnänkten Dateizugriffsrechte von UWP nutzt den Binary Reader und konvertiert den Stream in ein Byte Array. Für die Berechnung der Anzahl der Reads reicht die Länge des BaseStreams.

   1:  Dim f = Await KnownFolders.MusicLibrary.GetFileAsync("audio.wav")
   2:  Using fs = Await f.OpenSequentialReadAsync()
   3:  Dim buffer(1024) AsByte
   4:       Using sr = New BinaryReader(fs.AsStreamForRead())
   5:  Dim lang = sr.BaseStream.Length
   6:  While lang > 0
   7:               buffer = sr.ReadBytes(1024)
   8:               ...todo block send
   9:               lang -= 1024
  10:  EndWhile
  11:  End Using
  12: End Using

Diese 12 Zeilen Code haben mich 2 h gekostet, weil ich mehrere Varianten probiert habe.

 

Schritt Drei sendet die Byte Chunks der Audio Datei per HTTP Post Kommando an die Bing API. Dazu wird das HTTPWebRequest Objekt mit den nötigen Parametern gefüttert. Unter anderem den Token, der im ersten Code Block gewonnen wurde und nun im Textblock wartet. Der Vorige VB.NET Code wird nun um ein weiteres Using ummantelt, das eine Instanz des  Request als Stream erzeugt. In diesem Stream, werden dann die 1024 Byte Binär Blöcke an den Service gesendet (Zeile 14).

 

   1:  Dim request As HttpWebRequest = HttpWebRequest.Create(
"https://speech.platform.bing.com/speech/recognition/interactive/cognitiveservices/v1?language=de-de&format=detailed")
   2:  request.Accept = "application/json;text/xml"
   3:  request.Method = "POST"
   4:  request.ContentType = "audio/wav; codec=audio/pcm; samplerate=16000"
   5:  request.Headers("Authorization") = "Bearer " + text1.Text
   6:  Using requestStream = Await request.GetRequestStreamAsync()
   7:  Dim f = Await KnownFolders.MusicLibrary.GetFileAsync("audio.wav")
   8:       Using fs = Await f.OpenSequentialReadAsync()
   9:  Dim buffer(1024) AsByte
  10:                 Using sr = New BinaryReader(fs.AsStreamForRead())
  11:  Dim lang = sr.BaseStream.Length
  12:  While lang > 0
  13:                              buffer = sr.ReadBytes(1024)
  14:                              requestStream.Write(buffer, 0, buffer.Length)
  15:                              lang -= 1024
  16:  EndWhile
  17:  End Using
  18:  End Using
  19:         requestStream.Flush()
  20:  End Using

 

Hier telefoniert also die UWP App erfolgreich nach Hause. Allerdings hören bzw lesen wir noch keine Übersetzung. Erst wird auch ein Response Objekt benötigt. Kurze Zeit nach dem Flush antwortet der Service und man erhält die Antwort ebenfalls als Stream.

   1:  Using response = Await request.GetResponseAsync
   2:       Using sr = New StreamReader(response.GetResponseStream())
   3:             text1.Text = sr.ReadToEnd()
   4:  End Using
   5:  End Using

 

Das Ergebnis liest sich nicht so toll. Am besten kopiert man den Inhalt der Textbox in die Zwischenablage. In meinem Beispiel kommt folgende JSON Struktur als Antwort.

{"RecognitionStatus":"Success","Offset":3200000,"Duration":16500000,"NBest":[{"Confidence":0.7879451,"Lexical":"ist alina zu jung","ITN":"ist Alina zu jung","MaskedITN":"ist Alina zu jung","Display":"Ist Alina zu jung."},{"Confidence":0.7879451,"Lexical":"wie ist alina zu jung","ITN":"Wie ist Alina zu jung","MaskedITN":"Wie ist Alina zu jung","Display":"Wie ist Alina zu jung?"},{"Confidence":0.7835977,"Lexical":"wer ist alina zu jung","ITN":"Wer ist Alina zu jung","MaskedITN":"Wer ist Alina zu jung","Display":"Wer ist Alina zu jung?"},{"Confidence":0.5198187,"Lexical":"ist alina ziehung","ITN":"ist Alina Ziehung","MaskedITN":"ist Alina Ziehung","Display":"Ist Alina Ziehung."},{"Confidence":0.5198187,"Lexical":"wie ist alina ziehung","ITN":"Wie ist Alina Ziehung","MaskedITN":"Wie ist Alina Ziehung","Display":"Wie ist Alina Ziehung?"}]}

Mein Tipp zum Schluss. Die Visual Studio Funktion Paste Json as Class nutzen und eine Objekt Klasse erzeugen lassen.

image 

Die generierte Klasse hat eine Schwäche mit Eigenschaften als Arrays, die erst bei deserialisieren auftritt. Deswegen füge ich zwei Änderungen ein- hier gelb markiert.

   1:  PublicClass RestText
   2:  PublicProperty RecognitionStatus AsString
   3:  PublicProperty Offset AsInteger
   4:  PublicProperty Duration AsInteger
   5:  PublicPropertyNbest As List(Of Nbest1)
   6:  EndClass
   7:   
   8:  PublicClass Nbest1
   9:  PublicProperty Confidence AsSingle
  10:  PublicProperty Lexical AsString
  11:  PublicProperty ITN AsString
  12:  PublicProperty MaskedITN AsString
  13:  PublicProperty Display AsString
  14:  End Class

 

Nun noch JSON.NET per Nuget Manager in Visual Studio dem Projekt hinzufügen und mit folgender Zeile das Objekt füllen

 

   1:  Dim daten = New RestText
   2:  daten = JsonConvert.DeserializeObject(Of RestText)(text1.Text)

Nun braucht man kein Alexa, Siri und Cortana mehr. Hey ppedv!

Spezifität - oder "warum spinnt mein CSS?"

$
0
0

Wie entscheidet ein Browser, welchen Wert er verwenden soll, wenn einem Attribut mehrmals unterschiedliche Werte zugewiesen wurden?

Mittels eines Punktesystems namens Spezifität (englisch: specificity). Und ja, das heißt tatsächlich so, und es ist nicht etwa bei der Übersetzung aus dem Englischen eine Silbe verloren gegangen.

Mittels Spezifität wird entschieden, welcher der unterschiedlichen Werte die höchste Relevanz hat. Zumindest die Grundbegriffe dieser Regeln sollten dem Web-Designer bekannt sein, wenn es nicht immer wieder zu Überraschungen kommen soll. Dieser Artikel setzt sich mit eben diesen Grundbegriffen auseinander.

 

Überraschung, Überraschung…

 

Eines der ersten Dinge, die man lernt, wenn man beginnt, sich mit CSS zu beschäftigen, ist, wie man Elemente ansprechen kann: mit den sogenannten Selektoren.

Wir lernen, dass es ID-, Klassen- und Typ-Selektoren gibt, und wer schon ein bisschen fortgeschrittener ist, weiß auch um Universal-, Attribut- und Pseudo-Selektoren.

Und dann kommt irgendwann der Moment, in dem irgendein Element nicht so will, wie es soll. Beispielsweise eine Schriftfarbe, die ganz und gar nicht so ausfällt, wie wir das eigentlich erwartet hätten.

Das liegt vermutlich daran, dass hier die Spezifität (specificity) gegriffen hat.

Die Spezifität bestimmt anhand eines Punktesystems, welche Selektoren schwerer wiegen und daher zum Tragen kommen, wenn ein Wert (oft unbeabsichtigt) über mehrere Selektoren(-ketten) angesprochen wird.

 

Eine kleine Auffrischung

 

Diese vereinfachte Tabellenübersicht gibt einen kurzen Überblick über die gängigsten Selektoren:

 

Beispiel

Selektor

Erklärung

p

Element (Typselektor)

Wählt alle <p>-Elemente aus.

th, td

Element und Element

Wählt alle <th>- und alle <td>-Elemente aus.

div p

Element in Element (Nachfahren-Kombinator)

Wählt alle <p>-Elemente aus, die sich in einem<div>-Element befinden.

*

Universalselektor

Wählt alles aus.

.content

Klassenselektor

Klassenselektor; wählt alle Elemente mit dieser Klasse (class="content“)aus.

#container

ID-Selektor

Wählt das Element mit der Id (id="container“)aus.

:hover

Pseudo-Klassen-Selektor

Wählt einen bestimmten Zustand aus (hier: mouseover).

::first-letter

Pseudo-Element-Selektor

Wählt einen bestimmten Teil eines Elements aus (hier: den ersten Buchstaben).

[a=“xyz“]

Attributselektor

Wählt ein bestimmtes Attribut (mit einem bestimmten Wert) aus

 

 

Das ist einfach genug – wenn man denn die Seite genau genug geplant hat und das CSS-Dokument kurz, knapp und übersichtlich ist. Leider entspricht das nicht immer der Praxis. Manche Seiten sind im Lauf der Zeit gewachsen, sind von anderen Developern übernommen worden, die alle ihren Teil hinzugefügt haben, und man hat mit Skript-Monstern zu tun, in denen es schwer ist, überhaupt etwas zu finden. Da kann es leicht vorkommen, dass ein Element von mehreren Deklarationen angesprochen wird. Genau dann wird Spezifität wichtig.

 

Verwirrte Browser: Welcher Wert soll verwendet werden?

 

Wenn nun demselben Attribut mehrere Werte zugewiesen werden, gibt es Regeln, welcher Wert dann vom Browser zur Darstellung verwendet wird.

Nehmen wir als einfaches Beispiel die Schriftfarbe. Wird ein Attribut doppelt belegt, wird der Eintrag, der zuletzt kommt, verwendet:




 

 


So einfach haben wir es aber leider selten. Unsere Selektoren sind verknüpft und verschachtelt, und es gibt Klassen und IDs…

Manchmal wird ein Element mit einer Klasse versehen, um ihm ein gesondertes Styling verpassen zu können – aber nichts passiert. Dann hat vermutlich die Spezifität zugeschlagen:



 

In diesem Beispiel wurde versucht, einen bestimmten Paragraphen innerhalb eines Divs grün zu schreiben. Die Schrift ist allerdings weiterhin rot – denn der erste Eintrag hat eine höhere Spezifität. (Siehe Codepen-Beispiel hier.)

 

Von der höchsten bis zur niedrigsten Spezifität

 

Während ein paar Regeln, welcher Wert denn nun verwendet werden soll, intuitiv verständlich und allgemein bekannt sind, ist das dahinterliegende Prinzip der Spezifität doch etwas komplexer.

Stark vereinfacht gesagt: Es werden Punkte vergeben, und die Regel mit der höchsten Punkteanzahl „gewinnt“.

Hier ein Kurzüberblick über die Gewichtung der Selektoren:


 



 

In vielen Fällen wird das ausreichen, um zu erklären, warum welcher Wert verwendet wurde, aber natürlich können und werden wir noch etwas in die Tiefe gehen.

Zur Erklärung der Übersicht:

Inline

Spezifischer, als ein Element im HMTL-Dokument inline mittels Style-Attribut anzusprechen, geht’s nicht mehr. Damit wird sichergestellt, dass tatsächlich genau dieses Element gemeint ist, und in der Spezifität bekommt es die „höchste Punkteanzahl“.

Trotzdem ist inline-CSS normalerweise keine gute Wahl. Abgesehen davon, dass damit vielleicht auch ungewollt Attributswerte aus dem Stylesheet überschrieben werden, bläht inline-CSS auch das HTML-Dokument unnötig auf, macht es unleserlich und für nachfolgende Developer schwer zu finden.

ID

Ein ID-Selektor bekommt die nächsthöhere Priorität. Da eine ID ein eindeutiger Identifikator eines Elements ist, wird damit ganz genau ein bestimmtes Element angesprochen. Somit ist die ID von allen Selektoren die spezifischste– daher auch die Bezeichnung Spezifität. Wird eine ID verwendet, ist die Spezifität auf jeden Fall höher, unabhängig davon, wieviele Klassen- oder Typselektoren sonst noch verwendet werden. Das erklärt auch, warum die Schrift im Beispiel oben rot, nicht grün war.

Class

Eine Klasse kann mehreren Elementen zugeordnet werden. Sie ist somit weniger spezifisch als eine ID; aber immer noch spezifischer, als eine ganze Elementen-Gruppe anzuwählen. Zu dieser Spezifität gehören außerdem noch Attributselektoren und Pseudo-Klassen.

Element

Am wenigsten schwer wiegen ganze Element-Gruppen, also Typ-Selektoren. Wird beispielsweise „p“, als Selektor verwendet, gilt das zunächst für alle Paragraphen, ist also am wenigsten spezifisch. Auch Pseudo-Elemente zählen in diesem Fall zu dieser Gruppe.

 

Das Punktesystem der Spezifität

 

Wie also funktioniert nun das eigentliche Punktesystem?

Für jeden verwendeten Selektor wird ein Punkt in einer der obgenannten Kategorien vergeben. Man kann sich das so vorstellen:


 


Würde man beispielsweise einen Style für alle h1-Überschriften definieren, würde das folgendermaßen gezählt werden:


 


Die Spezifität für h1 wäre also 0,0,0,1.


Ein weiteres, realistisches, aber schon etwas kniffligeres Beispiel zur Spezifität:


 


Dieser Link, der sich in einer unordered list mit der ID „nav-bar“ und einem li-Element mit der Klasse „active“ befindet, hat die Spezifität 0,1,1,3. Somit kann ihm ein anderes Styling verliehen werden, als den anderen Links in dieser Navigationsleiste („ul#nav-bar li a“ hat nur eine Spezifität von 0,1,0,3).



 

Wird ein Wert im HTML-Dokument inline mittels Style-Attribut festgelegt, entspricht das der höchsten Spezifität. In diesem Beispiel 1,0,0,0.

 

Ausnahmen

 

·       Der oben in der tabellarischen Übersicht erwähnte Universalselektor (*) erhöht die Spezifität NICHT.

·       Die Pseudo-Klasse :not() erhöht die Spezifität ebenfalls nicht; das übergebene Argument allerdings schon.

Beispiel:

p:not(.myClass) hat eine Spezifität von 0,0,1,1.

·       !important überschreibt auch inline Style-Attribute. Allerdings sollte !important nur äußerst sparsam und wohlüberlegt (und idealerweise gar nicht) eingesetzt werden.

 

Links

 

Die W3C-Spezifikation zur specificity findet sich hier.

Andy Clarke beschreibt specificity in seinem Blogso:


 

 

 

 

 

UWP Kaufhaus

$
0
0

imageAb und zu muss man verrückte Dinge tun. Schon seit Windows 8 hat WinRT eine sehr umfangreiche API für sogenannte POS (Point of Sale) Devices. Ich habe zwar keine Ahnung warum, aber ist so. Das sind spezielle Drucker und Scanner.  Leider nur ganz wenige und dann auch nur wenn sie ESC/POS unterstützen. Die entsprechenden Thermodrucker von Epson sind ganz schön teuer. No Name Geräte gibt es schon ab 15€. Auf denen kann man halt nicht drucken. Dann kam mir die dumme Idee mal so ein ESC/POS kompatibles 2zeiliges Kassendisplay zu kaufen. das Glacetron 8035 erworben für 95€. Einfach per USB an den Rechner angesteckt und schon leuchtet es in sympathischen Blau. Die Aufmerksamkeit von Büro Besuchern ist dir ab sofort sicher.

Das Gerät hängt sich über eine CP210x UART Bridge als weitere serielle Schnittstelle rein. Mein Windows 10 Device Manager hat es zwar erkannt, ich musste aber Treiber bei Dr. Google suchen.

image

Nun könnte man das Display mit recht einfachen Kommandos per Serieller Schnittstelle beschicken. Es geht aber noch einfacher. Man holt sich einfach das Epson Opos ADK. Nach Installation konfiguriert man sein Gerät. Da das LineDisplay 2 Zeilen hat und der Befehlssatz ESC/POS ein Standard ist, habe ich wild geraten und das DM-D 210 ausgewählt.

image

Das OPOS Tool hat auch eine Check Health Funktion, die mir adhoc den Erfolg meldet. Das klappt also. Its Coding Time mit Visual Studio und einem leeren UWP Projekt.

Das XAML User Interface für meine Hello World Kasse enthält einfach einen Button und eine Zeile Text.

   1:  <TextBoxName="text1"Margin="78,20,0,0"VerticalAlignment="Top"/>
   2:   
   3:  <ButtonContent="show"
   4:  Visibility="Collapsed"
   5:  Name="btnDisplay"HorizontalAlignment="Left"
   6:  Margin="78,91,0,0"VerticalAlignment="Top"
   7:  Click="btnDisplay_ClickAsync"/>

Es wäre nicht die Universal Windows Platform, wenn man der sandboxed APP nicht erst das passende Recht zuweisen müsste. Im Manifest des VIsual Studio Projektes muss die DeviceCapability PointOfService eingetragen sein.

Im PageLoad wird dann das passende LineDisplay Device gesucht und einer Liste zugewiesen. Da diese realtiv lange dauern kann, so 15 –30 Sekunden, wird der Button erst aktiviert, wenn es mindestens ein POS Device gibt.

   1:  Dim devices As DeviceInformationCollection
   2:  Private Async Function MainPage_LoadedAsync(sender AsObject, 
e As RoutedEventArgs) As Task HandlesMe.Loaded
   3:          devices = Await DeviceInformation.FindAllAsync(
LineDisplay.GetDeviceSelector(PosConnectionTypes.All))
   4:  If devices.Count > 0 Then btnDisplay.Visibility
= Visibility.Visible
   5:  End Function

Im Button Event wird eine Referenz auf das Device über seine ID abgerufen. Da ich nur ein Display nutze, einfach per First. Die Position 0,0 zeigt auf die erste Stelle, erste Zeile. Zeile 2 wäre dann 0,1. Als zweiten Parameter gibt man noch an ob normal, invers oder blinkend. Die Anzeige wird gelöscht und im der nächsten VB.Code Zeile der Text entsprechend er beiden Parameter gesetzt. Wenn er länger ist, wird automatisch umgebrochen.

   1:   Using lineDisplay = Await ClaimedLineDisplay.FromIdAsync(devices.First.Id)
   2:  Dim position = New Point(0, 0)
   3:  Dim attribute = LineDisplayTextAttribute.Normal
   4:              Await lineDisplay.DefaultWindow.TryClearTextAsync()

5: Await lineDisplay.DefaultWindow.TryDisplayTextAsync(

text1.Text, attribute, position)

   6:  End Using

Supersimpel, deswegen noch der Bonustrack. Man kann die Fähigkeiten des Displays abfragen und so z.B. wie vorher erwähnt Text auch Blinkend ausgeben.

   1:  If Not lineDisplay.Capabilities.CanBlink = 
LineDisplayTextAttributeGranularity.NotSupported Then
   2:                  attribute = LineDisplayTextAttribute.Blink
   3:  End If

 

Das Wahnsinns UWP Kassen Projekt gibt es auch auf Github.

Höhepunkt mit Developer Vibrator

$
0
0

Ja Beate Uhse geht es schlecht und Online Shops wie Amoreli oder Eis sprießen aus dem Internet. Da wird es doch Zeit für eine App um mit Vibrationen stimulierend zu wirken. Das Device ist ein Wearable mit Windows IoT. Programmierbar mit UWP. Wenn wer noch ein WIndows mobile 10 Handy in der Schublade liegen haben sollte, lässt sich der Vibrator in der passenden API aktivieren. Um den Code Fehlerfrei in anderen Umgebungen zb auf dem Desktop auszuführen kann man den ApiContract auch abprüfen.

   1:  if (ApiInformation.IsApiContractPresent("Windows.Phone.PhoneContract", 1))
   2:                  Windows.Phone.Devices.Notification.VibrationDevice.GetDefault().
Vibrate(TimeSpan.FromSeconds(1));

 

Nicht nur das das UWP Projekt in Visual Studio als Compiler Target den passenden Build Target aufweisen, es braucht auch noch die API als Verweise

image

Wie man unschwer erkennen kann gibt es reichlich API Levels. Das Wearable Device ist leider erst auf dem Creators Update 15063.  Das reicht aber für unsere Zwecke. Die IoT Extensions beiten dafür einen Haptics Namensraum. Diese Vibrator Api scheint wesentlich mehr zu können.

Provides support for basic, non-directional haptic feedback such as clicks, buzzes, and rumbles that can be tuned through characteristics such as intensity and timing.

Ich denke das zielt auf Kontroller und Force Feedback. Aber auch das Surface Dial unterstützt haptisches Feedback. Darüber bin ich erst überhaupt auf die API gestoßen.

Ganz ohne Manifest per Code wird der Zugriff eingefordert und dann eine Instanz auf ein oder mehrere Vibrations Devices zugewiesen.

 

   1:  if (await VibrationDevice.RequestAccessAsync() != VibrationAccessStatus.Allowed)
   2:              {
   3:  
   4:              }
   5:   vib = await VibrationDevice.GetDefaultAsync();

 

Soweit ganz easy. Etwas komplizierter wird es, wenn man die Vibrationsfähigkeiten einfordert. Es scheint verschiedenen Frequenzen geben, die mit for each durchlaufen werden. Meine Smartwatch kann nur eines und der Debugger meint Bufffeedback ist 4100, was die Frequenz sein könnte.

   1:   SimpleHapticsControllerFeedback BuzzFeedback = null;
   2:  foreach (var f in vib.SimpleHapticsController.SupportedFeedback)
   3:     {
   4:  if (f.Waveform == KnownSimpleHapticsControllerWaveforms.BuzzContinuous)
   5:         BuzzFeedback = f;
   6:     }
   7:  if (BuzzFeedback != null)
   8:       {
   9:         vib.SimpleHapticsController.SendHapticFeedbackForDuration(BuzzFeedback, 1, TimeSpan.FromMilliseconds(200));
  10:     }

Bin gespannt ob dieses Wissen außer mir noch wer benötigt. Die Dokumentation war jedenfalls unterirdisch und quasi nichts zu finden im Internet.

Windows 10: Neustart nach Updates verhindern

$
0
0

Unter Windows 10 lässt sich Windows Update nicht einfach in den Einstellungen deaktivieren – im Gegensatz zu den bisherigen Windows-Versionen. Daher werden neue Updates automatisch heruntergeladen und installiert. Falls notwendig möchte Windows dann direkt einen Neustart durchführen, den der User über eine Benachrichtigung angekündigt bekommt und dann noch etwas verzögern kann – aber nur, wenn er zu dieser Zeit auch am PC sitzt. Ansonsten wird automatisch ein Neustart durchgeführt, was evtl. zu Datenverlust führen kann, falls noch Programme/Dokumente offen sind.

Über die Windows-Einstellungen (“Update und Sicherheit” –> “Windows Update”) lässt sich eine Nutzungszeit konfigurieren, während dieser Windows keine automatischen Neustarts durchführt.

Update - Nutzungszeit

Allerdings kann die Nutzungszeit max. 18h betragen. Man kann auch nicht immer ausschließen, dass man auch außerhalb dieses eingestellten Zeitraums am PC arbeitet (und evtl. kurzzeitig nicht davor sitzt). Vor der Version 1607 von Windows 10 konnte man per Registrierungsdatenbank (Registry) noch verhindern, dass nie ein automatischer Neustart seitens von Windows Update durchgeführt wird, solange ein User angemeldet ist. Diese Möglichkeit gibt es leider nicht mehr, da der entsprechende Schlüssel nicht mehr existiert und auch nicht mehr interpretiert wird.

Eine weitere Möglichkeit besteht darin, den Windows Update-Dienst zu beenden. Hierfür im Startmenü nach “Dienste” suchen. In dem Snap-In (Verwaltungsprogramm) “Dienste” einen Doppelklick auf “Windows Update” vornehmen.

Update - Dienst1

Dann als Starttyp “Deaktiviert” auswählen und mit “OK” die Einstellung übernehmen.

Update - Dienst2

Aber Vorsicht: Ab jetzt lädt Windows Update überhaupt keine Updates mehr herunter!

NFC Magie mit Windows Phone UWP und ein paar Cent

$
0
0

Das Thema NFC ging bisher an mir weitestgehend vorüber. Bis ich bei Amazon einen günstigen 40€ NFC Kartenleser entdeckt habe.

ACR122U NFC Reader/Writer + 5 Bonus NFC Tags NXP NTAG213

Den ACR 122U. Im Paket waren noch 5 Karten dabei. Zusätzlich orderte ich aufklebbare Tags NFC NTAG 213 mit 144Byytes Speicher. Diese wurden dann auch

meine treuen Begleiter im weiteren Tests. Um die Funktionsfähigkeit des Readers zu prüfen, wollte ich erfolglos aus den Windows Universal Samples das NFC Projekt kompilieren. Ein netter Zeitgenosse hat es allerdings im Microsoft Store zum Download angeboten.  Folgende Apps kommen zum Einsatz

NFC Demo App

https://www.microsoft.com/store/productId/9NBLGGH1R8BW

NFC Commander auf dem Lumia 650

https://www.microsoft.com/de-de/store/p/nfc-commander/9wzdncrdmmw0

Andere Apps wie von Andreas Jakl finden den NFC Reader nicht. Wie sich nach längerer Suche herausstellt, weil es keinen Windows 10 proximitry Driver für das ACR122U Device gibt. Der erste Versuch startet also mit diversen Kreditkarten, BUILD Teilnehmer Badge, den Karten und den NFC Tags und der NFC App.

image

Dabei zeigt sich, das Thema NFC ist unendlich. Es gibt ca 10 Verschiedene Kartenstandards, die wiederum in verschieden beschrieben werden können. Außerdem zeigt sich, das es eine kurze Weile dauert, bis die Karte erkannt und gelesen wird. Auch die Kommunikation zwischen Karte und Leser findet auf verschiedenen Arten statt. Da mein Wissen im Bereich NFC endlich ist, beschränke ich mich auf die so erkannte MifareUltraLight. Der Speicher wird in 4 +16 Byte Blöcken organisiert, die allerdings wenn man dem üblichen NDEF Format folgt nicht ganz zur Verfügung stehen. Mein Test ergibt 34 nutzbare Bytes.

Auch mein Microsoft Lumia 650 ist ein NFC Device, sozusagen eine Karte oder ein Leser. Angedacht war von Microsoft auch Zahlungsfunktion an der Supermarktkasse, analog zur Kreditkarte anzubieten. Beim probieren mit der App NFC Commmander auf dem Smartphone erkennt man die unglaubliche Vielfalt an Funktion, die in dem Thema steckt. Mit Annäherung lassen sich Apps Starten oder Anrufe tätigen, wenn der Treiber vorhanden ist. Mein Tag wird also mit einem einfachen Text beschrieben, Location DE, durch Annäherung an mein Telefon.

Die NFC Test App am Notebook zeigt nun auch andere Daten in Block 2-4.

Die WinRT API enthält Low Level Funktionen für Annäherung und lesen schreiben. Mit UWP wäre es also ganz einfach ala   Dim nfcDevice = ProximityDevice.GetDefault() auf ein Device zuzugreifen. Wären da nicht die fehlenden Treiber. Im Weiteren Fortgang habe ich dann versucht aus den Devices die Smartcard zu finden und über eine Smartcardconnection Instanz Low Level APDU Kommandos per  Await connection.TransmitAsync(cmd.AsBuffer) an die Karte zu senden. Nach realistischer Aufwandsschätzung die Erkenntnis, das Problem hat bestimmt schon wer gelöst. Eine Library muss her. Wie immer mehrere zur Auswahl. Da die Redmonder in ihrem UWP SDK ein scheinbar funktionierendes Sample ausprogrammiert haben fällt die Wahl auf pcscsdk. Das gibts als Nuget Paket, was mein UWP Projekt im Compilerlauf verweigert, oder einfach den Source Code aus dem SDK Sample “klauen”.

Es wird also ein leeres UWP Projekt erstellt und der Visual Studio Solution eine UWP Klassenbibliothek hinzugefügt. Dabei kann ich wie in meinem Fall auch die Sprachen mischen. Die C# Source Files werden als nächstes in das Library Projekt kopiert. Im UWP App Projekt muss unter Verweise, auf das Class Library Projekt verwiesen werden.

 

image

Das XAML UI enthält nur eine Textbox Text1. Aus einer Liste von in meinem Fall über 6000 Devices wird das mit einer speziellen GUID (siehe Code) herausgefilter um den Smartcardreader zu identifizieren. Dieser bietet dann zwei Events CardAdded, CardRemoved die wie abonniert werden.

   1:  Dim myNFC As SmartCardReader
   2:   
   3:  ....
   4:  Dim query AsString = "System.Devices.InterfaceClassGuid:=""{DEEBE6AD-9E01-47E2-A3B2-A66AA2C036C9}"" "
   5:  Dim devices As DeviceInformationCollection = Await DeviceInformation.FindAllAsync(query)
   6:  myNFC = Await SmartCardReader.FromIdAsync(devices(1).Id)
   7:  AddHandler myNFC.CardAdded, AddressOf CardAdded
   8:  AddHandler myNFC.CardRemoved, AddressOf CardRemoved

Das CardAdded Event erlaubt es eine Verbindung zur neuen NFC Karte aufzubauen. Zeile 3 und 4 nutzen bereits das pcscsdk und geben Informationen über den Kartenstandard wieder. In diesem VB.NET Code Beispiel wird das Ergebnis allerdings verworfen, da wir nur den MifareUltra Light Standard hier nutzen wollen.

Es werden 4 x 16 Byte gelesen und das Byte Array in einen String konvertiert. Da die ersten Bytes nur zur Steuerung sind wird in den beiden IF Zweigen der Nutzanteil gefiltert.

 

   1:  Private Async Sub CardAdded(sender As SmartCardReader, args As CardAddedEventArgs)
   2:  Dim card = args.SmartCard
   3:          Using connection As SmartCardConnection = Await card.ConnectAsync()
   4:  Dim cardIdentification = New IccDetection(card, connection)
   5:          Await cardIdentification.DetectCardTypeAync()
   6:  Dim mifareULAccess As MifareUltralight.AccessHandler = New MifareUltralight.AccessHandler(connection)
   7:   
   8:  Dim s AsString
   9:  For i = 0 To 3
  10:  Dim response = Await mifareULAccess.ReadAsync((4 * i))
  11:                  Await DispatcherHelper.ExecuteOnUIThreadAsync(Sub()
  12:  if i = 1 Then'die ersten 14 bytes irgendwas mit Typ 
  13:                               text1.Text += Encoding.UTF8.GetString(response.ToArray().Skip(14).ToArray)
  14:  EndIf
  15:  If i > 1 Then
  16:                                text1.Text += Encoding.UTF8.GetString(response)
  17:  EndIf
  18:  EndSub)
  19:  Next

Das CardAddedEvent läuft nicht im Kontext des UI Threads, deswegen Dispatching von Nöten ist. Der DispatcherHelper kommt aus dem Nuget Paket UWPCommunityToolkit.


Windows 10 NFC Proximity

$
0
0

Es gibt in UWP zwei relevante Wege mit einem NFC Device Reader zu sprechen, per SmartCardReader Klasse oder per ProximityDevice. In meinen ersten Versuchen mit einem USB NFC Reader musste ich per SmartCard Reader das Device ansprechen. Das ist zu einem relativ aufwändig und zum anderen kommt es wie es kommen muss. Nach einem Deploy auf mein Trekstore TN154W2 ist die Liste der gefunden Devices natürlich leer.

Bildergebnis für trekstore TN154W2

Also ein neuer Versuch mit dem Proximity Device  Klasse Ansatz. Da ich keinen passenden USB Reader habe, wird mein Lumia 650 als Remote Device per USB  in Visual Studio benutzt. Das ist sehr einfach, schnell und komfortabel zu deployen und debuggen. Wichtig ist das das Windows phone mit aktivierten Entwicklermodus betrieben wird.

image

Im VB.NET Code wird aus den Events für Karte da, Karte weg und Daten eingehend  jeweils eine Methode registriert. Nur die ankommende Message wird auscodiert und die eingehende Daten ausgelesen. NDEF ist ein spezielles Datenformat für NFC, das häufig verwendet wird um die Daten in Blöcken zu organisieren, aber eine gewisse Komplexität in Kommandos und Format aufweist.

   1:  Dim nfcDevice As ProximityDevice
   2:   
   3:  PrivateSub MainPage_Loading(...
   4:          nfcDevice = ProximityDevice.GetDefault()
   5:  If nfcDevice IsNot NothingThen
   6:  AddHandler nfcDevice.DeviceArrived, AddressOf NFCDevideArrived
   7:  AddHandler nfcDevice.DeviceDeparted, AddressOf NFCDeviceDeparted
   8:              nfcDevice.SubscribeForMessage("NDEF", AddressOf messagedReceived)
   9:  EndIf
  10:  End Sub

Da wir uns mit den tiefen von NFC nicht weiter beschäftigen wollen, kommt die NdefLibrary von Andreas Jakl per Nuget im Visual Studio UWP Projekt zum Einsatz. Da in diesem Beispiel nur ein bestimmter Typ von NDEF Daten kann direkt die NdeftextRecord Methode zur Umwandlung in Text verwendet werden. Da NDEF Meldungen auch Url oder App Aktivierung Links enthalten können müsste man dort auf den Typ per If verzweigen. Warum man überhaupt mit foreach Iterieren soll, könnte mit unterschiedlichen Größen der NFC Tags zusammenhängen. Bei den von mir verwendeten Ntag 213 sind 144 Bytes vorhanden, die in beim ersten Durchlauf des Foreach in der txt Variable zugewiesen werden. Da MessageReceived wohl im Background Thread statt findet, muss noch mit dem UI Thread synchronisiert werden. So wird die Textbox letztendlich gefüllt.

 

   1:  PrivateFunction messagedReceived(sender As ProximityDevice, message As ProximityMessage) As Task
   2:  Dim rawMsg = message.Data.ToArray
   3:  Dim ndefmsg = NdefMessage.FromByteArray(rawMsg)
   4:  ForEach record In ndefmsg
   5:  Dim typ = Encoding.UTF8.GetString(record.Type, 0, record.Type.Length)
   6:  Dim txt = New NdefTextRecord(record)
   7:          Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Sub()
   8:                                                                     text1.Text = txt.Text
   9:  EndSub)
  10:  Next
  11:  EndFunction

NFC Card Writer Mifare

$
0
0

Da ich für unsere Events eine neue Feedback Anwendung baue, entstand der Wunsch die NFC Karten zu beschreiben. Dafür kommt wieder der ACR 122 U Reader zum Einsatz wie im Blog Post beschrieben. Auch ein Großteil des Codes wird wieder verwendet. Konkret wird das CardAdded Event des SmartCardReader Objektes verwendet um gleich die Karte bzw den NFC Tag zu beschreiben. Der VB.NET Code ist exakt auf die Mifare UltraLight Tags ausgelegt.

Wie schon im vorigen Artikel beschrieben und per reverse enegineering eruiert, ist der Speicher in 4 Byte größe Blöcke organisiert. Block 8-15 sind reine Daten in die wir Buchstaben als Hex Werte schreiben können.

 image

Da die NDEF Spezifikation recht umfangreich sind, habe ich nur Teile herausgenommen.

Block 7 enthält in 2 Bytes die Sprache (de) und der Rest sind die ersten Daten Bytes.

Block 6 enthält 01 dann die Länge, gefolgt vom Buchstaben T und 02

Block 5 scheint an Stelle 2 einen Abweichenden Wert zu haben. Im NFC Sample haben ich diesen ignoriert.

Um die Aufgabe einfacher zu machen, wurde die Länge auf komplett gelegt, was 34 Bytes entspricht. Warum das ein Hex 25, also 37 Bytes sind, bleibt offen. Es sind immer 34 Zeichen im Notfall mit Spaces aufgefüllt.

 

Letztendlich noch mein etwas wackeliger VB.NET Code um eine NFC Karte im NDEF Format zu beschreiben.

   1:  Private Async Sub CardAdded(sender As SmartCardReader, args As CardAddedEventArgs)
   2:  Dim card = args.SmartCard
   3:          Using connection As SmartCardConnection = Await card.ConnectAsync()
   4:  Dim cardIdentification = New IccDetection(card, connection)
   5:              Await cardIdentification.DetectCardTypeAync()
   6:  Dim mifareULAccess As MifareUltralight.AccessHandler = New MifareUltralight.AccessHandler(connection)
   7:  Dim lang = "de"
   8:  Dim daten = "AAAAAAAAAAAAAAAAAAAAAAA"
   9:  'Block 5 03 ?? d1 01 
  10:  'Block 6 01 Länge T 02
  11:  Dim ib() AsByte = {&H1, &H25, &H54, &H2}
  12:              mifareULAccess.WriteAsync(6, ib)
  13:  Dim b = Encoding.UTF8.GetBytes((lang + daten).PadRight(36)) '34 Nutzlast = 36/9 Blöcke
  14:  For i = 7 To 15
  15:                  mifareULAccess.WriteAsync(i, b.Skip((i - 7) * 4).Take(4).ToArray)
  16:                  Debug.WriteLine(b.Skip((i - 7) * 4).Take(4).ToArray)
  17:              Next

Formulare stylen - gleiche Höhe für Label und Input

$
0
0

Formulare – allgegenwärtige Bestandteile ach so vieler Webseiten. Sie begrüßen uns beim Aufrufen einer Webseite, wenn wir uns einloggen müssen, als Auswahlformulare zwischendrin, und wenn wir etwas bestellen möchten, handelt es sich, ja richtig: um ein Formular. Dann wären da noch Kontaktformulare, Online-Formulare von Ämtern, Formulare für Newsletter… die Liste ist lang.

Für den Webdesigner bedeutet das natürlich vorallem eins: eine weitere Möglichkeit, sich beim Styling auszutoben! (Wer jetzt „Arbeit“ gedacht hat: Ja, auch eine korrekte Antwort.)

 

Es gibt unzählige Möglichkeiten, ein Formular zu stylen, beginnend mit der Entscheidung, wo das Label angeordnet werden soll. Die beiden häufigsten Varianten sind top-aligned und left-aligned Labels.

 

Ein einfaches Formularbeispiel

 

Sehen wir uns ein left-aligned Label anhand eines einfachen Formulars etwas genauer an:




Label- und Input-Text sind scheinbar auf gleicher Höhe, alles scheint seine Ordnung zu haben.

Bei diesem Beispiel wurde noch (fast[1]) kein Styling angewendet.

Spannender wird es, wenn man sich entscheidet, auch dem Label einen Rahmen oder eine Hintergrundfarbe zu geben. Dann fällt nämlich plötzlich auf, was man auf den ersten Blick gar nicht bemerkt: Input und Label befinden sich nicht auf gleicher Höhe.

 

 


Nun sieht man schon recht deutlich, dass sich der Rahmen des Labels und der Rahmen des Input-Feldes nicht auf gleicher Höhe befinden. Außerdem wirkt der Rahmen des Labels dicker als der des Input-Feldes. Und das, obwohl der rote Rahmen nur 1px breit ist und der des Input-Feldes per Default 2px (die Beispiele oben wurden mit Chrome betrachtet, aber in anderen Browsern bietet sich ein ähnlich trauriges Bild). Genauso deutlich fällt dieser Höhenunterschied auf, wenn das Label eine Hintergrundfarbe bekommt.


Das liegt unter anderem daran, dass der border-style in den meisten Browsern per Default auf „inset“ und die border-width auf 2px gesetzt ist. Dieser (Default) border-style:inset des Input-Feldes wird für uns erst sichtbar, wenn wir eine Hintergrundfarbe vergeben:


 

 

Ein erster Schritt ist für uns also, dafür zu sorgen, dass beide Elemente die gleiche border-width und den gleichenborder-style haben.


 




Label und Input-Feld sind jetzt zwar noch nicht gleich hoch, aber immerhin befindet sich der Rahmen jetzt auf der gleichen Grundlinie. Wirft man jetzt wieder einen Blick in die Developer-Ansicht des Browsers, stellt sich heraus, dass die Input-Felder außerdem ein Padding haben und eine andere Schriftart verwenden als die Standard-Schriftart der Seite.

Letzteres klingt nicht besonders spektakulär, allerdings sollte einem bewusst sein, dass die Schriftart Einfluss auf die Schriftgröße hat:

Castellar  Parchment

Diese beiden Schriftarten haben beide denselben Schriftgrad (16px)! Trotzdem ist die Schriftart Castellar beinahe doppelt so hoch wie die Schriftart Parchment.

Für unser Formular bedeuten unterschiedliche Schriftarten wiederum ein Problem auf dem Weg zu Feldern auf gleicher Höhe, denn die Standard-Schriftart für Input-Felder ist eine andere, als die Standard-Schriftart der Seite. Um den Unterschied deutlicher zu machen, einmal mit stark unterschiedlichen Schriftarten:




Auch die Vergabe einer Höhe für Label und Input-Feld bringen die Felder nicht auf gleiche Höhe.

Eine mögliche Lösung ist, für Label und Input-Feld die gleiche Schriftart zu verwenden:

 


 



Mit derselben font-family, font-size, padding und border befinden sich nun sowohl die Felder auf exakt gleicher Höhe, als auch die Schrift darin auf derselben Basislinie (baseline).

 

Eine andere Möglichkeit wäre, den Block-Container, in dem sich Label und Input-Feld befinden (in diesem Beispiel ein <p>), zu einer Flexbox zu machen und die Elemente darin in Zeilen zu organisieren:




  

Wie man sieht, sind die flex-items in Zeilenausrichtung gleich hoch – unabhängig von Rahmen und Schriftart.

Davon ausgehend sind der Fantasie fürs Styling keine Grenzen gesetzt.

Ein Beispiel für ein einfaches Formular auf der Basis von left-aligned Labels und Input-Feldern auf der gleichen Höhe:

 

 


Die „Unterstreichung“ ist keine text-decoration, sondern ein border-bottom für das Label mit border-style:solid und ein border-bottom für das Input-Feld mit border-style:dashed. Dank gleicher font-family, font-size, padding und border-width liegen diese jetzt auch auf der exakt gleichen Höhe.

Den Code für dieses simple Formular könnt Ihr Euch hier (auf Codepen) ansehen.

 

 

 



[1] Label und Input-Feld befinden sich innerhalb eines <p>-Elements und das Label wird als display:inline-block mit einer Breite von 100px dargestellt.

Temporary Post Used For Theme Detection (aebee881-f646-4c6d-a9ff-6c29a4dfd0a3 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)

$
0
0

This is a temporary post that was not deleted. Please delete this manually. (15b87a3f-4a4a-4501-8fc6-28f8f8dad234 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)

Windows 10 Paketmanager: Programmpakete installieren per PowerShell

$
0
0

Sucht man sich Programme aus dem Internet, stößt man immer wieder auf ein paar Herausforderungen. So ist eine davon die Toolbar, welche bei manchen Programmen mit installiert werden soll oder man kann sich nicht sicher sein, ob das gesuchte Programm virenbefreit und in der passenden Version zur Verfügung steht.

In Windows 10 gibt es die Möglichkeit mit dem Paketmanager per PowerShell Programme in Form von Paketen schnell und einfach zu installieren. In diesem Zusammenhang arbeitet Microsoft mit dem Paketprovider Chocolatey zusammen. Diese Stellen derzeit rund 1800 Installationspakete für die Installation per PowerShell kostenlos zur Verfügung.

Im folgenden Beispiel, zeige ich euch die Installation von Notepad++ mit PowerShell.

Zuerst muss man die Ausführungsrichtlinien für Skripte anpassen, damit PowerShell Skripte aus dem Internet verwenden kann. Hierzu öffnet man die PowerShell mit Administratorrechten und gibt folgenden Befehl ein: „Set-ExecutionPolicy Unrestricted“

clip_image002

Die Frage, ob man die Ausführungsrichtlinie wirklich ändern möchte, beantwortet man mit „J“.

Jetzt ist Windows bereit alle Konfigurationsdateien zu laden und alle Skripte auszuführen. Bei unsignierten Skripten aus dem Internet gibt es vor der Ausführung eine Sicherheitsfrage, die man erst bestätigen muss.

Als Nächstes wird mit dem Befehl „ Get-PackageProvider Chocolatey“ der Paketprovider hinzugefügt, in diesem Beispiel ist dies Chocolatey.

image

Vor der Installation von Chocolatey überprüft das System, ob das sogenannte „Nuget“ installiert ist. Falls es nicht vorhanden sein sollte, muss auch dieses erst heruntergeladen und installiert werden, was einfach durch ein Bestätigen mit „J“ durchgeführt werden kann. „Nuget“ kommt aus Visual Studios in den immer nur sogenannte Nuget-Pakete installiert werden.

Nachdem beides installiert worden ist, kann man sich die verschiedenen Pakete von Chocolatey mit dem Befehl „Find-Package * “ anzeigen lassen. In diesem Beispiel werden mit „Find-Package Notepad“ alle Pakte mit Notepad im Namen angezeigt.

clip_image006

Die einzelnen Pakete werden über den Befehl „Install-Package <Paketname>“ installiert. Wenn im Befehl nichts anders angegeben ist, lädt der Paketmanager immer die aktuellste Version des Paketes runter und installiert dies im Standardpfad. Die Änderung des Pfades ist leider nicht möglich.

In diesem Fall wird per „Install-Package Notepadplusplus“ das Programm Notepad++ nach einer vorherigen Bestätigung heruntergeladen und installiert.

clip_image008

Im Startmenü unteranderem unter Zuletzt hinzugefügt taucht jetzt Notepad++ auf und kann wie andere Programme per klicken gestartet werden:

clip_image009

So einfach und schnell lassen sich Programme Installieren ohne Toolbar oder sonstige unerwünschte Zusatzsoftware.

Weitere Möglichkeiten zu Windows 10 erfahrt ihr in unserem Kurs Windows 10 – Jumpstart.

Eine genaue Agenda und Buchungszeiträume dazu findet ihr hier.

Viewing all 1198 articles
Browse latest View live