Sunday, June 16, 2013

Fixing Internet Explorer 10: upgrade to Internet Explorer 9

This doesn't have anything to do with C# or Visual Studio today, other than to show how you can make utter crap with a decent language and an overcomplicated IDE.

Microsoft, as usual, has decided that it knows what broken piece of crap browser is better than what I'm using and keeps shoving the piece of crap Internet Explorer 10 down my throat. Well, during a backup and restore procedure, I accidentally missed telling Windows not to load that piece of crap IE10 on my computer. So I ended up with that piece of crap IE10 on my computer.

Well, it's a simple fix to remove it, right? Oh, hell no. Microsoft not only screwed up IE10, but they screwed up restoring IE9 also. After uninstalling IE10 program - oh wait, it's not a program that can be uninstalled, it's a part of the frigging operating system! OK, after uninstalling the piece of crap IE10 Windows component, just reinstall IE9.

But wait, there's more! When you try to reinstall IE9, Windows happily stops the installation and tells you it's already installed. Asshats.

OK. Now I get to go to the Microsoft Support site and find out how to get around the bug to get around the bug when removing the piece of crap IE10. Fortunately, Microsoft has several troubleshooting alternatives at for when the first solution decoy, Mr. Fixit Wizard, fails. The second one, running a command line, actually seemed to do the job Mr. Fixit failed to do. The Mr. Fixit Wizard is probably a union employee, and was smoking crack and drinking beer behind the curtain when he was supposed to be doing his job. Of course, I had to fix the command to remove the piece of crap IE10 rather than IE9. Here's what I ran:

FORFILES /P %WINDIR%\servicing\Packages /M Microsoft-Windows-InternetExplorer-*10.*.mum /c "cmd /c echo Uninstalling package @fname && start /w pkgmgr /up:@fname /norestart"

Windows still had some complaints and opened copious other command windows. But after that, at least, I was able to complete the IE9 installer.

But wait, there's more! After removing the piece of crap IE10, rebooting, and installing IE9, and rebooting, Windows decides that there are some files in use and fails to finish installing IE9. Run the installer again, reboot. Now is Windows happy?

Hallelujah, it is! Amazing how Microsoft can turn such a simple little procedure into an annoying mess. Better that mess than the mess that is the piece of crap IE10.

Oh, by the way, I don't like the piece of crap IE10.

Friday, September 28, 2012

WCF handles streamed content type badly

While trying to help a colleague with a perplexing deserialization problem with derived types, which the KnownTypes attribute wouldn't fix.

Take One: we tried to pass JSON data into our REST service through a Stream parameter. We were thinking that we could simply read the raw object data and perform our own deserialization. But, no, we began to get a "500 Internal Server Error" with the exception:

Incoming message for operation 'test' (contract 'RuleService' with namespace '') contains an unrecognized http body format value 'Json'. The expected body format value is 'Raw'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.

With .NET, it seems nothing is ever as easy as advertised.

The data was getting to our service, but it was throwing an exception before dispatching the request to our service method, so the Visual Studio debugger was useless to run down the problem.

Take Two: We created a test method to accept a Stream and return it as a string. This failed, too. WCF, WTF!

Turns out WCF is really that stupid. A Stream is supposed to accept any data regardless of format. It doesn't. WCF still tries to interpret the content according to the Content-Type header, instead of ignoring it as it should. The client must tell the service the data is unformatted before it will work without throwing an exception. So a client that isn't completely well-behaved and strictly compliant with the web service interface will blow up your program. I guess it's a security feature.

Here's the raw deal on raw data: if your method accepts a Stream, the client must set the request's Content-Type header to application/octet-stream or text/plain or some other type that indicates unformatted content. If you only switch your input parameter from a class to a Stream, a message that could have worked before will immediately fail. Using WebContentTypeMapper requires substituting your own mapper for the entire service, not just for a single operation. Apparently there is no simple workaround.

Take Three: luckily for us, the client is our own program. We can make it compliant. If it were a third-party application, we would be SOL.

The End: After we changed the client to set the message header to Content-Type: application/octet-stream, the service starting receiving data again and our program went on happily deserializing the object that WCF's stock deserializer wouldn't.

Tuesday, February 21, 2012

Random notes about getting IBM WebSphere MQ 7.1 installed and working

