Category Archives: Visual Studio

WinRT Raw Notifications and Suspended State

Something to note if your WinRT app uses raw notifications. They will be received by the device but not by the app if it is suspended. This makes sense but may not be obvious sometimes because swiping the left side of the screen may still show the app on the stack. So it will appear to still be active, even if not in the foreground. The exception, of course, is if your app is registered to use a background service and the user has decided your app is important enough to be one of the “Lucky Seven” (those apps given permission to use the Lock Screen). I wouldn’t count on it.

It took me a bit to spot this behavior. I was noticing an instance of the app on one machine would sometimes receive raw notifications if it wasn’t in the foreground, sometimes not. The “not” occurred after a decent time lapse, which was the first clue. My server notification logs were no help because only client devices that were off or logged out of would return a status other than OK from the notification service. As mentioned, if the device is on and logged into, the notification service will successfully send the message. This makes sense. All it cares about is reaching the client at the specified URI. It’s up to the client to do what it wants with the received message. In this case, it appears the WinRT designers elected not to wake up an inactive app. Not a problem, but something to be aware of.

In my case, raw notifications are used to tell the app to update its data. It just means that the same sort of behavior also has to be triggered by resuming from a suspended state. BTW, for those who don’t know, you can suspend an app from within Visual Studio while debugging. To enable this, select TOOLS > Customize from the Visual Studio menu. Check the box next to “Debug Location”. If you have a solution with multiple projects you may have to select the right WinRT project from the Process pull-down menu.

Nobody Notified Me About This!

Earlier on in the Windows 8 development cycle, apps had a checkbox in their app manifest indicating whether the app should be capable of receiving notifications. Later, that explicit requirement went away from the UI in the app manifest window. Thanks to a discussion with a Microsoft DPE (Development & Platform Evangelism) guy yesterday, I was steered towards using a version of the server-side notifications code that includes full diagnostics. My notifications were being sent, but had a “dropped” status, indicating they weren’t making it to the client app. The client app was running. So why, why, why wasn’t it working?

It was then that a little searching online turned up recommendations to check if the app had permissions enabled to receive notifications. Opening the XML for package.appxmanifest (by right-clicking on it and selecting “View Code” or select the file and hit F7), I was able to just add ToastCapable=”true” to the VisualElements tag. That took care of it.

Switching Between Remote Machines when Debugging

I’m currently switching between debugging on an ARM-based Surface RT and another remote machine (actually a VM running Windows 8 on my dev box). I wish there was a more convenient way to switch between remote machines, i.e. from the pulldown menu in Visual Studio. But at least there is a way. Open the project’s properties and select the Debug tab. You can then choose the remote machine. Using the Find button will show all the visible machines:

choosing_remote_machine

Using .NET 4.5 Task Async and Await with WPF and SQL Server

Most of the examples I’ve seen of  using the new async, await and Task methods in .NET 4.5 have been aimed at Windows 8 (Metro or “UI Style”) apps. This is understandable, given Microsoft’s push towards both a new OS and to populate the Windows 8 Store. But for some (many?) developers there is also a need to support both Windows 7 and Windows 8 Desktop. Notably missing from the WinRT scenario is the ability to directly connect to SQL Server. I (mostly) get the reasons for that, although it seems against Microsoft’s interests to cede that space to SQLite instead of a sandboxed, light version of SQL Server.

Anyway, I put together a sample WPF application (download below) that supports asynchronous connections to SQL Server. You can cancel or restart the demo query, which populates a ListView with data from the AdventureWorks DB Production.WorkOrder table, which had a decent number of records for testing. I really wanted to simulate some real world conditions, such as server-side delays, so that’s included too. One of my beefs with many of the samples I come across is that they never include decent error handling, especially to accomodate network latency or timeouts. This sample also includes the Microsoft.Data.ConnectionUI SQL Server connection dialog box.

One advantage of making a WPF app asynchronous is it no longer locks up while running a process. Try dragging the window around while the ListView is being populated with data. Yay, no UI-thread blocking!

Clicking the Start button triggers the StartTest method. Notice that in the query, I’ve embedded an artificial server-side delay of 3 seconds – WAITFOR DELAY ’00:00:03′; – which will simulate a slow server return. Also, a queryTimeout has been set to 120 seconds. If you set the WAITFOR delay longer than that, you will see an error occurs and is handled. I did my best to include specific SQL Server error handling so we get actual error details, rather than just “some crap happened and that’s all we know.”


