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

Windows Server Insider Preview

$
0
0

Microsoft veröffentlicht eine neue Windows Server Insider Preview und von mir, bekommt ihr die wichtigsten Neuerungen zusammengefasst. Microsoft wird seinen Server in Zukunft in zwei Update Zyklen anbieten. Das eine ist der “Semi-annual Channel” welcher zwei mal im Jahr mit neue Funktionen versorgt wird. Dieser Channel ist für den Windows Server Core und den NanoServer gedacht und steht auch nur zur Verfügung wenn Volumenlizenzierung und Software Assurance genutzt wird. Der Server Core wird zusätzlich auch mit der “Desktop Experience” wie bisher gewohnt vermutlich alle vier Jahre im LTSB (Long Time Service Branch) mit neuen Funktionen versorgt werden. Genaueres dazu könnt ihr bei meinem Kollegen im Blogartikel nachlesen.

Microsoft hat bei den Neuerungen für den Windows Server Insider Preview Build 16237, welcher sowohl für Windows Insider als aus auch für das Windows Insider for Business Programm zur Verfügung steht, seinen Augenmerk auf die Virtualisierung, Container und SDD (Software defined Datacenter) gelegt. Durch einige dieser Neuerungen haben sie es geschafft das Windows Server Core Container OS Image um 20 % zu schrumpfen und das NanoServer Image um sage und schreibe 70 %.

In Hyper-V kann jetzt mit sogenannten “Virtualized Persistent Memory” (vPMEM) gearbeitet werden, welcher ähnlich einer VHD Datei (.vhdpmem) auf Direct Access Volumes bereit gestellt wird. Zum erstellen und verwalten des Virtuellen Persistenten Speichers steht momentan nur die PowerShell zur Verfügung. Mit dem neu hinzugekommen Befehl Set-VM <VMName> –BatteryPasstroughEnabled ($true, $false) lässt sich jetzt konfigurieren ob der Batteriestand des Host Betriebssystems an die VM durchgereich werden soll. Diese Funktion ist meiner Meinung aber nur für Notebooks geeignet, und steht Momentan nur im Server Core zur Verfügung. Das heißt man muss im Umkehrschluss auf dem Notebook Windows Server Core Insider installieren, was meiner Meinung nach wieder nur für Entwicklungssysteme wirklich Sinn macht.

Die Neueinführung Nano Server ist jetzt nur noch für Container verfügbar und extra dafür optimiert worden. Dafür wurden Funktionen wie WMI, PowerShell, .NET Core und den Servicing Stack. Was unteranderem die um 70 % reduzierte Image Größe erklärt.

Genauere Informationen findet ihr im offiziellen Windows Blog. Wenn Ihr selbst mal handanlegen wollt braucht ihr einen privaten oder geschäftlichen Microsoft Account welcher mit ein paar wenigen Klicks im Insider Programm registriert werden muss. Wenn ihr bereits registriert seit könnt ihr über den folgenden Link die ungefähr 2,68 GB große Datei runterladen.

https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewserver

Für die Aktivierung stellt Microsoft für den Zeitraum vor dem Release, unbegrenzte Aktivierungsschlüssel zur Verfügung.

  • Server Datacenter Core: B69WH-PRNHK-BXVK3-P9XF7-XD84W
  • Server Standard Core: V6N4W-86M3X-J77X3-JF6XW-D9PRV

Welche ihr allerdings auch auf der oben verlinkten MicrosoftBlog Seite entnehmen könnt. Diesen Build könnt Ihr bis zum 04.12.2017 testen. Danach gilt dieser Build als abgelaufen.


XML-Export leicht gemacht–Teil 2

$
0
0

Wie wir im vorigen Artikel gesehen haben, ist es nicht mit Bordmitteln problemlos möglich, einen sauberen Export relationaler Datasets in eine gültige XML-Syntax durchzuführen.
Der SQL-Server erlaubt es uns allerdings Binärobjekte direkt aus einem SQL-Statement zu erzeugen, die XML-Codierte Inhalte haben.

   1:use TSQL2012
   2:go
   3:declare @result xml
   4:set @result = (select
   5:   [Customer].custid as [custid],
   6:   [Customer].companyname as [companyname],
   7:   [Order].orderid as [orderid],
   8:   [Order].orderdate as [orderdate],
   9:   [OrderPosition].unitprice as [unitprice],
  10:   [OrderPosition].qty as [quantity],
  11:   ([OrderPosition].unitprice * [OrderPosition].qty * (1 - [OrderPosition].discount)) as [total]
  12:from Sales.Customers as [Customer]
  13:innerjoin Sales.Orders as [Order]
  14:on[Customer].custid = [Order].custid
  15:innerjoin sales.OrderDetails as [OrderPosition]
  16:on [Order].orderid = [OrderPosition].orderid
  17:orderby [Customer].custid, [Order].orderid
  18:for xml auto
  19: , root ('CustomerOrders')
  20: , elements);
  21:selectcast(@resultas varbinary(max))

Diese Binärobjekte könen dann als Zeileninhalt einer Spalte vom Typ varbinary(max) in der Datenbank gespeichert werden. Hierbei geht die keinerlei Infomation verloren und es werden auch keine zusätzliche Sonder- oder Steuerzeichen eingefügt.
An genau dieser Stelle können wir mit der SQL-Server Version 2012 einhaken und mittels einer neuen Filestreamfunktionalität einen kleinen, schmutzigen Workaround bauen.
Hierzu ist allerdings erst ein wenig administrative Arbeit am SQL-Server nötig.

Wir müssen:

1. Auf Dienstebene das Feature File-Streaming aktivieren

2. Der SQL-Server-Instanz beibringen, das dies zu nutzen ist und

3. Eine neue Datenbank mit Filestreaming-Repistory erzeugen oder einer bestehenden Datenbank ein Solches hinzufügen

Für die Schritte 1 und 2 sind sysadmin-Rechte vonnöten, während Schritt mit dbcreator- bzw. db_owner-Rechten ausgeführt werden kann.

Schritt 1 ist noch am wenigsten aufwendig: hierzu öffnen wir einfach den
SQL-Server-Konfigurationsmanager, wählen im Knoten SQL-Server-Dienste den SQL-Server-Eintrag unserer Instanz und aktivieren auf der Registerkarte FileStream die drei Checkboxen.
Im zuge dessen wird eine Windows-Dateifreigabe erzeugt, die den Namen der SQL-Server-Instanz trägt und als Schnittstelle zwischen dem SMB-Protokoll für die Datenübertragung über das Netzwerk und dem SQL-Server selbst fungiert. Nur über diesen Weg können wir später auf unsere erstellten XML-Dateien zugreifen.
fs1
fs2
fs3

Für die Schritte 2 und 3 verwenden wir das SQL-Server-Management-Studio. Der 2. Schritt besteht darin, in der Instanzkonfiguration die Verwendung von FileStream zu ermöglichen. Auch hier ist der Ablauf ziemlich simpel: Rechtsklick auf den Instanznamen à Eigenschaften und dann auf der Seite „Erweitert“ im Knoten „FileStream“ den Wert für „FILESTREAM-Zugriffsebene“ auf „Vollzugriff aktiviert“ setzen.
fs4
fs5

Sollte das Filestream-Feature bereits während des SQL-Server-Setups aktiviert worden sein, sind die Schritte 1 und 2 unnötig.

Schritt 3 besteht aus 2 Alternativen: a) wir erstellen eine neue Datenbank oder b) wir fügen einer bestehenden Datenbank ein Filestream Repository hinzu.
Zu Demonstrationzwecken verwenden wir in beiden Fällen die Datenbank FSDemo.
Varinte a) funktioniert über den Datenbank-Erstellen-Dialog in dem wir (in dieser Reihenfolge) erst eine Filestream-Dateigruppe erstellen und danach eine Datebankdatei zu dieser Dateigruppe hinzufügen. Hierzu verwenden wir die Seite Dateigruppen und erstellen im Bereich FileStream eine neue Dateigruppe mit dem Namen fgFileStream. Als nächstes erzeugen wir auf der Seite Allgemein eine weitere Datei namens fsRepository, ändern ihren Typ auf Filestream und sehen, das die Dateigruppenzuordung autmatisch auf fgFileStream gesetzt wird.
fs6
fs7
fs8

Nun muss in den Eigenschaften der neuen Datenbank die Nutzung von FileStream konfiguriert werden. Auf der Seite Optionen setzt man im Knoten Filesteam die Werte für
„Filestream-Verzeichnisname“ und „Nicht transaktionsgebundener Filesteam-Zugriff“ auf den Datenbanknamen bzw. „Full“.
fs9

Natürlich kann auch hier ein TSQL-Statement als Alternative eingesetzt werden:

   1:USE [master]
   2:GO
   3:CREATEDATABASE [FSDemo]
   4:  CONTAINMENT = NONE
   5:ONPRIMARY
   6: ( NAME = N'FSDemo', FILENAME = N'C:\_SQLDB\MSSQL13.MSSQLSERVER\MSSQL\DATA\FSDemo.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB ), 
   7:  FILEGROUP [fgFileStream] CONTAINS FILESTREAM 
   8: ( NAME = N'fsRepository', FILENAME = N'C:\_SQLDB\MSSQL13.MSSQLSERVER\MSSQL\DATA\fsRepository' )
   9:  LOG ON
  10: ( NAME = N'FSDemo_log', FILENAME = N'C:\_SQLDB\MSSQL13.MSSQLSERVER\MSSQL\DATA\FSDemo_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
  11:GO
  12:ALTERDATABASE [FSDemo] SET FILESTREAM( NON_TRANSACTED_ACCESS = FULL, DIRECTORY_NAME = N'FSDemo' ) WITH NO_WAIT
  13:GO
  14:USE [FSDemo]
  15:GO
  16:IFNOTEXISTS (SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N'PRIMARY') ALTERDATABASE [FSDemo] MODIFY FILEGROUP [PRIMARY] DEFAULT
  17:GO

Die zweite Möglichkeit, Variante b) verwendet den Eigenschaften-Dialog der Datenbank FSDemo um die Filestream-Dateigruppe und das Filestream-Repository zu erzeugen. Die Reihenfolge der Abzuarbeitenden Schritte ist identisch mit Variante a). Zuerst erstellen wir auf der Seite Dateigruppen im Bereich FileStream eine neue Dateigruppe mit dem Namen fgFileStream. Danach erzeugen wir auf der Seite Dateien eine weitere Datei namens fsRepository, ändern ihren Typ auf Filestream und sehen, das die Dateigruppenzuordung autmatisch auf fgFileStream gesetzt wird.
fs10
fs11

Zuletzt wird auch hier die Nutzung von FileStream konfiguriert.
Auf der Seite Optionen setzt man im Knoten Filestream die Werte für „Filestream-Verzeichnisname“ und „Nicht transaktionsgebundener Filesteam-Zugriff“ auf den Namen der Datenbank bzw. „Full“.
fs12

Analog zu Variante a) kann stattdessen auch ein TSQL-Statement zum Einsatz kommen:

   1:USE [master]
   2:GO
   3:ALTERDATABASE [FSDemo] SET FILESTREAM( NON_TRANSACTED_ACCESS = FULL, DIRECTORY_NAME = N'FSDemo' ) WITH NO_WAIT
   4:GO
   5:ALTERDATABASE [FSDemo] ADD FILEGROUP [fgFileStream] CONTAINS FILESTREAM 
   6:GO
   7:ALTERDATABASE [FSDemo] ADDFILE ( NAME = N'fsRepository', FILENAME = N'C:\_SQLDB\MSSQL13.MSSQLSERVER\MSSQL\DATA\fsRepository' ) TO FILEGROUP [fgFileStream]
   8:GO

Wir können nun im Standardpfad für Datenbankdateien ein Verzeichnis mit dem Namen „fsRepository“ sehen. Hier werden de Binärobjekte, die in FileStream-Spalten einer oder mehrerer Tabellen geschrieben werden, abgelegt.
Das Speicherziel, in das unsere XML-Dateien geschrieben werden sollen, erzeugen wir jetzt in der Datenbank FSDemo. Dieses Speicherziel wird als sogenannte Dateitabelle erzeugt, eine FilestreamFunktion, die erst seit der SQL-Server-Version 2012 verfügbar ist und es erlaubt, mittels der Filestream-Freigabe, die wir zu Beginn dieses Artikels erzeugten, auf den Inhalt des Filesteam-Repositorys zuzugreifen.

Die Dateitabelle, die wir erzeugen, wird ExportLibrary heissen und kann nur mittels eines TSQL-Statements generiert werden:

   1:USE FSDemo
   2:GO
   3:CREATETABLE ExportLibrary AS FILETABLE
   4:WITH
   5:   (
   6:     FILETABLE_DIRECTORY = 'ExportLibrary',
   7:     FILETABLE_COLLATE_FILENAME = database_default
   8:   )
   9:GO

Die Optionen, die zusätzlich konfiguriert werden, erzeugen innerhalb der Filstream-Freigabe einen Unterordner für die Dateitabelle mit dem angegebenen Namen und setzen die Tabellen spezifische Sortierung auf den Datenbank-Standard fest.
Die aus unserer vorbereitenden Arbeit restultierenden Ordnerstrukturen werden nachfolgen dargestellt:
fs13