I had an enormous amount of trouble while starting to develop an application that had to interface to another application using IBM WebShere MQ 7.1 message queues. Installation is not simply using the setup program's defaults. These notes are vague because this procedure was painfully time-consuming and I didn't have time to hunt down the facts about what actually got it working.

1. Installation Part I. This gets the files onto the workstation. This took me a couple days because IBM's documentation is pretty obscure about what installation set is needed, server or client, or where it puts files. A lot changed between versions 7.0 and 7.1 that was undocumented. In addition to being vague, the documentation is also inaccurate, as the documented defaults are not the real defaults. In short, to develop and test on a single machine, the Server set (which includes the Client files) was required, not just the Client set. And you had to manually select the Client files from a custom installation because - contrary to the instructions - the Client files were not selected by default.

2. Installation Part II. Once the files are physically installed, a second part of the installation runs to "prepare" the message queues. Under Windows 7 at least, this portion terminates with a "there's something wrong" error. Real helpful. Fixing this had to deal with security. In addition to the domain user required to execute services, another two separate domain users had to be created. One user is apparently to create queue managers and another to manage queues. They are identical accounts except they have different names; complete waste of resources. And you may have to start the installed services manually. As an Administrator. A Domain Administrator. WTF!

3. More security problems. Attempting to create a remote queue runs afoul of more security issues. A minimum of four layers of Authorizations have to be set up (by a local Administrator this time?) before a queue can be created. Some permissions are for creating the queue manager and some are for creating the queue.

4. Sample programs. The sample programs provided as part of the installation cannot be built using the supplied bldcssamp2.bat batch file. Firstly, because the batch file must be run from the command line, the PATH environment variable must be updated to include the compiler directory; in my case, for compiling against the .NET Framework 4.0, it was setting:

Secondly, the path to the libraries must be edited. One every compile statement. Original:

On Windows 7 (and Windows Vista, from reading other comments) the compiled executables won't run. When you launch an executable, the program crashes and the following error shows up in the Windows Application Event Log:

Activation context generation failed for "C:\Program Files (x86)\IBM\WebSphere MQ\tools\dotnet\samples\cs\base\nmqsput.exe".Error in manifest or policy file "C:\Program Files (x86)\IBM\WebSphere MQ\tools\dotnet\samples\cs\base\nmqsput.exe.Config" on line 8. The element assemblyBinding appears as a child of element configuration which is not supported by this version of Windows.

This has something to do with Windows 7 not liking the "side-by-side" Win32 manifest files that the compiler generates by default. To get around this error, the batch file had to be edited yet again. Add to every compile statement:


So, parameterizing it a bit, in the interest of helping other IBM customers, here's the complete sample build script:

SET LIBPATH=..\..\..\..\Lib
SET MFTOPT=/nowin32manifest
echo building nmqsget.exe
csc /t:exe /r:System.dll /r:amqmdnet.dll /lib:%LIBPATH% /out:nmqsget.exe %MFTOPT% nmqsget.cs

echo building nmqsput.exe
csc /t:exe /r:System.dll /r:amqmdnet.dll /lib:%LIBPATH% /out:nmqsput.exe %MFTOPT% nmqsput.cs

echo building nmqswrld.exe
csc /t:exe /r:System.dll /r:amqmdnet.dll /lib:%LIBPATH% /out:nmqswrld.exe %MFTOPT% nmqswrld.cs

echo building MQPubSubSample.exe
csc /t:exe /r:System.dll /r:amqmdnet.dll /lib:%LIBPATH% /out:MQPubSubSample.exe %MFTOPT% MQPubSubSample.cs

echo building MQMessagePropertiesSample.exe
csc /t:exe /r:System.dll /r:amqmdnet.dll /lib:%LIBPATH% /out:MQMessagePropertiesSample.exe %MFTOPT% MQMessagePropertiesSample.cs

And another thing... The documentation makes no mention about how to compile against the .NET libraries. Oh, there's a sample solution for Visual Studio, but it makes web service calls instead of using the MQ library. Wonderful, another irrelevant example. Without scanning my hard drive and digging through the command-line samples, it would have been nearly impossible to find where they buried the correct DLL that had to be referenced: C:\Program Files (x86)\IBM\WebSphere MQ\tools\Lib\amqmdnet.dll.

Fortunately, there is this outdated but still useful RedBook reference document: WebSphere MQ Solutions in a Microsoft .NET Environment. It has some helpful information about developing MQ applications in .NET and Visual Studio .NET. The conceptual information in it is still relevant for current development.

