Thursday, June 28, 2012

Reading file content using DataReader.ReadBytes in Metro apps

The Windows.Storage.Streams.DataReader.ReadBytes method stupidly breaks with the convention of the other methods on the DataReader object, by requiring you to pass in a variable to populate, instead of instantiating a new variable and returning it.

Looking at the declaration of this method:

[MethodImpl]
void IDataReader.ReadBytes([Out] byte[] value);

we see that the value is marked with an Out attribute. Note that this is not the same as an out parameter modifier.

To have your passed in value correctly populated, you need to instantiate the byte array to pass in, using the correct capacity. The capacity is available on your reader in the UnconsumedBufferLength property.

Here's a sample of using this method:

StorageFile file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync("[filename]");
IBuffer buffer = await FileIO.ReadBufferAsync(file);
DataReader reader = DataReader.FromBuffer(buffer);
byte[] fileContent = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(fileContent);

Thursday, June 21, 2012

Deserialising a JSON formatted string to a dynamic object in C# Metro Style Apps

I found myself looking for an easy way to deserialise Json strings to dynamic objects today. Of course there are many excellent libraries (like Json.net) that will already do this for you. The problem is that I need to do it in a Metro Style app, which can't reference regular .Net libraries.

So, what to do?

First off, Json Serialisation has been provided as a first class citizen in Metro Style apps. There's no point in doing that again. We will use the Windows.Data.Json.JsonObject class provided in WinRT. Where our paths diverge from this provided class, is that the objects are accessed in a relatively gnarly way:

JsonObject jsonObject = JsonObject.Parse(jsonString);
string myStringProperty = jsonObject["myStringPropertyName"].GetString();
double myDoubleProperty = jsonObject["myDoublePropertyName"].GetNumber();
There are different methods you call depending on the type of the value you want. This type is exposed in the ValueType property of the IJsonValue interface, which is the type of the object returned by the indexing operation. We don't necessarily like this.

What I want to do is to read my Json object like this:

dynamic jsonObject = new DynamicJsonObjectReader(jsonString);
string myStringProperty = jsonObject.myStringPropertyName;
double myDoubleProperty = jsonObject.myDoublePropertyName;
It's debatable wether we would want the property to be returned as a concrete type, or as a dynamic object, but for these purposes I want a concrete type for string, double, bool and Array, and another DynamicJsonObjectReader for JsonObject.

To accomplish this, I created an object that wraps up the built-in JsonObject class and inherits from DynamicObject. I called the object a reader, because I've only overridden the TryGetMember method. To make it writable, I would also override the TrySetMember method. This is a bit more complicated, and surplus to my needs. For Now. The ToString method will spit out the Json formatted representation, which at the moment is useful for debugging. Once TrySetMember is properly implemented, ToString would be used for serialising. Here is the code:

Update:I've added an implementation for GetDynamicMemberNames. This enables the debugger to show you all the members and their values at runtime in the watch window. Pretty handy.

using System;
using System.Dynamic;
using System.Linq;
using Windows.Data.Json;

namespace JsonSerialisation
{
    internal class DynamicJsonObjectReader : DynamicObject
    {
        private readonly JsonObject jsonObject;

        public DynamicJsonObjectReader(string jsonString)
        {
            jsonObject = JsonObject.Parse(jsonString);
        }

        private DynamicJsonObjectReader(JsonObject jsonObject)
        {
            this.jsonObject = jsonObject;
        }

        public override string ToString()
        {
            return jsonObject.Stringify();
        }

        public override IEnumerable GetDynamicMemberNames()
        {
            return jsonObject.Keys;
        }
        
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            IJsonValue jsonValue;
            if (!jsonObject.TryGetValue(binder.Name, out jsonValue))
            {
                // return null to avoid exception.  caller can check for null this way...
                result = null;
                return true;
            }

            result = GetValue(jsonValue);
            return true;
        }

        private object GetValue(IJsonValue jsonValue)
        {
            object result = null;
            switch (jsonValue.ValueType)
            {
                case JsonValueType.Object:
                    result = new DynamicJsonObjectReader(jsonValue.GetObject());
                    break;
                case JsonValueType.String:
                    result = jsonValue.GetString();
                    break;
                case JsonValueType.Number:
                    result = jsonValue.GetNumber();
                    break;
                case JsonValueType.Boolean:
                    result = jsonValue.GetBoolean();
                    break;
                case JsonValueType.Array:
                    result = CreateArray(jsonValue.GetArray());
                    break;
            }
            return result;
        }

        private Array CreateArray(JsonArray jsonArray)
        {
            return jsonArray.Select(GetValue).ToArray();
        }
    }
}

Tuesday, June 12, 2012

Enabling PIN authentication on Windows 8 for domain logons

By default, PIN authentication is disabled for domain logons on Windows 8 Release Preview.

There is a new group policy setting for allowing pin authentication. The description reads:
This policy setting allows you to control whether a domain user can sign in using a PIN. If you enable this policy setting, a domain user can set up and sign in with a PIN. If you disable or don't configure this policy setting, a domain user can't set up and use a PIN. Note that the user's domain password will be cached in the system vault when using this feature.

The setting is located by running GPEdit.msc Then navigate to Computer Configuration -> Administrative Templates -> System -> Logon -> Turn on pin sign-in Set this setting to enabled to allow domain users to use a pin when signing in to the computer.

Tuesday, May 15, 2012

How to determine the username of the logged on user in Windows 8 Metro Style apps

There are 2 options available here, depending on what you would like to achieve.

If it's simply to authenticate a user, you would want to use the Windows.Security.Authentication.Web.WebAuthenticationBroker, and one or more OAuth2.0 identity services like Facebook or Windows Live. There are very good samples available on using these. Start with MSDN

