Friday 29 November 2013

Where’d my interface go?

One of the joys of modern development is that you get to work in pretty much any language there is.

I’ve been doing a lot of C# development lately (Phone, WinRT and WPF desktop), but occasionally have to drop back to some C++/MFC software.

Yesterday, I had to refactor some code, that made some glaring assumptions about it’s use (yes, I used reinterpret_cast to convert a CWnd derived object to a class derived from CPropertyPage so that I could call one of it’s public members).

So here’s what I did:

First, I declared an interface that represented exactly what I wanted to do:

interface IDoSomethingAwesome
{
public:
virtual void DoSomethingAwesome()=0;
};


Next, I modified my class, which needed to expose the interface


public class MyAwsomePropertyPage : 
public CPropertyPage, IDoSomethingAwesome
{
/// ... etc.
virtual void DoSomethingAwesome() override;
}


and provided an implementation in the class.


Then in an unrelated class, I made a call like this


CChildOfAwsome::SomeEventHander()
{
IDoSomethingAwesome *pInt = dynamic_cast<IDoSomethingAwesome>(GetParent());
if (pInt != NULL)
{
pInt->DoSomethingAwesome();
}
}


Only one problem:  pInt was always NULL!  That was odd, because looking at the pointer returned by GetParent() gave me an object that the debugger knew was of type MyAwesomePropertyPage, yet I couldn’t for the life of me figure out why this wasn’t working.


I started writing this up as a question on StackOverflow, but while doing so, ended up talking to the duck and discovered the error in my ways.


My C# had blinded me to the joys of C++ inheritance.


I had inadvertently declared my IDoSomethingAwesome interface not public.  As a result, asking for the interface dutifully returns null, as private inheritance is an implementation detail, and not visible in the inheritance tree.


So, the correct declaration is

public class MyAwsomePropertyPage : 
public CPropertyPage, public IDoSomethingAwesome
{
/// ... etc.
virtual void DoSomethingAwesome() override;
}

Friday 22 November 2013

Tap My App! Share your App with NFC!

As part of the DVLUP challenges, you can gain up to 500 points by adding NFC to your app.

Thanksgiving’s coming up very soon, so I thought sharing our Wishbone application between Windows phones would be a really cool way to do it.

If you read the documentation, you’ll find something promising in the ProximityDevice.PublishBinary documentation named LaunchArgs.WriteTag

There are some magic parts to this documentation that are a little bit difficult to work out, as I’ll soon describe, so your journey down this route will be frought, and unfortunately, after a lot of pain, I finally realized that this would not work, as it only writes to static tags.

I’ve ordered some of them like this, and they’re in the post.  I can't wait for the fun I'll have with these, but I digress.

The important thing to realize is that there aren’t any static tags on your phone.  I for some reason thought that what was happening is that you could write to them from your code, and appear as a tag.  That is most definitely not true.

So how do you launch your app?

I’ve come up with a class that makes all of this really easy.  Here’s the code that I add to my Application_Launching event handler.

mgr = NFCManager.Default;
if (mgr.NFCSupportedOnDevice) {
mgr.DisplayName = "Wieser Software Wishbone";
mgr.AddAlternateIdentity(platform: "Windows",
appid: "WieserSoftwareLtd.BouncingBalls_38031z1jk36d6!BouncingBalls.App");
mgr.Enabled = true;
}


Now if you tap your WP8 app against a Windows Tablet with NFC, it will attempt to launch our BouncingBalls App (Wishbone does not yet have a W8 version, though it’s in the pipeline for a Tidy 250 XP in the double challenge)


The format of the appid is difficult to determine.  The first part before the “!” character can be found when editing Package.appxmanifest.


The second part is really badly documented.  It is in fact the name of the class that contains the entry point of your App.  Now, we obfuscate using EazFuscator, and as a result, the namespace and class names are probably obfuscated.


As a result, when you tap, and the app isn’t installed, the user is asked if they want to get the app from the store.


On the other hand, if the app is installed, nothing appears to happen.  I can’t decide if this is because my app doesn’t claim that it supports Proximity, or that it doesn’t support networking at the moment, so some investigation is still required.


-update-
After further investigation, it appears that the part after the ! should just say App in my case.


Full source code of the class is available here:


#define NFC_DEBUG_STATUS_MESSAGES
using System;
using System.Diagnostics;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using Windows.Networking.Proximity;

