27.05.2013 14:08:00
|
Ralf Westphal
Wie soll man eigentlich Profi in der Anwendung der Prinzipien und Praktiken von Clean Code Developer werden? Durch Übung :-) Und zwar zunächst einmal durch Übung an Übungen, d.h. nicht am Produktionscode des Tagesgeschäftes.
Woher aber solche Übungen nehmen? Es gibt einige Übungsvorschläge, die sog. Code Katas. Doch die sind meist sehr, sehr überschaubar. Es sind vor allem Übungen im Entwickeln
23.05.2013 20:02:41
|
Christian Binder
ich kann schon mal ankündigen, dass wir im Oktober wieder eine Visual Studio Evolution planen. Dort werden wir an einem Tag die aktuellsten Neuerungen zu Visual Studio, .NET und der Windows Plattform zeigen. Wir haben uns schon einiges ausgedacht. Wir halten Euch auf dem laufenden, sobald wir die Details für das Event haben.
Ich selbst werde bis zum 1. September einen verdienten Sabbatical machen und wichtige Dinge in Angriff nehmen
, mein Team wird Euch während dieser Zeit aber weiterhin aktuelle Infos über meinen Blog bereitstellen.
23.05.2013 18:09:50
|
Fabian Deitelhoff
Sich für den richtigen Master nach dem Bachelorstudium zu entscheiden, ist gar nicht so einfach. Es gibt viele Wege und Möglichkeiten, die einem grundsätzlich offen stehen. Warum grundsätzlich? Sollte das Bachelor-/Mastersystem nicht den Wechsel von Fachrichtungen und Hochschulen beziehungsweise Universitäten erleichtern? Sollte es. Theoretisch ist das auch so. In diesem Beitrag möchte ich gerne ein [...]
23.05.2013 12:59:00
|
Ralf Westphal
Letzten Dienstag habe ich im wöchentlichen Unterrichtsblock der Clean Code Developer School (ccd-school.de) “TDD as if you meant it” anhand der Kata WordWrap vorgestellt. Dann wollten die Teilnehmer es selbst probieren. Als Aufgabe habe ich die Kata ToDictionary vorgeschlagen. Leider führte die dann nicht in so geradliniger Weise zu “Refactoring-Druck”, wie ich es mir erhofft hatte. Es wollten
22.05.2013 18:51:17
|
Fabian Deitelhoff
In the mid of February 2013 I’ve read this article on the Pluralsight blog. In this article Aaron Skonnard, the CEO of Pluralsight, mentioned a great opportunity for new authors in the year 2013. Because of the Series A funding announcement, Pluralsight will publish over 600 new courses during the year 2013. I immediately thought that [...]
21.05.2013 15:07:09
|
Oliver Scheer
Die Veranstaltungsreihe "App Developer Day – Windows 8 Edition" bietet den perfekten Einstieg in die App-Entwicklung. Renommierte Experten geben einen umfassenden Überblick über die Windows-Plattform sowie die Entwicklungsmöglichkeiten sowohl...(
read more)
20.05.2013 23:39:24
|
Alexander Zeitler
If you’re using SQL Azure and try to connect using SQL Server Management Studio or SQL Server Data Tools and you’re beaten with a dynamic IP address, you might face this on a daily basis:

The next step would be to open the Azure Management Portal and add a new Firewall rule for your current external IP address. And this becomes awkward on the second day at the latest.
Thanks to the Windows Azure PowerShell Cmdlets (you can get them using Web PI), this must not be.
Just create a new rule using the Cmdlets using NewAzureFirewallRule.ps1 and update it using SetAzureFirewallRule.ps1:
17.05.2013 02:32:00
|
Alexander Zeitler
If you’re hosting RavenDb 2.0 on IIS 7.5 / 8 and you have activated Windows authentication according to the official RavenDb documentation, your browser might keep prompting for the username and password and show you “Unauthorized” after the third attempt when you’re trying to create a new database:

If this is the case, you should set
<add key="Raven/AnonymousAccess" value="Admin" />
inside the web.config
Now you can create (and delete) new databases using Windows Authentication:

16.05.2013 18:19:00
|
Martin Hey
Die Anforderung ist recht schnell erklärt: Erkenne, wann ein Fenster einer Anwendung maximiert, minimiert oder wiederhergestellt wird. "Das kann doch so schwer nicht sein" denkt man sich da, schließlich wirft Windows ja nur so mit Nachrichten um sich, die man einfach nur abfangen muss. Die Windows-API ist dein Freund. Ok, ganz so einfach ist es dann doch nicht, sonst bräuchte dieser Blogpost ja nicht geschrieben werden.
Damit das Fensterhandling und auch so ziemlich alles andere in Windows funktioniert, werden Nachrichten an Fenster gesendet. Zumeist macht Windows das selbst (z.B. Fenster 358: Maximiere dich"). Kommt diese Nachricht am Fenster an, gibt es dort eine Kette von "Abonnenten" - die hook chain. Und in diese Kette kann man eigene Funktionen eingliedern lassen, die dann Teil dieser Kette werden.
Mit diesem Wissen ist die relevante Methode ist auch recht schnell gefunden: SetWindowsHookEx in der user32.dll. Damit gliedert man eine Funktion in die hook chain ein und bekommt dabei einen Handle für den nächsten Teilnehmer der Kette - also den an den die Nachricht dann geschickt werden muss, wenn meine Bearbeitung fertig ist.
Eine gute Anlaufstelle für Fragen, wenn es um die Syntax oder die Verwendung geht, ist entweder die Windows API-Dokumentation in der MSDN - wo C-Syntax verwendet wird und die Parameter inzwischen auch recht ausführlich beschrieben sind - oder pinvoke.net - wo es auch Beispiele zur Umsetzung in C# oder VB.NET gibt. Dort lernt man dann auch schnell, dass man einige Voraussetzungen schaffen muss, um diese Funktionen verwenden zu können.
Wie implementiert man den Hook?
Zunächst werden die Methoden definiert, die importiert werden sollen: Mit SetWindowHookEx kann die Methode in die Kette eingereiht werden. Und natürlich benötigt man dann auch noch UnhookWindowsHookEx, um diesen Eintrag später auch wieder entfernen zu können. Des weiteren habe ich schon erwähnt, dass man dafür Sorge tragen muss, den Folgeeintrag in der Kette aufzurufen, deshalb wird auch noch CallNextHookEx benötigt.
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int code, HookDelegate func, IntPtr hInstance, uint threadId);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
Im Import von SetWindowsHookEx wird im zweiten Parameter auf einen Delegate verwiesen. Dieser muss ebenfalls definiert werden:
public delegate int HookDelegate(int code, IntPtr wParam, IntPtr lParam);
Und man sieht, dass SetWindowsHookEx eine ThreadId erwartet. Damit die Funktion aber nun mit einen Fenster-Handle verwendet werden kann, wird nun noch GetWindowThreadProcessId benötigt, um dieses Mapping durchführen zu können. aber das ist nur Makulatur und für die eigentliche Funktionalität irrelevant:
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr lpdwProcessId);
So weit, so gut. Nun sieht man in den Deklarationen aber auch, dass sehr viele int-Werte verwendet werden. Für Menschen sind Zahlen immer etwas schwierig zu lesen - aus diesem Grund werden noch ein paar Enumerationen deklariert.
Der Hooktype definiert, welche Art von Nachricht interessant sind. Danach richtet sich im späteren Verlauf, wie die Informationen der Nachricht interpretiert werden müssen:
public enum HookType : int
{
WH_JOURNALRECORD = 0,
WH_JOURNALPLAYBACK = 1,
WH_KEYBOARD = 2,
WH_GETMESSAGE = 3,
WH_CALLWNDPROC = 4,
WH_CBT = 5,
WH_SYSMSGFILTER = 6,
WH_MOUSE = 7,
WH_DEBUG = 9,
WH_SHELL = 10,
WH_FOREGROUNDIDLE = 11,
WH_CALLWNDPROCRET = 12,
}
Für die gewünschte Funktionalität wird WH_CallWndProcRet von Interesse sein, da diese Art von Nachricht dann aufgerufen wird, wenn eine Fensterfunktion fertig ausgeführt ist. Die Nachricht dieses Nachrichtentyps lässt sich mit folgendem Struct darstellen:
[StructLayout(LayoutKind.Sequential)]
public struct CwpRetStruct
{
public IntPtr lResult;
public IntPtr lParam;
public IntPtr wParam;
public uint message;
public IntPtr hwnd;
};
Dabei wird dann im Feld message stehen, welche Nachricht geschickt wurde - im gezeigten Fall werden nur Systemcommands von Interesse sein:
public enum WindowsMessages : uint
{
WM_SYSCOMMAND = 0x0112
}
Und im Feld wParam wird stehen, welche genaue Ausprägung dieses Command hat:
public enum SystemCommands : int
{
SC_SIZE = 0xF000,
SC_MOVE = 0xF010,
SC_MINIMIZE = 0xF020,
SC_MAXIMIZE = 0xF030,
SC_NEXTWINDOW = 0xF040,
SC_PREVWINDOW = 0xF050,
SC_CLOSE = 0xF060,
SC_VSCROLL = 0xF070,
SC_HSCROLL = 0xF080,
SC_MOUSEMENU = 0xF090,
SC_KEYMENU = 0xF100,
SC_ARRANGE = 0xF110,
SC_RESTORE = 0xF120,
SC_TASKLIST = 0xF130,
SC_SCREENSAVE = 0xF140,
SC_HOTKEY = 0xF150,
SC_DEFAULT = 0xF160,
SC_MONITORPOWER = 0xF170,
SC_CONTEXTHELP = 0xF180,
SC_SEPARATOR = 0xF00F,
SCF_ISSECURE = 0x00000001,
SC_ICON = SC_MINIMIZE,
SC_ZOOM = SC_MAXIMIZE,
}
Nun aber genug der Vorbereitungen: Die Funktionalität muss auch noch implementiert werden. Der Rumpf meiner Klasse sieht nun wie folgt aus:
public class WindowMessageInterceptor : IDisposable
{
private IntPtr nextHookPtr;
private HookDelegate callbackDelegate;
public WindowMessageInterceptor(IntPtr hWnd)
{
}
public void Dispose()
{
}
}
Der Konstruktor erwartet ein Fensterhandle, es gibt Membervariablen für die Delegateinstanz und den Pointer auf den Folgeeintrag in der hook chain, im Konstruktor wird der Hook später gesetzt werden und im Dispose wird der Hook wieder entfernt werden.
Der Konstruktor sieht mit diesem Wissen auch recht unspektakulär aus:
public WindowMessageInterceptor(IntPtr hWnd)
{
// determine ThreadId for specified Window
var threadId = GetWindowThreadProcessId(hWnd, IntPtr.Zero);
// initialize the callback delegate
this.callbackDelegate = new HookDelegate(this.HookCallbackFunction);
// setup a window message hook and add it to hook chain
this.nextHookPtr = SetWindowsHookEx((int)HookType.WH_CALLWNDPROCRET, this.callbackDelegate, IntPtr.Zero, threadId);
if (this.nextHookPtr == IntPtr.Zero)
{
throw new Exception("unable to apply hook");
}
}
und ebenso das Dispose:
public void Dispose()
{
if (this.nextHookPtr == IntPtr.Zero)
{
return;
}
UnhookWindowsHookEx(this.nextHookPtr);
this.nextHookPtr = IntPtr.Zero;
}
Spannend ist die Callback-Funktion:
private int HookCallbackFunction(int code, IntPtr wParam, IntPtr lParam)
{
// If code is less than zero, the hook procedure must return the value returned by CallNextHookEx.
if (code < 0)
{
return CallNextHookEx(this.nextHookPtr, code, wParam, lParam);
}
// otherwise do all the things and call NextHookEx afterwards
// convert the lparam to our struct
var message = (CwpRetStruct)Marshal.PtrToStructure(lParam, typeof(CwpRetStruct));
// evaluate the message
if (message.message == (uint)WindowsMessages.WM_SYSCOMMAND)
{
Console.Write("syscommand detected: ");
switch (message.wParam.ToInt32())
{
case (int)SystemCommands.SC_RESTORE:
Debug.WriteLine("window restored from maximized state");
break;
case (int)SystemCommands.SC_MINIMIZE:
Debug.WriteLine("window minimized");
break;
case (int)SystemCommands.SC_MAXIMIZE:
Debug.WriteLine("window maximized");
break;
default:
Debug.WriteLine("not important");
break;
}
}
return CallNextHookEx(this.nextHookPtr, code, wParam, lParam);
}
Was passiert hier?
Zunächst wird geprüft, ob der Code größer als 0 ist. Laut API-Dokumentation ist die Nachricht nur dann auch für diese Methode gedacht. Im Anschluss daran muss die Nachricht ausgewertet werden. Damit das passieren kann, bietet das Framework die Methode PtrToStructure. Damit kann der lParam-Wert des Callbacks, in dem sich die Informationen befinden, in das Nachrichtenformat konvertiert werden. Und aus dieser Nachricht interessiert nun, wie man der API entnehmen kann der wParam-Wert.
Im Anschluss wird der Hook an den Folgeempfänger weitergeleitet.
Der Test
Für den Test gibt es einen weiteren Konstruktor, der als ThreadId einfach die ThreadId der aktuellen Applikation übergibt:
public WindowMessageInterceptor()
{
// initialize the callback delegate
this.callbackDelegate = new HookDelegate(this.HookCallbackFunction);
// setup a window message hook and add it to hook chain
this.nextHookPtr = SetWindowsHookEx((int)HookType.WH_CALLWNDPROCRET, this.callbackDelegate, IntPtr.Zero, (uint)AppDomain.GetCurrentThreadId());
if (this.nextHookPtr == IntPtr.Zero)
{
throw new Exception("unable to apply hook");
}
}
Und das funktioniert auch ganz gut: Die entsprechenden Nachrichten werden angezeigt. Und auch wenn man das Fensterhandle der aktuellen Anwendung übergibt, funktioniert alles super
Aber.....
Versucht man das Ganze nun mit einem fremden Fensterhandle, so schlägt das Setzen des Hooks fehl. Aber warum?
Auch hier hilft die Dokumentation weiter. Sinngemäß steht dort: Hooks können innerhalb der eigenen Anwendung gesetzt werden, indem als Modul-Handle (Parameter 3) IntPtr.Zero übergeben wird und dann im vierten Parameter die ThreadId. Um den Hook auf fremde Fenster zu setzen, muss als ModulId die ModulId des fremden Programms angegeben werden, der Callback muss in einer Dll sein und das Fremde Programm muss diese Dll geladen haben. Und genau das ist der Knackpunkt, denn hier greifen Sicherheitsmechanismen von .NET, die genau das verhindern.
Resümee
Für den gezeigten Anwendungsfall kommt man mit SetWindowsHookEx nicht weiter, da nur die aktuelle Anwendung abgefragt werden kann. Und das geht mit Bordmitteln wesentlich einfacher, indem man Events auf dem Hauptfenster abonniert - in WPF wäre das das WindowStateChanged-Event.
16.05.2013 15:09:36
|
Oliver Scheer
Zu gut Auf www.bing.com gehen und “beam me up” eintippen. ...read more...(
read more)
16.05.2013 14:18:03
|
Oliver Scheer
Ab dem 31. Mai 2013 gibt es Surface Pro in Deutschland über www.microsoftstore.com und im Fachhandel. Das Gerät wird in zwei unterschiedlichen Versionen verfügbar sein: Ein 64-GB Modell für 879 Euro (UVP) sowie eine Variante mit 128-GB für 979 Euro...(
read more)
16.05.2013 13:36:15
|
Thomas Schissler
Der TFS Build geht standardmäßig so vor, dass er vor einem Build, alle Dateien sauber
löscht und dann den kompletten Workspace neu aus der Versionsverwaltung holt. Ein
solcher “Clean Build” birgt natürlich das geringste Risiko, dass veraltete Dateien
in den Build einfließen oder dass der Build Dateien benutzt die gar nicht mehr in
der versionsverwaltung enthalten sind. Aber gerade bei größeren Projekten ist das
natürlich auch sehr ineffizient. deshalb kann man im TFS Build einstellen, wie er
sich verhalten soll.
In den Build Process Parametern gibt es eine Einstellung dafür.
Dieser Parameter hat 3 mögliche Einstellungen:
-
All – Mit dieser Einstellung werden sowohl der Source Code all auch alle Outputs des
Builds gelöscht (Clean Build). Dies ist die Default-Einstellung
-
Outputs – Der Build löscht die Outputs, nicht aber die Sourcen. Für die Sourcen wird
ein get Latest ausgeführt, d.h. es werden nur geänderte Dateien vom TFS heruntergeladen
-
None – Sowohl Outputs als auch Sourcen bleiben erhalten. Nach einem Get Latest wird
ein Build ausgeführt und dabei nur Projekte gebaut bei denen sich die SOurcen bzw.
die Referenzen geändert haben
So weit so gut. Ich hatte einen Build auf “Outputs” gestellt und dann folgenden Fehler
bekommen:
Warning C:\Builds\101\Projekt\artiso_Working1_CI\Sources\Solutions\artisoSolutions\WCH_Diff\NoDeploy.testsettings
- Unable to perform the delete operation because the file already exists locally
Völlig unlogisch, dass eine Datei nicht gelöscht werden kann, weil
sie schon existiert, aber nun gut. Die Ursache war dann auch schnell gefunden. Um
die Version in der AssemblyInfo.cs während des Builds zu ändern, hebe ich den Schreibschutz
dieser Dateien auf. Und der Get hat nun ein problem, wenn da Dateien rumliegen die
keinen Schreibschutz haben, da diese ja geändert sein könnten und er die nicht einfach
überschreibt. Es gibt aber eine kleine Einstellung im Workflow mit der man dieses
Verhalten anpassen kann:
Man sucht die Gte Workspace Activity im Workflow
Dann stellt man in den Properties die GetOptions auf “Overwrite”
Damit überschreibt der Build beim Get nun die Dateien ohne Schreibschutz-Attribut
und der Build läuft problemlos durch – und das nun auch deutlich schneller als zuvor.
>>
15.05.2013 22:44:19
|
Hendrik Loesch
… and all I got was this lousy Christmas tree. I like TDD and I like test automation. It is great to see the application growing with each successful test and to be sure that it will work even if a lot of changes are made on the code base. On the other I see [...]
15.05.2013 19:16:12
|
Stephan Walcher
Viele kennen sicherlich das Google Easter Egg do the barrel roll, durch das sich das komplette Google Fenster bewegt. Bing hat nun auch endlich sein erstes kleines Easter Egg das wohl passend zum neuen Star Trek Film eingeleitet worden ist. Gibt man nämlich bei Bing den Suchbegriff Beam me up, wird man vom normalen Hintergrund [...]
The post Bing mit Star Trek Easter Egg appeared first on Prometeo.
15.05.2013 15:30:15
|
Christian Binder
14.05.2013 12:23:00
|
Ralf Westphal
Warum soll im Business eigentlich immer alles perfekt sein? Oder, nein, nicht perfekt, aber "effizient". Ein Beispiel dafür ist mir gerade im Rahmen eines Hobbyprojekts untergekommen: der hey! publishing Verlag.
Eine befreundete Autorin hat dort einen Roman veröffentlicht, "Die Martinis":
Der ist als eBook erschienen. Und das war´s. Weiter ist nichts geschehen (Stand Anfang Mai 2013), obwohl
13.05.2013 17:41:22
|
Oliver Scheer
Kostenlos als Download hier verfügbar: http://www.microsoft.com/en-us/download/details.aspx?id=38782&WT.mc_id=rss_alldownloads_all ...read more...(
read more)
13.05.2013 17:10:55
|
Gregor Biswanger

