Visual Studio 2012 days in Toronto

The upcoming three weeks in Toronto will be action packed with several Visual Studio-related events.
-
Wednesday, October 10 - Visual Studio Launch Event at Microsoft Canada office in Mississauga. The main focus is ALM and DevOps
-
Saturday, October 13 - .NET Rocks Visual Studio 2012 Road Trip with Carl, Richard and a special guest, Michele Leroux Bustamante
-
Tuesday, October 16 - Introduction to Visual Studio 2012 and .NET 4.5 at Metro Toronto UG where I will talk about IDE, .NET framework and C# language improvements.
-
Thursday, October 18 (8:30 AM – 12:00 PM, Downtown) – Rise to the Consumer Challenge, a broad overview of the modern Microsoft platform and tools for this platform.
-
Thursday, October 18 (6:00 PM – 8:30 PM) – I will be speaking at North Toronto .NET UG - Introduction to Visual Studio 2012 and .NET 4.5
-
Tuesday, October 23 (8:30 AM – 12:00 PM, Toronto North) – Rise to the Consumer Challenge, a broad overview of the modern Microsoft platform and tools for this platform.
-
Thursday, October 25 (8:30 AM – 12:00 PM, Toronto West) – Rise to the Consumer Challenge, a broad overview of the modern Microsoft platform and tools for this platform.
File system change notifications in WinRT
.NET framework for Windows 8 Store apps provides a subset of features included in full .NET framework profile. Microsoft excluded many APIs considered obsolete or unsafe. One of the removed classes is FileSystemWatcher, a class that proves its usefulness in applications intensively working with Windows file system. Instead, WinRT provides an alternative mechanism for folders monitoring based on queries.
Any folder can be queried to filter and enumerate files in the folder. For example the following code will return all Word documents in app’s local storage.
async void SearchFolder()
{
var options = new Windows.Storage.Search.QueryOptions { FileTypeFilter = { ".docx" } };
var query = ApplicationData.Current.LocalFolder.CreateFileQueryWithOptions(options);
var files = await query.GetFilesAsync();
// …
}
This is one time search that returns current state of the target folder. If continuous folder monitoring is required, app needs to be subscribed on query’s ContentsChanged event.
async void SearchFolder()
{
var options = new Windows.Storage.Search.QueryOptions { FileTypeFilter = { ".docx" } };
var query = ApplicationData.Current.LocalFolder.CreateFileQueryWithOptions(options);
query.ContentsChanged += QueryContentsChanged; //subscription
var files = await query.GetFilesAsync();
// …
}
void QueryContentsChanged(Windows.Storage.Search.IStorageQueryResultBase sender, object args)
{
// handle changes
}
QueryContentsChanged will be called for every file system event that happens in the target folder. File type filter is not taken into account – WinRT will notify about new files of any type, new or deleted folders, etc.
At the same time, another query option – FolderDepth – affects content change notifications. E.g. for the query defined above WinRT will not send notifications for subfolders of LocalFolder. Next sample creates query that will track changes in LocalFolder and all subfolders, at any depth.
async void SearchFolder()
{
var options = new Windows.Storage.Search.QueryOptions
{
FileTypeFilter = { ".docx" } ,
FolderDepth = Windows.Storage.Search.FolderDepth.Deep
};
var query = ApplicationData.Current.LocalFolder.CreateFileQueryWithOptions(options);
query.ContentsChanged += QueryContentsChanged;
var files = await query.GetFilesAsync();
// …
}
Additional details
-
GetFileAsync()needs to be called for query in order to start receiving notifications -
Deletion and re-creation of the target folder does not invalidate query. Even more, WinRT notifies about both of these events.
-
ContentsChangedis triggered not only by creation or deletion of files or folders. Attributes change or content change for some file type trigger event as well. -
If app is suspended, all events are recorded and notifications are fired when app is resumed.
Limitations
- There is no way to identify reason of the event (new file, deleted folder, modified attribute, etc.)
args, ContentsChanged second parameter, seems to be always null. There is no information about affected items.
App contests for Windows 8 developers
Windows 8 isn't released officially yet, but developers already have all the tools required for Windows 8 Store app development. Writing applications for the new, almost empty marketplace is a unique opportunity by itself, but to make it even more interesting Microsoft and Intel initiated two competitions.
Apptivate.ms
This contest is a joint effort of Microsoft and StackOverflow. Submit your app before December 6th, 2012 to compete for cash prizes, one of the Windows RT tablets or a Grand Prize equals to $5000.
In addition to apps contest, Apptivate.ms includes a reviewer contest. By answering Windows 8-related questions and providing app reviews, you can win one of tablets or Windows 8 licenses.
The Windows 8 & Ultrabook App Innovation Contest
The contest is brought to you by Intel and CodeProject. Prize pool for this event includes 300 Ultrabooks, fifty $1,000 cash prizes, seven $10,000 cash prizes and a grand prize of $20,000.
The goal of the contest is to create Ultrabook enabled Windows 8 applications. Windows 8 Store apps or Ultrabook-optimized desktop applications are equally acceptable.
During the first round, ends October 24, participants need to submit app write up as a CodeProject article. 300 first round winners will get Ultrabooks for app development and testing and will compete for the grand prize in round 2. Round 2 ends November 21.
What is Extensible Storage Engine and how it can be used by Windows 8 apps to persist data
If you start to explore Windows 8 system folders, you will quickly find a set of the same files presented in various locations:

What are these files? They are generated by Extensible Storage Engine (ESE), indexed sequential access data storage technology. ESE runtime has been a part of Windows since version 2000, empowering such products as Exchange, Active Directory and Desktop Search.
Windows 8 is not an exception. ESE is used by Zune Music, Zune Video, app repository and is available as a native API for all Windows Store app developers.
How to start
While ESE APIs can be used directly, C# developers may find using of a managed wrapper called ManagedEsent more convenient. All code samples in this post use ManagedEsent.
ManagedEsent supports Windows 8 starting from version 1.8. At this moment binaries for v1.8 are not available for download and you will need to compile sources by yourself or download assembly compiled by me to start using library .
The following code samples demonstrate how to create DatabaseRepository class that allows to instantiate ESE database, put, get and delete data. The data are represented by Event class:
public class Event
{
public Guid Id { get; set; }
public string Description { get; set; }
public double Price { get; set; }
public DateTime StartTime { get; set; }
}
Database
Creation of database includes two steps: creation of ESE instance and creation of database itself. Instances can include up to six databases and provide shared transaction log for all attached databases.
Create and configure instance
private Instance _instance;
private string _instancePath;
private string _databasePath;
private const string DatabaseName = "Database";
public void CreateInstance()
{
_instancePath = Path.Combine(ApplicationData.Current.LocalFolder.Path, DatabaseName);
_databasePath = Path.Combine(_instancePath, "database.edb");
_instance = new Instance(_databasePath);
// configure instance
_instance.Parameters.CreatePathIfNotExist = true;
_instance.Parameters.TempDirectory = Path.Combine(_instancePath, "temp");
_instance.Parameters.SystemDirectory = Path.Combine(_instancePath, "system");
_instance.Parameters.LogFileDirectory = Path.Combine(_instancePath, "logs");
_instance.Parameters.Recovery = true;
_instance.Parameters.CircularLog = true;
_instance.Init();
}
Create database
The following function creates database file and configures database schema to store Events.
public void CreateDatabase()
{
using (var session = new Session(_instance))
{
// create database file
JET_DBID database;
Api.JetCreateDatabase(session, _databasePath, null, out database, CreateDatabaseGrbit.None);
// create database schema
using (var transaction = new Transaction(session))
{
JET_TABLEID tableid;
Api.JetCreateTable(session, database, "Events", 1, 100, out tableid);
// ID
JET_COLUMNID columnid;
Api.JetAddColumn(session, tableid, "Id",
new JET_COLUMNDEF
{
cbMax = 16,
coltyp = JET_coltyp.Binary,
grbit = ColumndefGrbit.ColumnFixed | ColumndefGrbit.ColumnNotNULL
}, null, 0, out columnid);
// Description
Api.JetAddColumn(session, tableid, "Description",
new JET_COLUMNDEF
{
coltyp = JET_coltyp.LongText,
cp = JET_CP.Unicode,
grbit = ColumndefGrbit.None
}, null, 0, out columnid);
// Price
Api.JetAddColumn(session, tableid, "Price",
new JET_COLUMNDEF
{
coltyp = JET_coltyp.IEEEDouble,
grbit = ColumndefGrbit.None
}, null, 0, out columnid);
// StartTime
Api.JetAddColumn(session, tableid, "StartTime",
new JET_COLUMNDEF
{
coltyp = JET_coltyp.Currency,
grbit = ColumndefGrbit.None
}, null, 0, out columnid);
// Define table indices
var indexDef = "+Id\0\0";
Api.JetCreateIndex(session, tableid, "id_index",
CreateIndexGrbit.IndexPrimary, indexDef, indexDef.Length, 100);
indexDef = "+Price\0\0";
Api.JetCreateIndex(session, tableid, "price_index",
CreateIndexGrbit.IndexDisallowNull, indexDef, indexDef.Length, 100);
transaction.Commit(CommitTransactionGrbit.None);
}
Api.JetCloseDatabase(session, database, CloseDatabaseGrbit.None);
Api.JetDetachDatabase(session, _databasePath);
}
}
Data manipulation
Most of ESE data manipulations require opened session, started transaction and active table, so it makes sense to create a function to encapsulate all these activities:
private IList<Event> ExecuteInTransaction(Func<Session, Table, IList<Event>> dataFunc)
{
IList<Event> results;
using (var session = new Session(_instance))
{
JET_DBID dbid;
Api.JetAttachDatabase(session, _databasePath, AttachDatabaseGrbit.None);
Api.JetOpenDatabase(session, _databasePath, String.Empty, out dbid, OpenDatabaseGrbit.None);
using (var transaction = new Transaction(session))
{
using (var table = new Table(session, dbid, "Events", OpenTableGrbit.None))
{
results = dataFunc(session, table);
}
transaction.Commit(CommitTransactionGrbit.None);
}
}
return results;
}
Add event
public void AddEvent(Event ev)
{
ExecuteInTransaction((session, table) =>
{
using (var updater = new Update(session, table, JET_prep.Insert))
{
var columnId = Api.GetTableColumnid(session, table, "Id");
Api.SetColumn(session, table, columnId, ev.Id);
var columnDesc = Api.GetTableColumnid(session, table, "Description");
Api.SetColumn(session, table, columnDesc, ev.Description, Encoding.Unicode);
var columnPrice = Api.GetTableColumnid(session, table, "Price");
Api.SetColumn(session, table, columnPrice, ev.Price);
var columnStartTime = Api.GetTableColumnid(session, table, "StartTime");
Api.SetColumn(session, table, columnStartTime, DateTime.Now.Ticks);
updater.Save();
}
return null;
});
}
Delete event
public void Delete(Guid id)
{
ExecuteInTransaction((session, table) =>
{
Api.JetSetCurrentIndex(session, table, null);
Api.MakeKey(session, table, id, MakeKeyGrbit.NewKey);
if (Api.TrySeek(session, table, SeekGrbit.SeekEQ))
{
Api.JetDelete(session, table);
}
return null;
});
}
Get all events
public IList<Event> GetAllEvents()
{
return ExecuteInTransaction((session, table) =>
{
var results = new List<Event>();
if (Api.TryMoveFirst(session, table))
{
do
{
results.Add(GetEvent(session, table));
}
while (Api.TryMoveNext(session, table));
}
return results;
});
}
private Event GetEvent(Session session, Table table)
{
var ev = new Event();
var columnId = Api.GetTableColumnid(session, table, "Id");
ev.Id = Api.RetrieveColumnAsGuid(session, table, columnId) ?? Guid.Empty;
var columnDesc = Api.GetTableColumnid(session, table, "Description");
ev.Description = Api.RetrieveColumnAsString(session, table, columnDesc, Encoding.Unicode);
var columnPrice = Api.GetTableColumnid(session, table, "Price");
ev.Price = Api.RetrieveColumnAsDouble(session, table, columnPrice) ?? 0;
var columnStartTime = Api.GetTableColumnid(session, table, "StartTime");
var ticks = Api.RetrieveColumnAsInt64(session, table, columnStartTime);
if (ticks.HasValue)
ev.StartTime = new DateTime(ticks.Value);
return ev;
}
Get event by ID
public IList<Event> GetEventsById(Guid id)
{
return ExecuteInTransaction((session, table) =>
{
var results = new List<Event>();
Api.JetSetCurrentIndex(session, table, null);
Api.MakeKey(session, table, id, MakeKeyGrbit.NewKey);
if (Api.TrySeek(session, table, SeekGrbit.SeekEQ))
{
results.Add(GetEvent(session, table));
}
return results;
});
}
Get events for a price range
public IList<Event> GetEventsForPriceRange(double minPrice, double maxPrice)
{
return ExecuteInTransaction((session, table) =>
{
var results = new List<Event>();
Api.JetSetCurrentIndex(session, table, "price_index");
Api.MakeKey(session, table, minPrice, MakeKeyGrbit.NewKey);
if (Api.TrySeek(session, table, SeekGrbit.SeekGE))
{
Api.MakeKey(session, table, maxPrice, MakeKeyGrbit.NewKey);
Api.JetSetIndexRange(session, table,
SetIndexRangeGrbit.RangeUpperLimit | SetIndexRangeGrbit.RangeInclusive);
do
{
results.Add(GetEvent(session, table));
}
while (Api.TryMoveNext(session, table));
}
return results;
});
}
Conclusion
Extensible Storage Engine is a fast, transactional database optimized for sequential data access. It provides simple, native data storage mechanism for Windows 8 Store apps. The main disadvantages of ESE are the verbose API and limited querying capabilities. Additional information about Extensible Storage Engine is available on Wikipedia.
Download complete implementation of DataRepository class.
Transhipment: A WinRT library for sharing Schema.org formatted data
Windows 8 provides a standard mechanism for sharing data between apps – Share Contract. It works like a charm for the well-known formats like HTML or Url, but there are some issues with custom structured data sharing. I have mentioned the formats compatibility issue before in "Do you need a reference implementation for schema.org formats?" post and now I’d like to introduce Transhipment library that aims to resolve this issue.
Transhipment provides implementation for the most popular schema.org formats that make sense in the context of data sharing. Supported schemas:
- Article
- Book
- ContactPoint
- CreativeWork
- Event
- GeoCoordinate
- LocalBusiness
- Movie
- MusicAlbum
- MusicGroup
- MusicPlaylist
- MusicRecording
- Organization
- Person
- Place
- PostalAddress
- Product
- Recipe
In addition, the library includes a few helpers to simplify use of these schemas with Share Contract:
SchemaFactoryclass creates data schema objectsSchemaclass provides identifiers for the supported schemasSetStructuredDataandGetStructuredDataAsyncextension methods forDataPackage
Below you can see a complete example of using Transhipment for sharing geo coordinates from C# app:
void DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
var request = args.Request;
var geo = SchemaFactory.Create(Schema.GeoCoordinates) as IGeoCoordinates;
geo.Name = "Polar Bear Provincial Park";
geo.Latitude = "54.596931";
geo.Longitude = "-83.283978";
request.Data.Properties.Title = "Sample data";
request.Data.Properties.Description = "data for " + geo.Type;
request.Data.SetStructuredData(geo);
}
Transhipment is a WinRT library and can be used from all supported languages, e.g. from JavaScript:
function dataRequested(e) {
var request = e.request;
var geo = Transhipment.SchemaFactory.create(Transhipment.Schema.geoCoordinates);
geo.name = "Polar Bear Provincial Park";
geo.latitude = "54.596931";
geo.longitude = "-83.283978";
request.data.properties.title = "Sample data";
request.data.properties.description = "data for " + geo.type;
Transhipment.SchemaFactory.setStructuredData(request.data, geo);
}
Retrieving of shared data in target app is also easy:
public async void Activate(ShareTargetActivatedEventArgs args)
{
var shareOperation = args.ShareOperation;
var geo = await shareOperation.Data.GetStructuredDataAsync(Schema.GeoCoordinates) as IGeoCoordinates;
if (geo != null)
{
DefaultViewModel["ThingName"] = geo.Name;
DefaultViewModel["Latitude"] = geo.Latitude;
DefaultViewModel["Longitude"] = geo.Longitude;
}
// ...
}
Extensibility
All Transhipment schemas support ExtendedProperties dictionary to extend formats and share application-specific data.
How to start
Transhipment is available as a NuGet package.
PM> Install-Package Transhipment
Transhipment source code is on GitHub and if you miss any of schema.org formats – feel free to send me your pull requests.
Inspecting local and roaming settings for Windows 8 Store app
ApplicationDataContainer class supports saving of complex hierarchies of local and roaming settings. Sometimes there is a need to verify saved values but unfortunately Windows 8 development toolset doesn’t include any settings inspector. This post describes a method for inspecting settings manually.
Application settings are stored in C:\Users\<user_name>\AppData\Local\Packages\<package>\Settings\settings.dat. settings.dat is a Windows NT registry file (REGF) and includes local and roaming settings. This file format, REGF, also known as Registry Hive File, is supported by Registry Editor.
To open settings file, close your app and open Registry Editor. Than select HKEY_LOCAL_MACHINE or HKEY_USER and open Load Hive dialog from File menu.