Links sehen wir die Struktur der FileStream-Freigabe und rechts das physische Filestream-Repository, zu beachten sind hier die beiden Verzeichnisse, die GUIDs als Namen tragen: dies sind, von oben nach unten ,die ObjectID der Tabelle bzw. der Binärspalte „file_stream“ innerhalb der Tabelle.
Für unsere Zwecke ist das physische Filestream-Repository vollkommen uninteressant, weshalb dieses keine weitere Erwähnung finden wird.

Nachdem wir jetzt ein Speicherziel erzeugt haben, das es uns erlaubt Binärdateien direkt aus einem TSQL-Statement zu generieren, können wir mit folgendem Statement eine Datei namens XMLExport4.xml in der Tabelle FSDemo.dbo.ExportLibrary erstellen und sie anschließend über die Filestream-Freigabe auf den Desktop kopieren und anzeigen lassen:

   1:use TSQL2012
   2:go
   3:declare @result xml
   4:set @result = (select
   5:   [Customer].custid as [custid],
   6:   [Customer].companyname as [companyname],
   7:   [Order].orderid as [orderid],
   8:   [Order].orderdate as [orderdate],
   9:   [OrderPosition].unitprice as [unitprice],
  10:   [OrderPosition].qty as [quantity],
  11:   ([OrderPosition].unitprice * [OrderPosition].qty * (1 - [OrderPosition].discount)) as [total]
  12:from Sales.Customers as [Customer]
  13:innerjoin Sales.Orders as [Order]
  14:on[Customer].custid = [Order].custid
  15:innerjoin sales.OrderDetails as [OrderPosition]
  16:on [Order].orderid = [OrderPosition].orderid
  17:orderby [Customer].custid, [Order].orderid
  18:for xml auto
  19: , root ('CustomerOrders')
  20: , elements);
  21: insert into FSDemo.dbo.ExportLibrary (file_stream, name) values (cast(@resultas varbinary(max)), 'XMLExport4.xml')
  22: go

Das Ergebnis ist eine vollständige, gültige XML-Datei, die sogar in einem Standardpfad abgelegt wird und von automatisiert ausgeführten Parsern immer unter diesem Pfad erreicht werden kann.
fs14

Die Ergebnis-Datei wird allerdings ohne irgenwelche XML-Formatinformationen, sondern als eine fortlaufende Zeile binär gespeichert. Wenn auf Lesbarkeit ausserhalb interpretierender Programme wie Internet-Explorer, Word, etc. Wert gelegt wird, muss eine nachträgliche Formatierung durchgeführt werden.

Wir sehen also, dass mit dem SQL-Server 2012 die Möglichkeit zum direkten Export relationaler Datasets in XML-Dateien mitgleifert wird. Diese Variante ist allerding recht gut versteckt und erfordert Eingriffe in die Konfiguration der SQL-Server-Instanz sowie der Datenbank. Dieser Mehraufwand wird allerings durch die Vorteile dieser Vorgehensweise wie vollständige Automatisierbarkeit oder feste Zielpfade für den Export mehr als aufgewogen.
Hierdurch wird die Integration des MS-SQL-Server mit anderen Systemen vereinfacht und dieses Vorgehen kann auch verwendet werden, um die mit SQL 2016 eingeführte native Unterstützung für JSON zu verwenden und direkte Exporte in JSON-Dateien durch zu führen.

OCR mit Windows 10 und Webcam

$
0
0

Das typische Windows 10 Gerät besitzt eine Kamera. Mit ein wenig net Code wird so aus einem mobile phone oder Desktop PC ein  Scanner. Das folgende VB.net Beispiel, dient zur Erkennung von IP Adresse. Der Benutzer hält einen Ausdruck vor die Kamera und die UWP App erkennt die gültige IP Adresse.

READIP

Dazu benötigen wir folgende Dinge: eine Windows 10 UWP Anwendung. Um den Zugriff auf Webcam zu erlauben muss, im Manifest des Visual Studio Projektes, Mikrofon und Webcam als Funktion aktiviert werden. Weiters benötigen wir eine XAML Page mit einem CaptureElement und einem Image Element. Mit einem DispatcherTimer lesen wir alle 100 Millisekunden das Bild von der Webcam aus. Der Einfachheit halber wird die erste Webcam verwendet, das als Device Information vom Typ Video Capture zurück geliefert wird. Das MediaCapture Objekt, liefert den Video Stream zur Webcam und wird dem  Preview Control als Quelle zu gewesen.

   1:  Private MediaCapture1 As MediaCapture
   2:  Dim dp AsNew DispatcherTimer
   3:  Private Async Function MainPage_LoadedAsync(sender AsObject, 
e As RoutedEventArgs) As Task HandlesMe.Loaded
   4:          dp.Interval = New TimeSpan(0, 0, 0, 0, 100)
   5:  AddHandler dp.Tick, AddressOf ScanIPAsync
   6:          dp.Start()
   7:   
   8:  If MediaCapture1 IsNothingThen
   9:  Dim allVideoDevices = Await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture)
  10:   
  11:  Dim cameraDevice =
  12:              allVideoDevices.FirstOrDefault()
  13:  If cameraDevice IsNothingThenReturn
  14:   
  15:              MediaCapture1 = New MediaCapture()
  16:   
  17:  Dim settings = New MediaCaptureInitializationSettings With
  18:              {.VideoDeviceId = cameraDevice.Id}
  19:   
  20:  Try
  21:                  Await MediaCapture1.InitializeAsync(settings)
  22:   
  23:  Catch ex As Exception
  24:  EndTry
  25:              PreviewControl.Source = MediaCapture1
  26:              Await MediaCapture1.StartPreviewAsync()
  27:   
  28:   
  29:  EndIf
  30:  End Function

 

Das CaptureElement zeigt sozusagen das Kontrollbild live. Alle 100 Millisekunden wird die Methode ScanIPasync aufgerufen. Darin wird aus dem Video auf das aktuelle Bild zugegriffen und dem Image UI Element zugewiesen. Das ist dann das Standbild, der snapshot.  Das so erzeugte bitmap wird der OCR Engine übergeben. Diese analysiert auf einen enthalten Text. Mit Hilfe der Funktion IPAdress.Parse wird der Text geprüft ob dieser eine gültige IP Adresse darstellt.

   1:  Private Async Function ScanIPAsync(sender AsObject, e AsObject) As Task
   2:  Dim pp As VideoEncodingProperties = 
MediaCapture1.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview)
   3:   
   4:  Dim videoFrame = New VideoFrame(Windows.Graphics.Imaging.BitmapPixelFormat.Bgra8,
   5:                                          pp.Width, pp.Height)
   6:   
   7:          Using currentFrame = Await MediaCapture1.GetPreviewFrameAsync(videoFrame)
   8:   
   9:  Dim ocrLanguage = New Language("en")
  10:  Dim oe As OcrEngine = OcrEngine.TryCreateFromLanguage(ocrLanguage)
  11:   
  12:  Dim bitmap = currentFrame.SoftwareBitmap
  13:  Dim imgSource = New WriteableBitmap(bitmap.PixelWidth, bitmap.PixelHeight)
  14:              bitmap.CopyToBuffer(imgSource.PixelBuffer)
  15:   
  16:  Dim ocrResult = Await oe.RecognizeAsync(bitmap)
  17:   
  18:  Dim ip = IPAddress.Parse(ocrResult.Text)
  19:  If ip IsNot NothingThen
  20:                  dp.Stop()
  21:                  PreviewImage.Source = imgSource
  22:   
  23:  Dim msg = New MessageDialog("Hab Ip:" + ip.ToString)
  24:                  msg.ShowAsync()
  25:  EndIf
  26:  End Using

 

Ich bin immer wieder begeistert, was in native Apps alles drin steckt. Die IP Adress Erkennung werde ich später für das Pairing von Devices nutzen.

https://github.com/hannespreishuber/readIp Source Code auf Github

Fall Creators Update naht ohne Klassiker

$
0
0

Microsoft veröffentlicht immer mehr Informationen zum “Fall Creators Update” und ich werde die wichtigsten Informationen für euch zusammenfassen.

Zu aller erst bitte ich um eine kurze Trauerminute da uns ein lieb gewonnener Klassiker welcher uns seit Windows 95 begleitet aus dem Betriebssystem verschwindet und zwar MS Paint. MS Paint war lange die erste Wahl wenn es darum ging Screenshots/ Bilder oder Skizzen zu speichern, obwohl es eigentlich dafür praktischere Tools gab. Microsoft setzt hier voll auf die neue Version Paint 3D welche auch den 3D Builder ersetzen soll. Anstatt des 3D Builders soll wie schon erwähnt Paint 3D und Print3D verwendet werden. Nachdem viele User jedoch sehr emotional reagierten, wird Paint über den Store wieder zur Verfügung gestellt und integriert sich dann in Paint 3D.

Weitere Anwendungen oder Funktionalitäten die verschwinden ist unteranderem Outlook Express, die “Reader App”, welche in Microsoft Edge integriert wurde. Und leider die System Image Backup Solution (SIB), welche die OnBoard Funktionalität hatte System Images zu erstellen. Für die meisten dürfte als Ersatz der Dateiversionsverlauf reichen, welcher in festgelegten Abständen Kopien von geänderten Dateien weg kopiert.

Microsoft versucht sein System immer weiter von Altlasten zu befreien um schlanker und agiler zu werden. Was sich z.B. durch die Entfernung von zwei weiteren Funktionalitäten erkennen lässt. Die Windows PowerShell 2.0 Engine und die IIS 6 Management Kompatibilität wurde ebenfalls auf veraltet gesetzt und wird wahrscheinlich in nächster Zeit aus dem System verschwinden. Welche Systembestandteile noch verschwinden könnt ihr hier nachlesen:

https://support.microsoft.com/en-us/help/4034825/features-that-are-removed-or-deprecated-in-windows-10-fall-creators-up

Aber jetzt erstmal zu den Neuerungen. Die Cloud SSPR (Cloud Self Service Password Reset) welche bisher nur im Azure AD Premium beinhaltet war und Helpdesk bzw. IT Abteilungen entlastet, dadurch das die User ihre Kennwörter selbst zurücksetzen können, wird jetzt in die normalen Windows Systeme integriert. Wenn ein Azure AD Account oder ein Microsoft Account verwendet wird besteht jetzt die Möglichkeit über die Links “Reset Password” oder “Reset Pin” bei bestehender Internetverbindung diese zurück setzen in dem man den folgenden Dialog folgt und richtig beantwortet.

Eine weitere Neuerung die uns im nächsten Build erwartet sind Neuerungen im Taskmanager. So werden ab dem Update im Performance / Leistung Tab zusätzliche die vorhandenen Grafikkarten mit eingeblendet sowie weitere hilfreiche Informationen wie Auslastung oder GPU Memory. Des Weiteren werden die Microsoft Edge Prozesse nun gruppiert und die einzelnen Prozesse werden mit Aufgaben bzw. Sinn bezogenen Namen betitelt.

Auch die Übermittlungsoptimierung welche für den Download und auch optionalen Upload von Updates zuständig ist wird mit neuen Funktionen und Einstellungen versehen. So lassen sich wie z.B. in den folgenden Screenshots sichtbar ist dann Statistiken einsehen an denen ersichtlich wird woher die Updates geladen werden oder an wen  (lokales Netzwerk / Internet) Updates bereit gestellt werden. image

Wer wie ich mit einer sehr reduzierten Bandbreite leben muss (ISDN oder 384 kbit[und ja ISDN gibt es nochWinking smile ]) hat vermutlich festgestellt das das runterladen von Updates eine Internetznutzung des Gerätes oft nur noch sehr schwer Möglich macht aufgrund des gefühlt relativ hoch priorisierten Update Downloads. Ab jetzt kann man sich damit behelfen indem sich die Download und Upload Bandbreite Prozentual einschränken lässt, sowie eine monatliche Obergrenze für Uploads. Die Einstellungen für das hochladen von Updates bezieht sich allerdings nur  den Upload ins Internet und nicht ins lokale Netz.

image

Das Subsystem für Linux ist endlich soweit fertig das sich jetzt Ubuntu aus dem Store heraus installieren lässt. Nach der Installation aus dem Store ist der erste Teil der Installation abgeschlossen, der zweite Teil der Installation muss in einer Kommandozeile mit dem Befehl “ubuntu” angestoßen werde. Ist diese Installation fertig, frägt das Subsystem noch nach einem Benutzernamen und einem sudo Kennwort. Ist das erledigt lässt sich das Subsystem verwenden um z.B. Linux Software zu installieren. Dazu aber mehr in einem anderen Blogartikel.

Da dies nur ein Auszug der Änderungen war verlinke ich euch hier den Microsoft Blog mit den allen aufgeführten Änderungen. Sobald diese Version veröffentlicht wird, werden wir unseren Windows 10 Kurs mit dieser Version ausführen auch gerne innerhalb des Kurses gerne auf Neuerungen wie z.B. das Subsystem für Windows genauer eingehen.