namespace Framework
{
public class NFCManager : IDisposable
{
static NFCManager _instance;
ProximityDevice _nfcdev;
DispatcherTimer dt;

[Conditional("NFC_DEBUG_STATUS_MESSAGES")]
private void Trace(string s)
{
Debug.WriteLine(s);
}

public void Dispose()
{
if (this == Interlocked.Exchange(ref _instance, null))
{
// this is us.
if (_nfcdev != null)
{
_nfcdev.DeviceDeparted -= _nfcdev_DeviceDeparted;
_nfcdev.DeviceArrived -= _nfcdev_DeviceArrived;
PeerFinder.AlternateIdentities.Clear(); // clear anything we added
Deployment.Current.Dispatcher.BeginInvoke(() => dt.Stop());
_nfcdev = null;
GC.SuppressFinalize(this);
}
}
}

~NFCManager()
{
if (_nfcdev != null) Dispose();
}

private NFCManager()
{
_nfcdev = ProximityDevice.GetDefault();
if (_nfcdev != null)
{
_nfcdev.DeviceArrived += _nfcdev_DeviceArrived;
_nfcdev.DeviceDeparted += _nfcdev_DeviceDeparted;
dt = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) }; // tick once per second
dt.Tick += dt_Tick;
}
}

bool bPeerFinderRunning = false;
DateTime dtExpiry;
private void StartPeerFinder()
{
if (!Enabled) return;

if (bPeerFinderRunning) StopPeerFinder();
dtExpiry = DateTime.UtcNow.AddSeconds(15); // don't leave this on too long.
bPeerFinderRunning = true;
Deployment.Current.Dispatcher.BeginInvoke(() => dt.Start());
PeerFinder.Start();
Trace("Started Peerfinder");
}

private void StopPeerFinder()
{
if (Enabled && bPeerFinderRunning)
{
bPeerFinderRunning = false;
// now get onto UI thread to stop the timer
Deployment.Current.Dispatcher.BeginInvoke(() => dt.Stop());
PeerFinder.Stop();
Trace("Stopped Peerfinder");
}
}

// check if we've overrun, and if so, Switch it off.
void dt_Tick(object sender, EventArgs e)
{
if (dtExpiry < DateTime.UtcNow) StopPeerFinder();
}

// this runs on some arbitrary thread
void _nfcdev_DeviceDeparted(ProximityDevice sender)
{
StopPeerFinder();
}

// this runs on some arbitrary thread
void _nfcdev_DeviceArrived(ProximityDevice sender)
{
StartPeerFinder();
}

public static NFCManager Default
{
get
{
if (_instance == null)
{
_instance = new NFCManager();
}
return _instance;
}
}

public bool NFCSupportedOnDevice { get { return _nfcdev != null; } }

/// <summary>
/// Adds an alternate launch string, depending on your platform.
/// Sample values are for Windows 8
/// platform:"Windows", appid:"WieserSoftwareLtd.BouncingBalls_38031z1jk36d6!BouncingBalls.App"
/// where the part before the ! is your package ID, and the last part is the
/// namespace of your Application Object (full namespace). This is despite obfuscation.
///
/// For Windows Phone 8: The GUID is your app ID.
/// platform:"WindowsPhone", appid:"{41004b9e-eab4-4784-94d6-d1bdd219e4de}"
///
/// Don't add an alternate identity for the platform you're on, or you'll get an exception
/// </summary>
/// <param name="platform">see strings above</param>
/// <param name="appid">see strings above</param>
public void AddAlternateIdentity(string platform, string appid)
{
PeerFinder.AlternateIdentities.Add(platform, appid);
}

public string DisplayName
{
get { return PeerFinder.DisplayName; }
set { PeerFinder.DisplayName = value; }
}

private bool _bEnabled;
public bool Enabled {
get { return _bEnabled; }
set
{
if (!NFCSupportedOnDevice) throw new NotSupportedException("There is no NFC support on this device");
if (value != _bEnabled)
{
StopPeerFinder();
_bEnabled = value;
}
}
}
}
}


A couple of comments on the code:


First, you’ll need to enable ID_CAP_PROXIMITY on your app.


You’ll also note some code that uses a dispatcher timer that fires once a second once a device has come in range.  This code is there to switch it off if a connection isn’t made in time.


Have fun, and follow me on @WieserSoftware

Sunday 17 November 2013

AdDuplex requires ID_CAP_PHONEDIALER

We’ve recently started using AdDuplex in our trial apps to get some extra promotion, as using the Microsoft PubCenter. 

We previously had the Microsoft Ad Control in the app, and it required a lot of capabilities that frankly I think scares off users.

So, I was very happy to learn that AdDuplex required only ID_CAP_NETWORKING

One of the apps we updated was a WP7 app, and as part of the submission Capabilities are automatically detected (this is no longer the case on WP8), and I was surprised that it flagged up ID_CAP_PHONEDIALER.  I suspected that I had done something wrong with remove of the old ad control.  ID_CAP_PHONEDIALER is added when you use the PhoneCallTask API