Browse for the settings file, open it and enter key name

Registry Editor will open selected settings and attach them as a new key

All values are stored as binary data with last 8 bytes containing timestamp or version information – these bytes are modified with every value change.

You can modify values in Registry Editor and after unloading hive they will become available for your application.
My next talk about VisualStudio 2012 at Markham .NET UG
I will speak about Visual Studio 2012 on Monday, September 10 at Markham .NET User Group and Thursday, October 18 at North Toronto .NET UG.
Visual Studio 2012 has reached RTM and will be officially launched on September 12. Join us to see what is new in VS 2012 and which opportunities are unlocked by this release. This presentation will cover a variety of topics around Visual Studio 2012, including Web and Cloud, Windows 8, Team Development and much more.
Details at MarkhamDotNet.com and NorthTorontoUG.com
Preventing unauthorized modifications of XAML files in Windows 8 apps with XamlIntegRT
1. Your Metro-style app needs protection and here is why
2. Simplest approach to protecting advertisements in your Windows 8 app
3. Preventing unauthorized modifications of XAML files in Windows 8 apps with XamlIntegRT
I finished my last post with the example of instantiating ad controls in code behind to prevent having them turned off. While this method is simple to implement, it forces developer to use code behind and doesn’t protect other parts of XAML from unauthorised modifications.
An alternative approach for protection is implemented in XAMLIntegRT library. It is based on comparison of hash codes generated design-time for XAML pages with hashes calculated for pages installed on the target system. XAMLIntegRT includes two components – command line hash code generator and C# library for run-time validation.