Windows Boot-Manager: Betriebssysteme hinzufügen und entfernen

$
0
0

Seit Windows 8 kommt das Betriebssystem mit einem grafischen Bootmanager daher. Dieser wird aber erst sichtbar, wenn mindestens ein zweites Betriebssystem auf dem Rechner installiert wurde. In der Regel ist kein Eingriff in dem Bootmanager nötig. Aber spätestens dann, wenn das zweite Betriebssystem im Bootmanager fehlt oder das Windows nicht mehr startet, muss ein Eingriff vorgenommen werden.
Microsoft bringt seit Windows Vista das Befehlszeilen-Tool bcdedit.exe zum manuellen Bearbeiten des Boot-Managers mit.

Zum Beheben von Startschwierigkeiten, oder das automatische Hinzufügen von Einträgen in den Boot-Manager, eignet sich das Tool bootrec.exe. Dieses Tool ist im Windows Reparaturmodus zu finden (Dazu später mehr).

Ziel in diesem Beispiel ist es, ein zweites Windows im Boot-Manager zu hinterlegen, damit später ausgewählt werden kann, welches Betriebssystem gebootet werden soll.

Hierzu benutze ich eine Virtuelle Maschine, die mit Hyper-V auf einem Windows 10 Laptop gehostet wurde. Auf der VM ist Windows 10 installiert. Auf einer zweiten virtuellen Festplatte ist zwar Windows 8.1 installiert, aber nicht im Boot-Manager von Windows 10 hinterlegt. Windows 8.1 soll dort nachträglich hinzugefügt werden.

Erster Umgang mit bcdedit:
Um das Tool bcdedit.exe nutzen zu können, muss eine Eingabeaufforderung mit Administratorrechten gestartet werden. Danach im Kommandozeilenfenster einfach bcdedit eingeben. Nun werden alle Einträge angezeigt, die im Boot-Manager hinterlegt sind. Dabei zeigt der Bezeichner “{current}” auf das aktuell laufende Betriebssystem.

BCD1


Sichern und Wiederherstellen:
Wenn Daten im Boot-Manager geändert werden, sollte vorher immer eine Datensicherung des aktuellen Boot-Managers gemacht werden:

Bcdedit /export [Dateipfad\Dateiname]    


Das Backup kann auch mithilfe des Windows Reparaturmodus wiederhergestellt werden, falls das System gar nicht mehr startet:

Bcdedit /import [Dateipfad\Dateiname]    


Windows Reparaturmodus und bootrec:
Nun wird zum automatischen Erstellen des Boot-Manager Eintrages für Windows 8.1 das Befehlszeilentool bootrec.exe benötigt. Dazu muss das Betriebssystem in den Reparaturmodus gestartet werden. Unter Windows 10 geht man dazu unten links auf den Start Button -> Ein/Aus Symbol -> SHIFT-Taste gedrückt halten und auf „Neu starten“ klicken.
Alternativ erreicht man diesen Punkt auch, wenn das Betriebssystem entweder einige Male nicht richtig startet, oder wenn kurz bevor der Bootscreen erscheint (Achtung: Sehr kurzer Zeitraum) die Taste F8 gedrückt wird.

Restart

Im Reparaturmodus angelangt navigiert man dort zu Problembehandlung -> Erweiterte Optionen -> Eingabeaufforderung. Nach dem Einloggen des Benutzers (Administrator-Konto) erscheint die Eingabeaufforderung des Reparaturmodus.

Nun müssen die Festplatten nach Betriebssystemen gescannt werden, die nicht im Boot-Manager eingetragen sind. Diese lassen sich auch sofort in den Boot-Manager eintragen:

bootrec /rebuildbcd   


Danach lässt sich im gleichen Konsolenfenster mit bcdedit überprüfen, ob die neuen Einträge auch wirklich geschrieben wurden. Es wurde ein neuer Eintrag mit der description „Windows 8.1 Einterprise“ hinzugefügt.

BCD-Neu


Nach Neustart der VM wird der grafische Boot-Manager angezeigt. Man muss sich nun für den Start eines Betriebssystems entscheiden.

Boot2

Weitere bcdedit Kommandos:

bcdedit /delete [Bezeichner]    

Löscht den bezeichneten Eintrag aus dem Boot-Manager

bcdedit /set [Bezeichner] description „[Beschreibung]“    

Ändert die Beschreibung des bezeichneten Eintrags

bcdedit /displayorder [Bezeichner1] [Bezeichner2]    

Ändert die Reihenfolge der Einträge

bcdedit /displayorder [Bezeichner] /addfirst    

Den bezeichneten Eintrag mit /addfirst nach ganz oben oder mit /addlast nach ganz unten der Liste setzen

Weitere bootrec Kommandos:

bootrec /scanos    

Installierte Betriebssysteme anzeigen lassen, die nicht im Boot-Manager eingetragen sind

bootrec /fixmbr    

Schreibt den Master Boot Record erneut auf die Festplatte

bootrec /fixboot    

Stellt den Bootloader wieder her

EDGE Browser geheime Webcam

$
0
0

Zugegebenermaßen ist das eine Clickbait Headline. Wenn Du schon mal da bist will ich Dir ein cooles Feature von UWP zeigen das auch im EDGE Browser genutzt werden kann. Mit dem FileopenPicker Contract kann man (seit Windows 8) spezielle Apps als Filesource herhalten lassen, unter anderem auch die Webcam. Aber erst mal der Anwendungsfall.

Ich bin eitel und wäre gerne wieder 27. Microsoft bietet seit einer Weile eine Website how-old an mit der man das Alter von Personen schätzen lassen kann. Dies war einer der ersten Showcases für den Azure MachineLearning Dienst. Das Teil ist in der Regel ziemlich gut, bis auf den einen Morgen im Büro

how-old

Geil, nicht!? Fast 27!

Wie kommt nun das Foto in die Website? Durch einen üblichen Upload Dialog. Also Datei öffnen, bestes Bild aussuchen und OK. Wenn man kein aktuelles parat hat, erst Webcam an und… #boring.

Mit UWP geht beides auf einmal. Aus dem Datei öffnen Dialog heraus lassen sich alle UWP Apps nutzen, die den FileOpenPicker Contract implementiert haben. Die Kamera App ist eine davon. Dazu später ein wenig mehr.

image

Grundlegend bezeichne ich das Verteilen von Verantwortungen auf verschiedene Apps als Microapp Architektur. Etwas was sich in UWP vielfach konzeptionell findet.

Wenn man das gleiche auf einem Windows 10 Phone (ja und nur dort!) macht, erscheint ein Zwischendialog der die verfügbaren Apps mit passenden Contract einblendet.

fileopencontract

In beiden Fällen sieht man die Sample UPW App “Fle Picker Contract C#” zur Auswahl. Warum diese und andere Apps dort auftauchen, findet sich im appxManifest der jeweiligen App.

In Visual Studio wird die Datei Package.AppxManifest eines UWP Projektes geöffnet. Im Reiter Declarations/ Deklarationen wird definiert für welche Dateiendungen diese App als Dateiquelle herhalten soll.

image

In einem weiteren Blog Artikel werde ich dann zeigen wie man auch Daten austauscht.

PS: Chrome, Mozilla und co können das nicht, also gar nicht erst probieren Smiley

Neue benutzerdefinierte Visualisierungen in Power BI

$
0
0

Visualisierungen spielen für die Auswertung der Daten eine erhebliche Rolle. Auf den ersten Blick bietet Power BI zwar eine solide Grundlage an Visualisierungen, um Daten den letzten aussagekräftigen Schliff und Look zu verpassen, und doch sind es auf den zweiten Blick nur eher die klassischen Diagramme und Darstellungen.

Über das Menü mit den drei Punkten hinter der letzten Darstellung gelangten wir in der vorletzten Version von Power BI zur Menüauswahl „Benutzerdefiniertes visuelles Element importieren“

Über das Dialogfenster mittels Link Weiter Informationen konnte man nach weiteren Visualisierungen suchen und diese importieren.

clip_image002

Neu ist jetzt die Auswahl -> Aus Datei importieren, bzw. Aus Speicher importieren im Gegensatz zu der früheren Version. Ebenfalls hinzugekommen sind im Menüband die Schaltflächen „Aus Speicher“ und „Aus Datei“, wie in der nachfolgenden Abbildung dargestellt.

clip_image003clip_image004

Sofern Sie noch nicht angemeldet sind mit Ihrem Konto, gilt es sich danach anzumelden um die neue Funktion nutzen zu können.

clip_image006

Bisher war es immer wieder ein langer Weg die verschiedenen Visualisierungen zu finden, da die Verlinkungen auf den jeweiligen Websites von Microsoft ständig verändert, bzw. neu angeordnet worden sind. Nun ist es sehr gut nach Kategorie gruppiert und übersichtlich dargestellt ohne im Netz danach suchen zu müssen.

clip_image008

Eine Visualisierung lässt sich so ganz einfach hinzufügen, das ist sehr praktisch, bis auf einen kleinen Umstand, der mir hier persönlich fehlt, nämlich ein Beispiel herunterzuladen.

Nach der Auswahl, indem Sie auf die Darstellung klicken, können weitere Informationen, ggf. Bewertungen eingesehen werden, nachdem der Klick auf Hinzufügen erfolgt ist eine positive Rückmeldung und das Visual ist im Katalog in Power BI für den aktuellen Bericht drin.

clip_image009

Früher war es über die Kataloge der verschiedenen Websites möglich, vor dem Einfügen einer Visualisierung, sich ein Beispiel Bericht herunterzuladen und vor dem Einsatz anzuschauen, was jetzt leider über diesen Weg fehlt.

Aus diesem Grund verweise ich zusätzlich auf eine Quelle aus dem Web, um bei Bedarf an fertige Beispiele zu kommen. Über folgende Adresse gelangen Sie zum Office Store.

clip_image010

Von hieraus lassen sich unter anderem Visualisierungen für Poser BI finden. Nach dem Klick auf eine interessante Darstellung folgt ein Abruf, wahlweise die Visualisierung oder ein Beispiel.

clip_image012

clip_image014

Ein Klick auf Add führt zu der Auswahl des Charts oder wie rechts zu sehen ist, zum Download eines Samples.

clip_image016

Mit dieser Option wird ein fertiger Bericht heruntergeladen (.pbix). Diesem kann man hervorragend entnehmen, ob die jeweilige Visualisierung den eigenen Vorstellungen entspricht anhand fertig aufbereiteter Daten und der eingesetzten Diagramme inklusive Einstellungen.

clip_image018

Abschließend kann der Benutzer eingehend die Möglichkeiten erkunden.

clip_image020

UWP und ADO.NET is back

$
0
0

Bereits seit Silverlight ist der direkte Zugriff auf Datenbanken nicht mehr möglich. Die mehrschichtige Architektur mit einem Service Layer findet sich naturgemäß in Web Frameworks, aber eben auch in WinRT bis hin zu UWP. Ich gehe mal davon aus, das irgendwer bei Microsoft in die Runde gefragt hat, “warum WPF?” und dann kam die Antwort, “Weil wir ADO.NET lieben”.

Man glaubt es kaum. SQLClient und auch Entityframework sind zurück. Mit UWP (Universal Windows Platform) gibt es nun wieder direkten Zugriff auf einen SQL Server. Gerne auch 2 Schicht Architektur genannt. In den diversen Feeds wird schon wieder abgewettert, ob der furchtbaren Software, die da entstehen wird. Nehmen wir es mal gelassen, manchmal muss es schnell gehen und oft sitzen die Clients auch nahe und im gleichen Subnetz eines SQL Servers.

Das ganze ist reichlich vorab und mir erst seit 8.August 2017 überhaupt erfolgreich gelungen. Aus den Issues auf Github kann man rauslesen, das es reichlich Veränderung (breaking changes) gibt.

bei mir läuft (ohne Gewähr)

  • Windows 10 Insider Build 16257.1
  • Visual Studio 2017 15.3 Preview 7
  • SQL Server 2016 Developer Edition

Dazu Anmerkungen: das TCP/IP Netzwerkprotokoll in den SQL Server Configuration Manager aktivieren und den Dienst neu starten. Von Remote PC per Telnet auf die IP Port 1433 prüfen. Eventuell muss in der Windows Firewall die APP aktiviert werden.

Jedenfalls läuft folgender Code in einer WPF Anwendung ohne Probleme und in einer UWP ohne vorige Änderungen nur in eine Exception in der Art

System.Data.SqlClient.SqlException occurred
HResult=0x80131904
Message=A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 35 - An internal exception was caught)

   1:  var conn = new SqlConnection("Data Source=WIN10-PRE;
Initial Catalog=NORTHWND;Integrated Security=True"
);
   2:  conn.Open();
   3:  var cmd = new SqlCommand("Select * from Customers",conn);
   4:  using (var reader = cmd.ExecuteReader())
   5:         {
   6:  while (reader.Read())
   7:                  {
   8:   
   9:   
  10:                  }
  11:   
  12:          }

Ich habe dann den Connection String auf User Id und Password umgestellt. Entspricht auch mehr dem reellen Szenario.

