Scott Hanselman

The Weekly Source Code 50 - A little on "A generic error occurred in GDI+" and trouble generating images on with ASP.NET

February 18, '10 Comments [12] Posted in ASP.NET | Source Code
Sponsored By

I got a nice little Yellow Screen of Death (YSOD) error on some code running under IIS that worked fine when running on the VS Developer Web Server. The error was "A generic error occurred in GDI+" and you know that if an error is generic, it's sure in the heck not specific.

My little application takes an overhead map that's stored in a local file, does some calculations from user input and draws an X on the map, then returns the resulting dynamically generated image.

There's basically three ways to do images on the server side. Use Native APIs and Interop, which only works in full trust, use System.Drawing, which "isn't supported" or use WPF on the server side, which also, ahem, isn't officially supported. I'm still trying to figure out why, but just to be clear, I used System.Drawing in extremely high traffic sites with no problems. As long as paid close attention to my unmanaged resources, I have never had a problem. I've heard anecdotally of people having trouble with GDI+ (System.Drawing) and switching over to WPF and having no problem with that. As with all things, test what you're doing. There's even some ASP.NET Controls on CodePlex that might help.

Now this post can't answer ALL reasons you're getting "a generic error occurred in GDI+" but it can answer mine. In my particular case (and I think this is the most common mistake) I was saving the composited image as a PNG.

First, I'll show you a little chunk of a code from 5 years ago that took two images and built a single image from them.

public class SomeCheckImageHandler : IHttpHandler
{
//some stuff snipped

public SomeCheckImageHandler(){}

public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/jpg";

//some stuff snipped
GetCheckImageRequest req = new GetCheckImageRequest();
//some stuff snipped, get the params from the QueryString
GetCheckImageResponse res = banking.GetCheckImage(req);

//some stuff snipped
if (res.ImageBack != null)
{
//merge them into one image
using(MemoryStream m = new MemoryStream(res.BackImageBytes))
using(Image backImage = System.Drawing.Image.FromStream(m))
using(MemoryStream m2 = new MemoryStream(res.BrontImageBytes))
using(Image frontImage = System.Drawing.Image.FromStream(m2))
using(Bitmap compositeImage = new Bitmap(frontImage.Width,frontImage.Height+backImage.Height))
using(Graphics compositeGraphics = Graphics.FromImage(compositeImage))
{
compositeGraphics.CompositingMode = CompositingMode.SourceCopy;
compositeGraphics.DrawImageUnscaled(frontImage,0,0);
compositeGraphics.DrawImageUnscaled(backImage,0,frontImage.Height);
compositeImage.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
}
else //just show the front, we've got no back
{
using(MemoryStream m = new MemoryStream(frontImageBytes))
using(Image image = System.Drawing.Image.FromStream(m))
{
image.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
}
}
}

This code generated a JPEG. No problems, runs fine even today. Now, the code I was working on created a PNG and when you create a PNG you need a seekable stream. This little sample uses the BaseHttpHandler Phil and I made.

Note the highlighted lines in this sample. (You'll see the highlights if you view this post on my blog directly, rather than from RSS.)

The Trick for making PNGs: Without the extra intermediate MemoryStream to save to, you won't be able to make PNGs. You can't image.Save() a PNG directly to Response.OutputStream.

namespace FooFoo
{
public class MapHandler : BaseHttpHandler
public override void HandleRequest(HttpContext context)
{
string filename = context.Server.MapPath(".") + @"\images\newmap2000.jpg";

using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
using (System.Drawing.Image image = System.Drawing.Image.FromStream(fs))
{
using (Graphics g = Graphics.FromImage(image))
{

BrickFinderDrawing drawer = new BrickFinderDrawing(...somedata...);
drawer.DrawBrick(g);
drawer.DrawName(g);

using (MemoryStream stream = new MemoryStream())
{
image.Save(stream, ImageFormat.Png);
stream.WriteTo(context.Response.OutputStream);
}
}
}
}

}

public override bool RequiresAuthentication
{
get { return false; }
}

public override string ContentMimeType
{
get { return "image/png"; }
}

public override bool ValidateParameters(HttpContext context)
{
return true;
}
}
}

Just a little something I wish I remembered when I hit the YSOD. Sure glad I have a blog to put this kind of stuff on! ;)

Related Links

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

DIY: Making a Very Wide Angle Webcam on the Cheap

February 17, '10 Comments [23] Posted in Remote Work | Reviews
Sponsored By

imageAfter I made my Webcam Cart and blogged about it a package I'd forgotten about arrived. It was a cheap "Zeikos ZE-WA37S 37mm 0.45X Wide Angle Lens." Only $10. I've looked all over for wide-angle webcams and they just don't exist. Over the counter webcams have a very narrow field of view.

