I was playing around with building scripted objects in Second Life and ran across a function to pull text from the web. I thought it might be neat to create Live Messenger buddy object in Second Life that showed whether I was online or offline. I figured I could query the Windows Live Presence API directly from script and be done. Unfortunately it turns out there is a bit of a gap between Second Life and Windows Live. The Presence API serves up information by way of JSON. Second Life does not know what to do with JSON file coming back as the payload and gives an error.
Given this gap, I thought Azure might make a nice bridge. I could call the Live Presence API from a cloud based service, reproduce the information in a very simple format for Second Life, and then consume the new service with an HTTP call in Second Life.
I had to accomplish three things in order to get everything wired up.
- Put something in the cloud to provide a simple service
- Consume JSON from server code instead of a browser
- Connect Second Life to Azure
To get started, I registered for the Azure Community Technical Preview. This gave me a sandbox in the cloud to play with and I downloaded the free Visual Studio 2008 Web Developer 2008 which provided all the power I needed for this little project. Once in Visual Studio I created a new Web Cloud Service and used the following code.
1: using System.Net;
2: using System.IO;
3: using System.Text;
4: using System.Runtime.Serialization.Json;
5:
6: namespace SecondLife_WebRole
7: {
8:
9: [Serializable]
10: public class Presence
11: {
12: public string status;
13: public string displayName;
14: }
15:
16: public partial class _Default : System.Web.UI.Page
17: {
18: string LiveUrl =
19: "http://messenger.services.live.com/users/5a11680377739a32@apps.messenger.live.com/presence";
20:
21: protected void Page_Load(object sender, EventArgs e)
22: {
23: // Make a web request to Live service
24: HttpWebRequest request = (HttpWebRequest)WebRequest.Create(LiveUrl);
25: HttpWebResponse response = (HttpWebResponse)request.GetResponse();
26:
27: // Hydrate a .Net object from the JSON response
28: Stream receiveStream = response.GetResponseStream();
29: DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Presence));
30: Presence presence = ser.ReadObject(receiveStream) as Presence;
31:
32: // Output very simple text so Second Life can consume it
33: Response.Clear();
34: Response.ContentType = "text/plain";
35: Response.Write(presence.status + "\n");
36: Response.Write(presence.displayName + "\n");
37: }
38: }
39: }
I was pretty happy that the .NET Framework had a JSON helper class and a rich language with C# to work with the data. This code worked fine from an ASP.Net application but not from a cloud application. Turns out I needed to set enableNativeCodeExecution to true so that the stream classes would not hit a security exception.
1: <?xml version="1.0" encoding="utf-8"?>
2: <ServiceDefinition name="SecondLife" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
3: <WebRole name="WebRole" enableNativeCodeExecution="true">
4: <InputEndpoints>
5: <!-- Must use port 80 for http and port 443 for https when running in the cloud -->
6: <InputEndpoint name="HttpIn" protocol="http" port="80" />
7: </InputEndpoints>
8: </WebRole>
9: </ServiceDefinition>
Once I had that working, I used the cloud deploy feature of Azure to get the service hosted. It worked and my service was now serving something easily consumable by Second Life:
Finally I went into Second Life and added script to a buddy object created all in-game. The Second Life script simply makes an HTTP request to the cloud service and returns the very-simple-to-parse name and status. If I am online, i set the object to light blue and glowing and if I am offline, I dim the object and use a darker color.
// Use an Azure service in the cloud to get Live Messenger status
string AZUREHOST = "http://secondlife.cloudapp.net/Default.aspx";
key http_request_id;
default
{
touch_start(integer total_number)
{
llSetText("", <1,1,1>, 1.0);
string response = "";
http_request_id = llHTTPRequest(AZUREHOST, [], "");
}
http_response(key request_id, integer status, list metadata, string body)
{
if (request_id == http_request_id)
{
list lines = llParseString2List(body, ["\n"], []);
string status = llList2String(lines, 0);
string name = llList2String(lines, 1);
if (status == "Online")
{
llSetText(name + " is Online", <0,0,1>, 1);
llSetLinkColor(LINK_SET, <0.15686, 0.58039, 1.00000>, ALL_SIDES);
llSetLinkPrimitiveParams(LINK_SET, [PRIM_GLOW, ALL_SIDES, .1] );
llSetLinkPrimitiveParams(LINK_SET, [PRIM_BUMP_SHINY, ALL_SIDES, PRIM_SHINY_LOW, PRIM_BUMP_BRIGHT] );
}
else // user offline
{
llSetText("User Offline", <0,0,1>, 1);
llSetLinkColor(LINK_SET, <0.38824, 0.38824, .38824>, ALL_SIDES);
llSetLinkPrimitiveParams(LINK_SET, [PRIM_GLOW, ALL_SIDES, 0] );
llSetLinkPrimitiveParams(LINK_SET, [PRIM_BUMP_SHINY, ALL_SIDES, PRIM_SHINY_NONE, PRIM_BUMP_NONE] );
}
}
}
}
The Messenger buddy in second life is darker with no glow if I am logged out of Messenger. For Second Life builders, buddy is 10 prims big:

… but when I’m logged into Messenger, buddy lights up like a Christmas light:
So what's the big deal? Why use Azure for such a little thing? I think the answer is that it is such a "little thing." As a developer I just wanted to get my service online and working. I didn't want to have to go find a hosting provider, sign up and spend a bunch of money, and then take a few days trying to get everything working. I'd rather just spend time on getting the code to work. If I add significant features later on, or make the service public, I am confident Azure will scale with me. Again, I can just focus on the functionality of the service and not worry about scale and configuration.
When I account for my time on this project, I’m pretty happy with the breakdown. Much of the time was spent on community: Ben Williams pointed me towards the Windows Live Presence API. Jim O’Neil gave me a rough architecture by suggesting I try a WebRequest and then use the JSON Serializer. The venerable Steve Marx helped me debug by showing me the enableNativeCodeExecution flag. Second Life resident and coffee machine builder, amira Mathilde helped me craft the “buddy” object so it wasn’t terrible looking.
My Second Life resident is “Macaw Roogus” so say hi to me if you see me online and maybe we can find some more interesting things to build.
June 26 - October 31 2007
http://www.theingenuitypoint.com/main/default.aspx
Microsoft is holding a contest to showcase applications written for healthcare, clean technology, and education. Just looking through the People's Choice Gallery... some neat entries and pretty good odds of winning a trip to France.