UWP Anwendungen werden in Zukunft (als jetzt als preview) auf dotnetcore zugreifen (integrieren?) können. Dazu muss allerdings auch das Windows 10 preview SDK gesondert installiert sein.

https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewSDK

Dafür muss man natürlich Mitglied im Windows Insider Programm sein, was nur ein paar Klicks kostet.

Dann legt man ein ganz normales Windows Universal C# Projekt an und wählt als Zielversion und Min Version 16257. Das sollte man auch später noch ändern können über die Projekteigenschaften. Das entspricht dem Creators Update Fall Edition (oder wie das heißen wird).

In dem so erzeugten UWP Projekt taucht ein neuer Verweis auf Microsoft.NETCore.UniversalWindowsPlatform vermutlich in einer 5.x Version. Um nun auf die neuesten und täglichen Bits zu bekommen, habe ich in Visual Studio einen weiteren Nuget Server eingerichtet, der auf die Url ttps://dotnet.myget.org/F/dotnet-core/api/v3/index.json verweist.

image

Wählt man im Paketmanager diesen aus, zeigt Visual Studio ein verfügbares Update auf eine 6.x Version (Preview 2 25609). Führen Sie das Update durch, Nur Mut jetzt ist es auch schon egal.

image

Hinter diesem Verweis stecken per Alias eine Reihe von Libraries - .NET Assemblies wie System.Threading und eben SqlClient als .NET Standard 2.0 Variante und können dann direkt im C# Referenziert werden ohne zusätzliche Pakete per Nuget zu holen.

Referenziert ist dieses Paket seit kurzer Zeit wieder im .csproj File  ala

   1:  <PackageReferenceInclude="Microsoft.NETCore.UniversalWindowsPlatform">
   2:  <Version>6.0.0-preview2-25609-02</Version>
   3:  </PackageReference>

 

Was habe ich gelernt. SQLExpress Local DB ist nicht möglich, weil diese Treiber auf die Registry zugreifen und das in .NET Standard für die Librarys nicht definiert ist und auch nicht sein wird weil Windows Plattform spezifisch. Weiters gibt es eine .NET Standard 1.6 Variante, die ziemlich anders ist. Die Portable Class Librarys (PCL) machen in Zukunft keinen Sinn mehr und sind als abgekündigt angekündigt Zwinkerndes Smiley.
Update: SqlClient macht im klassischen .NET einen Fallback von TCP/IP auf Named Pipes und Shared Memory. .NET Core tut das nicht. Das Attribut “Network Library” wird im Connection String von Core nicht unterstützt. Statt dessen kann man das Protokoll als Prefix mitgeben, z.B. lcp: (local) um per Shared Memory auf den lokalen SQL Server zuzugreifen. Wird im Testszenario mit einer T%CP Provider Error 35 Exception quittiert. Ich geh davon aus, es ist nicht implementiert und es könnte auch sein, das UWP Apps das grundsätzlich nicht können.

Feedback oder Fragen einfach über das Github Projekt https://github.com/hannespreishuber/ado.netsharp3

adcteaser360x90


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.

UWP und EntityFramework Lab .NET Standard 2.0

$
0
0

In diesem Lab lernt man eine einfache ToDo App mit direkter Anbindung an einen SQL Server zu erstellen ohne REST Web API Service. Mit der kommenden Windows Version werden weite Teile von .NET Bestandteil der WIndows API. Auch z.B. SQLClient aus ADO.NET. Da diese API dem .NET Standard folgt sind die Bibliotheken direkt in .NET Core, .NET Framework und .NET native nutzbar, Man erhält so mit UWP eine optisch aufgehübschte Alternative zu WPF.

Es wird benötigt (Stand 29.08.2017)

WIndows 10 Creators Update Fall Build 16267 (FCU)

Windows SDK Preview Build

Visual Studio 2017.4 Preview

SQL Server Developer Edition mit lokalem sa User

Starten Sie Visual Studio Preview erstellen ein C# Projekt vom Typ “leere App (Universal Windows App) und nennen diese ToDoCore. Die minimale Version muss der Build 16257 (FCU) sein.

todo2

In den Referenzen des Projektes findet sich ein Verweis auf Microsoft.NETCore.UniversalWindowsPlattform. Wählen Sie  den Nuget Paket Manager aus dem Projekt Menu von Visual Studio und lesen sie Version ab. Diese muss mindestens V6 enthalten. Suchen Sie im Dursuchen Reiter des Nuget Dialoges nach Microsoft.EntityFrameworkCore.SqlServer und installieren die Version 2.0.0 (preview 1 final).

todo3

Nun hat das Projekt 2 Referenzen und ist damit Startklar für UWP und EntityFramework 2 Core. Diese Version weist durchaus Unterschiede zu EntityFramework 6 für .net auf.

todo4

Fügen Sie dem Projekt eine Klasse Todo.cs hinzu, die das Model im MVVM Context darstellt. Implementieren Sie die Schnittstelle INotifyPropertyChanged. Es könnte sein das die üblichen Tools von Visual Studio den Namespace nicht automatisch erkennen. Fügen Sie dann die Zeile

using System.Componentmodel per Hand ein.

   1:  publicclass ToDo : INotifyPropertyChanged
   2:   
   3:      {
   4:   
   5:  publicint ID { get; set; }
   6:   
   7:  privatestring _task;
   8:   
   9:  publicstring Task
  10:   
  11:          {
  12:   
  13:              get { return _task; }
  14:   
  15:              set { _task = value;
  16:   
  17:                  RaisePropertyChanged("Task"); }
  18:   
  19:          }
  20:   
  21:  publicbool Done { get; set; } = false;
  22:   
  23:  publicevent PropertyChangedEventHandler PropertyChanged;
  24:   
  25:  void RaisePropertyChanged(string propertyName)
  26:   
  27:          {
  28:   
  29:              PropertyChanged?.Invoke(this, 
new PropertyChangedEventArgs(propertyName));
  30:   
  31:          }
  32:   
  33:      }

 

Wenn Property ID enthält und vom Typ GUID oder Int ist wird später in der Datenbank per Konvention automatisch eine Identity Spalte als Primary Key erstellt.

Um das Model zu komplettieren wird für EntityFramework eine weitere Klasse benötigt, die ToDoContext.cs benannt wird. In dieser werden die Modelklassen zusammengeführt und die Konfiguration per Code vorgenommen. Ggf. per Using den EntityFrameworkCore Namensraum einbinden.

   1:  class ToDoContext:DbContext
   2:   
   3:      {
   4:   
   5:  public DbSet<ToDo> ToDos { get; set; }
   6:   
   7:  public ToDoContext()
   8:   
   9:          {
  10:   
  11:  //              Database.EnsureCreated();
  12:   
  13:          }
  14:   
  15:  protectedoverridevoid OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  16:   
  17:          {
  18:   
  19:              optionsBuilder.UseSqlServer(@"Data Source = 
desktop-k0ag27t; Initial Catalog = tododb; User Id = sa; Password = xxxx; "
);
  20:   
  21:          }
  22:   
  23:   
  24:   
  25:      }

Das auskommentierte Kommando Ensurecreated erzeugt bei Bedarf die Datenbank samt laut DBContext definierten DbSet Tabellen automatisch, sobald jemand eine Instanz der Klasse erstellt. Dies ist für Entwicklerzwecke sehr praktisch. Die gewohnten Assistenten für Code First Model Building sind in meiner Version von Visual Studio aktuell nicht vorhanden.

Um dazu einen Funktionstest zu starten, fügen Sie in der vorhandenen Datei MainPage.xaml.cs ein Codezeile nach InitializeComponent für die Instanziierung der ToDoContext Klasse ein und kommentieren Zeile 11 wieder ein (EnsureCreated).  Falls nun der Compiler Fehler meldet, installieren sie die Preview 2 Version von einem Daily Build Server in das Projekt.

https://dotnet.myget.org/feed/dotnet-core/package/nuget/Microsoft.NETCore.UniversalWindowsPlatform/6.0.0-preview2-25628-01

Da die Pakete teilweise mehrmals täglich neu erstellt werden, kann es hier zu Problemen kommen. Kein produktiver Einsatz sinnvoll. Dies funktioniert generell nur mit der 2017.4 Version von Visual Studio!

Wenn hier das Programm kompiliert, gestartet wird und keine Exception wirft, sind wir sozusagen durch.

Im Server Explorer von Visual Studio kann dann die Datenverbindung zum lokalen SQL Server mit den oben SA Benutzernamen und gewählten Passwort hergestellt werden. Per Rechtsclick (Tabellendaten anzeigen) auf die Tabelle Todos, wird per Kommando in den Editiermodus gewechselt und es lassen sich Einträge in die Tabelle hinzufügen.

todo5

Als nächstes wird das User Interface im XAML Code der Datei Mainpage.xaml definiert, wie oben dargestellt. Leider funktioniert aktuell der visuelle Designer in Visual Studio nicht. Im MVVM Kontext wird das gemeinhin als View bezeichnet.

todo1

   1:  <Grid>
   2:  <Grid.ColumnDefinitions>
   3:  <ColumnDefinitionWidth="1*"></ColumnDefinition>
   4:  <ColumnDefinitionWidth="1*"/>
   5:  </Grid.ColumnDefinitions>
   6:  <StackPanelWidth="300"Grid.Column="0">
   7:  <ListViewx:Name="listView1"SelectionMode="Single"
   8:  SelectionChanged="listView1_SelectionChanged"
   9:  ItemsSource="XXXX">
  10:  <ListView.ItemTemplate>
  11:  <DataTemplatex:DataType="XXXX">
  12:  <StackPanelOrientation="Horizontal">
  13:  <CheckBoxIsChecked="XXXX"Width="50"
  14:  ></CheckBox>
  15:  <TextBlockText="XXXX"></TextBlock>
  16:  </StackPanel>
  17:  </DataTemplate>
  18:  </ListView.ItemTemplate>
  19:  </ListView>
  20:  <ButtonContent="Done"Click="XXXX"></Button>
  21:  </StackPanel>
  22:  <StackPanelGrid.Column="1">
  23:  <TextBlockText="ToDo Items"></TextBlock>
  24:  <TextBoxText="XXXX"
  25:  ></TextBox>
  26:  <StackPanelOrientation="Horizontal">
  27:  <ButtonContent="Neu"Click="XXXX"Margin="5"></Button>
  28:  <ButtonContent="update"Click="XXXX"Margin="5"></Button>
  29:  </StackPanel>
  30:  </StackPanel>
  31:  </Grid>

 

Alle Attribute mit dem Wert XXXX dienen hier nur als Platzhalter und werden später bei der Datenbindung Bindung ausgetauscht.

Nach dem View wird das Viewmodel wiederum als Klasse mit dem Namen ToDoVM.cs dem Projekt hinzugefügt. Das Viemodel beinhaltet als Property eine Liste der ToDo Tasks, den aktuellen ToDo Task und diverse Funktionen zum hinzufügen oder speichern. Wie im XAML Umfeld üblich wird das Interface INotifypropertyChanged (aus System.ComponentModel) implementiert um Änderungen in VIewModel dem View per Event mitzuteilen. Darüber hinaus wird die generische Liste aus System.Collections.Objectmodel benötigt. Dies ist nur erste Schritt des Viewmodels um die Anzeige der Liste der ToDo Items und das hinzufügen eines neuen Eintrages in die Tabelle zu demonstrieren.

   1:  publicclass ToDoVM : INotifyPropertyChanged
   2:      {
   3:  public ObservableCollection<ToDo> 
ToDoList { get; set; }= new ObservableCollection<ToDo>();
   4:  private ToDo _item;
   5:  public ToDoVM()
   6:          {
   7:              Item = new ToDo();
   8:          }
   9:  public ToDo Item
  10:          {
  11:              get { return _item; }
  12:              set { _item = value;
  13:                  RaisePropertyChanged("Item");
  14:              }
  15:          }
  16:  publicevent PropertyChangedEventHandler PropertyChanged;
  17:  publicvoid SaveItem()
  18:          {
  19:              var ef = new ToDoContext();
  20:              ef.ToDos.Add(_item);
  21:              ef.SaveChanges();
  22:              Load();
  23:          }
  24:  publicvoid Load()
  25:          {
  26:              var ef = new ToDoContext();
  27:  foreach (var t in ef.ToDos)
  28:              {
  29:                      ToDoList.Add(t);
  30:              }
  31:          }
  32:  void RaisePropertyChanged(string propertyName)
  33:          {
  34:              PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(propertyName));
  35:          }
  36:      }

Ein paar Hinweise, warum der Code so aussieht wie er ist. Eine Observable Collection aktualisiert das UI nur wenn ein Eintrag hinzugefügt oder gelöscht wird. Deswegen muss das für jeden Eintrag einzeln geschehen (foreach Zeile 29). Wenn der Benutzer neue Daten eingeben hat und auf den Speichern Button clickt, wird dem Datacontext in Zeile 20 der neue Eintrag vom Typ ToDo aus dem Formular hinzugefügt. Um die Anzeige in der Liste zu aktualisieren wird diese einfach neu geladen. Dies wird später noch im Code geändert. Das ganze Stück Software ist nur ein Prototyp und sollte beim zweiten neuen Task eine Exception werfen. Nicht vergessen den eingefügten Code in das Codebehind des Views Mainpage.Xaml.cs  wieder entfernen.

