Solving “The Remote Desktop configuration was not generated by Windows Azure Tools”

For some time I’ve had issues with enabling Remote Desktop connections through the Publish dialog from within Visual Studio 2010, where I’ve gotten the following error message:

This time I really wanted to start using Web Deploy to iterate changes quickly, so I needed to fix this, and it turned out to be relatively simple. Just follow the following two steps:

Step 1 – Remove the RemoteAccess and RemoteForwarder modules from ServiceDefinition.csdef

<Imports>
  <Import moduleName="RemoteAccess" />
  <Import moduleName="RemoteForwarder" />
</Imports>

Step 2 – Remove all RemoteAccess/RemoteForwarder settings and the RemoteAccess certificate from ServiceConfiguration.*.cscfg

<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.Enabled" value="false" />
<Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountUsername" value="xxx" />
<Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountEncryptedPassword" value="xxx" />
<Setting name="Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountExpiration" value="2011-12-31T23:59:59.0000000+01:00" />
<Setting name="Microsoft.WindowsAzure.Plugins.RemoteForwarder.Enabled" value="true" />
<Certificates>
<Certificate name="Microsoft.WindowsAzure.Plugins.RemoteAccess.PasswordEncryption" thumbprint="xxx" thumbprintAlgorithm="sha1" />
</Certificates>
</ConfigurationSettings>

Now it should work to enable Remote Desktop (and Web Deploy) through the Publish dialog.

Publically exposing a service on my laptop using the AppFabric Service Bus

To learn a bit more about the AppFabric Service Bus in Azure, I am creating a relatively simple solution and documenting it as I go in this blog post.

The idea: Create a WCF (REST/JSON) service that runs on my laptop and exposes a public endpoint on the Service Bus that I can connect to from any browser to find out where my laptop is physically located. The service must work as long as there is an active Internet connection, even if the computer is behind various firewalls and with NAT.

In other words, very similar to various “Find my device” services that exist, but this one will be even more rough and inaccurate in its positioning ;).

Round 1 – Create Service Bus namespace

First I needed to create a service bus namespace where my service will be exposed. This is done via the Windows Azure Management Portal. First, navigate to the Service Bus tab and click to create a new service namespace:

Then fill in the unique namespace name that you want and select a region, subscription and connection pack size. The connection pack size has an effect on cost, and I will choose “0 connections” which basically means pay-as-you-go (but at a higher per connection cost than if I would have selected a fixed package size). More information about pricing for the Service Bus can be found here.

That is all that’s needed to create the namespace. Note that there is a button to retrieve a key that we will need later on to publish the service to this namespace

Round 2 – Creating an application that exposes a service on the Service Bus

The next phase is to develop the actual application that will host the service and expose the endpoint on the AppFabric Service Bus. I will do this in a simple Console Application, even though it would be very easy for someone who steals my laptop to shut down the application and stop me from finding it :).

First, we need to reference Microsoft.ServiceBus.dl which comes with the Windows Azure AppFabric SDK and is located in the following folder after installation:
C:\Program Files\Windows Azure AppFabric SDK\V1.5\Assemblies\NET4.0

The target framework for the project has to be changed to the full “.NET Framework 4” to expose a WCF service:

Exposing the service is very similar to creating a “normal” WCF service. One difference is a specific helper method for creating the URI for your service. In the example below the first parameter is the protocol prefix, the second parameter is the service namespace, and the last parameter is the relative path that the service will be exposed on:

ServiceBusEnvironment.CreateServiceUri("https", "findmylaptopdemo", "findmylaptop");

The resulting URL for the service methods will be:
https://findmylaptopdemo.servicebus.windows.net/findmylaptop/METHODNAME

We then need to specify a relay binding, in my case a WebHttpRelayBinding which is recommended for WCF REST implementations. I specify to not require any authentication from the clients:

var binding = new WebHttpRelayBinding();
binding.Security.RelayClientAuthenticationType = RelayClientAuthenticationType.None;

The next thing to create a behavior with the issuer name and secret. This is required to add the service to the AppFabric service namespace. You get the secret and issuer name (default=owner) from the Management Portal as described earlier.

var behavior = new TransportClientEndpointBehavior();
behavior.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(IssuerName, IssuerSecret);

The last step involves defining the interface and writing the code for the service, just like with any service. Part of the  service interface:

[ServiceContract]
public interface IFindMyLaptopService
{
[OperationContract]
[WebInvoke(
Method = "GET",
UriTemplate = "/ip")]
Stream GetIp();
}

The code for the derived method:

public Stream GetIp()
{
Console.WriteLine("Incoming request for GetIp(), getting and returning external IP:");

var ip = WhatIsMyIpService.GetExternalIpAddress();
Console.WriteLine(ip);
Console.WriteLine("");

var html = string.Format("<html><body>Laptop's IP address: {0}</body></html>", ip);

return new MemoryStream(System.Text.Encoding.UTF8.GetBytes(html));
}

The helper method to retrieve the IP from WhatIsMyIp:

public static IPAddress GetExternalIpAddress()
{
const string whatIsMyIpUrl = "<a href="http://automation.whatismyip.com/n09230945.asp">http://automation.whatismyip.com/n09230945.asp</a>";
var webClient = new WebClient();
var utf8 = new UTF8Encoding();
var html = utf8.GetString(webClient.DownloadData(whatIsMyIpUrl));
var externalIp = IPAddress.Parse(html);
return externalIp;
}

The full solution can be downloaded from:
https://p2piter.blob.core.windows.net/theazureexperience/AzureFindMyLaptop.zip

You will need to enter your own information in the constants at the top of Program.cs:

private const string ServiceNamespace = "findmylaptopdemo";
private const string IssuerName = "owner";
private const string IssuerSecret = "XXXYYYZZZ";

Good luck!