So I fired up JustDecomple from Telerik and did a search for that in my xap project.

Eventually, that led me to the AdDuplex.Models.NetworkManager class and it’s DisplayPhone method, which is called by AdDuplex.HandleAdClick

It turns out that if a phone number is supplied by the ad, that is the preferred mechanism for serving the ad!  I contacted AdDuplex about this, and I was told that the server currently will not serve these ads.

What DOES this mean for users of the control?

In the case that it does in the future, you will be pleased to know that your app will crash if you haven’t added the capability to your app if the user clicks on one of these links.  This also means that a man in the middle attack on AdDuplex’s servers could also cause your app to crash.

I contacted AdDuplex to ask about this and was told:

“We will consider removing the capability from the SDK. It’s only there for some future feature which is unlikely to materialize any time soon and we don’t actually want to serve ads like that. Thank you for bringing this to our attention.”

In the meantime, it’s still there in the latest November 14th update, 2.8.0.4

Saturday 16 November 2013

Slider and IsDirectionReversed–Why doesn’t my app work on WP8 (part 6 of N)

Just when you thought all the bugs must have been ironed out by now, you stumble across a new one.

I’ve recently been updating all of my apps to Visual Studio 2013 so support will be simpler in future, and as a result started porting to WP8 from our old WP7 codebase.

Of course, everything is supposed to just work.  Today we’ll focus on the IsDirectionReversedProperty, which as will see should really be called IsDirectionReversedProperly!

Try sticking this in your WP app:

<Slider Orientation="Horizontal" Maximum="10" IsDirectionReversed="True" />

Can you see where this is going?

Now add Minimum="5" and be amazed that this slipped through testing.

It’s broken on the 720p emulator.  It’s broken on my Lumia 920 with GDR3.  It’s not broken in a WP7 app though.

So, I wonder how Microsoft can fix this out in the wild, (though it only seems to work in any kind of reasonable way if Minimum is set to 0).  Someone may be depending on this behavior.

Sunday 10 November 2013

RateMyApp challenge on DVLUP code defects and gotchas

If you’re trying to run the RateMyApp challenge over at DVLUP (if you haven’t signed up, you should.  Click the link), you may be interested in a few problems I’ve stumbled across.

First, your app bar will still be active, even if the rating window is open. 

To fix that, you’ll need to wire up to the feedback controls VisibilityChanged event, and then in the handler, set

ApplicationBar.IsVisible = FeedbackOverlay.GetIsNotVisible(feedbackctrl);

Secondly, you’ll find that if you have any touch events, they may be handled as well.  This includes ListBox manipulation and scrolling, so you’ll need to turn that off in the handler too.

And finally, the bug.

If your app has multiple pages you’ll find that on the 5th and 10th run, your user will continue to be pestered every time you navigate back to the main page of your app.

To fix this, I suggest you do the following:

In FeedbackOverlay.xaml.cs add the following to the SetVisibility(bool visible) function inside the bottom of the else statement:

FeedbackHelper.Default.State = FeedbackState.Inactive;

If you don’t, the state will remain the same, even though the FeedbackOverlay was dismissed, so it will continue to be shown.

In addition, you must also change the yesButton_Click handler to SetVisibility(false) at the end of the function, rather than the beginning.

Wednesday 6 November 2013

Detecting .NET 4.5.1

According to Microsoft on this page, this is how you detect .NET 4.5.1

However, on both of the Windows 8.1 machines I currently have, I see a version for release of 378675.

I wonder if they’ve got it wrong.

UPDATE:

After further investigation, on my 32 bit windows 8.1 machines, I’m seeing 378675, including after installing the packages.

On 64 bit windows 8.1 machines, I also see 378675.

However on 64 bit windows 7 machines, after installing the packages, I see the correct version of 378758.

This is especially humorous in light of yesterday’s post where an 8.1 app will report that it’s 8, causing the installer to repeatedly try to install 4.5.1.

Tuesday 5 November 2013

GetVersionEx won’t help you now!

If like me, you’ve built some crash handling code into your app so you can find out where your application is crashing in the wild, and find that WER isn’t the most effective way to get your crash dumps, you might be in for a suprise.

Since the Windows 8.1 update, you’ll no longer be able to find any machines that run a version later than Windows 8?

Why?  Because of this change they made on Windows 8.1.  Apparently, since we developers can’t be trusted to get version checks right, they’ve deprecated GetVersionEx, and to add insult to injury, make it lie and claim that it’s only Windows 8.

So, if you want to retarget for Windows 8.1, and actually find out what version it is, you’ll need to add this to your app manifest.