My friend Burzin Patel co-authored a book on SQL Server. Get all your SQL Server knobs turned in the right direction with this book.
Eugene Asahara has launched SoftCodedLogic.com. The same idea of soft coding UI and data has been extended to program logic. Eugene's implementation is a clever update to prolog to bring it into the world of SQL, XML, and .NET.
My colleague, Vince Maraia, has come out with a book on configuration management called The Build Master.
Jim Owen, a Technical Account Manager at Microsoft, made a clever song using keyboards and the Windows sounds.
Have a listen.
Are you gosu with .NET? Email me your resume. I'll get the full job description posted on the microsoft.com careers site soon.
Deep .Net development expertise
n C#, J# if possible
n Extensive experience with performance testing and optimization of .Net applications, and ASP.Net on IIS optimization
o Profiling
o Debugging with symbols and trouble shooting application bottlenecks
o Analysis of performance data
o Expertise with a myriad of testing/profiling tools
Web Queries in Excel let you grab tabular data off of a web page without writing any code or messing with web services. I use this feature all the time as a manager trying to grab internal business data off of many different systems in order to analyze it. In this example, I build a computer model of the political race. The entire project can be done in less than 20 minutes.
- Open Excel 2003
- Choose Data | Import External Data | New Web Query...
- Browse to http://vote.wa.gov/general/status.aspx and select the table that lists ballots left to be counted by county.
- After the table is imported do it again for the results in the race found so far found at http://vote.wa.gov/general/resultsbycounty.aspx?o=3001&t=s
- You should now have both tables side-by-side in Excel. You can color and format them however you like:
- Create further columns to find the percentage a candidate gets from each county and then multiply that percentage against the remaining ballots in that county.
- Finally, total the projected votes with the votes a candidate already has and you will arrive at a projected final outcome.
- Now here is the really cool part: whenever new totals are posted on the web sites you can update your spreadsheet with Data | Refresh Data. Excel keeps your nice formatting and fomulas and just gives you the new numbers.
A final solution can be downloaded here.
Check it out. One of the most brilliant people I know:
http://weblogs.asp.net/eugenea
I've was playing around with image generation. Below is a picture of Josh who is a very interesting guy. His picture worked quite well because it was a clean slate to write text on.
The HTML tag <img src="http://www.rulesroost.com/josh.aspx?Text=Got%20Milk?"> produces:
And <img src="http://www.rulesroost.com/josh.aspx?Text=This%20is%20a%20much%20longer%20sentence."> shows:
And here is the code for the aspx file:
1<%@ OutputCache Duration="500" VaryByParam="Text" %>
2<%@ Page Language="C#" trace="false" Explicit="true" aspcompat="true" Debug="true" %>
3<%@ Import Namespace="System" %>
4<%@ Import Namespace="System.IO" %>
5<%@ Import Namespace="System.Text" %>
6<%@ Import Namespace="System.Drawing" %>
7<%@ Import Namespace="System.Drawing.Imaging" %>
8<%@ Import Namespace="System.Drawing.Text" %>
9<%@ Import Namespace="System.Drawing.Drawing2D" %>
10
11<script runat="server">
12 private void Page_Load(object sender, System.EventArgs e)
13 {
14 Bitmap bitmap = new Bitmap(Server.MapPath("josh.bmp"));
15 MemoryStream memStream = new MemoryStream();
16
17 // generate image
18
19 // Create a graphics object for drawing.
20 Graphics g = Graphics.FromImage(bitmap);
21 g.SmoothingMode = SmoothingMode.AntiAlias;
22
23 int width = bitmap.Width;
24 int height = bitmap.Height;
25
26 string familyName = "Tahoma";
27 string text = Request.Params["Text"];
28
29 // get a rectangle on his shirt
30 Rectangle rect = new Rectangle(150, 216, 210, 135);
31
32 // Set up the text font.
33 Font font;
34 font = new Font(familyName, 16F, FontStyle.Regular);
35
36 // Set up the text format.
37 StringFormat format = new StringFormat();
38 format.Alignment = StringAlignment.Center;
39 format.LineAlignment = StringAlignment.Center;
40
41 // Create a path using the text and warp it to fit over his contour
42 GraphicsPath path = new GraphicsPath();
43 path.AddString(text, font.FontFamily, (int) font.Style, font.Size, rect, format);
44
45 PointF[] points =
46 {
47 new PointF(rect.X - 10, rect.Y - 8),
48 new PointF(rect.X + rect.Width - 20, rect.Y + 4),
49 new PointF(rect.X - 8, rect.Y + rect.Height - 15),
50 new PointF(rect.X + rect.Width - 10, rect.Y + rect.Height + 4)
51 };
52 Matrix matrix = new Matrix();
53 matrix.Translate(0F, 0F);
54 path.Warp(points, rect, matrix, WarpMode.Perspective, 0F);
55
56 // Draw the text.
57 HatchBrush hatchBrush = new HatchBrush(
58 HatchStyle.LargeConfetti,
59 Color.LightGray,
60 Color.DarkGray);
61
62 g.FillPath(hatchBrush, path);
63
64 Response.Clear();
65 Response.ContentType="image/jpeg";
66 bitmap.Save(memStream, ImageFormat.Jpeg);
67 memStream.WriteTo(Response.OutputStream);
68
69 // Clean up.
70 font.Dispose();
71 hatchBrush.Dispose();
72 g.Dispose();
73 bitmap.Dispose();
74
75 }
76
77</script>
78
Notice the Reponse.ContentType="image/jpeg" - that causes the output to be a picture and not HTML.
Also notice the word-wrap is done for me with the StringFormat object.
Other resources:
I've noticed that some recent blog entries talk about the new .NET framework supporting Data Protection API.
What is the Data Protection API? The DPAPI is used to hide secrets like connection strings and user credentials that are typically stored in a config file. Instead of storing the plain text, you can use DPAPI to encrypt and decrypt the secrets at a machine or user specific level.
A couple years ago I posted a sample DPAPI component on GotDotNet. It's still there and you can use it until the real Data Protection API comes out with the next Visual Studio. There are some warts with this one so read the comments people posted in the download link.
The component comes with a WinForms and WebForms example:
Code behind the Encrypt button:
1private void Encrypt_Click(object sender, System.EventArgs e)
2 {
3 byte[] entropy = new byte[0];
4 if (UseEntropy.Checked)
5 {
6 entropy = Encoding.Unicode.GetBytes(EntropyText.Text);
7 }
8
9 DataProtector dp = new DataProtector(Store.MachineStore);
10 byte[] dataToEncrypt = Encoding.Unicode.GetBytes(SecretText.Text);
11
12 try
13 {
14 CipherText.Text = Convert.ToBase64String(dp.Encrypt(dataToEncrypt, entropy));
15 }
16 catch (Exception ex)
17 {
18 MessageBox.Show(ex.Message);
19 }
20
21 }
Code behind the Decrypt button:
1private void Decrypt_Click(object sender, System.EventArgs e)
2 {
3 byte[] entropy = new byte[0];
4 if (UseEntropy.Checked)
5 {
6 entropy = Encoding.Unicode.GetBytes(EntropyText.Text);
7 }
8
9 DataProtector dp = new DataProtector(Store.MachineStore);
10 byte[] dataToDecrypt = Convert.FromBase64String(CipherText.Text);
11
12 try
13 {
14 DecryptResults.Text = Encoding.Unicode.GetString(dp.Decrypt(dataToDecrypt, entropy));
15 }
16 catch (Exception ex)
17 {
18 MessageBox.Show(ex.Message);
19 }
20
21 }
The DataProtector class imports CryptProtectData and CryptUnprotectData from the CryptoAPI to do the work.
Other options:
- The .Net Security Blog has two articles on DPAPI.
- MSDN has an article on DPAPI that you could use to construct a component.
- Jerry Dixon has an excellent DPAPI wrapper posted on his blog.
Many years ago (1994) programmer, and my geek idol, Tim Robinson compiled a list of ways to output the lyrics to the song 99 Bottles of Beer. It started with someone posting to a mailing list the entire lyrics to the song and then someone else replied with a Basic version of the song:
10 REM BASIC Version of 99 Bottles of beer
20 FOR X=100 TO 1 STEP -1
30 PRINT X;"Bottle(s) of beer on the wall,";X;"bottle(s) of beer"
40 PRINT "Take one down and pass it around,"
50 PRINT X-1;"bottle(s) of beer on the wall"
60 NEXT
Tim posted a C++ version and it grew from there to hundreds of versions. Unfortunately Tim's web site (and Tim) disappeared from the 'net and all was lost for a few years. Now, Oliver Schade has posted the entire collection and then some on a web site: http://www.99-bottles-of-beer.net.
One of my contributions was Modula-2:
MODULE BottlesOfBeer;
FROM InOut IMPORT WriteCard, WriteString, WriteLn;
CONST
BOTTLES = 99;
VAR
counter : CARDINAL;
BEGIN
counter := BOTTLES;
REPEAT
WriteCard( counter,2 );
WriteString(" bottles of beer on the wall, ");
WriteCard( counter,2 );
WriteString(" bottles of beer."); WriteLn;
WriteString(" Take one down, and pass it around, ");
DEC( counter );
WriteCard( counter,2 );
WriteString(" bottles of beer on the wall."); WriteLn;
UNTIL ( counter = 1 );
WriteString("1 bottle of beer on the wall, 1 bottle of beer"); WriteLn;
WriteString("Take it down and pass it around, ");
WriteString("No more bottles of beer on the wall."); WriteLn;
END BottlesOfBeer.
What I enjoy about this catalog is that people tried to incorporate features from the language. Along with the usual cast of languages like SQL, C#, and various C++ versions, some clever languages were posted. Here are some of my favorites:
SmallTalk
99 to: 1 by: -1 do: [ :i |
i print. ' bottles of beer on the wall, ' print.
i print. ' bottles of beer. ' print.
'take one down, pass it around, ' print.
(i-1) print. ' bottles of beer on the wall, ' print.
]
Meta HTML
<html>
<head> <title> 99 Bottles of Beer: The Compleat Lyrics </title> </head>
<body>
;;;
;;; The actual source code to The Compleat Lyrics.
<defsubst plural whitespace=delete>
<if <not <eq %0 1>> s>
</defsubst>
<set-var beers=99>
<while <gt beers 0>>
<get-var beers> bottle<plural beers> of beer on the wall, <br>
<get-var beers> bottle<plural beers> of beer, <br>
You take one down, pass it around, <br>
<decrement beers>
<get-var beers> bottle<plural beers> of beer on the wall.
<p>
</while>
No more bottles of beer on the wall, <br>
No more bottles of beer, <br>
Go to the store, and buy some more, <br>
<form method=GET action="<get-var mhtml::current-url>">
<input type="submit" name="button" value="99 Bottles of beer on the wall">
</form>
</body>
</html>
Perl for Signature
#!/usr/bin/perl -iake_one_down_pass_it_around:_bottles_of_beer:_on_the_wall:99
for(($t,$a,$b,$i)=split/:/,$^I;$i;print){$_="-$i$a$b,-$i$a,-T$t,-".--$i."$a$b
";s/(-1_.*?e)s/$1/g;y/_-/ \n/}# by Randolph Chung and Joey Hess
POV Ray
POV-Ray is a ray-tracing program.
// povray 3 file for the 99 bottles of beer ...
#declare S1 = " bottles"
#declare L1 = " of beer on the wall,\n"
#declare L2 = " of beer.\n"
#declare L3 = "Take one down and pass it around,\n"
#declare L4 = " of beer on the wall.\n\n"
#declare Beer = 99
#declare S2 = concat(str(Beer,0,0),S1)
#render "\n"
#while (Beer > 0)
#render concat(S2,L1)
#render concat(S2,L2)
#render L3
#declare Beer = Beer - 1
#if (Beer = 1)
#declare S2 = "1 bottle"
#else
#if (Beer = 0)
#declare S2 = "No more bottles"
#else
#declare S2 = concat(str(Beer,0,0),S1)
#end
#end
#render concat(S2,L4)
#end
sphere { 0, 1 pigment { colour rgb <1,0,0> } }
light_source { x*2, colour rgb 1 }
camera {
perspective
location x*2
look_at 0
}
There are also some unmentionables like this one and this one. 621 versions so far. One glaring omission is Managed C++ [looks over at Yves Dolce]. I also wonder whatever happened to Tim Robinson. He was the brains behind Excalibur BBS which was a Windows based BBS that served up screens with meta-driven GUI. Instead of writing classic BBS doors you would write DLL add-in's. It was unfortunately timed to come out just as the WWW was emerging but the software was very cool nonetheless.
I found a company that sells giant fresnel lenses. What is a Fresnel lens? Think of a lighthouse or the top of an overhead projector. As light goes through the lens, spiral cut ridges focus the light to a focal point. You end up with the equivalent of a giant magnifying glass or parabolic mirror. There is some really juicy math invovled in calculating how to create a lens, determining the focal length and lens strength.
I framed the lens with some 2“x2“ lumber and secured it with electrical tape. When I carried the lens out of the garage, I knew we were in for a good show. The asphalt driveway started smoking. Our first target was a penny which the lens quickly melted into slag. Next up was a hamburger. We widened the focus and it flash cooked the top of the burger.
What I learned:
- You really need welding goggles. I have none so we had to use a spotter from a distance to help us focus. If you knelt down and tried to focus it without eye protection, you would surely suffer eye damage.
- If the sun is directly overhead, the lens is easier to focus and burns significantly hotter.
- Burgers cooked with a giant death ray don't taste very good. It's about like cooking in a microwave: you don't get the smoky taste that a BBQ gives you.