Monday, June 27, 2011

Running Device Emulator in XP Mode

If the frustration of VS2008 corrupting some of the VS2005 SDKs isn't enough to burn your butt, it's just a warm-up exercise to getting the Device Emulator working in Windows 7's XP Mode.

The first month of isolating VS2008 and VS2005 by installing one of them into XP Mode Virtual PC (VPC) was certainly disappointing. VS2008 didn't want to cooperate at all. So I did the next best thing: installed VS2005 there instead. It was a long and boring process to get VS2005, its service packs and a bunch of SDKs installed, but it worked without much pain. It even compiled some code. But launching a device emulator was a different story.

On connecting to the Mobile 5 Pocket PC Emulator device, which I use regularly for testing, the computer just stared blankly at me for a few minutes before declaring:

Cannot connect to device. Error: 0x8007064a

Try a web search for that. Mwa-hah-ha!

Anyway, the short story and the two-part solution. I finally found some obscure and easily overlooked references from people who had similar experiences.

Part One. Visual Studio won't open the project.

  1. Open the solution. Visual Studio complains: "The project file cannot be loaded. The application for project ... is not installed.". Shutting down VS and restarting does nothing.

  2. Right-click the project (which offers no information about why it fails. Other than some stupid message about "platform not available" or something moronically insulting like that. It's all BS - the SDKs are installed.

  3. Select Reload project.

  4. Watch with anger and puzzlement as VS loads the project correctly this time. Shoot me.

Part Two. The device emulator fails when running in XP Mode. I followed Brian Peek's useful guide to replacing the missing Microsoft network adapter, Windows Virtual PC and the Microsoft Device Emulator, which may have helped solved other future problems. For the emulator error, the article Cannot connect to device. Error: 0x8007064a was helpful.

  1. Launch the emulator by trying to connect or by executing in with or without debugging. VS complains: "Cannot connect to device. Error: 0x8007064a".

  2. Terminate the Device Emulator Manager.

  3. Rename the Folder "CoreCon" (in "Documents and Settings\Application Data\Microsoft\") to "xCoreCon".

  4. Start the Device Emulator (list of devices is now empty).

  5. Terminate the Device Emulator.

  6. Rename "xCoreCon" back to "CoreCon".

  7. Now the emulator works. Shoot me and the computer.

Is Microsoft running the US Congress? Maybe that's the problem. Well, at least Solitaire still works.

Thursday, May 26, 2011

Visual Studio 2005 & 2008 side-by-side incompatibility

The short story:
VS2005 and VS2008 will not co-exist peacefully.

The long story:
After several fruitless days trying to create an environment for developing an application for the Windows CE 5.0 platform using Visual Studio 2008, I had to admit defeat. The reason is, when Visual Studio 2008 is installed on a system that has Visual Studio 2005 already, it clobbers the Windows CE 5.0 platform so it cannot be used by either IDE. No complaints, no warnings, just gone.

Microsoft contends that VS2005 and VS2008 can be installed and will work side-by-side. What they did not document - typical for MS - is that certain platforms not only are incompatible between the two, but are also disabled for both. The Standard Windows CE 5.0 SDK is one of those platforms that is disabled when VS2008 is installed. I haven't had time to find out what additional platforms may be affected.

It's not an operating system issue. I develop on a Windows 7 machine. My co-worker uses Windows XP. Both of us experienced identical problems.

My objective was to install VS2008 to work on a project I had inherited where a back-end database application had already been written as a VS2008 project. I wanted to create a Windows CE 5.0 application using the same IDE. Silly me, always expecting "new and improved" tools to work as advertised.

VS2005 with the Standard Windows CE 5.0 SDK was already installed and working fine, as I had just completed another project with that exact combination. Install VS2008. See Windows CE 5.0 platform disappear. Did installing with Administrator Privileges work better? Nope. Uninstall, reinstall, uninstall, reinstall without Documentation = No joy. Jump up and down on keyboard, smash fist through monitor, throw laptop through front window - *sigh* just wishful thinking.

Last resort, uninstall VS2008. Gee, that worked; now I had my Windows CE 5.0 platform back in VS2005. So I couldn't use VS2008 for my new project. In summary, VS2005 and VS2008 can co-exist, but only if they are on separate machines. :-/ I was burned by Microsoft marketing hype yet again.

And they want me to upgrade to VS2010. Hahahahahahaha!

Tuesday, April 19, 2011

Using Crystal Reports Basic for VS2008 with VS2005

I had a client for whom I developed a project in Visual Studio 2005. The reports were written for the bundled version 10.2 of Crystal Reports (CR). The application was to be installed on the client's server that already had a number of applications that were using the later Crystal Reports version 10.5 (bundled as Crystal Reports Basic for Visual Studio 2008), a newer version.

Anecdotal evidence showed it was possible to use a version of CR other than what was bundled with VS2005. Unfortunately, no hard documentation existed that defined or instructed one on how to do so. These notes are what I pieced together after a week of intense research and trial & error.

The first thing that must be done is to create and test reports with CR v10.2 that is bundled with VS2005. Easy, right? Of course I'm being sarcastic.

The next step is to install the CR v10.5 runtime package. These can be acquired from several places, the official one being the Crystal Reports page on the SAP Community Network web site. Another source is Visual Studio 2008 Pro, if you have it handy. The x86 package, though, is hidden deep in the bowels of the installation: C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\CrystalReports10_5\CRRedist2008_x86.msi. Install it on your machine; I've encountered no problems with it co-existing with CR v10.2.

Depending on your architecture, you need one of these setup packages:
   CRRedist2008_ia64.msi (64 bit Itanium)
   CRRedist2008_x64.msi (64 bit Intel)
   CRRedist2008_x86.msi (BootStrapper)

In your project, make a list of all references to the CR assemblies and remove them. Here comes the fun part. You can't simply add references to the new assemblies. From a command prompt, go to your %windir%\assembly directory. You will find GAC, GAC_32, and GAC_MSIL directories there. Inside those are subdirectories for each version of the Crystal Reports assemblies on your machine. Copy the 10.5.* version of the DLLs to a folder you create within your project: I called mine CRRedist2008.

In your project, add references by browsing to your CRRedist2008 folder and selecting the same assemblies as were in your original list. Why the copying? Visual Studio does not allow adding references to assemblies in the General Assembly Cache. You need separate files so VS lets you add them as references to your project.

One more step: if you check the reference properties, you may still see the v10.2 assembly being referenced. Set the Use Specific Version property to True to force VS to use the v10.5 assembly you added as a reference.

Recompile and your reports should now run with the VS2008 version of the Crystal Reports libraries.

Barrel of fun, huh?

Thursday, March 10, 2011

Updating the MDI parent menu icon for maximized child form

While working on a C# .NET program recently, I ran up against an infamous (and another apparently long-standing) bug in Microsoft's Multiple Document Interface (MDI) architecture. When a child form has been maximized, and its window icon is updated, the icon that is merged into the MDI parent's menu strip is not updated to reflect the change.

I was using the child window icon to identify the document type being displayed and to mark when it had been modified. Everything worked fine when the window was open in Normal mode, but the icon stopped being updated when the child was maximized to fill its parent's client area.

After literally days of searching the web to see if anybody else solved the problem, I found answers ranging from "impossible" to "keep track of your own windows" (a.k.a. the old roll-your-own interface standby). Digging through the layers of classes with the debugger, I figured out a hack that seems to work.

Here's the basis of my solution: when a child window is maximized, the controls on its title bar are merged with its parent window. The parent menu inserts an image as its first element that is a copy of the child window's icon. The image (a Bitmap image) is copied only at the time the child is maximized, and is never updated afterward, regardless of calling Refresh(), Update(), Invalidate(), etc. So, to get around this missing functionality, my solution was to check the parent menu when I changed the icon of the child window; if it had an image in its first element, I converted the Icon into a Bitmap and replaced the image. It may sound hokey, but it worked.

These are the steps I used for updating the icon. I raised an event to update the parent form.

// Change the child icon according to the document state.
// Called from a method in the child form.
int newState = this.GetChildState();
this.Icon = (newState == 0) ?
myProject.Properties.Resources.savedicon :

// ...raise event to notify the parent. sender is the child form.

// Change the parent menu icon when child is maximized.
// Called from an event handler in the parent form.
if (MainMenuStrip.Items[0].Image != null)
// Copy the new state icon from the child window.
MainMenuStrip.Items[0].Image = ((Form)sender).Icon.ToBitmap();

The MDI architecture has its quirks. This is just a way to get around one of them. I think this is an inelegant solution to an inelegant problem, but sometimes you just have to be practical.