Quick start
1) Add XAMLIntegRT library to your project by getting sources from GitHub repository or by using NuGet:
PM> Install-Package XamlIntegRT
2) Compile command line hash code generator from retrieved source code or download compiled XamlIntegRTGen.exe from GitHub.
3) Generate hash data for your XAML files. XamlIntegRTGen.exe accepts three mandatory and one optional parameter:
XamlIntegRTGen.exe <project_folder> <file_path> <namespace> [/ads]
- project_folder - path to project source files, e.g.
C:\sandbox\BookReader\src - file_path - path for the file with the generated hash codes, e.g.
C:\sandbox\BookReader\src\App\XamlData.cs - namespace - desired namespace to place data in
- /ads - optional parameter to hash XAML files with
AdControlsonly
XamlIntegRTGen.exe generates .cs file that contains hashes for XAML pages. The generated file needs to be added to the target project. You need to perform this step every time XAML page is modified and it makes sense to automatically call XamlIntegRTGen.exe from your build script as a pre-build event.
4) Now you are ready to implement run-time validation:
async void MainPageLoaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
if (!await XamlValidator.Validate(new XamlFilesData()))
{
var dialog = new MessageDialog("XAML modifications detected");
await dialog.ShowAsync();
}
}
XamlValidator.Validate method returns false if any of the pages are modified and it’s up to you how to proceed from this point. Library source code is available and you can easily add validation for any additional types of files, for example images or text resources.
Simplest approach to protecting advertisements in your Windows 8 app
1. Your Metro-style app needs protection and here is why
2. Simplest approach to protecting advertisements in your Windows 8 app
3. Preventing unauthorized modifications of XAML files in Windows 8 apps with XamlIntegRT
Here is a screenshot of app running on my tablet:

And here is the same app a couple of minutes later:

What’s happened? Where is Gears of War Ad?
As I posted before, app assemblies, non-compiled XAML and html pages are easily accessible for users. Windows 8 RTM doesn’t bring anything new for apps protection. Neither special knowledge nor tools are required to open app’s package in WindowsApps folder, find .xaml page with advertisements and remove AdControl elements. Your grandma can do it between backing a cake and knitting socks given good instruction.
Even more, I spent just ten extra minutes and created a tool that automatically scans all installed Windows 8 apps and removes all Ad controls.
How can this simple hack be avoided? Probably the easiest solution is to create AdControl in code behind:
var adControl = new AdControl
{
ApplicationId = "test_client",
AdUnitId = "Image_300x250"
};
adControl.SetValue(WidthProperty, 300);
adControl.SetValue(HeightProperty, 250);
AdGrid.Children.Add(adControl);
Discovering data formats supported by Windows 8 share contract target apps
Windows 8 apps run in sandboxed environment where all direct communications between apps are prohibited. Instead, Windows 8 provides several mechanisms to facilitate indirect communications – protocols, file type associations and share contracts.
All these mechanisms allow transferring data between independent apps – in most of the cases developers don’t care about data source or destination. However, occasionally there is a need to support communications with a particular app. In this case all protocols, associations and contracts supported by target app need to be identified.
Declared protocols and file type associations can be determined through Control Panel:
- Search for Default Programs and open Set Default Programs screen
- Select desired app and press Choose defaults for this program

Unfortunately, Windows 8 does not provide any UI to discover share targets’ data formats. The only way is to go through manifest files for the installed apps and search for data format declarations. Some of these files are not well formatted so I decided to automate the task and created a small utility, AppXplorer:

This application lists all the installed apps and allows discovering supported protocols, file type associations, shareable data formats and file types.
You can download compiled executable or build it by yourself from source code (.NET 4.5/WPF).