Nun das ViewModel mit dem View verbunden. Das geschieht bei UWP compiled Bindings ganz einfach in dem man schlichtweg das Viewmodel zum Property der Page erklärt.  Hinweis, nur wenn man MyVM bei der Deklaration mit einer Instanz von ToDoVM belegt funktioniert das Binding. Macht man das im Konstruktor, bleibt die Anzeige im Listview später leer. Die Liste wird dann geladen.

   1:  public ToDoVM MyVM { get; set; } = new ToDoVM();
   2:  public MainPage()
   3:        {
   4:  this.InitializeComponent();
   5:              MyVM.Load();
   6:          }
   7:  privatevoid listView1_SelectionChanged(object sender,
SelectionChangedEventArgs e)
   8:          {
   9:              MyVM.SelectedID((ToDo) listView1.SelectedItem);
  10:          }
  11:   

In einem späteren Schritt wird der ausgewählte Eintrag in der Liste dem Formular zugewiesen, so das der Benutzer den Eintrag auch editieren kann. Ergänzen Sie den Code wie oben beschrieben und schliessen damit die Arbeiten an diesem C# File ab.

Nun wird wieder im Viewmodel das Binding an die Propertys und Funktionen des Views definiert. Das XAML Listview Controll erhält die Daten aus dem Property MyVM. Im Viewmodel wiederum ist die Liste als Eigenschaft ToDoList hinterlegt. Generell gilt das in UWP Compiled Bindings der default Wert OneTime ist und daher immer abweichend definiert sein muss. Besonderheit ist der Typ im Datatemplate, der auf die ToDo Model Klasse verweist.  Der Namensraum local muss von  Visual Studio automatsich im Kopfbereich mit einem Verweis auf die App deklariert sein. Die X: Bind Syntax ist ähnlich der {Binding} Syntax.

   1:  ItemsSource="{x:Bind MyVM.ToDoList,Mode=TwoWay}">
   2:  <ListView.ItemTemplate>
   3:  <DataTemplatex:DataType="local:ToDo">
   4:  <StackPanelOrientation="Horizontal">
   5:  <CheckBoxIsChecked="{x:Bind  Done,Mode=TwoWay}"Width="50"
   6:  ></CheckBox>
   7:  <TextBlockText="{x:Bind  Task,Mode=OneWay}"></TextBlock>

 

Das Formular für Neu und Edit wird analog mit Binding versehen. Dabei sticht natürlich ins Auge wie einfach Button Events gebunden werden. Ganz ohne ICommand aus WPF.

   1:  <TextBoxText="{x:Bind MyVM.Item.Task,Mode=TwoWay}"
   2:  ></TextBox>
   3:  <StackPanelOrientation="Horizontal">
   4:  <ButtonContent="Neu"Click="{x:Bind MyVM.AddNew}"Margin="5"></Button>
   5:  <ButtonContent="update"Click="{x:Bind MyVM.SaveItem}"Margin="5"></Button>
   6:  </StackPanel>

Im letzten Schritt wird die Benutzerauswahl eines Tasks implementiert und das speichern der erledigten Einträge. Dazu wird im ViewModel ToDoVM.cs eine Update Funktion erstellt, die Änderungen per EntityFramework in die Datenbank zurück schreibt. Die gewählte C# Logik nimmt die Liste und sucht sich aus der EF Liste den Eintrag und ändert den Wert für die Done Eigenschaft. Das abschliessende SaveChanges schreibt die Werte in die Datenbank zurück.

 

   1:  publicvoid SelectedID(ToDo item)
   2:          {
   3:              Item = item;
   4:         }
   5:  publicvoid UpdateDone()
   6:          {
   7:              var ef = new ToDoContext();
   8:  foreach (var item in ef.ToDos)
   9:              {
  10:                  item.Done = ToDoList.Where(id => id.ID == item.ID).First().Done;
  11:              }
  12:              ef.SaveChanges();
  13:          }

Im XAML muss noch das Attribut im Listview Control ergänzt werden um auf die Benutzerauswahl zu reagieren. Dadurch wird die Methode SelectedID im Viewmodel angestossen und das Formular mit dem ToDo Item belegt, statt dem leeren.

   1:  SelectionChanged="listView1_SelectionChanged"

In der Tat gibt es einige UWP Funktionen die so noch nicht sauber genutzt werden. So finden sich Animationen beim entfernen oder hinzufügen eines ListView Items. Entsprechend wird der Code der Load Methode angepasst, das nur einzelne Einträge hinzugefügt werden. Ausserdem kann nun die SaveItem Methode anhand der ID des ToDo Items erkennen ob es sich um eine neues (ID=0) oder ein altes Item handelt. Entsprechend wird nur gespeichert oder per Add neu eingefügt.

   1:  publicclass ToDoVM : INotifyPropertyChanged
   2:      {
   3:  public ObservableCollection<ToDo> ToDoList { get; set; }=
new ObservableCollection<ToDo>();
   4:  private ToDo _item;
   5:  public ToDoVM()
   6:          {
   7:              Item = new ToDo();
   8:          }
   9:  public ToDo Item
  10:          {
  11:              get { return _item; }
  12:              set { _item = value;
  13:                  RaisePropertyChanged("Item");
  14:              }
  15:         }
  16:  publicevent PropertyChangedEventHandler PropertyChanged;
  17:  publicvoid AddNew()
  18:          {
  19:              Item = new ToDo();
  20:          }
  21:  publicvoid SaveItem()
  22:          {
  23:              var ef = new ToDoContext();
  24:  if (_item.ID>0)
  25:              {
  26:                  var item=ef.ToDos.Find(_item.ID);
  27:                  ef.Entry(item).CurrentValues.SetValues(Item);
  28:                  ToDoList.Where(
id => id.ID == _item.ID).First().Task = _item.Task;
  29:              }
  30:  else
  31:              {
  32:                  ef.ToDos.Add(_item);
  33:              }
  34:              ef.SaveChanges();
  35:              Load();
  36:          }
  37:  publicvoid Load()
  38:         {
  39:              var ef = new ToDoContext();
  40:  foreach (var t in ef.ToDos)
  41:              {
  42:  if (ToDoList.Where(x => x.ID == t.ID).Count() == 0)
  43:                  {
  44:                      ToDoList.Add(t);
  45:                 }
  46:              }
  47:          }
  48:  publicvoid SelectedID(ToDo item)
  49:         {
  50:              Item = item;
  51:          }
  52:  publicvoid UpdateDone()
  53:          {
  54:              var ef = new ToDoContext();
  55:  foreach (var item in ef.ToDos)
  56:              {
  57:                  item.Done = ToDoList.Where(id => id.ID == item.ID).First().Done;
  58:              }
  59:              ef.SaveChanges();
  60:          }
  61:  void RaisePropertyChanged(string propertyName)
  62:          {
  63:              PropertyChanged?.Invoke(this, 
new PropertyChangedEventArgs(propertyName));
  64:          }
  65:      }

Wenn Probleme oder Fragen auftreten bitte als Issue dort anlegen https://github.com/hannespreishuber/App4EF

Windows 10 FCU Conditional XAML

$
0
0

Nun ist es da, das Windows 10 Fall Creators Update (FCU) oder auch Build 16299 genannt. Mit der nun 5ten Version der Windows API (WinRT) kommen einige kleinere Neuerungen. Eine ist der Glass Effekt aus Vista ist zurück, hier nun Acrylic genannt. Kurz gesagt, es scheint der Hintergrund bei der aktiven App durch, aber nur wenn die App so entwickelt ist. Auch im Stromsparmodus wird der Effekt deaktiviert. Dazu wurde ein neuer Brush Typ definiert, der für den Modus aktiv und passives Window die Farbe definiert.

   1:  <AcrylicBrush
   2:  FallbackColor="Yellow"
   3:  TintColor="LightBlue"
   4:  TintOpacity="0.3">
   5:  </AcrylicBrush>

 

Das führt uns nun zum zweiten Feature, conditional XAML. Normalerweise wird ein Hintergrund wie folgt als Brush deklariert

   1:  <GridBackground="{ThemeResource ApplicationPageBackgroundThemeBrush}">

 

Das ist sozusagen “klassik” UWP Style. Will man Acrylic Style,  benötigt man einen passenden AcrylicBrush und eine TintOpacity kleiner als 1. Per Xaml könnten man das machen

   1:  <GridBackground="{ThemeResource SystemControlAcrylicWindowBrush}">

Um auf die verschiedenen Api Level von Windows 10 zugreifen zu können, kann die Hilfsfunktion IsApiTypePresent genutzt werden. Per Zeichenkette als Parameter lassen sich verschiedene Funktionen abprüfen und so die Logik anpassen, abhängig von verwendeter Hardware und Windows Version. Was mir mir ganz neu war ist, das man das man das im XAML auch nutzen kann. Die Funktion nennt sich conditional XAML und ist bereits seit Creators Update, also ca. 6 Monate, fester Bestandteil des Redmonder Betriebssystems. Zunächst werden zwei Namespace angelegt und per Type Abfrage umgeschalten. Dies ist nötig um in jedem Fall bzw. jedem Windows Build eine korrekt definierte UI zu haben. Würde man nun das Text Property per Namespace und ohne (default) verwenden, kommt es zu einer Fehlermeldung “Text property is set more than once”

Mit IsTypePresent lassen sich verschiedenste Fähigkeiten prüfen. Der einfach API Level wird per

IsApiContractPresent(Windows.Foundation.UniversalApiContract, 5) = true abgefragt. Die Nutzung im deklarativen XAML Code muss dem Schema xmlns:myNamespace="schema?conditionalMethod(parameter)" folgen.

Alles zusammengeführt folgender XAML Code um eine App zu bekommen die in Creators Update und Creators Update Fall Edition korrekt läuft

   1:  xmlns:classic="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsTypeNotPresent(Windows.UI.Xaml.Media.AcrylicBrush)"
   2:  xmlns:acrylic="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsTypePresent(Windows.UI.Xaml.Media.AcrylicBrush)"
   3:  ......
   4:  classic:Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
   5:  acrylic:Background="{ThemeResource SystemControlAcrylicWindowBrush}"

Windows 10 FCU UWP Hamburger Menü

$
0
0

Das Hamburger Menü hat sich dank Web und Android zum quasi Standard erhoben, vor dem auch UWP Anwendungen nicht halt machen können. Bisher musste man als UWP Developer ein Splitview Control nutzen und per Hamburger Icon erweitern.

In der nun 5ten Windows 10 Version taucht ein neues Steuerelement in der Toolbox von Visual Studio 2017 auf, das NavigationView.

Das UWP Navigation Control ist ein sehr mächtiges Steuerelement, das eine Reihe von Anwendungsfällen abdeckt, wie man im folgenden Screenshot erkennen kann.

image

image

Ein und Ausklappbarer Menübereich, mit Abschnitten und Suchbox. Die Menüitems können statisch als NavigationViewItem oder dynamisch als NavigationViewList definiert werden. Letztes mit der MVVM üblichen Bindung per Binding oder x: Bind. Im Headertemplate kann eine modern Appbar mit oder ohne Datenbindung erstellt werden.

   1:  <NavigationView
   2:  ItemInvoked="NavigationView_ItemInvoked"
   3:  SelectionChanged="NavigationView_SelectionChanged">
   4:  <NavigationView.HeaderTemplate>
   5:  <DataTemplate>
   6:  <Grid>
   7:  <Grid.ColumnDefinitions>
   8:  <ColumnDefinitionWidth="Auto"/>
   9:  <ColumnDefinition/>
  10:  </Grid.ColumnDefinitions>
  11:  <TextBlockStyle="{StaticResource TitleTextBlockStyle}"
  12:  FontSize="28"
  13:  VerticalAlignment="Center"
  14:  Margin="12,0"
  15:  Text="Hallo Welt"/>
  16:  <CommandBarGrid.Column="1"
  17:  HorizontalAlignment="Right"
  18:  DefaultLabelPosition="Right"
  19:  Background="{ThemeResource SystemControlBackgroundAltHighBrush}">
  20:  <AppBarButtonLabel="Refresh"Icon="Refresh"/>
  21:  <AppBarButtonLabel="Save"Icon="Save"/>
  22:  </CommandBar>
  23:  </Grid>
  24:  </DataTemplate>
  25:   
  26:  </NavigationView.HeaderTemplate>
  27:  
  28:  <NavigationView.AutoSuggestBox>
  29:   
  30:  <AutoSuggestBoxx:Name="controlsSearchBox"
  31:  Margin="0,8,12,0"
  32:  Width="270"
  33:  PlaceholderText="Search"
  34:  QueryIcon="Find"
  35:  TextChanged="controlsSearchBox_TextChanged"
  36:  QuerySubmitted="controlsSearchBox_QuerySubmitted"
  37:  RelativePanel.AlignRightWithPanel="True"/>
  38:   
  39:   
  40:  </NavigationView.AutoSuggestBox>
  41:   
  42:  
  43:   
  44:  <!--NavigationViewList-->
  45:   
  46:  <NavigationView.MenuItems>
  47:  <NavigationViewItemHeaderContent="Gruppe">
  48:  <NavigationViewItemHeader.Foreground>
  49:  <SolidColorBrushColor="{ThemeResource SystemBaseHighColor}">
  50:  
  51:  </SolidColorBrush>
  52:  </NavigationViewItemHeader.Foreground>
  53:  </NavigationViewItemHeader>
  54:  <NavigationViewItemIcon="Pictures"Content="Eins"/>
  55:  <NavigationViewItemIcon="Camera"Content="Test"Tag="zwei"/>
  56:  </NavigationView.MenuItems>
  57:  
  58:  <NavigationView.PaneFooter>
  59:  <HyperlinkButtonContent="Datenschutz"></HyperlinkButton>
  60:  </NavigationView.PaneFooter>
  61:  <Framex:Name="MainFrame">
  62:   
  63:  </Frame>
  64:   
  65:  </NavigationView>