Passend zu meiner letzten DVD “Meine erste Windows 8 App”, gibt es jetzt das umfangreiche Video-Training zum Thema “Windows Store Apps mit XAML und C#”. In diesem Video-Training erkunden und erlernen wir ausführlich die faszinierenden Möglichkeiten der App-Entwicklung für Windows 8 und Windows RT. Wir steigen mit den Grundlagen von XAML ein und sind auch bald mit den wichtigsten Neuerungen der Windows Runtime vertraut. Mit den Best Practices zum Thema MVVM - Model View ViewModel - und vielen Profi-Tipps steigst Du bald auf zum versierten App-Entwickler und -Designer.
Weitere Informationen
- Produktübersicht
- Inhaltsverzeichnis
Kostenfreie Probevideos
Facebook Fanpage
Weitere Tipps und Tricks zur Windows Store App Entwicklung findest du regelmäßig auf der Facebook Fanpage von “Meiner ersten Windows 8 App”: https://www.facebook.com/MeineErsteWindows8App
Großes Geek-Gewinnspiel in Kooperation mit WindowsDeveloper.de bis zum 19.05.2013

Zu Gewinnen gibt es eine Signierte-Version meiner DVD “Meine erste Windows 8 App”. Dabei wurde die DVD nicht von mir persönlich unterzeichnet, sondern ich habe diese direkt in Redmond vom WinRT-Team verewigen lassen. Dabei sind Unterschriften von Tim Heuer (Program Manager für Microsoft XAML), Unni Ravindranathen (Program Manager für Microsoft Expression) und drei weiteren Mitgliedern des WinRT Teams.
Außerdem verlosen wir vier Zugänge zum neuen video2brain-Online-Training “Windows Store Apps mit XAML und C#”.