<!-- Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>

along with all the previous versions.

I wonder if 8.2 or whatever will lie, and say it’s 8.1 without the correct manifest too?

Upgrading a C++/CLI project to VS2013 from VS2010

Today, I begin to update an old C++ project to the latest compiler, and while building got this error message:

1>stdafx.cpp : fatal error C1107: could not find assembly 'mscorlib.dll': please specify the assembly search path using /AI or by setting the LIBPATH environment variable

That’s all very well, but it wasn’t obvious what to do.

Here’s how I solved it:

First, I created a new CLR Class Library project with C++, and examined the vcxproj file generated.

I then took my project that wouldn’t build, and right clicked and said, unload project, followed by edit on the same project.

Looking for differences I spotted this:

<TargetFrameworkProfile>Client</TargetFrameworkProfile>

Of course, .NET 4.5 doesn’t support the client profile, and surprise surprise, it now works once I remove that line.

It looks like the VS2013 project upgrade doesn’t quite get this one right.

Monday 4 November 2013

We’ll make an exception, just for you! Fun with accelerometers on Windows 8.1

I've been getting repeated failures on one of my apps that uses accelerometers, and I've been guessing where the failure was.  As the cert team wouldn't send me crash reports, I ended up building a version that I had no intention of releasing, but puts up in your face stack traces.

This time, I got a result, but the findings are extremely worrying.

I have code in my app that goes like this:

Accelerometer _accelerometer;

void NewReading(object sender, AccelerometerReadingChangedArgs e)
{
  ... nothing of interest here...
}

private void Initialize()
{
    _accelerometer = Accelerometer.GetDefault();
   if (_accelerometer != null)
   {
        // the next line throws an exception!
        _accelerometer.ReadingChanged += NewReading;
   }
}

This throws an exception as follows:

The object identifier does not represent a valid object: (Exception from HRESULT 0x800710D8)
Call Stack
  at Windows.Devices.Sensors.Accelerometer.add_ReadingChanged(TypedEventHandler`2 handler)
at
System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMarshal.NativeOrStaticEventRegistr...(Func`2 addMethod, Action`1 removeMethod, T handler)
at System.Runtime.InteropServices.WindowsRuntime.WindowRuntimeMarshal.AddEventHandler[T](Func`2 addMethod, Action`1 removeMethod, T handler)

This looks like a hardware driver problem to me, and anyone who is tested on this particular computer will fail.

The event log said it was:
BEI-AC75

Any other developers out there seeing cert failures on Windows 8.1 like this?

Friday 1 November 2013

How to make SuspensionManager.RestoreAsync in W8.1 app throw

One of the requirements for the store is that the application shouldn't close unexpectedly. So your app catches an exception, but then what?

One of the things I find really troublesome about the modern style of development is knowing what to do after an exception is thrown. Most API's don't even mention that an exception is thrown, let alone what state you might be in afterward.

For instance, many of you may be upgrading your apps from 8 to 8.1. I did, and found a very odd exception.
SuspensionManager failed
at Common.SuspensionManager.<RestoreAsync>d__9.MoveNext()
This exception had an internal exception as follows:
System.Exception
Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
at Windows.UI.Xaml.Controls.Frame.SetNavigationState(String navigationState)
at Common.SuspensionManager.RestoreFrameNavigationState(Frame frame)
at Common.SuspensionManager.<RestoreAsync>d__9.MoveNext()

The reason for the exception boils down to Windows.UI.Xaml.Controls.Frame.SetNavigationState being passed a serialization string that has changed format between versions of my code (for example the main window class name changed in between).

I think what actually happened was this in my specific case: I had an app that had been suspended and terminated, and then I upgraded that same app from the store. When I launched the app it failed.

This exception managed to bring my code down, and fall into the unhandled exception handler because I'd modified the internal code in my app for the logic calling SuspensionManager.RestoreAsync()


In the new vs2013 wizards, you get code like this:

if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) 
{
// Restore the saved session state only when appropriate
try
{
await SuspensionManager.RestoreAsync();
}
catch (SuspensionManagerException)
{
//Something went wrong restoring state.
//Assume there is no state and continue
}
}




Now, given that my app saw a SuspensionManagerException, how can anyone know what the state of the rootFrame is? The code in the current App.xaml.cs generated by the wizard will blindly carry on, and do this (in the SplitApp)


if (rootFrame.Content == null) 
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(ItemsPage), e.Arguments);
}



in the grid app it does a similar comparison, and creates a GroupedItemsPage.


But how can we know this is safe? Could we not have a partially restored navigation stack, which will lead to another crash later? Or should I just "stop worrying and learn to love the bomb"?