Im Frame UI Element wird per Navigation eine weitere Page nachgeladen. Etwas seltsam muten die beiden Event ItemInvoked und dann SelectionChanged des NavigationViews. Beide werden ausgelöst. Ersteres übernimmt die Beschriftung (Content) als args.InvokedItem, das zweite Event den Wert des Tag Attributes args.SelectedItem. Noch seltsamer reagiert das erste Event ItemInvoked auf die Settings Aktion. Das Settings Icon befindet sich unten, wenn das Attribut IsSettingsVisible nicht oder auf true gesetzt wird. Im ItemInvoked Argument kann dies abgefragt werden und auf eine Settings Page navigiert werden.

   1:  if (args.IsSettingsInvoked)
   2:              {
   3:                  MainFrame.Navigate(typeof(MySettings));
   4:  return;
   5:              }

Die Dokumentation erscheint mir aktuell sehr dünn und es findet sich kein passendes C# Code Beispiel.

UWP FCU Parallax Control

$
0
0

Der ganze Flat Design Mode Trend ist am Ende. Man fügt wieder Schatten ein und Microsoft nennt die Design Sprache Fluent Design. Das visuelle Verhalten zeigt beim Scrollen unterschiedliches Bewegungstempo um mehrere Ebenen zu simulieren. Man nennt dies Parallax Effekt. Ganz gut kann man das an der Wetter App selber ausprobieren. Folgender Blog gilt für Windows 10 Fall Creators Update.

Irgendwann 2015 hat Microsoft die sogenannte Composition API als Layer zwischen XAML und Direct X eingeführt. Ziel war es wohl, solche modernen UI Effekte zu realisieren. Ich habe mich ein wenig damit beschäftigt und fürchterlich gelangweilt. Man benötigt Unmengen von Sourcecode um Dinge zu tun, die ein Designer tun sollte. Meine damalige Nachfrage beim Team nach irgendwas XAML basierendes, wie z.B. Behaviour, wurde beantwortet “mit kommt noch”.

Nun ist es da, das ParallaxView als Steuerelement. Keine XAML Erweiterung, kein Verhalten. Das Control wird per Binding an ein bewegtes Control, vermutlich immer etwas in der Richtung ListView gebunden. Die Dynamik des Hintergrunds wird über VerticalShift gesteuert, 0 ist statisch.

   1:  <ParallaxViewSource="{x:Bind Vordergrund}"VerticalShift="200">
   2:  <Imagex:Name="Hintergrund"Source="Assets/WP_20170820_17_04_43_Pro.jpg"
   3:  Stretch="UniformToFill"/>
   4:  </ParallaxView>
   5:  <ListViewx:Name="Vordergrund"Margin="100"Background="Azure"Opacity="0.9">

So sind die Probleme sauber im XAML getrennt beim Designer, da wo sie hingehören. Nach ersten Tests ergibt sich, das es gar nicht so einfach ist, ein passendes Hintergrundbild auszuwählen. Es darf keine Focuspunkte aufweisen, muss farblich passen und im Scrollen keine Unlesbarkeiten erzeugen. So komme ich in dem Beispiel auf den Ansatz, den Hintergrund der Liste zu mit Transparenz zu färben.

parallax

Wisch Geste Windows 10 FCU UWP

$
0
0

Obwohl Microsoft seit Windows XP Touch und Pen im Betriebssystem als integralen Bestandteil behandelt, ist es noch immer schwierig mit Gesten umzugehen. Lediglich Manipulation Events die speziell auf Finger Eingaben reagieren, werden ausgelöst. Aber kein Zoom, Pinch oder Rotate. Um aus den Events, den EventArgs eine Geste letztendlich zu erkennen, hilft eine Klasse GestureRecognizer in Kombination mit ManipulationInputProcessor. Nichts was intuitiv von der Hand flutscht. Schon recht früh keimte die Idee in Listen ein Delete per Wischgeste auszulösen. Der Aufwand und das Ergebnis, endeten in der Empfehlung, das Wipe and Delete Feature aus den Spezifikationen zu entfernen. Ähnliches gilt für das bei Android und IPhone verbreitete aktualisieren einer Liste durch ziehen.

Wieder einmal soll ein neues UWP Steuerelement Abhilfe schaffen. Zumindest teilweise gelingt dies dem SwipeControl Control. Nicht nur der Name ist sonderbar, sondern auch die Nutzung und Parameterisierung, so das mich brennend interessieren würde ob die Entwickler in Redmond sitzen oder überhaupt bei Microsoft beschäftigt sind.

Das Stuerelement ist eine Art Container der im Datatemplate einer z.B. Listview platziert wird und dann den üblichen Inhalt des Datatemplates enthält. Je nach Wischrichtung (Links Rechts) wird ein Template (Leftitems RigthItems) aktiviert. Darunter muss ein SwipeItems Element angelegt werden. Per Mode Reveal oder Execute wird das Verhalten des eingewischten Kontext Menüs gesteuert. Reveal lässt nur ein aktiviertes Element zu und verschwindet nach Funtkionsaufrauf automatisch. Bei Execute bleiben auch mehrere Items aktiviert.

image

Weder erschließt sich mir, warum der Standard ein dauerhaft aktiviertes Menüitem ist, noch wie Benutzer es wieder wegbekommen soll. Eine Gegenläufige Wischgeste ist es jedenfalls nicht. Bleibt nur das Attribut   BehaviorOnInvoked="Close" des SwipeItem Elements. Von den SwipeItems können auch mehrere in das rechte oder linke SwipeItems Control deklariert werden. Besonders absurd finde ich das man das Icon nicht einfach per Name definieren kann, sondern explizit eine SymbolIconSoruce als Resource anlegen muss. Das wird an anderen Stellen der UWP API mit Icon=”Delete” besser gelöst. Der komplette XAML Code

   1:  <Page.Resources>
   2:  <SymbolIconSourcex:Key="DeleteIcon"Symbol="Delete"/>
   3:  <SymbolIconSourcex:Key="EditIcon"Symbol="Edit"/>
   4:  </Page.Resources>
   5:   
   6:  <GridBackground="{ThemeResource ApplicationPageBackgroundThemeBrush}">
   7:   
   8:  <ListViewx:Name="liste1"Width="600"Height="300">
   9:  <ListView.ItemTemplate>
  10:  <DataTemplatex:DataType="x:String">
  11:  <SwipeControlx:Name="ListViewSwipeContainer">
  12:  <SwipeControl.LeftItems>
  13:  <SwipeItemsMode="Reveal">
  14:  <SwipeItemText="Edit"
  15:  IconSource="{StaticResource EditIcon}"
  16:  Invoked="SwipeItem_Invoked"
  17:  />
  18:  
  19:  </SwipeItems>
  20:  </SwipeControl.LeftItems>
  21:   
  22:  <SwipeControl.RightItems>
  23:  <SwipeItemsMode="Execute">
  24:  <SwipeItemText="Delete"
  25:  IconSource="{StaticResource DeleteIcon}"
  26:  Invoked="SwipeItem_Invoked_1"
  27:  BehaviorOnInvoked="Close"
  28:  Background="Red"/>
  29:  </SwipeItems>
  30:  </SwipeControl.RightItems>
  31:  <StackPanelOrientation="Vertical"Margin="5">
  32:  <TextBlockText="{x:Bind}"FontSize="18"/>
  33:  <StackPanelOrientation="Horizontal">
  34:  <TextBlockText="Mein bestimmter Monat..."FontSize="12"/>
  35:  </StackPanel>
  36:  </StackPanel>
  37:  </SwipeControl>
  38:  </DataTemplate>
  39:  </ListView.ItemTemplate>
  40:  </ListView>

Als nächstes noch der Blick in den C# Soruce Code, der Code Behind. Auch diskussionswürdig der Name des Events Invoke (an anderer Stelle auch mal InvokeItem). Mit folgendem Code kann ich zuverlässig Visual Studio ins Nirvana schicken, bzw den  Debugger. Normal gestartet läuft die App.

   1:  private async void SwipeItem_Invoked_1(SwipeItem sender, SwipeItemInvokedEventArgs args)
   2:          {
   3:  
   4:              var msg = new MessageDialog("Ping");
   5:              await msg.ShowAsync();
   6:   
   7:          }

 

swipe

für mich noch offen sind Layout Fragen. Konkret ist die Liste eigentlich 400px breit, aber auch bei Swipe Geste wird nur der Bereich der maximalen Textlänge eines Listeneintrages genutzt. Noch eine Menge zu lernen.

Windows 10 Emojis

$
0
0

Wer lange genug oder erst sehr kurz mit dabei ist, wird die ASCII Kunst kennen. Wer nun der Erfinder von Smiley wirklich war, wird sich nie herausfinden lassen. Der Smiley als Ikone der Techno Bewegung entstand in den 80igern. Knapp 10 Jahre später wurden wir zu Simsern. In den SMS wurden Symbole  genutzt um Gefühle in kurzer Form auszudrücken. Die folgenden Chat Systeme und Clients  nutzten Emoticons auf Basis von ASCII Zeichen intensiv, ersetzen aber schon die Zeichen durch ein Bildschriftzeichen. Ab 2000 findet sich der Begriff Emoticon im Duden. Auch heute entstehen im Zeichen von Kommandozeile node.js und Tooling immer wieder gerne ASCII Kunstwerke ala ¯\_(ツ)_/¯ , Shruggy.

Bereits 1981 lieferte IBM im ASCII Zeichensatz zwei Zeichen für das Smiley mit. In der Zwischenzeit gibt es im Unicode 7 Standard über 2000 Symbole für Menschen, Gefühle, Tätigkeiten oder Flaggen. Diese werden in dieser Form nun als Emoji bezeichnet und lassen sich jeweils mit einem zwei Byte langem  Unicode Zeichen darstellen.

Üblicherweise geschrieben als U+Code. Also U+23CF oder in HMTL &#x23cf;. Dies stellt das Eject oder auch Auswurf Symbol dar.⏏

Wie kommt nun das Emoji in meinen Text? Die einfachste Möglichkeit, wenn auch beschränkt, stellt das Windows 10 Touch Keyboard dar, das im Tablet Modus automatisch aktiviert wird. Der Screenshot zeigt Notepad, das mit Fahrzeugen statt Text gefüllt wird.

Screenshot (7)

Wir erkennen, das die Darstellung durchaus abweichend sein kann. Dazu später mehr. Wer einen numerischen Tastaturblock nutzen kann, dem steht noch immer die Eingabe Methode [ALT] hold [+] Hex Code zur Verfügung.

Nutzer einer UWP App sehen die Emojis in einer Textbox, genauso und in Farbe, wie auf der Tastatur ersichtlich.

Symbole für was?

Mehr oder weniger sinnbehaftete Icons verfolgen den Benutzer seit Erfindung der der grafischen Benutzeroberfläche. Diese unterliegen genauso Modetrends wie vieles andere. Erst plump und pixelig, dann animiert, später mit viel Aufwand in 3D und plötzlich wieder flach und glanzlos. Zu Zeiten des Flat Designs mussten diese einfach, schlank und vor allem kontrastfähig sein. Wie eine Beschilderung in der U-Bahn auch als  Metro bekannt und so nannte Microsoft kurzfristig seine Windows 8 Design Sprache folgerichtig METRO. Eine Reihe von Icons decken sich mit Emojis haben aber trotzdem eine völlig andere Zielrichtung. Die Windows 10 Icons sind noch immer schlank, aber nicht mehr einfarbig. Neu hinzu kommt ein Blauton um ein wenig der Tristesse zu entfliehen. Bei einem Hell Dunkel Kontrastwechsel, durch den Benutzer, funktionieren die Icons automatisch.

icons1

icons2

Sowohl Icons als auch Emojis basieren bei Microsoft auf True Type Schriftarten. Die Schrift Segoe UI MDL2 Assets für typische Windows Icons und Segoe UI Emoji für die bunten Bildchen. Allerdings ist mit dem Programm Zeichentabelle nur ein Teil der Wahrheit versteckt, weil die Emoji Schrift komplexer ist, als eine übliche TTF.

image

