Tuesday, December 22, 2009

Vista is stupid

Two things I noticed today. First of all, if I copy a file onto a memory stick, it checks if there's enough space for the file BEFORE working out if it's going to be overwriting an existing file. So it tells me I don't have enough space, until I manually delete the old copy that I wanted to overwrite.

The other thing, which has annoyed me forever, is that the details view in explorer seems to always default to a view that's designed for media files, even if there are none in the folder. So when I do a search, I get a view that shows me Artist, Album, Genre, as if the only thing I'd ever search for is mp3s. I was searching for a .cfg file, as it happens. The date the file was modified, which is to me the thing I need most when I search for a file, as I'll often find many copies and want the latest one, is not there. Sure, I can right click and add it, and I do, EVERY TIME, but why not remember my preference, or give me a sane preference, based on the type of files found perhaps ?

Friday, November 6, 2009

Let it go....

I am working with SQL Server Compact. I've opened my database in the management console. Now I find that even after I disconnect, I cannot delete the database file in question. I close the Management Console, and I can delete the database. Surely if I disconnect from the file, the program shouldn't keep the file open, but apparently it does. This is not the first time I've had this sort of issue. If I close a file, then I'm telling you I want it back. Is that so hard ?

Thursday, October 29, 2009

More Vista misery

Did I mention this before ? I have reinstalled Vista using the CDs that came with the computer. It's as fresh as it gets. The control panel does not work, it appears then disappears. I can run the control panel items if I know their names, but the control panel itself is simply gone.

Windows search is useless

So, one of the worst things about vista is the new search in folders, which doesn't return any matches even when you know they exist. I'm not sure what the logic is there. We recently had a bug report where one video in our app would not play with the WMP control, and the WMP control default view was changed. I fixed the latter issue, but still cannot repro the former on XP. In my attempts to do so, I ran every Windows update available ( I usually never run them because they have broken my PC more often than any malware ever has ). So, today I right click on a folder and choose search and a new dialog appears. I vaugely recall 'windows search' being on that upgrade list....

The new dialog tells me I cannot search the folder I want to as it is 'not indexed'. Funny, I used to be able to just search my hard drive. And there's no UI to help you, you have to go and read the help, then open a dialog, then work out how to add the folder you want to search to the index. Nice one, that makes like SO much better. Well worth the update.