private async void StartTest(object sender, RoutedEventArgs e)
{
try
{
 if (_connectionString == String.Empty)
 {
 var scsb = new SqlConnectionStringBuilder(Settings.Default.DBConnString);

_connectionString = scsb.ConnectionString;

if (_connectionString == String.Empty)
 {
 throw new Exception("Please use Change DB to first select a server and database.");
 }
 }

if (DbInfo.DbName == String.Empty)
 {
 throw new Exception("Please use Change DB to first select a database from the server.");
 }

// Note: If the start test button was disabled, this would be unnecessary
 _cts.Cancel();

// Re-initialize this. Otherwise, StartTest won't work.
 _cts = new CancellationTokenSource();

DataItemsList.Clear();

// Note the simulated delay, which will happen on the DB server. You can vary this to see its effect.
 // Try dragging the window around after hitting the start test button.
 const string query =
 @"WAITFOR DELAY '00:00:03'; SELECT * FROM [Production].[WorkOrder];";

// Note that setting the WAITFOR delay to exceed this, eg. 00:02:01, will trigger an exception
 int queryTimeout = 120;

RequestStatus = "started";

await ProcessQueryCancelleable(_connectionString, query, queryTimeout, _cts.Token);
}
catch (Exception ex)
{
 MessageBox.Show(ex.Message + " (from StartTest)");

Debug.WriteLine(ex.Message);
}
}

The ProcessQueryCancelleable method. Note the use of the CancellationToken…’cause users might actually want to cancel a long-running query. Inside this method is another simulated delay (await Task.Delay(TimeSpan.FromMilliseconds(1));):

/// <summary>
/// Runs a cancelleable query
/// </summary>
/// <param name="connectionString">SQL Server connection string</param>
/// <param name="query">SQL query</param>
/// <param name="timeout">SqlDataReader timeout (maximum time in seconds allowed to run query). Note: Try varying this in conjunction
/// with the WAITFOR DELAY in the SQL query, e.g. make it shorter than the WAITFOR or maybe a second longer</param>
/// <param name="cancellationToken">Allows cancellation of this operation</param>
/// <returns></returns>
private async Task ProcessQueryCancelleable(string connectionString, string query, int timeout,
 CancellationToken cancellationToken)
{
 // await Task.Delay(TimeSpan.FromSeconds(5));

try
 {
 // Keep sqlConnection wrapped in using statement so disposal is handled automatically
 using (var sqlConnection = new SqlConnection(connectionString))
 {
 await sqlConnection.OpenAsync(cancellationToken);

using (SqlCommand cmd = sqlConnection.CreateCommand())
 {
 cmd.CommandTimeout = timeout;

cmd.CommandText = query;

using (SqlDataReader dataReader = await cmd.ExecuteReaderAsync(cancellationToken))
 {
 while (!dataReader.IsClosed)
 {
 // While the dataReader has not reached its end keep adding rows to the DataItemsList
 while (await dataReader.ReadAsync(cancellationToken))
 {
 // Process dataReader row
 WorkOrder workOrder = GetWorkOrderFromReader(dataReader);

DataItemsList.Add(workOrder);

// Another simulated delay...this one internal
 await Task.Delay(TimeSpan.FromMilliseconds(1));
 }

if (!dataReader.NextResult())
 {
 dataReader.Close();
 }
 }

Debug.WriteLine("done with reader");

RequestStatus = "finished";
 }
 }
 }
 }
 catch (SqlException sqlEx)
 {
 Debug.WriteLine(sqlEx.Message);
 }
}

Download C# Project (an MDF with just the WorkOrders table is included)

Fun with ClickOnce and XML files…and Prerequisites

I have a recent WPF project that is published using ClickOnce. However, the application has some XML templates that weren’t being copied over to the install directory. It was strange because they were being published to the deployment package. What I found was that in Visual Studio, you need to open Properties > Publish and click on the Application Files button.

Find the files that aren’t being copied over and change the Publish Status to “Include”. Mine were originally set to “Data (Auto)” and that didn’t cut it:

Incidentally, within the Solution Explorer, each file has its Build Action set to Content and Copy to Output Directory is set to Copy always.

An update: Don’t forget to deal with prerequisites – in my case, .NET 4.5 and the Visual C++ 2010 Runtime – x64. We had three developer machines where installation worked fine and client machines where it didn’t. I installed a fresh copy of Win7 in a VM and was able to fairly quickly determine this. To Microsoft’s credit, you can create a setup program to install prerequisites. However, IIRC, you get to download and install them even if they’re already installed. Still, better than beating your head against it all day. Cable broadband is a lot cheaper than my mental bandwidth.