Es wäre nicht das Internet, wenn es nicht jemanden gibt, der dafür nicht eine Lösung hätte. Jeremy Burge verdient sein Geld damit, die Website Emojipedia.org zu betreiben. Dort lassen sich nicht nur alle Emojis nachschlagen, die definiert sind, sondern auch die Interpretation der verschiedenen Software Anbieter. Jüngster Shitstorm im Emoji Universum wurde ausgelöst durch den Google Hamburger. Abrufbar per https://emojipedia.org/hamburger/. Das Apple Emoji ist schon beinahe Fotorealistisch. Der große Fail beim Google Burger befindet sich der Käse völlig unrealistisch unten.

image

Der mir bis dato wenig bekannte Google CEO kündigt darauf hin drastische Maßnahmen an. Den Microsoft Burger erspare ich dem Leser an dieser Stelle. Der Käse ist zwar auf dem Patty, aber ansonsten eher unappetitlich dargestellt. Zum Redmonder Emoji Konzept aus der Fluent Design Sprache komme ich später noch.

image

 

Technische Umsetzung UWP und Icons

Icons und Emojis sind also in der Regel Schriften. Diese lassen sich sauber skalieren und rendern ohne Raster. Jedes Icon ist ein UTF-16 definiertes Unicode Zeichen. Im einfachsten Fall wird einfach der Text eines Steuerelements samt Font gesetzt und so das Smiley angezeigt. Dabei kann vom Entwickler definiert werden ob mit oder ohne Farbe. Aus einem Emoji dient damit auch ein Icon.

   1:  <TextBlockText="&#x263A;"
   2:  IsColorFontEnabled="False"
   3:  FontFamily="Segoe UI Emoji"
   4:  FontSize="20"/>
   5:  <TextBlockText="&#x263A;"
   6:  IsColorFontEnabled="True"
   7:  FontFamily="Segoe UI Emoji"
   8:  FontSize="20"/>

 

image

 

Die Codes kann man sich schlecht merken und deshalb bietet UWP eine Auflistung Symbol. Über diese Namen ala Accept oder Contact werden dann in Buttons, Appbar oder Listen passende Symbole aus der Schrift MDL2 Assets eingebunden. Es gibt eine Reihe von Steuerelementen die Zusatz Icon enthalten. Das einfachste ist ziemlich sicher das UI Element SymbolIcon. Intellisense schlägt dank Enum die Iconnamen vor.

   1:  <SymbolIcon Symbol="Emoji" />
   2:  <SymbolIcon Symbol="Emoji2" />

 

Diese Windows Icons sind optisch schlanker und leichter gestaltet, als die vorigen Emojis.

image

Recht ähnlich ist das Control Fonticon. Wesentliche Unterschiede zum Symbolicon: Keine Named Values per Enum, mehrere Zeichen im Attribut Glyph möglich, nur als Subelement eines anderen UI Elements. Folgender XAML Code definiert einen Button mit der Lupe, also einen Search Button.

   1:  <Button>
   2:  <FontIconFontFamily="Segoe MDL2 Assets"Glyph="&#xE11A;"FontSize="12"/>
   3:  </Button>
   4:  

Um der Frage vorzugreifen, das wäre in dem Fall auch per SymbolIcon möglich. Eine Reihe von Controls kennen das Icon Attribut und nutzen die Namen wie AppBarButton Icon="Accept".

Beide Segoe Schriftarten sind auf einem Windows 10 Computer installiert. Nichts desto trotz kann man diese oder jede andere Schrift auch mit dem Projekt bundeln. Einfach die TTF Datei in das Projekt einfügen und als Eigenschaft Content/Inhalt festlegen. Im nächsten Beispiel nutz das Glyphs Element diese Methode, rein aus akademischen Gründen. Das Steuerelement (Name Plural) kann mehrere Zeichen darstellen über die Eigenschaft Indices. Das erscheint schon mal eigenartig, vor allem da der Typ String ist. Auch in den offiziellen UWP Samples von Microsoft findet sich kein einziges Mal das Steuerelement in Benutzung. Die Dokumentation führt dazu aus, das es ein sehr schnelles und leichtgewichtiges Steuerelement ist. Jedenfalls scheint (so sicher bin ich mir noch nicht) es sich beim Attribut Indices um eine Semikolon getrennte Nummerische Liste zu handeln, die die Postition des Font Icons in der Schrift wiederspiegelt.

   1:  <GlyphsFontUri="Assets/seguiemj.ttf"
   2:  FontRenderingEmSize="30"
   3:  Indices="301"
   4:  Fill="Red"
   5:  ColorFontPaletteIndex="1"
   6:  IsColorFontEnabled="true"/>

Wir sehen einen Regenschirm in drei Farbvarianten, wobei nur der erste aus dem XAML Code stammt. Beim Schirm #2 wurde ColorFontPaletteIndex auf 0 gesetzt. Beim letzten das Attribut IsColorFontEnabled auf False.

image

Das alles geht nur, weil Segoe UI Emoji eine sogenannte Colored Font ist. Man findet auch häufiger Bezeichnungen wie Multicolored Font oder Chromatic Font. Das Emoji ist in diesem Fall dreifarbig. Die drei Einzelsymbole befinden sich in der Tat in der Schrift. Durch ändern des Attributs    Indices="1931;1932;1933;1934;1935;1936;1937” tauchen diese im UI auf und werden Silver, weil die Eigenschaft Fill dies so anweist. Man kann Emojis auch kombinieren. Von Microsoft genannter Anwendungsfall dreht sich um die zahlreichen Personen, denen man mit einem Emoji Skin Tone eine andere Hautfarbe verpassen kann. Diese Definition von 5 Skintones aus Unicode 8 scheint aktuell nur von Microsoft unterstützt zu werden. Außerdem ist mir keine Methode das im XAML oder wenigstens komfortabel mit C# zu lösen.

image

Microsoft hat sich seit Windows 8 erkennbar wieder in Richtung bunter und 3D bewegt. Auch aber nicht nur in Bezug auf Emojis. Wer möchte, kann aber auch ältere Fonts ins Visual Studio Projekt einbinden und so einen Windows 8.1 Umbrella with Rain nutzen.

image

Bleibt nur die Frage, woher bekommt man den Wert (1931) für den Regenschirm um den Indicies Parameter im Glyphs zu füllen. Die Antwort ist: keine Ahnung. Je nach verwendeter Version der Seguiemj.ttf ist Umbrella mit Rain woanders. Bei Windows 8.1 ist es 301 und aufwärts. Mein Testcase war einfach eine Liste, die ein Glyphs Control an Integerwerte gebunden hat, um alle möglichen und vorhandenen Emojis anzuzeigen. Das geht aktuell bis ca 11.000.

Ich brauche mehr Icons

Eingangs kam der bescheidene Microsoft Hamburger zur Sprache. Um eine wiedererkennbare Identität zu erzielen benötigt man ein paar UI Emoji Guidelines. Microsofts Designer bauen auf einer Matrix auf die mit Kreisen und Strichen einer gewissen Dicke gefüllt werden. Dazu kommt eine definierte Farbpalette.

Hamburger emoji

Mahlzeit und dazu noch ein Clinking Beer Mugs on Microsoft Windows 10 Fall Creators Update. Wobei da nähert sich schon der nächste Shitstorm. Die Gläser von Google sind nur Halbvoll.


Ich bin sauer UWP Rating Control

$
0
0

In Windows 10 Fall Creators Update (FCU) tauchen auch eine Reihe neuer Steuerelement auf. Ich habe mich bei einigen schon gefragt ob die Entwickler aus der gleichen Company stammen. Einfach inkonsistente Eigenschaften und unlogischer Aufbau. Nun kommt auch ein Colorpicker und Rating Control hinzu. Also die Anzahl der Anwendungen die einen Color Picker benutzen ist recht überschaubar. Apps die ich in 35 Jahren geschrieben habe mit einem Color Picker – Zero.

Also wende ich mich dem Rating Control zu. Brauch ich ab und zu, aber ist immer in kürzester Zeit implementiert. Irgendeine Liste mit 5-7 Sternen und gut.

Nun kann das schnucke Rating Control zwar Animationen, aber dann wird es auch schon dünn.

rating

 

Um einen Text daneben zu schreiben, wie die Anzahl der Ratings soll man laut den unbekannten Entwicklern das Attribut Caption verwenden. Im ersten Test steht das irgendwie schräg unten unmotiviert rum und ich wüsste keine Möglichkeit das anders zu platzieren. Mann kann zwar die Sterne warum auch immer  Kursiv oder Bold darstellen, aber nicht über Fontsize größer machen. Das Attribut ist da, wirkt aber nicht.

   1:  <RatingControl HorizontalAlignment="Stretch" VerticalAlignment="Center"
   2:                         Height="150"  
   3:                        IsTextScaleFactorEnabled="True"
   4:                        FontSize="72"
   5:                         MaxRating="7"
   6:                         IsClearEnabled="True"
   7:                         IsReadOnly="False"
   8:                         Caption="(2323)"
   9:                        PlaceholderValue="7"

 

Dann gibt es so eine unsägliche Eigenschaft PlaceholderValue, die dann 7 Sterne schwarz färbt, aber nicht auswählt. Ausgewählte Stars sind blau.

Unsagbarer Bullshit. Ich ärger mich über jede Minute, die ich mit der völlig unzureichenden Dokumentation und dem erraten von Features beschäftigt habe. Note 6.

UWP PersonPicture Control

$
0
0

Noch so ein neues Steuerelement in Windows 10 Fall Creators Update. Das PersonPicture Steuerelement. Es zeigt im Kern ein Bild rund beschnitten oder Initialen an. Typischer Einsatz Zweck: Login Control oder eine Personen Liste.

Dies macht Sinn um ein konsistentes Look&Feel über die WIndows Plattform und seine Apps zu erreichen. Allerdings ist das Control an manchen Stellen etwas seltsam und magisch gestrickt. So nutzt PersonPicture ein Attribut DisplayName, dessen Inhalt aber nirgends angezeigt wird. Nur wenn kein Bild vorhanden ist UND kein Attribut Initials, dann werden die beiden Anfangsbuchstaben als Initialen genommen. Wer denkt sich so was aus?

 

image

   1:  <StackPanelOrientation="Horizontal">
   2:  <PersonPicture
   3:  DisplayName="Florian Silver"/>
   4:  <PersonPicture
   5:  DisplayName="Anne Will"
   6:  Initials="AW"/>
   7:  <PersonPicture
   8:  DisplayName="Babsi Tess"
   9:  BadgeText="Sepp?"/>
  10:  <PersonPicture
  11:  DisplayName="Anne Will"
  12:  ProfilePicture="Assets\hannes.jpg"
  13:  Initials="AW"
  14:  BadgeNumber="99"/>
  15:  <PersonPictureName="Test1"
  16:  BadgeGlyph="&#xe7bf;"
  17:  ProfilePicture="Assets/hannes.jpg"
  18:  DisplayName="Hannes Preishuber"
  19:  FlowDirection="RightToLeft"
  20:  />
  21:  <PersonPictureName="Test5"
  22:  BadgeImageSource="Assets/image02.png"
  23:  ProfilePicture="Assets/hannes.jpg"
  24:  DisplayName="Hannes Preishuber"
  25:  Initials="HP"/>
  26:  <PersonPictureName="Contact1"/>
  27:  </StackPanel>

Nur das Attribut BadgeText scheint gar keinen Anwendungsfall zu kennen.

Eine spannende Variante ist über die Eigenschaft Contact des PersonPictures zu erreichen. Man kann per Binding oder im Codebehind ein Contact Objekt zuweisen. Dies lässt sich auch über den Contact Picker durch den Benutzer auswählen. Das letzte Person Icon in der Liste wird so vom Anwender zugewiesen. Wenn man den C# Code bis Zeile 6 nimmt und das Objekt Contact aus dem ContactPicker dem PersonPicture zuweist, wird man kein Bild sehen, sondern nur die Initialen. Es braucht etwas mehr.

 

   1:  var cp = new ContactPicker();
   2:  cp.DesiredFieldsWithContactFieldType.Add(ContactFieldType.Email);
   3:  cp.DesiredFieldsWithContactFieldType.Add(ContactFieldType.Address);
   4:  cp.DesiredFieldsWithContactFieldType.Add(ContactFieldType.PhoneNumber);
   5:  Contact contact = await cp.PickContactAsync();
   6:  if (contact != null)
   7:      {
   8:      var contactStore = await ContactManager.RequestStoreAsync();
   9:      Contact mycontact = await contactStore.GetContactAsync(contact.Id);
  10:      Contact1.Contact = mycontact;
  11:       } 

Deshalb wird ab Zeile 8 aus dem ContactManager Objekt auf den ContactStore des Users zugegriffen. Dies benötigt aber  ein spezielles Recht Kontaktpersonen, das per Manifest Option zur Laufzeit angefordert wird. Der Benutzer erhält einen Dialog in dem er der App das Recht für Kontakte Zugriff einräumen muss.

image

Neue Angular-Version 5: einfachere JSON-Abfragen, neues Internationalisierungs-API und Performanceverbesserungen

$
0
0

Die neueste Version von Angular ist da: Nach neuntägiger Verspätung und sechs zusätzlichen Release Candidates wurde nun am 1. November mit Angular 5 die neueste Version von Googles Frontend-Framework veröffentlicht.