I started with my favorite webcam, an amazing value, the Lifecam Cinema HD. I've got 4 of these. Now, the wide angle lens has a large opening, about an inch and a half, while the Lifecam is maybe an inch in diameter. I needed something to build up the diameter in such a way that it'd hold the wide angle lens in position while avoiding ruining the camera itself.

How? Electrical tape. Lots of it. I wrapped it around and around until it could offer enough outward tension to keep the lens on tightly.

Zeikos ZE-WA37S 37mm 0.45X Wide Angle Lens Lifecam with Wide Angle Zeikos Lens

Here's a still shot taken with the Lifecam Cinema HD with the lens it came with.

Lifecam HD Sample Photo

Here's a still shot taken with the same Lifecam Cinema HD with the cheap Zeikos Wide-Angle lens attached. Note the blurriness in the periphery and the slight fish-eye warping in the shelves.

Lifecam HD with Zeikos Wide-Angle Lens attached

The Lifecam is ideal for this kind of hack because it has a built in AutoFocus that REALLY works hard to keep things focused. I'll be using this for meetings and "getting a sense of the room" since I can't afford a $3000 "Roundtable" camera. I haven't measured it, but I fell I'm getting at least 100 degrees or more of field of view (my gut) so I think it's a good tradeoff of visual acuity for seeing a LOT more of the room for only $10.

Thoughts?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Building an Embodied Social Proxy or Crazy Webcam Remote Cart Thing

February 17, '10 Comments [22] Posted in Coding4Fun | IIS | Microsoft | Remote Work
Sponsored By

Channel 9 Video on Embodied Social Proxies As a remote worker I'm always looking to find better ways to work with the team that don't involve actually going to Seattle. As much as I love/hate Microsoft, I'm not moving. However, this always puts me at a disadvantage. There's only so many places (and only so far) i can go as a remote worker.

When Phil and I made the "HanselPortal," essentially a persistent always-on Skype Chat, that gave folks a place to drop by and chat (at least those two lazy to just call me via Office Communicator) but there's already two people in Phil's office, I can't move (I'm a desktop computer) and my field of view is very small. Phil has a small inside office and I can't exactly hold meetings. It's a start, but it's not perfect.