Zum Gewinnspiel geht es hier lang: [Geek-Gewinnspiel] Zeit für Windows 8! – Einsteiger-Tutorials zu gewinnen
Nun wünsche ich allen viel Spaß beim Rätseln!
Besten Dank
Besten Dank an das ganze video2brain-Team!

12.05.2013 23:50:51
|
Robert Mühsig
Windows Authentifizierung ist eine einfache (und naheliegende) Authentifizierungs-Option für “Haus-interne” Webapplikationen. Setup Im IIS selbst kann man die Windows Authentifzierung sehr leicht anschalten: Natürlich kann man dies auch über die web.config steuern: <system.web> ... <authentication mode="Windows"/> ... </system.web> ... Fehlermeldung “HTTP Error 401.2 – Unauthorized”: Dies kann (wie fast immer) viele Gründe haben, z.B. weil ...
09.05.2013 19:45:00
|
Stefan Lange
Zu meinem Vortrag „Einführung in die Windows Azure Mobile Services“ auf der dotnet Cologne 2013 finden sich hier die Slides.
Die Slides wurden an den aktuellen RC der Mobile Services angepasst.
Materialien zum Vortrag:
08.05.2013 20:12:46
|
Thomas Schissler
Seit dem Update 2 ist es nun endlich wieder möglich, das Lab Management im TFS 2012
auch mit XP-Maschinen zu betreiben. Das Problem war hier bisher, dass der Test Agent
2012 das .Net Framework 4.5 benötigt, dass sich das aber auf XP nicht installieren
lässt. Man kann nun die Test Agents für 2012 Update 2 hier herunterladen: http://www.microsoft.com/en-us/download/details.aspx?id=38186.
Wie man bei der Installation vorgehen muss, wird hier beschrieben: http://msdn.microsoft.com/en-us/library/jj153008.aspx#installagent.
Das Dokument hat jedoch einen kleinen Schönheitsfehler. Es verschweigt nämlich die
Tatsache, dass man vor der Installation des Test Agents das .Net Framework manuell
installieren muss. Das Setup des Test Agents versucht nämlich das Framework zu installieren,
wenn keines vorhanden ist, dummerweise aber immer das 4.5er. Probleme gibt es übrigens
auch, wenn nur ein älteres Framework (z.B. 3.5) installiert ist. Dort schlägt die
Installation fehl. Auch hier hilft einfach Framework 4.0 manuell zu installieren.
Lustig finde ich auch die Fehlermeldung “0x800713ec – Asia”
08.05.2013 01:28:59
|
Robert Mühsig
Wo APIs im Spiel sind, ist das JSON Format nicht weit. Da ich immer mal wieder zwei Tools benutze, möchte ich diese hier auch mal kurz würdigen. JSON Viewer Wer nur den JSON-Text vor sich hat sieht meist die Struktur nicht. Über JSON Viewer kann man sich recht einfach einen Überblick verschaffen: [URL] JSON2CSharp Der ...
07.05.2013 17:38:51
|
Thomas Schissler
Wenn man unter Windows 8 Coded UI Tests auf laufen lassen möchte, hat man Probleme,
wenn man die Tests z.B. in einer Lab Umgebung mit Autologon ausführen möchte. D.h.
die Maschine bootet aus einem Snapshot und wird automatisch angemeldet. Dann bekommt
man als erstes den Windows 8 Startbildschirm. Da der Coded UI Test diesen nicht steuern
kann, haben wir hier ein Problem. Mit einem kleinen Tool kann man Windows 8 aber auch
so konfigurieren, dass es direkt mit dem Desktop startet. Vielleicht ist das ja auch
für andere Szenarien als dem hier beschriebenen interessant
http://win-8.de/MetroDeactivator/
07.05.2013 12:10:00
|
Ralf Westphal
Könnten Sie oder die Firma, für die Sie arbeiten, mehr verdienen? Ja? Wunderbar, dann los! Nein? Warum nicht? Woher weiß man das?
Auf diese Frage bin ich neulich bei einem Aufenthalt im Marriott Hotel in Zürich gestoßen. Dort fand ich nämlich dieses Angebot vor:
Zum Verkauf auf dem Zimmer standen solche 1 Liter Flaschen Wasser für 8,00 CHF (ca. 6,50 EUR) das Stück.
Ein stolzer Preis,
07.05.2013 10:07:00
|
Sascha Dittmann
In den bisherigen Teilen meiner Windows Azure Mobile Services Serie wurde eine Windows Store App erstellt, welche Nachrichten in der Cloud speichert.
Bislang waren diese Nachrichten keinem Benutzer zugeordnet worden.
Dies soll sich heute ändern, indem die Benutzer via Microsoft Account authentifiziert werden...
App im Live Connect Developer Center registrieren
Damit sich die Benutzer der Windows Store App via Microsoft Account authentifizieren können, muss diese zuerst im Live Connect Developer Center registriert werden.
Dazu navigiert man zuerst auf die My Applications Seite des Live Connect Developer Centers.
Mit einem Klick auf den Create Application-Link wird die Registrierung gestartet:

Nachdem man den Namen der App sowie die primäre Sprache angegeben hat, klickt man auf "I accept":

Unter den API Settings findet man dann die Client ID und das Client Secret, die man im nächsten Schritt benötigt.
Außerdem muss die URL des entsprechenden Mobile Services als "Redirect Domain" eingetragen werden:

Änderungen bei den Mobile Services
Die gerade erhaltene Client ID, sowie das Client Secret, trägt man anschließend in den Identity Bereich des Mobile Services ein und klickt "Save":

Jetzt sind die Mobile Services bereit, um die Benutzer via Microsoft Account authentifizieren zu können.
Änderungen an der Windows Store App
Damit die Anwender der Windows Store App zur Eingabe ihrer Microsoft Account-Benutzerdaten aufgefordert werden, genügt eine Zeile Code:
await _mobileServiceClient.LoginAsync(
MobileServiceAuthenticationProvider.MicrosoftAccount);
Um dabei auch mögliche Fehlermeldungen, die beispielsweise beim Abbrechen des Dialogs auftreten, abzufangen sieht die entsprechende Methode im ViewModel der "Let's Talk"-App wie folgt aus:
private async Task Authenticate()
{
if (_mobileServiceClient.CurrentUser != null) return;
var message = String.Empty;
try
{
await _mobileServiceClient.LoginAsync(
MobileServiceAuthenticationProvider.MicrosoftAccount);
}
catch (InvalidOperationException)
{
message = "login unsuccessful";
}
catch (Exception ex)
{
message = ex.Message;
}
if (!String.IsNullOrEmpty(message))
await new MessageDialog(message, "Authenticate User").ShowAsync();
}
Für die Benutzer stellt sich das wie folgt dar:

Bei der ersten Anmeldung muss außerdem der Zugriff auf die Daten des Benutzers bestätigt werden:

Berechtigungen auf Tabellenebene anpassen
Nur angemeldete Benutzer sollen Nachrichten hinzufügen bzw. löschen können.
Um dies zu gewährleisten, müssen die Insert- und Delete-Rechte der Messages-Tabelle auf "Only Authenticated Users" gesetzt werden.
Außerdem sind in den "Let's Talk"-Apps Änderungen an den Nachrichten nicht zulässig, weshalb das Update-Recht nur für Skripte und Administratoren freigegeben wird:

Damit beim Hinzufügen einer Nachricht auch der Benutzer gespeichert wird, muss eine weitere Zeile im Insert-Skript hinzugefügt werden:
function insert(item, user, request) {
if (!item.body || item.body.length < 2) {
request.respond(statusCodes.BAD_REQUEST, 'The message text must be 2 or more characters long.');
return;
}
item.createdAt = new Date();
item.userId = user.userId;
request.execute();
}
Durch das Dynamische-Schema-Feature der Mobile Services wird beim nächsten Speichervorgang die Messages-Tabelle um die UserID Spalte erweitert.
Auch das Löschen der Nachrichten soll nur dessen Besitzer erlaubt werden.
Dies kann durch folgendes Delete-Skript der Messages-Tabelle erreicht werden:
function del(id, user, request) {
var messagesTable = tables.getTable('messages');
messagesTable.where({
id: id,
userId: user.userId
}).read({
success: function(results) {
if (results.length === 0) {
request.respond(statusCodes.UNAUTHORIZED, 'You can only delete you own messages.');
}
else {
request.execute();
}
}
});
}
Dieses macht eine Lookup-Abfrage auf die Messages-Tabelle und wirft eine Fehlermeldung, wenn der Benutzer versucht eine fremde Nachricht zu löschen.
Wie geht es weiter?
Im nächsten Teil dieser Serie wird die Windows Store App mit einer Microsoft-Account-Authentifizierung via Live SDK erweitert, damit die Benutzer sich automatisch mit ihrem für die Windows Anmeldung genutztem Konto anmelden können.
 |
Beispielanwendung:
Weitere Informationen:
|