Nachdem das vor etwa einem Jahr veröffentlichte Angular 2 ein komplett neues Framework darstellte, beinhalteten die seither veröffentlichten Versionen 4 und 5 nur vergleichsweise kleine Änderungen und bestätigen damit, dass Angular einen stabilen und ausgereiften Zustand erreicht hat.

Zu Angular 5 erklärt Google, dass das Hauptziel dieses Releases war, Angular kleiner, schneller und einfacher zu machen. Dementsprechend gibt es eher wenig neue Funktionalität und ein Upgrade sollte sich simpel gestalten.

Neues Modul für HTTP-Anfragen

Ursprünglich hielt das neue httpClient-Modul schon mit Version 4.3 Einzug in Angular, um als Alternative zum http-Modul zu dienen. Nun ist in Version 5 das alte http-Modul explizit als veraltet gekennzeichnet. Das neue httpClient-Modul macht insbesondere die Kommunikation mit JSON-APIs einfacher. Da JSON nun als Standard-Format angenommen wird, kann beispielsweise eine explizite Umwandlung mittels ".map(res => res.json())" entfallen.
Soll doch einmal eine HTTP-Anfrage gesendet werden, die kein JSON zurückliefert, kann dies mit Hilfe des 'responseType'-Parameters erfolgen.

Beispiele:

// das Resultat muss nicht mehr explizit in json konvertiert werdenthis.http.get('https://jsonplaceholder.typicode.com/todos/1')
  .subscribe(data => this.title = data['title']);// Soll etwas anderes als JSON-Daten empfangen werden, muss der Datentyp explizit angegeben werdenthis.http.get('textfile.txt', {responseType: 'text'})
  .subscribe(text => console.log(text));

Internationalisierung

Die i18n-Pipes zur Internationalisierung haben in Angular 5 nun ein leicht verändertes Verhalten und eine neue API bekommen.
Angular 5 greift dafür nicht mehr auf die interne Browserfunktionalität zur Internationalisierung zurück, sondern bedient sich der Daten aus der Unicode Common Locale Data Repository (CLDR). Das hat zur Folge, dass die Darstellung nicht mehr von Browser zu Browser unterschiedlich ist und auch keine Polyfills für alte Browser mehr benötigt werden.
Auch die API für die Internationalisierung in Angular hat sich im Zuge dieser Umstellung geändert. So wird nun für das Datumsformat die Schreibweise und die Standardeinstellung von CLDR verwendet. Bei Geldbeträgen hat sich beispielsweise das Standardformat von "USD4.99" auf "$4.99" geändert.

mehr dazu: https://github.com/angular/angular/blob/master/CHANGELOG.md#i18n-pipes

Angular Universal State Transfer

Angular Universal ist die Technologie, die in Angular serverseitiges Rendering erlaubt. Das führt einerseits zu einer schnelleren Darstellung auf Endgeräten und bewirkt andererseits, dass eine entsprechende Angular-Anwendung einfacher durch web-crawler von Suchmaschinen oder ähnlichem verarbeitet werden kann. Neu ist hier nun eine einfachere Methode, um zusätzlich zur gerenderten Website gleichzeitig die Daten für die anschließende dynamische Dartellung von Inhalten mitzusenden. Die Dokumentation hinkt bei diesem Feature noch hinterher und soll in den nächsten Wochen fertiggestellt werden.

Formular-Validierung

Eine weitere kleine Änderung betrifft die Validierung von Formularen: Hier ist es nun beispielsweise möglich, die Validierung erst durchzuführen, wenn der Benutzer das Formular submittet. Das macht insbesondere Sinn, wenn die Validierung serverseitig und damit mit Verzögerung geschieht: Der Endbenutzer würde seine Eingaben zunächst ohne Validierung im Browser durchführen und beim Absenden eines Formulars eine eventuelle Mitteilung über eine ungültige Eingabe erhalten.

Reduzierte Anwendungsgrößen

In zweierlei Hinsicht wurde bei Angular 5 daran gearbeitet, die im Build-Prozess entstehenden Dateien kleiner zu machen: Zum einen ist der Angular build optimizer nun standardmäßig aktiviert, zum anderen kann irrelevanter whitespace automatisch aus Templates entfernt werden.

Der build optimizer in Angular bedient sich zweier Techniken: Einerseits unterstützt er die schon bestehende tree shaking Funktionalität, um möglichst viel an nicht verwendeten Klassen und Funktionen aus den Bundles entfernen zu können. Andererseits kann er aus den Bundles die Definition von Decorators entfernen, die dort nicht gebraucht werden.

Schnellere AOT-Kompilierung

Eine weitere Optimierung fand bei der ahead-of-time - Kompilierung statt. Mit Hilfe von Typescript Transforms konnte hier bei wiederholt ausgeführten Builds die Performance drastisch gesteigert werden. Beispielsweise soll laut Angular-Team ein erneuter Build von https://angular.io nun statt 40 Sekunden nur noch 2 Sekunden dauern.

Da AOT-Kompilierung bisher nur bei Production Builds - und nicht während der Entwicklung - eingesetzt wurde, war diese Performanceverbesserung bisher nur beim Deployment relevant. Das Angular-Team zielt aber darauf ab, dass nach weiteren Performanceverbesserungen AOT-Kompilierung auch in Development-Builds zum Standard werden kann. Bisher kann das mit dem folgenden Befehl schon ausprobiert werden:

ng serve --aot

Upgradeprozess von alten Angular-Versionen

Das Angular-Team hat für Entwickler den folgenden Upgrade-Guide erstellt, der beim wechseln auf zukünftige Versionen hilft:

https://angular-update-guide.firebaseapp.com/

Davor ist es noch wichtig, das npm-Paket “angular-cli” auf die neueste Version 1.5 zu aktualisieren.

Angular 5 - Schulungen bei PPEDV

Immer auf dem neuesten Stand: Schon jetzt bieten wir bei PPEDV Schulungen an, die auf Angular 5 abgestimmt sind und Ihnen die Grundlagen dazu innerhalb von 2 Tagen vermitteln: http://ppedv.de/Schulung/Kurse/AngularJS-JavaScript-SinglePage-WebApp-SPA-MVC-MVVM-Seminar-Training.aspx

Windows 10: Erstellung eines neuen Administrator-Kontos per Eingabeaufforderung

$
0
0

Heutzutage werden viele Themen der Arbeitswelt in der Cloud geregelt. So setzt auch Microsoft immer mehr auf Microsoftkonten die kostenlos erstellt werden können und einiges an Vorteile bieten, wie zum Beispiel die Synchronisation von Daten auf alle mit diesem Konto verbundene Geräte. Sollte man einmal das Passwort zu einem Onlinekonto vergessen haben, gibt es verschiedene Möglichkeiten diese zurück zu setzten. Doch wie geht man vor, wenn ich das Passwort meines lokalen Kontos vergesse und im schlimmsten Falle dieses auch noch das Administratorkonto ist?

Heute zeig ich euch wie man sich ein neues Administratorkonto per Eingabeaufforderung erstellt:
(Solange die Systemplatte nicht Bitlocker-Verschlüsselt ist)

Zu aller erst ist es wichtig, das System von einem bootfähigem Medium zu starten. Hier reicht schon eine einfache Windows10 DVD oder zum Beispiel ein bootfähiger USB Stick.

Sobald sich das Setup für eine neue Installation öffnet, kann man mit der Tastenkombination
“Shift + F10” eine Eingabeaufforderung öffnen.

Hier müssen nun folgende Befehle eingegeben werden:

    1. move c:\windows\system32\utilman.exe c:\windows\system32\utilman.alt
      Damit wird die Datei für die erleichterte Bedienung verschoben
    2. copy c:\windows\system32\cmd.exe c:\windows\system32\utilman.exe
      Damit wird eine Commandline als erleichterte Bedienung im System platziert

Anschließend muss das System neu gestartet und bis zum Anmeldefenster gebootet werden.

Wenn jetzt auf das Symbol der erleichterten Bedienung geklickt wird ( clip_image002) öffnet sich eine Eingabeaufforderung mit Administrator Berechtigungen.

Hier müssen zwei Befehle eingegeben werden:

    1. net user BENUTZERNAMEPASSWORT /add
      Zum Anlegen eines neuen Kontos mit Passwort
    2. net localgroup administratoren BENUTZERNAME /add
      Hinzufügen des Kontos zu der Gruppe der Administratoren

clip_image004

Nachdem das Konto erstellt und der Gruppe hinzugefügt wurde, muss das System neugestartet werden. Daraufhin kann man sich mit dem neuen Konto anmelden.

Da es sich hier um einen neuen Benutzer handelt, wird man alle Standardeinstellungen vorfinden und nicht seine personalisierte Oberfläche.

Mit der Tastenkombination „Windows-Taste + R“ öffnet sich das Ausführen Fenster. Dort muss der Befehl „control userpasswords2“ eingegeben werden um das Fenster für die Benutzerkontenverwaltung zu öffnen. Dort hat man die Möglichkeit bei seinem ursprünglichen Benutzerkonto auf „Kennwort zurücksetzten“ zu klicken und ein neues Passwort zu vergeben.

image

Danach muss Windows erneut gestartet werden und ein Anmelden mit dem alten Konto ist wieder möglich. Über die Benutzerkontenverwaltung kann das neue Konto wieder entfernt werden.

Wichtig ist, dass am Ende die Utilman.exe gelöscht wird und die Utilman.alt wieder zu Utilman.exe umbenannt wird, sonst bleibt die erleichterte Bedienung eine Commandline.
(Ort der Dateien bei Standardinstallation: C:\Windows\System32 )

Jetzt seid ihr wieder in der Lage auf euer System und eure ganzen Daten zuzugreifen.

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

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

ASP.NET Webforms Login mit bestehender Datenbank

$
0
0

Es gibt Oracle Server und ASP.NET Webforms und gewachsene Infrastrukturen. Genau so ein Fall ist mir in meiner letzten ASP.NET Webforms Schulung begegnet. Authentication ohne Identity oder Membership Provider. Ganz Easy.

Um ehrlich zu sein, es war doch nicht so einfach. Wenn man heute ein Web Projekt mit Visual Studio anlegt, wird nämlich auf das neue ASP.NET Identity Login gesetzt. Der erste Weg führt in die Datei Web.config um die gute alte Forms Authentifizierung zu aktivieren.

Als erstes wird Zeile 3 entfernt um das Modul im Web Server wieder nutzen zu können.

   1:  <system.webServer>
   2:  <modules>
   3:  <removename="FormsAuthentication"/>
   4:  </modules>
   5:  </system.webServer>

 

Weiters werden anonyme Zugriffe (das Fragezeichen)  verboten und die Authentication auf formularbasiert eingestellt. Das Login Formular wird als login.aspx deklariert.

   1:  <authenticationmode="Forms">
   2: <formsdefaultUrl="default.aspx"loginUrl="login"></forms>
   3:  </authentication>
   4:  <authorization>
   5:  <denyusers="?"/>
   6:  </authorization>
   7:  

Normalerweise würde man die login.aspx Seite auch nicht aufrufen können, aber ASP.NET fügt eine Ausnahme hinzu. Da im Standard Projekt die FriendlyUrl Erweitertung aktiviert ist loginurl ohne aspx.

Allerdings ist noch eine weitere Erweiterung aktiv die erst, abgedreht werden muss. In der Datei Startup.cs (app_code) muss folgende C# Codezeile entfernt werden :    ConfigureAuth(app);

Die Login Seite enthält neben dem Formular nur eine Zeile, die die eigentliche Authentifizierung durchführt und auf die ursprüngliche angeforderte Seite umleitet. Der zweite Parameter true, setzt den Login Cookie dauerhaft

image

Natürlich wird statt dem if(true) der Vergleich mit Username und Passwort aus der Datenbank durchgeführt.

   1:  <!DOCTYPEhtml>
   2:   
   3:  <scriptrunat="server">
   4:   
   5:  protectedvoid login_Click(object sender, EventArgs e)
   6:      {
   7:  //superduper komplexe Datenbank abfrage
   8:  if (true)
   9:          {
  10:              FormsAuthentication.RedirectFromLoginPage(benutzer.Text, true);
  11:          }
  12:   
  13:      }
  14:  </script>
  15:   
  16:  <htmlxmlns="http://www.w3.org/1999/xhtml">
  17:  <headrunat="server">
  18:  </head>
  19:  <body>
  20:  <formid="form1"runat="server">
  21:  <div>
  22:              Benutzer<asp:TextBoxID="benutzer"
runat="server"></asp:TextBox><br/>

23: Passwort<asp:TextBoxID="password"Te

xtMode="Password"runat="server"></asp:TextBox><br/>

  24:  <asp:ButtonID="login"runat="server"
Text="login"OnClick="login_Click"/>
  25:  </div>
  26:  </form>

In allen anderen Seiten kann dann mit dem User Objekt auf den Login Status oder den Usernamen zugegriffen werden.

   1:  <h1>Hallo <%=User.Identity.Name %></h1>
   2:  
Viewing all 1198 articles
Browse latest View live