If you need to do authorization or log a user in using a web service, you may need to know the logged in user's username. This can be found in the UserInformation object, like so:

Windows.System.UserProfile.UserInformation.getPrincipalNameAsync().then(function (result)
{
    Debug.writeln(result);
});
 
 
You can then look at using the various web services and APIs provided by your chosen identity provider. One option is to provide your own web service, which may perform any further required logging in for the user, if Kerberos is not working for you.

Another option when having to ask the user for credentials is to use the CredentialPicker object. Here's an example of how to use it:

var credentialPickerResults;
var credentialPickerOptions = new Windows.Security.Credentials.UI.CredentialPickerOptions();
credentialPickerOptions.targetName = "My App";
credentialPickerOptions.caption = "My App";
credentialPickerOptions.message = "Sign in to My App";
credentialPickerOptions.authenticationProtocol = Windows.Security.Credentials.UI.AuthenticationProtocol.ntlm;
credentialPickerOptions.alwaysDisplayDialog = false;
var credentialPicker = Windows.Security.Credentials.UI.CredentialPicker;
credentialPicker.pickAsync(credentialPickerOptions).done(
function complete(result) {
    console.log("pickAsync complete: username = " + result.credentialUserName + ", password = " + result.credentialPassword + " errorCode = " + result.errorCode);
    credentialPickerResults = result;
},
function error(e) {
    console.log("pickAsync error: " + e.message);
});
 
 
The result object will contain the credentials the user specified. No authentication is performed on these credentials.

Tuesday, May 8, 2012

Displaying your product version in a Windows 8 Metro App

When creating a package for the store, the wizard gives you an option to automatically increment the package version number. This version number is used for a variety of important things. Wouldn't it be useful to display this number to the user when doing support, or logging errors?

To access the version you can easily use

Package.Current.Id.Version;

This returns a PackageVersion, with the regular 4 version properties.

Format it like so:

PackageVersion packageVersion = Package.Current.Id.Version;
string.Format("{0}.{1}.{2}.{3}", packageVersion.Major, packageVersion.Minor, packageVersion.Build,packageVersion.Revision);

Extra points for turning this into an extension method if you'll be doing it in more than one place!

In my current app, I've decided to add it to the application resources, and then bind to it from wherever I want to display it.

Windows App Certification Kit Test can't find the app

I've been trying to run the Windows App Certification Kit Test for a while now and again after building a package. It failed every time with an error stating that it couldn't find the app. I found this rather strange, because whenever I open the start menu, it's right there!

It turns out, before you run the kit, you have to install the package. When Visual Studio deploys the app, it is deployed as an unpackaged app. The certification kit looks for a packaged app, with a particular application name (a product guid). I won't go into the details about the other differences.

First, you have to uninstall the unpackaged app that Visual Studio deploys. Right click on the app in the start menu, and click Uninstall in the app bar.
To install the app, click on the link to the build package location in the window that is displayed after package creation. Next, open the folder with the name of your package, right click the Add-AppxDevPackage.bat file, and click Run as administrator. This will install your app as a packaged app.

You can now click the button to run the certification kit.

Sunday, May 6, 2012

COM Exception "HRESULT E_FAIL has been returned from a call to a COM component" in C# Windows 8 Metro app

I've recently been developing a few Windows 8 apps using the Consumer Preview release of Windows 8 and VS11. For the last week I've been struggling with a bug that occurred in a Windows 8 C#/XAML app.

In my app I have a Hub Page, which displays a grid with grouped items. I bind this grid to a CollectionViewSource, which takes care of this grouping for me. I also have a snapped view, which uses a ListView bound to the same CollectionViewSource. I got a ComException intermittently whenever I navigated to the page in the Snapped view. No exception would occur when navigating around in the filled view.

The exception would only be reported as a System.Runtime.InteropServices.COMException, with the message "Error HRESULT E_FAIL has been returned from a call to a COM component." and the error code -2147467259

I thought for a long time that it was a syncronisation problem on the ObservableCollection I was binding to, as I had several threads updating this collection. The problem only occurred when I was replacing items in the collection.

Eventually, the fact that it was only occurring in the snapped View, made me question what the difference was between the two. The only meaningful difference was that they never showed at the same time, and the snapped view was bound to the CollectionViewSource after the first. I remembered noticing in a different article about ObservableCollection that there could be problems binding multiple UIElements to the same collection, so this made me have another look at the XAML. My first attempt was to create a copy of the CollectionViewSource for my snapped view, and change the binding for the ListView.

It worked! I almost ran naked down the street!

I have no idea why it wouldn't work previously, but I can only speculate that the filled GridView may be taking too long to render the individual items, as the process to do so is actually quite involved in this instance. Using 2 identical CollectionViewSources is less efficient, but seems to be a sad necessity this time around.

Wednesday, February 15, 2012

T-SQL for killing active connections to your database

Here is some handy t-sql for killing active connections to your database. Replace 'DB_NAME' with the name of your database.
USE master 
GO 
 
SET NOCOUNT ON 
DECLARE @DBName varchar(50) 
DECLARE @spidstr varchar(8000) 
DECLARE @ConnKilled smallint 
SET @ConnKilled=0 
SET @spidstr = '' 
 
Set @DBName = 'DB_NAME' 
IF db_id(@DBName) < 4 
BEGIN 
PRINT 'Connections to system databases cannot be killed' 
RETURN 
END 
SELECT @spidstr=coalesce(@spidstr,',' )+'kill '+convert(varchar, spid)+ '; ' 
FROM master..sysprocesses WHERE dbid=db_id(@DBName) 
 
IF LEN(@spidstr) > 0 
BEGIN 
EXEC(@spidstr) 
SELECT @ConnKilled = COUNT(1) 
FROM master..sysprocesses WHERE dbid=db_id(@DBName) 
END