I stumbled upon the Embodied Social Proxies project at Microsoft Research and got a tour from their team. While their system costs about $3000 to $4000 (While I'd love an Axis 213 PTZ camera I can't afford the $1300 and I'm still trying to convince the boss.) and has a great cart, monitor and camera, I figured I could at least do a proof of concept on the cheap. And by proof of concept, I mean, in the same way my 1963 Ford Falcon was a proof of concept; I kept driving it until it stops, then started walking.

The Idea

While the name "Embodied Social Proxy" is very PHDy and very Researchy, the idea is that you want a physical stand-in for yourself. Sure, people can call me and contact me in any of a dozen ways and honestly, it's one click at Microsoft. I'm in the address list, I'm on chat, and I've even got a 5 digit phone extension. I've done all this and more to integrate with headquarters. However, out of sight, out of mind is really true. People subconsciously or not like to associate something physical with you. So, until I can get a 6 foot tall mobile video conferencing robot a $20 cart with a laptop super-glued to it might help. I'll set it up in an office in Building 5 so folks can "stop by." I can be "brought" to meetings where perhaps setting up a RoundTable isn't feasible. Maybe it'll work, perhaps not. But I'm going to continue to try.Network Diagram

The Problems

The researches have done many iterations and discovered many things. You want "eye gaze" to be natural so you can tell when folks are looking at you and they can tell when you're looking at them. They recognize that you need to "look around" and watch whiteboards, so being able to pan and zoom around is important.

Security is important also. We don't want a domain-logged-in real user on a mobile cart wandering around Microsoft. However, as a remote person I need to be able to start up the camera without having to ask a person to do it. I need to control as much of the cart as possible remotely.

The General Solution

I've got Office Communicator "corporate chat" on my side, so that makes things easier. If you wanted to generalize this solution you could use Skype or other things. I also have Exchange so my free/busy details are available programmatically. Again, this could be Google Calendar, or whatever.

I'll have a laptop mounted (not movable) to a cart. It'll include an HD Webcam at a fixed position (no zoom or pan) and a second IP camera that allows Pan/Tilt/Zoom (PTZ). This should let me look around a bit. This is an IP camera because there are no good pan/tilt/zoom USB cameras on the market. PTZ cameras can be $200 or up to $3000 and more. Mine's $200.

I need the laptop to have both wired and wireless. Here's where things get a little weird. The camera will have one IP and the laptop will have another. However, the laptop will have a security certificate that will allow it to get on the network while the camera will not only not be reliable, but it'll be hard to find from a DNS perspective. I would like to be able to access both the camera and the machine as a unit, reliably. I solve that below, in what I think is a pretty clever way.

The (Cheap) Hardware

The hardware for my build is beyond cheesy cheap.

The Software

There's a custom WPF-based .NET client written by the MS Research Team. I'm gonna continue to bug them to let me release the code or Open Source it or something. I don't think the software is the important part, it's the idea. The software is a little tricky and cobbled, but workable.

Talking to Office Communicator

The machine is running on a local account that isn't Administrator. It's set to log in automatically, but the account has access to nothing. There's another Non-User Domain Account called "hanselcart" but while this account is in the Active Directory, but also has no access to resources or anything. That account has had Office Communicator access turn on so I can chat with it. Communicator is set to start up automatically as well. It's that ability to chat (really "address") the cart that makes it reasonably seamless.

You'll see that if I'm not currently visible on the screen, the program makes a call to Exchange Web Services and uses the Office Communicator Presence information to show where I am and what I'm doing generally, as well as a way to call me.

Screenshot of the Social Proxy Software

There's an Office Communicator SDK so you can automate and listen to Communicator:

this.messenger = new Messenger();
this.messenger.OnSignin += new DMessengerEvents_OnSigninEventHandler(messenger_OnSignin);
this.messenger.OnContactStatusChange += new DMessengerEvents_OnContactStatusChangeEventHandler(messenger_OnContactStatusChange);
this.messenger.OnIMWindowCreated += new DMessengerEvents_OnIMWindowCreatedEventHandler(messenger_OnIMWindowCreated);
this.messenger.OnIMWindowDestroyed += new DMessengerEvents_OnIMWindowDestroyedEventHandler(messenger_OnIMWindowDestroyed);
this.messenger.OnMyStatusChange += new DMessengerEvents_OnMyStatusChangeEventHandler(messenger_OnMyStatusChange);
this.messenger.AutoSignin();

The code is very COM-ish, which is unfortunate, but it's easy enough to write to. If I chat "Start Video" to the cart, the program sees it and calls me back:

void StartVideo()
{
IMessengerAdvanced advanced = (IMessengerAdvanced) this.messenger;
object result = advanced.StartConversation(CONVERSATION_TYPE.CONVERSATION_TYPE_VIDEO, this.contact, null, null, "1", null);

// Float a "hang up" window on top
if(hangupWindow == null) {
hangupWindow = new HangupWindow(MachineName);
hangupWindow.Closed += new EventHandler(hangupWindow_Closed);
hangupWindow.Owner = this;

// put the hang up window top-right corner
hangupWindow.Top = 0;
hangupWindow.Left = System.Windows.SystemParameters.PrimaryScreenWidth - hangupWindow.Width;
}

// Set the video to full-screen
maxVideoTimer.Start();
hangupWindow.Show();
}

The FullScreen part is a horrific SendKeys hack to press F5 for me until I talk to the OC team and figure out how to do this programmatically.

How to Address the IP Camera - "It's a WebFarm of WebCams with IIS's AAR"

I'm rather proud of this hack. Let's say the cart is called http://hanselcart. I'd like to be able to address the WebCam reliably even though it's not technically a managed-object on the MS network. Essentially, if the cart itself is on and online, I'd like to use the cart to get to the camera.

Then I remember that IIS (Internet Information Services, our Web Server) has an insanely powerful free module you can download called Application Request Routing or ARR. Regardless of what you think of the name IIS ARR, it really takes IIS to the next level. Think about it next time you are trying to do something tricky with IIS. It adds a bunch of features, but I figured I needed a Reverse Proxy, which ARR can do.

Instead, I made my local IIS a WebFarm with one node, the WebCam. ;) I put the Webcam on a local network "behind" the laptop (192.168.x.x) and told my Laptop's instance of IIS to route all traffic to the Webcam. In fact, ARR smartly did it for me when i used the Add WebFarm Wizard. Whole thing took 5 minutes, counting download time.

A Web Farm of Web Cams

NOTE: I did also try a tool called WebcamXP, and while it's amazingly cool for other things and has some really diverse features around Webcams, especially IP webcams, it used about 30% CPU for what I wanted, while IIS's ARR used 1-2%.

So now, I can just hit the cart by name and I'll get the IP Webcam. This Webcam has its own HTTP server and includes a quasi-RESTful API for Pan/Tilt/Zoom so I can video chat via Office Communicator and look around with the web interface of the IP Cam.

HanselCam

Here's a few shots of the cart itself. I'll be driving it up to Seattle for testing and installation this week.

HanselCart Full Body Shot Close Up of IP Cam

Thanks to Gina and John and especially Peter Provost for helping me (virtually from Dallas) build it. Wish me luck!

Related Links 

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselminutes Podcast 200 - Jon Skeet!

February 16, '10 Comments [3] Posted in Podcast
Sponsored By

