Update (1 July 2007): The newer versions no longer exhibit this problem (tested on beta 12.0.1183.516). Just make sure you chose "None" for the image borders. Looking back at my post on Windows Live Writer dating back to August, it seems that I either missed a very significant fact about the product or perhaps something has changed in one of the betas. The short story is that Windows Live Writer sucks at handling images; whenever I embed an image it goes on to severely reduce the image quality: You be the judge: on the left, the original. On the right, the "improved" version Not only does WLW upscale my image for some unknown reason, it also does this via an extremely low quality scaler. In the case of simple images such as the one above, this will also result in larger file sizes (this example demonstrates a 400% increase in file size - from under 21KB to a little over 104KB). This reminds me of the old image pasting problem with Microsoft Outlook, and what kills me is that I can't think of any conceivable reason why anyone would develop this "feature". To add insult to injury, the only feedback link I could find (via this post in the Windows Live Writer blog) is an MSN Groups page that requires registration. The registration process itself asks you about a hundred completely personal questions that Microsoft has absolutely no business asking. I'll try and get in contact with the WLW team since I do want to keep using the tool, but this particular issue is starting to cost me a lot of time and effort.
Footnote: This is fast becoming a series of posts on the woes of using the .NET Compact Framework. In fact, I've added a subcategory for this exact purpose; you can access the category and its RSS feed from the Categories list on the right-hand side of the screen. Here's another one of those "bang your head repeatedly against the wall and look for a sharp object" issues: closing a stream derived from HttpWebResponse.GetResponseStream takes an abnormally long time. In fact, the (blocking) call to Stream.Close takes approximately the same amount of time as it would to read to the end of the stream. I've only encountered one other reference to this in a newsgroup post from 2004, which (according to Todd, the original author of the post) was never actually answered. Seeing as I was trying to use HttpWebRequest to create a minimalistic download manager for one of our applications, I had to come up with a solution: one option was to close the stream asynchronously and just let the download run its course, wasting valuable memory, CPU time and bandwidth; another was to never close the stream and make do with a resource leak. Not content with these solutions I decided to dig into the framework code with the ever-useful Reflector. The first hurdle was locating the assemblies; they're not trivial to find, but if you look hard enough you can find actually useful versions in your Visual Studio 2005 installation folder, under SmartDevices\SDK\CompactFramework\2.0\v2.0\Debugger\BCL. These are regular .NET Assembly PEs so it's trivial to load them up in Reflector. Some digging into the BCL sources proved that HttpWebRequest does, in fact, read until the end of the stream when closing; this is the relevant code excerpt, from HttpWebRequest.doClose: if (!this.m_doneReading) { byte[] buffer1 = new byte[0x100]; while (this.ReadInternal(buffer1, 0, buffer1.Length, true) != 0) { } }
It only started to make sense when I did some reading on HTTP (a protocol I'm not deeply familiar with). Apparently, HTTP 1.1 connections are persistent by default, which means the connection is maintained even after the request is completed, and further requests are served from the same connection. Technically, this means that the KeepAlive property of HttpWebRequest is true by default, and a Connection="Keep-alive" header is added to the HTTP request. I can only surmise that, with persistent connections, the response must be read in full in order to allow future requests (if the response was cut off, some concurrency issues may apply). Unfortunately, setting the KeepAlive property to false did not resolve the issue and the connection was maintained until closed.
Since I could find no way to resolve the problem, I decided to hack around it:
stream.GetType().BaseType .GetField( "m_doneReading", BindingFlags.Instance | BindingFlags.NonPublic ) .SetValue( stream, true );
Screwing around with BCL internals is obviously NOT a recommended practise and it's something I tried very hard to avoid, however this problem had to be resolved in one way or another. I traced the code a bit deeper to see if this would actually have the expected results; apparently HttpWebRequest keeps an internal "reference counter" (actually a bitfield, but same principle) on the connection. According to the implementation for HttpWebRequest.connectionRemoveRef, if the reference counter reaches 0 the private m_connection field of the request becomes null, and the connection is released. I started out by testing this:
Before and after - you can see that the m_connection field becomes null
Unfortunately I have no idea how to test whether ot not the connection is actually disposed (conceptually, if KeepAlive is set to false then the connection should be immediately closed); when I find the time I'll try and track the HTTP session using Wireshark, but currently this horrible hack will just have to do.
I've been hacking away quite a bit at an application that contains large managed and unmanaged portions, and a necessarily complex interop layer in between. It appears that interop marshalling behaves somewhat differently between the full and Compact framework. Here's a somewhat laconic list of the issues I've encountered and how to resolve them: - You may encounter NotSupportedException on calls to Marshall.SizeOf. Although the documentation does not specify this as a possible exception, experience shows that this is a result of wrong marshalling attributes: for example, although trying to marshal a bool to UnmanagedType.I4 makes sense from a C programmer's perspective, it results in the behavior described above. The article describing this is called "Using the MarshalAsAttribute Attribute," but the version in my locally installed copy of MSDN Library (August 2006) does not contain this information.
- Annoyingly, the default marshalling, or even an explicit UnmanagedType.Bool, results in corrupt values (probably some minor framework bug). I worked around this by defining the member as int and manually giving it the value 0 or -1.
- It's not obvious, but you can't use UnmanagedType.LPArray from within structures - it only works on P/Invoke method declaration parameters. The only way to do this is to manually call Marshal.StructureToPtr and do some pointer arithmetic with IntPtr (annoying, but at least it's safe code).
- The marshaller always frees up memory; although this makes a lot of sense from the .NET perspective, it probably means that you'll have to code in some sort of deep copying mechanism in your native code if you want any of that information in your state. This also has performance repercussions you should consider when architecting your interop layer.
I'll post updates to this as I come across more issues.
I was writing some code with Visual Studio 2005, and pressed Alt+Keypad 8 (under ReSharper, this moves the current method up/down). Not only did this produce the ASCII code 8 - backspace (control character) or inverse bullet (printable character) - but it also completely screwed up the font on the same line:
For some reason the Visual Studio 2005 debugger (on my native Smart Device project) flat out refused to halt on Data Abort errors. Instead it would just show the error information on the debug trace and crash the application: Data Abort: Thread=81e27040 Proc=804c68c0 'Client.exe' AKY=00000041 PC=00eb1cc0(emnative.dll+0x00001cc0) RA=00eb6d6c(emnative.dll+0x00006d6c) BVA=0e537510 FSR=00000007 For obvious reasons, I wasn't particularly happy with this. Digging into Google and the documentation didn't help; after some serious headscratching I figured that the Windows CE kernel must be catching these exceptions at some point, so from the Debug->Exceptions... menu I enabled, under Win32 Exceptions, catching of thrown Access Violations: After this, I managed to finally get proper trapping in the debugger, and easily find out what code actually caused the access violation:
Robbie Williams plays an amazing comedian turned president in Man of the Year. The movie is a non-too-small jab at American democracy, the American democratic process and the American voting public in general. As such it's inevitably cynical, however it still manages to temper cynicism with a genuine attempt to make people see that the democratic process is not completely rotten, that things people take for granted are the result of a lot of hard-work by a lot of usually well-meaning people, and finally reiterates the old adage to "never attribute to malice that which is adequately explained by stupidity." Otherwise, it's a well-directed, well-acted (featuring, among others, Christopher Walken, Laura Linney and Jeff Goldbloom) and well-written movie. Recommended.
This is an absolute must-read for anyone who gives even a bit of a damn about their rights as consumers. (via Aynde) My brother thinks it's basically FUD-based propaganda, but I suppose if it's a way to make people listen it works for me (when fighting fair just isn't enough...) Update (02-Jan-2007): Read this rebuttal. It's extremely cynical, but also makes several valid points. Update (03-Jan-2007): For a more cynical and consumer-oriented view, check out this scathing editorial from The Inquirer. It's amazing how much it echoes my thoughts - as a consumer - on the subject. I wrote a few sentences about the subject before I realized it deserved a proper post, which I'll handle later this week.
It really yanks my chain when I put my faith into what is presumably a solid foundation for my code, and end up running into a huge number of unexpected pitfalls. Be warned: .NET Compact Framework is incomplete. Oh yes, it's a fleshed out version of CF 1.0 with generics and various important bits and pieces finally included (COM interop. I mean, seriously, .NET is useless without it even on the desktop), but it's still lacking a lot of vital components (ActiveX hosting) and has major shortcomings in others (no XSLT support). But that isn't the worst of it: the documentation is sparse at best, and flat out wrong in some cases. You cannot use asynchronous delegates in .NET CF 2.0. In case it isn't clear to you, let me repeat it: you can't use Delegate.BeginInvoke. If you're really unlucky, like me, you'll write a bunch of code and go on to compile, run, test and debug it and then run into a completely bogus NotSupportedException on a seemingly innocuous internal method call, and have to do some serious digging to figure out the culprit. This goes particularly well with (admittedly documented) fineprint in methods such as Windows Media Player's player.URL property setter, which for some reason mustn't be called from an event handler.
I've blogged about Neil Gaiman's MirrorMask before, and have neglected to follow up with comments on the movie. To make it short and to the point: it's brilliant. Original story (Alice-esque, but is otherwise new and fascinating), amazing artwork, impressive photography, great music and terrific acting. This is a top-notch movie which in many ways is better than Labyrinth, and easily parallels Dark City in imagination and visual production. Although this is not a movie for everyone, I would greatly recommend it to anyone who's enjoyed the above movies, or for that matter Lemony Snicket's A Series of Unfortunate Events. A completely different beast is Borat (I'll spare you the full title). Anyone who's ever watched Ali G should already be familiar with how hysterically sad this character is; it's not that Borat as a character is funny, it's just how stupid the people he interviews are. To put it mildly, it was difficult getting up when the movie ended because my stomach muscles were so sore from laughing. And Borat speaks Hebrew almost the whole movie, to boot! (Disclaimer: it's worth noting that this movie is completely idiotic, full of profanity and racist jokes. If you're touchy enough to be bothered by this, you shouldn't be reading this blog.) I won't deny being an Alfonso Cuarón fan; although I've only seen two of his movies, they both impressed me by being completely original and visually striking. His newest movie, Children of Men, definitely struck a chord with me. I'm not sure if this is obvious to anyone but me, but the narrative is like a modernized version of War of the Worlds with a human emphasis (i.e. no aliens): a regular joe getting caught in turbulent times, just one amazing thread of story that appears meaningless when viewed in the grand scheme of things. I'm not a professional writer so it's difficult for me to explain this properly - I hope I've managed to at least pique your curiosity. Finally, I just feel the need to share a bunch of anecdotes: - The Princess Bride is still (after so many years) a masterpiece of duality: sentimentality and criticism, virtue and wickedness, beauty and hardship. It's simply a brilliant tale, and if you haven't seen the movie you literally owe it to yourself.
- Holy shite, they're making a new Beowulf movie! One directed by Robert Zemeckis and written by Neil Gaiman no less. Who knows, maybe it won't utterly suck?
- They're actually making new Rocky and Rambo movies. Rocky 5000 all over again?... I mean, I like Sly as much as the next guy, but he's over 60!
- Pan's Labyrinth looks really gorgeous. The visual style is starting to get old, but the movie itself looks incredibly promising, and I'm definitely looking forward to it.
Update (January 16th, 2007): Not only does this apparently only work on the emulator, you would do well to stay away from Managed DirectX in general because common drivers, such as those on the Willcom W-Zero3 - do not support rendering in landscape mode (I wonder which devices DO support those features). After messing with this collectively for weeks we eventually went with the obsolete GAPI. The code here will probably not work for you.
For some reason, elementary DirectX operations are not very well documented in the .NET Compact Framework documentation; I kept running into InvalidCallExceptions for no aparent reason, and couldn't figure out the "simple" way to lock surfaces from the documentation (it's worth noting that I was only interested in basic 2D functionality). Basically you just need the right set of flags and the right order of operations. Here's the code I used and that worked for me (even under the considerably buggy emulator). To create the device, use the following parameters: PresentParameters p = new PresentParameters();
p.SwapEffect = SwapEffect.Discard;
p.Windowed = true;
p.EnableAutoDepthStencil = false;
p.PresentFlag |= PresentFlag.LockableBackBuffer;
p.MultiSample = MultiSampleType.None;
m_device = new Device( 0, DeviceType.Default, this, CreateFlags.None, p );
To draw on the backbuffer, you can use the following code:
m_device.BeginScene();
using ( Surface s = m_device.GetBackBuffer( 0, BackBufferType.Mono ) )
{
int pitch;
using ( GraphicsStream gs = s.LockRectangle( this.ClientRectangle, LockFlags.None, out pitch ) )
{
// Your code goes here...
}
s.UnlockRectangle();
}
m_device.EndScene();
m_device.Present();
I hope this helps someone avoid a couple hours of frustration.
|