Having indexed my source code folder ( which happens instantly, it seems and therefore seems like something that I could have been asked instead of being told I just plain can't search my own file system ), I now find that the search cannot find the files I want. I KNOW there's some files there that match my search, I just can't see the one I want. A bit more digging and I find out that the actual UI is just a mess. There's a text box, whose purpose I am not sure of, but if I type my term in there, it searches and tells me there were no matches. Maybe it searches the desktop and the UI under searches where I wanted to search ? Either way, yet another piece of totally useless UI and an update that makes things worse, not better.

Stop the presses. There's a button at the bottom called 'search companion'. The 'companion' is the old search, the one that actually works. So if you've accidentally installed this mess, just push that and you'll get a working search again.

Wednesday, October 28, 2009

SQL Server crash

I just started SQL Server, connected to my SQL Server Compact DB, and got a null reference error. My SQL Server 2008 is now showing me the connection dialog, but there are no options in it. Here's the error that I was shown:

See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.

************** Exception Text **************
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.SqlServer.Management.UI.ConnectionDlg.LoginControl.UpdateInstanceLabel()
at Microsoft.SqlServer.Management.UI.ConnectionDlg.LoginControl.Sync(UIConnectionInfo ci)
at Microsoft.SqlServer.Management.UI.ConnectionDlg.ConnectionDialog.DoOneTimeInitialization()
at Microsoft.SqlServer.Management.UI.ConnectionDlg.ConnectionDialog.OnVisibleChanged(EventArgs e)
at Microsoft.SqlServer.Management.UI.VSIntegration.ShellConnectionDialog.OnVisibleChanged(EventArgs e)
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WmShowWindow(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

How is this remotely possible ? It sure isn't acceptable. Here is the dialog box:




On top of this, my SQL Server 2005 ( my default instance ) just up and died a week or so ago. I've spent far too long on google, and I can't work out how to make it work, if I start the service, it just stops. I've googled the errors in the logs, but I've had no luck. I've basically given up on it at this point, if I need any of the data, I assume I can import it in to SS2008 from the files on my file system still...

Monday, October 26, 2009

Burning CDs or, why can't it just remember my preference ?

I am burning some installer DVDs using Vista. I put in a DVD, and it prompts me how I want to use the disc. I choose to burn with the file system. EVERY TIME I do this, it selects to do it using a format that lets me add files as I go, despite my EVERY TIME selecting to do a 'master' burn so it's more likely to work on other machines. And of course, it HIDES the options, which is why I forget from time to time that they exist. I have to expand the list and select the same option EVERY time, or I lose a disc and some time.

I've lost several discs to forgetting this little wrinkle. Why can't it just remember that I have NEVER willingly burned a DVD this way, I've only ever done it accidentally, pressed cancel, found that cancel does nothing, and waited to throw the disc out ? It's bad enough that search in Vista is fundamentally useless, that UAC makes the machine unusable ( and I can't turn it off b/c I need to use it to test for our vanilla users ), and so on, but surely Microsoft, who make their living on average products that copy other ideas but improve the UI, can make a UI that remembers how I like to burn DVDs ?

Sunday, October 25, 2009

NotYetImplimentedException

This is just a little thing, and it's something that has since been fixed, but it kind of illustrates the lack of communication or thought between different parts of Microsoft teams. When I became an MVP, I was almost immediately whisked to a Microsoft summit. I believe VS2005 was in development at the time. During the summit, the person in charge of the VS IDE gave a presentation. I asked her at the time why it is that visual studio will create stub methods on a right click, so I can do

myClassInstance.NewMethod();

then right click and create a stub to then navigate to, to add this method, and the default method would throw a generic exception. The point being that a 'NotYetImplimentedException' existed in the framework and is what should be thrown here. She 'took a note'. However, this was not rectified in 2005 ( although I did get sent a nice paperweight that says 'thanks for helping us improve Visual Studio 2005', the fact is that not one bug I reported was corrected ). I believe it was fixed in VS2008, but the point is not so much that they didn't immediately make a tiny change to a product in development to make it act in a sane manner, it's the fact that they didn't do what I was suggesting in the first place. Like the issue with Visual Studio not working in Vista without setting it up to run as admin, or any number of other issues we all encounter, the problem is that the teams at Microsoft don't seem to talk to one another, don't seem to care about using the framework as a whole consistently, and don't seem to care about how their product will work in relation to the rest of the Microsoft product base.

Friday, October 23, 2009

Default behaviour/WMP control

When I was an MVP, one of the first things I did was ask the C# team for default values on variables, like C++ has, and VB.NET has. They would get tied in knots over how complex it would be. We are finally getting this feature. In the meantime, if I had a method and I wanted to extend it, I'd do something like this:

old method :

bool DoSomething(string name, int age)

new methods:

bool DoSomething(string name, int age, bool doSomethingExtra)
{
...
}


bool DoSomething(string name, int age)
{
return DoSomething(name, age, false);
}

In other words, you need to keep your default behaviour for existing clients of the code, and then allow changes of the code for any client who wants to use the new functionality. In any situation, if you want to extend something that exists, you need to make sure you don't break it for people already using it, right ?

Our WPF application uses the Windows Media Player control, I've already explained why in the past. We just wrapped up our installer for our new version and shipped it. Shortly after release, we started to get reports from people that the player in our app was showing the WMP controls. It turns out the person who wrote that code, never added code to set the uiMode. I have searched and can't find any way to set the default value for that, but I have had it happen on one machine, further confirming that a windows update has changed windows media player so that if you don't set a uiMode, the default is no longer none. This is major for us because it also means the control catches right clicks, which we use when we put the control in full screen mode.

On top of that, a video which plays fine on all of my test machines, some of which are completely virgin, is reporting that 'Windows Media Player cannot open files of type wmv'. Now, all our videos are WMVs, but either way, WMP can't play WMVs ? Again, it's clear by the fact this is happening on computers where before everything was fine, that a windows update has basically changed how the windows media player control behaves, and broken our app. I am shipping an update that sets the uiMode, and we should have done that in the first place, but either way, if you do an update, you should make sure you're not going to break existing clients. That's just common sense.

Update: I installed IE8 ( I actually asked it to install 5 times, it would not install until I selected to participate in the customer experience improvement program ), and now I can reproduce the UI issue. The video in question still plays fine, but it looks to me like IE8 is the cause of the other issue. I need still to install XP SP3, I've avoided that since it completely trashed one of my AMD based machines, I'll install that next ( my Mac is Intel based ), and see if that creates the issue with the file not playing.

(update) I have updated my Vista machine to the hilt ( 100+ updates, took an evening and a morning to do ), and I can't repro the issue with the file not playing, so I assume that was actually an issue with a single install, and not a Microsoft issue at all. As I updated my Vista machine, I once again saw our UI change from no UI over WMP to the full UI, as reported above. I am just rolling out the patch now to fix this issue for our users.

Tuesday, September 15, 2009

Not every computer is online

I had to test some installers yesterday. Four of them. I needed to run them on a virgin machine, so I could test all the installation of prerequisites. So, I wiped my notebook, and put Vista on it, using the factory install DVD. I hoped to use the XP on the machine, but I'd never activated it, and despite having a license, activation failed. So, I went the quickest route open to me.

Vista is frustrating, as always. In fact, after running the uninstaller once, I found that the control panel stopped working. It would flash up and disappear. If I ran in safe mode, it works, but gives an obscure message about permissions when I try to uninstall something. For the record, I installed .NET 3.5, Acrobat, and my program, so one of those screwed it up. I was able to keep working by running Programs and Features ( because they HAD to rename it in Vista, or it may have been easy to find the first time I used it ), from My Computer.

So, my installer is running, and taking *forever*. I know the stupid .NET 3.5 install claims to be downloading, even tho I have the full version on the DVD. I suddenly realise, it's trying to connect to download, even though it doesn't need to, and timing out five times before noticing it has the data locally. Then it moves up a bit, and repeats the sequence. It's bad enough that our clients are shown a screen saying that .NET 3.5 is downloading, when it's not, but this is just the height of stupidity in my opinion. I was at a family dinner, testing, so I didn't have the option of connecting to the web, which slowed down my work considerably. Another example of Microsoft's inability to see past their own assumptions, and consider what the possible situation of real users may just well be.



Tuesday, September 1, 2009

Consistency

So, I am using the Windows Media Player control within my WPF project, because the built in control is too slow. My problem is, I want the control to not play the video right away, but to have it loaded, so there's no moment of black screen when you press play. The only way I can see to do this, is to turn off the volume, tell it to play, and when it starts, pause it and turn the volume back on. Which is, of course, messy.

What is also messy, is that when I search the MSDN, the media play control has a ton of different types of volume settings. One allows for the volume to go between 0.0 and 1.0, with 0.0 being off. At other times, the windows media player control apparently has settings between 0 and -10,000, where 0 is full volume. When I find the right documentation, for the right version of the object, it tells me that the settings property "... gets an IWMPSettings interface that provides a way to modify various Windows Media Player settings." What is a IWMPSettings interface ? What does it expose ? I did find a link which would tell me that, and, for the purposes of the COM control, under C#, the range is 0 to 100. I think. I mean, it's not really clear enough for me to be sure, given all the other options I have been given. I'll try that and see.

My point today is - why does Microsoft have to do the same thing 100 different ways ? Why can't they just decide on something and stick to it ?

Monday, August 17, 2009

How is this possible ?

OK, so I have a media player control in my WPF app. For reasons that I cannot fathom, WPF does not let me easily find out the native size of a video, so I have added a map of video paths to sizes. I have built this map, and when I load a video, I grab a screenshot of the first frame. After that, you can play and pause the video, when you pause, it goes to the static screenshot, so that it will appear in screen grabs, which we print and email.

if (MediaAccessManager.Instance.VideoSizeMap.ContainsKey(srcPath))

This is the line of code I use to check if I have a size for this video in my map ( users can import their own videos and then I need to just use DirectX via a third party dll to find the size. I don't do this for my own videos, because sometimes the size reported, is incorrect. Here is the issue. The first time this code runs, I get an exception, stating that the key in question already exists in the collection. Believe me, I have read this code over and over, there is NO code here to put anything into the collection, nor does this crash after the first time. The only possible reason I can think of, is that perhaps the collection does not blow up when I put in a duplicate key, it blows up the first time I try to access it after the fact. However, I call ContainsKey before adding each item, and I have written some code to further confirm that I have no duplicate keys. I also wrote code to deliberately add the same key twice, and it threw an exception at the point of adding the item, as you'd expect.

I really don't have time to debug this, so I've added the block of code above in it's own try/catch. The first time this runs, it throws an exception, but then it does it again right away, and the second time it works fine, causing my code to work perfectly. It's just not at all pretty.

Sunday, August 9, 2009

Why can't I drag and drop a csproj file ?

I was reminded again today that if I drag and drop a sln or csproj file onto the main window of VS2008, I get a message box saying that I am not allowed to do that.  It doesn 't even open File/Open for me, just tells me I need to do it.  Why ? I can't think of any reason for them to insert a message box instead of a jump to the code that opens a project ( with a prompt if they would feel better that way ).  Whose smart idea was that ? It's just a pain.

Wednesday, August 5, 2009

Path.Combine is essentially useless

One of the great things about .NET, coming from C++, is all the stuff that is built in.  Need to send an email ? Sure thing.  Want to use regular expressions ? Go for it.  It took me a while to learn that things I expected to write in C++, I could look for in the library and often find there already.

The System.IO namespace has a Path class, which is used to manipulate file paths.  Things like 'GetFileNameWithoutExtension' are very, very useful.  Some things are a little counter intuitive, such as Path.GetDirectory walking up the directory tree if the string you have is a directory already, but overall, it saves a lot of work.

One of the things I use the most, is Path.Combine, which takes two fragments and merges them to make a path.  In the past, I'd be checking if one string had a trailing slash, if the other had a leading slash, etc.  Path.Combine takes care of that for you.  Right ? Not quite.

There's a couple of quirks here.  To illustrate, the following table has three columns.  The first two are the arguments passed into Path.Combine, the third is the result.


c:\path\dir\file.txtc:\path\dir\file.txt
c:\path\\dir\file.txt\dir\file.txt
c:\pathdir\file.txtc:\path\dir\file.txt
c:\path\dir\file.txt\dir\file.txt
c:dir\file.txtc:dir\file.txt
c:\dir\file.txt\dir\file.txt

The first thing to notice, is that if the second string starts with a \, then you get the second string back verbatim.  This is the issue that hit me in the past.  I assumed that this method existed so no matter what slashes happened to be in the two strings, they would get joined into a single path.  As you can see, this is not so.  Now, I assume there's a specific case for which this behaviour is desirable, but it's not the most obvious one to me, and if there's a reason for it, surely the method could have an overload, or better yet, a method called something in line with the reasoning for not combining these two strings could exist ( a method called Combine, is one I call to combine strings, not to SOMETIMES Combine them ).

The second one is more interesting.  If my first string is a drive letter, with no slash in it, then no slash is added.  I just did a test, I have a file called c:\procs.txt.  File.Exists (@"c:procs.txt") returns false, File.Exists(@"c:\procs.txt") returns true.  So, it seems to me that the slash is needed, but Path.Combine does not add it.  

Overall, this method is basically broken as far as I am concerned, and I have rolled my own version to use instead.  It basically makes sure the first string has a \ at the end, the second doesn't have one at the start, then calls Path.Combine, just out of spite ( given that at this point I could just concatenate the two strings and be done with it )
 

Thursday, July 30, 2009

WPF designer cannot render most forms

I have written a few projects in WPF now. What I don't understand is, why is the designer so fragile ? It seems as soon as I create any sort of reusable control, and use it on a form, even though the control exists in the same code base as the form, the form will no longer be able to render properly, it will report errors, which are invariably 'can't create an instance of MyCoolControl'. Of course, at run time it works fine, and the code for the control is right there, so I don't really understand what the issue is. I have talked to other people who have THEIR controls inside seperate dlls, which is apparently the recommended way to resolve this 'issue'. They still have the same error, and the way they have solved it, is by putting those dlls in the GAC.

Wait a minute. If I want to create a control inside my WPF app ( which is surely the OO way to do things, create it once and reuse it ), then I should create it in a seperate dll, and THEN put that dll in the GAC, so that the designer will work properly ? Am I the only person who thinks that is insane ?

Of course, I've not seen VS 2010, there is some possibility that this has been fixed. But, for now, it's a constant annoyance.

Tuesday, July 28, 2009

Pop unders/child windows

I am updating our website. So, in VS I open each image in my website, then I copy it to do a new screenshot in our updated UI. Then I save it from photoshop. Here's where the problem starts. VS opens a window telling me the image has been updated. I need to close this before VS becomes responsive again. Only, it's not a child window of the IDE, so I have to ALT-TAB looking for it every time, so I can close it. I know I've had other issues with popunder windows like this making other MS programs seem to freeze up. Is it that hard to set the owner of a window before you show it ? I don't know. I know it's frustrating to have to do over and over, because some basic UI rules were ignored.

Wednesday, July 22, 2009

Object Orientation in .NET ( has anyone at Microsoft heard of it ? )

It's not uncommon to be working with code and want to call an event explicitly. In this case, classes derived from the EventArgs class, have an Empty property, which returns an empty instance, useful for doing exactly that, without having to construct an object we will not use. However, while it's possible to use the 'new' keyword to override a property, doing MyMethod(this, RoutedEventArgs.Empty); returns a compiler error, as the Empty propertly returns EventArgs, not RoutedEventArgs. In other words, while RoutedEventArgs in particular represents a class where you are very likely to not examine the event arguments, you still cannot use the property, it is worthless.

This is true of ALL derived classes of EventArgs, although I can see how, for example, a mouse related event args can be assumed to contain data you need ( although this is often not true, if I handle the mouse left button click event, I don't often care about anything passed in ) The only place I can think of where this is almost sure to not be the case, is keyboard events, where usually I want to know what key was pressed. It is for this reason that I've never tried to use KeyEventArgs.Empty, that is, assuming I were to forget that the construct as a whole is useless.

In the same way when I use Bitmap.FromFile in C# in general, I need to cast the Image that is returned, to a Bitmap. This is because it's calling a base method, I guess. That makes sense, but then why not make the base method return a Bitmap, given that you can't alter a method by return type, however, if I called Image.FromFile and got back a Bitmap, I could quite happily assign the value to an Image, and it would downcast. In fact, all things being equal, it's possible that the class always returns a Bitmap, but always specifies an Image as the return type.

Yes, I am right. The Image.FromFile ultimately calls this:

internal static Image CreateImageObject(IntPtr nativeImage)
{
int type = -1;
int status = SafeNativeMethods.Gdip.GdipGetImageType
(new HandleRef(null, nativeImage), out type);
if (status != 0)
{
throw SafeNativeMethods.Gdip.StatusException(status);
}

switch (((ImageTypeEnum) type))
{
case ImageTypeEnum.Bitmap:
return Bitmap.FromGDIplus(nativeImage);
case ImageTypeEnum.Metafile:
return Metafile.FromGDIplus(nativeImage);
}

throw new ArgumentException(SR.GetString("InvalidImage"));
}

As an aside, surely this code would be prettier if the exception came from a default case, instead of just sitting underneath like that. Do they have coding standards in Redmond ? In fairness, if my suggestion would compile at all, I am pretty sure that it didn't work in early versions at least, b/c the compiler could not work out that every case had a return value. So, perhaps this code has just not been looked at in a long time.

The return type here is an Image. Bitmap.FromGDIplus looks like this:

internal static Bitmap FromGDIplus(IntPtr handle)
{
Bitmap bitmap = new Bitmap();
bitmap.SetNativeImage(handle);
return bitmap;
}
So, in a nutshell, even if I am using an Image, I get sent a Bitmap, but if I am using a Bitmap, or an Image, either way, the object is downcast to an Image for no good reason that I can see, before I get it back. No memory is saved, all that happens, is another reason for a meaningless cast.

Bitmap bm = (Bitmap) Bitmap.FromFile(@"c:\Image.jpg");

Is that really the best we can do ?

Tuesday, July 7, 2009

Working with images in WPF is not straightforward

It's taken me a while to get my head wrapped around exactly what is going on here, but there's some serious issues with image controls in WPF.  My first manifestation of all this was that I'd load a BitmapSource into an Image, and it would not be visible, the control would continue to have a width and height of 0.  If I wrote code to try to manually set sizes ( even though I shouldn't have to ), the size of my image would come back as 0.  

What happens is, images are loaded on another thread.  So, when my code asks for the image size, it's 0.  Of course, this means if I am debugging, then I introduce a delay, so the thread can run, and the size is there.  So, if you want to do anything when an image is loaded, your best bet, is to use the size changed event on the Image control.  I've found that I need to put the images inside a StackPanel, if I put them in a Grid, they are just never visible, if I use the * notation, which I always try to do, to create forms that can be resized smoothly.  

What the framework desperately needs, is an ImageLoaded event, so you can write code to run when the image loads, THEN tell it to start loading.  I don't understand how this was missed, I'd have thought that being able to load an image, then do something based on the size of the image, would be pretty common in a framework whose main claim to fame is a freeform user interface.

Thursday, July 2, 2009

Update : hotfix for bugs in XAML designer in VS 2008

With thanks to Mark for the link, http://code.msdn.microsoft.com/KB963035 is the hotfix for the issue I reported previously, where the VS2008 designer will freeze if you edit XAML. I remain confused how such a bug escaped testing, but at least there's a fix. I don't have it installed yet, but others tell me it's helped them.

Wednesday, July 1, 2009

Breaking Visual Studio is too easy

My first real WPF app started out fine, but over time, I found that I could build it perhaps once, then I'd get an out of memory exception and have to restart the IDE, or sometimes even reboot. You can imagine what a pain this was. I did some research and found that this is quite a common issue for a lot of people. There are other issues, for example, someone I know tells me that for him the linker crashes with an internal error inside the "IncrBuildImage" function, every second build. He's building native code. I don't know the answer to his issue, but I know how I solved mine.

The issue is that the compiler often can't deal with a WPF app that has a lot of resources in it ( my exe was 32 MB which included a lot of UI elements as PNGs ). There's two solutions here:

1 - make your UI elements XAML. This just makes sense, they take up less space, and scale to any size. Expression Design is actually awesome at taking Adobe Illustrator and other formats and turning them in to XAML. This is the approach I am taking going forward

2 - put all your resources in a dll. If you're showing big images, as I invariably am given the apps I write, then you may not want or be able to convert them to XAML. So, put them in a dll, which you never change, and therefore do not have to build more than once.

I would prefer not to have my images in a resource dll, but it's made me a lot more productive. If they fix this bug in VS2010, I may go back to how it was, but certainly this works, and it is an effective workaround for yet another Visual Studio bug.

I am actually travelling to the US for a couple of weeks starting tomorrow, so my post frequency may slow down, although I do have at least 10 other .NET issues bookmarked to write about, so with some luck I may manage to keep up my current post frequency of a couple every now and then. Doesn't sound too challenging, but if this post is two weeks old and it's on top, that's my excuse, and I'll be posting again for sure when I get back.

Sunday, June 28, 2009

Things I hate about my Mac

It's not quite a year since I moved to Mac. My reasoning was simple. A Mac IS a PC, so I'm not choosing either/or, I am saying, I will buy a PC, will I also choose to have a Mac at the same time ? My Mac has 20 gig of RAM and 8 cores. It's a pretty sweet box. I generally love using the Mac, too, there just seems to be little things where the OS seems to work with you, instead of against you.

The whole point of my blog is to point out things that I've found to not work as I'd expect, in all aspects of my computing life, especially where I know the solution, and hopefully I can feature in the search results of people trying to solve the same problems I have solved. What I'm basically writing about today, is VMWare Fusion and Boot Camp. VMWare Fusion is a piece of software that lets me install virtual machines on my Mac, and to basically run OSX and have windows running in a window. This is how I've used my Mac for most of it's life, which means I can use Safari, Pages, XCode, etc. as needed, but still go over to Windows when I need to write some Windows code, open a newer format Office file, etc. This has not been without issue, VMWare loses it's internet connection frequently, and while I've been given step by step instructions for what to type into the console to reset it, I am new enough to Mac that I am still working my way up to power userhood, I don't fully follow what it is that I'm doing, so I needed to keep looking it up. The support also takes the form of a public forum and it took me a while to work out that the people who were incredibly rude to me ( I assume for being a Windows user ), were actually not employees of VMWare. This made me feel better, because I know some people who work at VMWare, and I've found them to be really great folks, in real life. I must say, the guy who told me how to get around the internet dropout issue, also did not work for VMWare.

The main reason I use VMWare and not Parallels, is that the question I asked when buying was "who has the best 3D support ?". As my apps are all WPF, I need good DirectX support. VMWare also works with Boot Camp drives, so I had tried to set up a boot camp partition in the past, but had failed in my efforts to do so, so I had kept using an old PC for final testing, 3D was definitely sluggish under VMWare.

As I was going to the US in May, I took my Mac in to the Mac store, and told them I'd buy a hard drive from them, if they set up Boot Camp for me with Windows XP. I made clear that I am well capable of doing such things, given the time to work it out, but my one attempt at Boot Camp had not worked out, and I plain do not have the time to dedicate a day to making this thing work. While I was away, I emailed to check progress, they told me the XP CD I had given them was broken. I assured them this was not the case, and gave them some suggestions ( they claimed the CD was not booting ).

I got back, and picked up my Mac. When I tried to start it, it would tell me that there was no bootable media. As you can imagine, this upset me. Now, all my source code is backed up off site, but it's invariably the case, even with a Time Machine, that some data is lost when a HDD dies. To cut a long story short, my Mac was returned to me in a state where it kept trying to boot from my Windows CD, and would not boot from anything else. Once I worked this out, I found that the machine would indeed claim that my boot CD was corrupt.

I managed to convince the Mac to boot back to OSX ( I confess I don't recall how, this took place over 2 days and was a whole lot of stress ). So, I reformatted my new hard drive, and tried to install again. Same error. I verified the CD again. Fast forward a few hours of me doing this, and variations on the theme, and we get to my first point. I had asked the Mac store to create three partitions, I hoped to create a multi boot hard drive that booted XP ( for my day to day life ), Vista ( for testing only ) and Windows 7. It turns out that you can only install an OS for Boot Camp, on a drive that has only one partition. Once I formatted with one partition, the whole process worked effortlessly, with the CD I had given the Mac store. I called them and explained all this, for the benefit of the next person to walk through their doors and ask for some help.

So, I next tried to repartition my drive after windows was installed. This utterly broke my machine again, and I had to reinstall Windows again. For a time, my Windows would boot, but I could not recover the space I had moved to other partitions. At the same time, Acronis True Image could no longer back up my drives, as it could not recognise them. I wrote to their tech support, and they responded to say 'We understand you cannot back up from your drives. If this is true, let us know and we will mark this issue as closed'. I sent an angry reply, and by the time they followed up two weeks later, I had moved to Ghost, which is a great piece of software, and which worked when True Image would not. So, my second point is, buy Ghost, not True Image.

Apparently, the Boot Camp instructions tell you to never use repartitioning software, this was the point at which I realised that what I asked the Apple people to do for me, and they agreed, was in fact utterly impossible. Of course, I've heard these people tell prospective clients that Macs never have viruses, so I should have known better than to think they were experts.

I tend to update my Mac once every few months, I don't really keep track of when things come out, I just update as I think of it. So, I recently ran the update, and got told that there was an OSX update. I installed this, and then found that VMWare no longer worked, I would start a WPF app and immediately be told that the 3D was broken. It turns out that ATI video cards combined with the new OSX update, doesn't work with VMWAre. VMWare say that they knew this was the case in advance ( but chose not to email their clients to tell us ), and that they blame ATI and Apple ( despite Parallels apparently working fine with this update ). I've followed up on this on the VMWare forums, as far as I can tell, no VMWare employee has responded to me, but some guy who likes to insult me has basically blamed ATI and said that I should never install any update without doing a full system backup first. This is probably good advice. I just didn't see it coming that VMWare was so fragile, or that they wouldn't bother to tell their clients that their system is about to break.

So, my days of running Windows and Mac at once are over for now. I also found that running a Boot Camp partition in VMWare is not wise, it seemed to mess it up a bit, in fact, at one stage, my XP was so confused, that it would just reboot over and over, it took three hours of going between safe mode and normal to get my PC back. I would love to set up a shared drive to put data on, that is visible to boot camp and VMWare, once this ATI issue is resolved. I am assuming when it is fixed, they won't bother to email their clients to tell them. I suspect that the end result will be that I'll fall out of love with VMWare, get used to using boot camp, and just not use VMWare again. Which is a shame, it was very cool when it worked.

Tuesday, June 23, 2009

Changing tables in SQL Server 2008/good UI design


I was using SQL Server 2008 client tools to make some database changes today ( you'll recall, if I install SS 2005, it reports success, but does not install client tools ). I usually prefer to create tables in script, so I can easily execute the script again when I deploy, but this was a simple one, and I figured I'd just use the table designer. I created my table, saved it, and realised I missed a column, so I went ahead and modified the table. Set up my column, hit save, and got the following dialog:

So, an empty table, and the program feels I need to be told that I can't change it, because it would require dropping the table. I don't see that this is even true, can't I add a column using SQL, so long as I provide a default value ( or the table is empty ), and there's no need for the DB to drop the table and recreate it ?

Assuming for a moment that I did have data in the table, and this action WOULD cause me to lose data, why not ASK me before proceeding, instead of locking me out ? And, if I need to change a preference, why not provide a way to open the preferences in the right section ? I NEVER tell a user in my software that they need to set a preference to do what they requested, without opening the preferences on the right page, to show them where it is.

I guess this tells me what I knew all along. Never use the tools, always hand write code, it's the only thing that you can trust.

ASP.NET custom validators do not fire

An ASP.NET custom validator allows you to perform ( not surprisingly ) custom validation on user input. In theory, you can specify both a client and a server side function to call.

I have three checkboxes, they are not generated by a checkboxlist, because I want more control over their layout, AND I want to attach some js events on specific options. So, I created a custom validator like this:

<asp:customvalidator runat="server" id="selectOne" controltovalidate="address1" clientvalidationfunction="IsOneSelected" onservervalidate="CheckSelection" errormessage="*" text="*" display="Static">

Note that address1 is not one of my checkboxes, the custom validator will not allow me to validate a checkbox. I've tried removing this property, because some blogs I've read, suggest this. Then I write a validator method like this:

function IsOneSelected(source, args)
{
alert("got here");

var valid = false;

var demo = document.getElementById(demoCD);
if (demo)
{
var Trial = document.getElementById(trial);
if (Trial)
{
var Webinar = document.getElementById(webinar);
if (Webinar)
{
if (Webinar.checked) valid = true;
if (Trial.checked) valid = true;
if (demo.checked) valid = true;
}
}
}
args.isValid = valid;
}

The alert is obviously a temporary measure. Apparently, the js editor has support for enforced bracing standards, and it defaults to K&R braces, so I kept getting this:

function MyFunc(){

}

I hate that, but I can't be bothered finding it to turn it off ( as you can probably tell, I don't write js that often ). What worried me more was that my script block changed itself from language="javascript" to language="jscript". But, I digress.

It turns out that the client side event only fires if the control you are validating has been changed. So, in theory if I hook up the control to a textbox that needs to be filled, that textboxes validator will help out if it's not, otherwise, this one will fire and I'll get my validation on the client side, right ? Well, I get my alert, but even if I hard code the validator to ALWAYS fail, the postback always occurs, my validator never stops a postback.

Now for the fun bit. MS apparently respond to complaint about this by pointing out that validation should always occur on the server, so even if the client side fire fails, there should always be a server side that fires. I agree with this, although in our case, there's nothing malicious anyone could do by circumventing the validators, it's still good practice not to trust anything that has been on the client side. Here's the issue. No matter what I do, I can *never* get my server side validator to fire. It simply does not work.

Now, I have run the examples that are on MSDN, and they obviously work. There is something else going on here, some reason why it won't work in my page. I guess I could trawl through the script, and see what that reason is ( actually, this gives me a good excuse to install firebug ), but I don't have time, I will just add an OnClientClick to my submit button and do my validation there. If anyone knows either what I did wrong ( possible, obviously ), or what circumstances cause a custom validator to do nothing, even when it fires, please let me know.

Update - Wow. My OnClientClick does not fire, either. Only the server side click event will fire, looks like that is my only option for validation.

Further Update - Although I did initially try to make the validator part of my validation group, I suspect my use of validation groups is part of the problem. However, that does not explain why my OnClientClick event would not fire.

WPF crashes on XP when using MediaElement

The MediaElement has been the bane of my life for some time now. In our first release, we actually used the Windows Media Player in a dll, because we had issues with performance. I did ask about this many times on MSDN forums and never got a real answer. A lot of other people were asking, too, so let me answer that question: even when you're playing a video in a form that has no real 3D, you're still creating a video on a DirectX surface, because that's how WPF works. So, it's not surprising really when a MediaElement is not as smooth as Windows Media Player, which just throws frames at the screen. The resolution of a DVD is around 800 x 600, (although HD is bigger, so is your LCD TV bigger than the average monitor), if your video is much bigger, remember that doubling the width of your video ( so if you go 1600 x 1200 ), gives you four times as many pixels that need to be scaled and drawn. It took me a while to work this out, but once I got our videos rendered in a sensible resolution, they play just fine in the media element ( I did a project where playing one video was unreliable, because of high resolution, I didn't generate the videos, and when I checked the resolution, it all made sense ).

I use a Mac ( I need to post about Boot Camp, actually ). As a result, I probably rebuild my Windows more often than most, as it's easy to build a new VM without even touching the old one. As a result, I have more experience than most with the fact that if you install Windows XP, SP2, and then install .NET 3.5 and run a WPF app that has a media element in it, one of several things will happen:

1 - The app will blow up on start, with a message that the XAML is invalid
2 - If you try to show still images on the MediaElement, it just won't do anything at all.

It seems to me that if I install a framework, it should work from there. It also seems to me like if I need to install a specific extra component, that I could get a meaningful error message to tell me what is going on. The first time this happened to me, I spent a half day trying to work out why my code was broken. I don't believe that winforms ever had this sort of issue. I presume there's a reason why WPF requires WMP10, but if that's true, why can't it try to tell me ? I can see how Microsoft has had legal trouble for bundling stuff in the past, but I am either going to install WMP10, or I am going to not use the application I just bought ( assuming now I am an end user ). How does making it confusing, help anyone ? What if the install for WMP10 fails somehow ( remembering my post the other day on installers ) ? This is just going to cause work and headache for support staff, and general frustration for end users.

Of course, it works fine out of the box in Vista. The only downside is, then you're using Vista.

Saturday, June 20, 2009

Visual Studio has encountered a breakpoint....

OK, this one is new to me. I had selected a solution from the MRU, to open, and I got this error:


Clicking debug, indeed goes into the debugger, after telling me it's loading a ton of symbols, it tells me ( not surprisingly ) that it has no symbols for the code from within the IDE that has crashed. Has anyone seen this before ? I thought I'd seen it all, but this is news to me.

Editing XAML crashes the editor

Today I am playing with some personal stuff, just looking to improve my WPF skills. I found out this week that if you restyle a slider, you need to remember to put in the XAML for the areas you click outside the slider, to change your selection. However, I have a file with a styled slider, and because of the effect I want ( I have buttons in the background and I want to be able to click them ), I want to remove those areas from this particular style. EVERY time I open my XAML and delete the one that is below the slider, VS 2008 uses 13% of my processor ( always 13% ) and it locks up until I kill it. I am going to have to edit my XAML in notepad and then reopen the project.

And, that worked fine. The editor couldn't handle me removing some XAML ( as in, I select it, and remove it, the XML is valid before, and after the operation ) and it locks the editor every time. Remove the XAML in notepad, and reopen the project, it opens fine. So, my XAML was legible to the IDE before the operation, and also afterwards. I am assuming that some sort of control tree is maintained from the XAML to generate the preview, and that this somehow doesn't like having to deal with this ( invisible ) element being removed.

I believe Blend is less hostile to the idea of people hand editing XAML than it used to be ( the first versions I saw didn't even support searching in text, which was by design, because you were not supposed to use it if you wanted to edit code ). I am falling in love with Expression Design's ability to open an Adobe Illustrator file and let me export XAML. It often fails, but what it does is impressive enough that I am happy to fiddle with it to make it work. I still worry that the theory that Blend is what you use to create XAML, may be a reason that the tools in VS 2008 are still so poor, tho.

Update: This is the first project where I've used resources, I don't know if this is a factor, but I am finding more and more simple edits which kill the IDE and which therefore need to be done in notepad. How is this possible ? Surely the thing would be, if the control tree can't take the edit, just rebuild it. I am changing my resources file, so the IDE is not even rendering any sort of preview at the time.

Friday, June 19, 2009

ASP.NET traps for young players

No other area of programming seems to have as many inexperienced, beginner 'programmers' taking on contract tasks that they have no idea how to perform, than ASP.NET. I guess everyone wants a cheap website. There's a few ways that the framework does not help.

When you create a default page, it will have a page load event in it. As a result, a lot of people write all their code in the page load event, and never add a page prerender event. Because of the order of the page lifecycle ( that is, page load, then events fire, then page prerender ), the prerender is often the only event you really need to handle, and it's the one that any data bound page should handle. This leads to several issues.

First is the "I push a button and it doesn't work, I push it again and it does" scenario. This means they bound to a data source, then the event changed the data source, so, on refresh, the changed source is loaded and bound to, but the first time, the data was loaded before it was changed. Then there's the 'my control loses it's selected value' problem ( which should ideally be fixed with a !IsPostback block, but would also be fixed in terms of reading the value in code behind by reading the value first, then data binding ).

The next thing I don't understand is, if I write a site in VS, and use the built in web server, it will allow me to write code behind like this:

if (!someTest())
{
MessageBox.Show("The test failed, please open a file");
OpenFileDialog ofd = new OpenFileDialog();
ofd.ShowDialog();
}

This apparently WORKS in Visual Studio. So, every day, when people in a certain continent clock in for work, programming forums worldwide get the 'This works on my local machine, but when I deploy it, it gives me this error on the server, what does it mean ?' question. Now, it's true that this is a problem with the so-called programmer, and it's true that the error message explains the issue in plain English, but, as far as I can see, the MVP program exists to give people incentive to provide Microsoft tech support by answering these sort of questions, so I assume that having these people write code is part of Microsoft's business model. I am guessing they skim the cream of the programmers in these low wage countries for their own benefit, I don't know. Either way, why would you create an IDE that allows you to write code that is plainly not going to run on deployment, under any circumstances ?

And don't get me started on how AJAX fits into this mix. Most people using the ASP.NET AJAX library, both think it IS AJAX, and think that Microsoft invented AJAX. They certainly have no idea what AJAX is, or what it means, I see questions every day that say 'I want to use AJAX to do xxx', where xxx has nothing to do with AJAX, although it may involve javascript. It's become the new XML, if you write a website, you need to use AJAX, where-ever you can. As the AJAX library does include some controls that don't really need AJAX to exist, the line is blurred even further. The ASP.NET AJAX library is also horribly inefficient, when I worked on a website in ASP.NET that used AJAX, I rolled my own code, because our site had far too much traffic to pay the price of the library. I am glad, because it means I was able to learn how to hand code AJAX, and I believe anyone who uses a library, should have some idea of what it does, so they know what performance cost is associated with their actions.

Of course, in .NET, it's not deemed important to even make the decision between a vector or a list, so I guess performance doesn't matter nowadays.....

Wednesday, June 17, 2009

.NET 3.5 won't install with an ATI video card

I did my support call this morning, and solved the issue. Just so we're clear, I am not saying this is Microsoft's fault. However, I do think that their installer could give some more intelligent feedback to the lay person.

Basically, by reading the logs, I found that a file called CLI.exe was stopping .NET from being updated. This is a driver utility program for ATI video cards. So, if you have an ATI video card, and the .NET 3.5 installers don't work, and give you a meaningless error 1603 ( which is a generic error, and tells you nothing, which means if you google it, you'll get given all sorts of totally different solutions ), then I'd suggest stopping the video card utility and trying again. But, that just means I've added one more to the pile of wildly different solutions to the 1603 error code, because I know from googling, lots of people have solved the problem in totally different ways.

Your best bet is therefore to look at the error logs in the temp directory ( although they are quite verbose and therefore hard to read and close to useless ), or to read through the Warning and Information messages in the Event Viewer (Control Panel/Administrative Tools/Event Viewer), the errors in there are useless, things have broken by then. It's the Application list you want to select, that's where the action is.

SQL Server 2008 is installed, and it's able to connect to my SQL Server 2005 database, although it could not restore my old databases, I am guessing I need to install SS 2005 SP1 to maintain compatibility. I'll get around to that, I was able to script my website database, run the SQL, and get up and going again to do the development work I need to. I do wish that the SS 2005 would install it's client tools, or tell me why it is refusing to ( instead of claiming that it has ), but at least I had 2008 as an option, even if it means my dev machine is no longer a remotely valid test machine for my products.

Tuesday, June 16, 2009

Installers that don't

I am the final line of support for our product, and I've been informed of a machine that will not install .NET 3.5. It gives an error message, which I googled and found every possible suggestion from logging in as a local admin, to sacrificing a goat. It appears that the error message is meaningless, and I need to read the log files to find out what is wrong. Which means, I need to log in to a client machine and dig around, trying to work out why they can't install .NET.

Why is it so hard to give a meaningful error message ? We also are not distributing .NET 3.5 SP1, because it is 300 MB and can take hours to install, because it installs every possible windows update along the way. This bit me, because I wrote an app which shows video thumbnails in WPF, which I stress tested for hours. I had installed .NET 3.5 SP1 and wound back to 3.5, so I can test on the same environment our users will have. Well, when I deployed, that screen would crash within a few minutes, I guess some sort of memory bug in Windows Media Player that was fixed by a patch that was not uninstalled when I removed SP1. I fix this for .NET 3.5 by using the memory stomping code I've needed for every WPF app I've ever written that uses resources, the subject of a future blog entry.

I am currently trying to install SQL Server 2005. I can't install 2008, it installs .NET 3.5 SP1., which I can't run for the reasons stated. So, the installer runs fine, but at the end, the client tools are not installed. They are just not there. Now when I try to run the installer, it warns me that I should use a command line switch if I am upgrading versions. Why make it that hard ( why not, press 'here' to install an upgrade, for example ), and what version ? All I am trying to do, is make the installer install what I asked it to, and what it falsely claimed to have done. I've found several fixes on the web, so this is happening to other people, too. But, none of them have worked.

How hard is it to write installers that work ?

Update: I have given up and am installing SQL Server 2008. Wow, this install has got to a lot to be a more work than in the past. Tons of screens where I need to provide a login and other details, lots of user hostile error screens, and now I need to install VS 2008 SP1 before it will continue. How many of these service packs are actually needed to make these programs work ? Not many, I am betting.

Further Update: The VS 2008 SP1 took 90 minutes to download, and is close to taking an hour to install. This machine has 8 processors and 20 gig of RAM, the 1 TB drive is almost empty, so the machine is not the issue, nor do I have slow internet. 7 hours of trying to install SQL Server and counting.......

Sunday, June 14, 2009

Update - ArrayList is not a List

As Shog pointed out below, ArrayList is in fact an array. I did know that at one point, but I embraced typed containers from the moment they appeared, as I would hope most people did, and my experience with ArrayList for many years has been limited to saying 'why on earth do you use that ?' to people in forums. But, like the terrible MFC containers that were only written as a stop gap until they got STL, and yet so many shops forced their devs to use them, because 'we're a Microsoft shop', ArrayList is with us to stay, because it's part of the language, they can't remove it. Which is why we should have got typed containers in the first place.

But, even worse is that there was no list class in .NET 1.0. I can see how I forgot about this, it's really hard to believe. No list class ? How long could it have taken to 'whip one up' ? I realise that ArrayList is a name that came from Java, but, guys, steal the good stuff, not the bad. ArrayList is a stupid, stupid name for a container class, the benefits and pitfills of an array/vector class compared to a linked list are basically opposite ( which is also why both should be provided by any language released in the 21st century ).

I should mention, I set out to have a bit of content from the get-go, but I'm not claiming that MS has 365 bugs for me to report in a year, so although I have about 8 items queued up, rather than run out of steam, I am going to post roughly once a week, probably over my weekend. I do want to post with some gotchas that brought my Mac to it's knees this past week ( I do intend to post about anything where I know how to help someone fix something, Microsoft happens to be where I live, and so where I know of the most issues, but the Mac won't get off 100% scott free ), I may do that sometime this week, before a weekend post on a .NET or WPF bug.

Saturday, June 13, 2009

Missing C# language features

I'd be the first to admit that coming from C++ to C# was hard for me, because C++ had been my core language, and while I learned things like Python, they were so obviously NOT C++, that I just accepted they were different. C# is named after C++, and goes out of it's way to look like C++, so when it was plainly very different, I often took it hard. This was, obviously, my fault.

However, there are things about C# that still make no sense to me. I still hate that C# won't allow fallthrough in case statements, such as

case SaveAndQuit:
Save();
case Quit:
Quit();
break;

When I asked the C# team, I was told that C# will always err on the side of being easy for beginners, rather than being powerful. I believe a strength of C++ is that it assumes skill on the part of the programmer, rather than treating him like an idiot.

I was also astounded at the lack of generics support in C# 1.0. I still talk to people on forums using ArrayList today, despite generic containers having been in for some time now. The generics support we have is very limited compared to C++ templates, I don't see how 1.0 could not have contained an engine that generates a typed List class, for every templated argument given. That's basically all we have now, right ? Although at least the CLR means that you don't end up with a ton of different classes in your exe, as you did in C++.

In addition, in C++, we had the STL, with a vector and a list class. The vector is an array class, which means fast random lookups, but slow inserts. A list has the opposite O notation. In C#, we were given a class called ArrayList. OK, is it an array, or is it a list ? ( It's a list, by the way ). To my knowledge ( and I just googled again to make sure ), there's still no array class, although you can arguably just use an array, and HashSet only arrived in .NET 3.5. I don't understand why such basic things were not implimented.

I will say that I love LINQ and I love that C# is moving past being a poor mans C++, and establishing it's own set of power features.

One thing I asked the C# team for many times, was optional parameters. They want to keep the language simple, yet instead of having the compiler generate a method like

bool SomeMethod(int n)
{
return SomeMethod(n, "The default value");
}

they want me to write it and maintain it instead ? In C# 4.0, they are finally implimenting this, and doing it all the way, with named optional parameters, which is pretty cool, but it's sure been a long wait, and I don't see what damage an intermittent, non named parameter version could have done in the meantime.

Which brings me to my main point. One thing that took some getting used to in C#, is that classes are always passed by reference. If you pass me a class instance, and I change it, I changed it for you, too. So, it seems to me that if I were writing a library, I would want to create an interface that provides a contract to my users - I am not going to change this object, I can be trusted to return it in the state it was given to me. The fact that they kept a const keyword, but made it mean something totally different in C# to C++ threw me at first, but I eventually found the readonly keyword, I just don't see why it can't be applied to parameters on a method definition. Sure, it's syntactic sugar, it doesn't change what the method does, but, writing code that a computer can understand is EASY. The thing we need most to focus on, is writing code that HUMANS can understand and trust. Code that is maintainable, AND that explains itself well to a first time user, should always be the goal.

I do see that there's a level of complexity there, if a method takes a const parameter, passes it to another method, which passes it somewhere else. And I can see that the solution to the fallthrough problem in case statements apparently being goto means that we're encouraged to write spaghetti in C#, but, I still find myself from time to time wishing that when I write a method, I could actually remind others, and have the compiler remind me, that I wanted to pass an object into a method, without that method changing the object in any way. The only alternative I can see is to write and pass in a wrapper class which only allows getting of properties in the contained class. And, while I used to spend time writing strongly typed containers in C# 1.0, even I am not pedantic enough to do that.

And if anyone tells you they are learning C#, and know C++, the best piece of advice to give, is to say, C# is not based on C++, it's Java on steroids.

Friday, June 12, 2009

WPF destroys images when resizing them

This is the bug I was reminded of, which caused me to decide it was time to start a blog. Two years ago, I wrote my first WPF project. Basically, it's a program that gives you access to high quality images, which you can zoom in on, etc. Now, because of issues with WPF memory management ( which I'll cover at a later date ), we decided to save memory, by loading images as requested, then resizing them to the size of the screen. We'd reload at a bigger size if the user zoomed. What we found was, some of our images would become distorted sometimes when we zoomed ( which involved reloading the image at a new size ). WPF has a control for scaling images, however, it keeps the full size image in memory, making it useless for our purpose ( it just wasn't what it was for ). So, we resize the image the way the docs tell you to. Something like this:


fullHeight = bi.PixelHeight;
fullWidth = bi.PixelWidth;
bi = new BitmapImage();
bi.BeginInit();
if (heightBasedAR)
{
bi.DecodePixelHeight = (int)Math.Min(height, fullHeight);
}
else
{
bi.DecodePixelWidth = (int)Math.Min(width, fullWidth);
}
bi.StreamSource = new MemoryStream(fileBuffer);
bi.EndInit();

As I said, this worked sometimes, and others, would destroy the image. We have illustrations in the program which are PNGs, and photos which are JPEGs. I am not sure if it was the photographic content, or the JPEG format that made the latter ones get distorted, but I have a feeling we changed some images to PNG and that helped, so I'd say that I believe it's the format that is the issue. In any case, it would only happen sometimes, but by experimenting, I proved that the issue was that it would only happen for certain sizes of image, that is, the same image would consistently break, if you found a new size that would break it.


I created a sample app and sent to Microsoft, it produces the following output:




As compared to my original image, which looked like this:




It actually took me three emails back and forth of 'I don't see a problem', before the Microsoft guy accepted that image 1 does NOT look like image 2. This seemed to me to be a pretty major bug, and it was duly reported and went on the pile. Two years later, I run the latest version of WPF and .NET ( 3.5 SP1 ), and my program still destroys this image, which is how I got that screenshot.

The only solution I could find, was to revert to GDI+ to do my image resizing. So, our application does something like this every time we load an image:

int scaledWidth = (int)Math.Round(fullWidth * scale);
int scaledHeight = (int)Math.Round(fullHeight * scale);
System.Drawing.Size newSize = new System.Drawing.Size(scaledWidth, (int)height);
using (System.Drawing.Bitmap bp = new System.Drawing.Bitmap(img, newSize))
{
using (MemoryStream ms2 = new MemoryStream())
{
bp.Save(ms2, System.Drawing.Imaging.ImageFormat.Png);
bi = new BitmapImage();
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.StreamSource = ms2;
bi.EndInit();
}
}

So, GDI+ reloads the image at a new size, then saves it to a memory stream, and from there we read the stream into a WPF BitmapImage. Hardly neat, but it works, and WPF still does not.

Thursday, June 11, 2009

Welcome, one and all

So, after years of resistance ( apart from a brief dalliance with a music blog ), I am blogging. Why ? Well, I was a Microsoft MVP for three years ( I was kicked out for not liking Microsoft Vista ), and I was assured at the start of that experience that I now had an inside track to report issues with Microsoft, etc. I have found many bugs in Microsoft products, before, during and since. What is consistent in all my experiences is that reporting bugs means they either claim they can't reproduce ( although usually I press on until they accept the issue ), tell me it's a feature, or just plain don't fix it. So, I'm going to blog about the bugs I've found in Microsft frameworks, particularly C# and WPF, because that's what I tend to use nowadays, but, I'll be bringing stuff up that I reported in the past, so there will be other C# stuff as well. The idea is not to have a mindless bash at Microsoft, it's to report real issues in their frameworks, and, where possible, to report workarounds, so that hopefully I'll find readers from people who google the same error messages, and are looking for solutions. That's assuming anyone googles anymore, reading programming forums sometimes makes me wonder if that is true.

So, that's my statement of intent. I have a few decent issues in mind already, but I doubt I'll come up with an issue a day ( it's not THAT bad, bad as it can be ), but we'll see how long I can keep it up.