jonskeet My TWO-HUNDREDTH podcast is up. It's show 200, and we've got Jon Skeet. Jon writes Java at Google, but he's also got a new book out called C# in Depth, Second Edition. Jon is also well-known for his answers on StackOverflow, gaining him the title "The Chuck Norris of Programmers." Listeners can get 40% off with code "HanselC40" at http://manning.com/skeet2 until March 15th. Someone even made an Ask Jon Skeet search engine!

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

Download: MP3 Full Show

Links from the Show

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

I want to add a big thanks to Telerik. Without their support, there wouldn't be a Hanselminutes. I hope they, and you, know that. Someone's gotta pay the bandwidth. Thanks also to Carl Franklin for all his support over these last 4 years!

Telerik is our sponsor for this show.

Building quality software is never easy. It requires skills and imagination. We cannot promise to improve your skills, but when it comes to User Interface and developer tools, we can provide the building blocks to take your application a step closer to your imagination. Explore the leading UI suites for ASP.NET AJAX,MVC,Silverlight, Windows Forms and WPF. Enjoy developer tools like .NET reporting, ORM, Automated Testing Tools, TFS, and Content Management Solution. And now you can increase your productivity with JustCode, Telerik’s new productivity tool for code analysis and refactoring. Visit www.telerik.com.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Back to Basics: C# 4 method overloading and dynamic types

February 12, '10 Comments [30] Posted in Back to Basics | Learning .NET | Programming | VS2010
Sponsored By

C# 3.0 introduced the implicit type "var". I've explained var as saying:

"I'm too lazy to tell you the type of this variable, so you figure it out, compiler."

However, it's more useful than just promoting terseness or laziness:

var i = 10; // implicitly typed
int i = 10; //explicitly typed

Although var is a great way to start arguments about coding standards at your work, there are times when it is required around anonymous types. Here's an example from MSDN:

/ Example: var is required because
// the select clause specifies an anonymous type
var custQuery = from cust in customers
where cust.City == "Phoenix"
select new { cust.Name, cust.Phone };

// var must be used because each item
// in the sequence is an anonymous type
foreach (var item in custQuery)
{
Console.WriteLine("Name={0}, Phone={1}", item.Name, item.Phone);
}

C# 4 (not 4.0, the marketing folks say it's .NET 4, etc.) adds the dynamic keyword. I've explained this saying:

"There's no way for you or I to know the type of this now, compiler, so let's hope that the runtime figures it out."

Here's how this looks from an Intellisense point of view. Here I'm hovering over the dynamic keyword:

dynamiccalc1

And here is the tooltip after pressing "." after "calc."

dynamiccalc2

Now, to the interesting question of the day. Christoff Turner asked this question, essentially:

"I noticed the following while doing some research within C# 4.0:"

using System;
namespace ConsoleApplication1
{
class Program
{
static void f(Int32 x) { }
static void f(dynamic x) {}
static void f(Int32 x, dynamic y) {}
static void f(dynamic x, Int32 y) {}
static void f(Int32 x, dynamic y, Int32 z) {}
static void f(dynamic x, Int32 y, dynamic z) {}
static void Main(string[] args)
{
f(10); // Works - obvious
f(10, 10); // Ambiguous - obvious
f(10, 10, 10); // Ambiguous - not so obvious - since it should be possible to resolve
}
}
}

"Looking at f(10,10,10), what is the reasoning behind this call being ambiguous?"

I stared it it a while longer, then realized what is happening, and called Mads Torgersen to confirm. Mads says this.

In short, the behavior is totally by design:

  • dynamic in method signatures doesn’t come into it: it behaves like System.Object does.
  • Given that, neither of the ternary signatures is better because each fits better than the other on some arguments (Int32 fits 10 better than object does)

The key point here, in bold, because it's significant is: having the type dynamic means “use my runtime type for binding”.

The problem in the context of method calls is that you can't use the runtime type of something until, um, runtime. ;) Binding with dynamic expressions (dynamic binding) happens at runtime.  In this case, we're compiling against method signatures that are known at compile type and we're compiling with a (mostly) static language, so there's no dynamic method dispatching happening that could select a different method overload at runtime.

The dynamic type is statically-typed as dynamic. The compile-time type is "dynamic" (but really it's object, hence the method overloading trouble.)

Another way to look at this is with Reflector. This C# code:

static void f(Int32 x, dynamic y, Int32 z) {}

is essentially this, from a method signature point of view:

static void f(int x, [Dynamic] object y, int z) {}
and if there was a method that returned dynamic, it'd look like this:
[return: Dynamic]
private static object GetCalculator() {}

So, given how dynamic works as a type, how the DLR works in the context of method dispatching, etc, you can see why things didn't work like Christoff thought they would.

Enjoy!

Related Links

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.