Friday, August 12, 2011

Avoiding AddressAccessDeniedException: Change WCF Binding To netTcpBinding

I was trying to deploy a nifty new ASP.NET and Windows service application pair, in which the ASP.NET application included a WCF client which accessed the Windows service which hosted a WCF server.  But I found when deploying it to a Windows 2003 server (instead of my XP development box) that when I tried to start the service, I got the following error in the event log:

Service cannot be started. System.ServiceModel.AddressAccessDeniedException: HTTP could not register URL http://+:50621/XX1TestSuiteService/RemoteInterface/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details).

A little googling turned up this page (among others):


Certainly trying to reconfigure the server to allow for the registration of the use of an HTTP listener might eventually have gotten me where I needed to go.  But I only used the HTTP binding because it was the default for WCF.  These applications were going to be on the same server.  So between the performance improvement I understood the netTcpBinding provided and my desire to eliminate this error, I reconfigured my two apps to use that binding, with the help of a very detailed and easy process described by Microsoft here:


After re-installing the Windows service, it started without any error.

Tuesday, August 2, 2011

WCF Client Disposal Broken!

While running a recently-developed application I wrote through the Visual Studio 2010 code analyzer, I was told that I wasn't calling Dispose on an object which implemented IDispose.  Chagrined, I took a look and found that WCF client objects, derived from ClientBase, do indeed derive from IDispose.

Oddly, the autocomplete didn't allow me to test this, by attempting to call the Dispose method directly off the client object.  It turns out this is a known oddity; the Dispose method in ClientBase is private.  The reason that "using" would work is that using will effectively cast the client object back to IDisposable, where Dispose is once again callable:


But wait, that's not really why I'm posting.  Apparently the ClientBase's Dispose method calls Close, which can throw if there are errors performing the close.  Apparently, throwing exceptions out of Dispose is not recommended by Microsoft's own "Framework Design Guidelines":


What this means for a WCF client is that if you use the "using" approach for cleanup, any errors that occur during the implicit Dispose call at the end of the using block will mask any exceptions which occurred in the using block.

There is an extraordinarily ungainly approach recommended by Microsoft:


in which you create a try block with a call to Close() and explicitly provide catch blocks for each of CommunicationException, TimeoutException, and Exception; and in each of those blocks, you call Abort; and in the Exception catch block, you re-throw the original error after calling Abort().  No way I'm doing that.

Suggested elsewhere was what seemed a cleaner variation to me:

bool isSuccessful = false;
MyClient myClient = new MyClient();
try
{
    // use the client object here
    myClient.Close();
    isSuccessful = true;
}
finally
{
    if (!isSuccessful)
        myClient.Abort();
}

What a pain!  Why would the WCF developers do this to us?  Some notes on the internal discussion are available here:



and I think the pertinent part of that second link (well worth the read in its entirety!) is:
After much debate, IDisposable was left on ServiceHost and ClientBase, the theory being that for many users, it’s ok if Dispose throws, they still prefer the convenience of using(), and the marker that it should be eagerly cleaned up.  You can argue (and some of us did) that we should have removed it from those two classes as well, but for good or for ill we have landed where we have. It’s an area where you will never get full agreement, so we need to espouse best practices in our SDK samples, which is the try{Close}/catch{Abort} paradigm.
There were two decisions to make: should the client object inherit IDisposable; and if yes, should Dispose call Close or Abort?  All three outcomes (not IDisposable, Dispose calls Close, and Dispose calls Abort) are ugly in one way or another.  So how come other self-cleaning-up objects don't have this ugliness?

I guess I'm going to have to put up with warnings from code analyzer about missing calls to Dispose.  [sniff]

Monday, July 18, 2011

Removing A Windows Service No Longer In Add/Remove Programs

So the Visual Studio 2010 installer projects for Windows Services make me more and more frustrated every time something odd crops up.  This time, I began getting error messages during installation saying something like the service couldn't be started from the command line... wha?  So I deleted the ProjectInstaller.cs and re-added it, and this time during the install I didn't get that error message *and* it asked me for the user under which the service should run (which it wasn't doing).  But then it gave me an error saying that the service already existed.

And here's the pain: the service was still showing up in the Services control panel, but it was no longer showing up in the Add or Remove Programs control panel.  Ugh.  Googling to the rescue:


The use of the command-line "sc" program worked just fine:

sc delete "service name"

did the trick.

Friday, July 15, 2011

I Want My 5.1 Surround Sound Speakers, And I Want Them Now

I usually play games with headphones on.  The sound would otherwise disturb those around me, who are generally asleep when I play those games.  This means that I choose the "Stereo Headphones" configuration, so that the sound of the game goes to the main right & left speakers of my Creative SB Audigy 2 ZS sound card.  But then in the morning when everyone's awake, we can turn on the speakers and enjoy all six speakers, right?

But that involves hitting Start / Control Panel / Sounds and Audio Devices / Advanced and choosing a speaker setup.  Who needs that angst?  Every morning?  Who can remember?  Sound still comes out, right?

Wait, c'mon now, I'm a developer.  Surely there's an easy way to write something quick to change that setting and have it run automatically on boot.  Surely...

Much googling turns up interesting pages like good ole stackoverflow:


which pointed me in the direction of this MSDN Social page:

which says Hey, there's a SetSpeakerConfig() function!  More googling turns up the reference page for IDirectSound8::SetSpeakerConfig().  Yay!  Um... wait, COM?  You want me to bother with calling CoInitializeEx() and checking return values and DLL hell and... 

Yes, there's a better way for us lazy (and productive) .NET developers.  Managed DirectX sounded really good, until I read that it wasn't supported any more and was replaced by XNA and other stuff really not related to my wanting to call SetSpeakerConfig.  Well, gawd bless Wikipedia which led me to the rapid-fire conclusion to this tale.  Starting with the speakers in the headphones configuration:

1.  Download and install the open-source .NET library SlimDX.
2.  Fire up Microsoft Visual C# Express Edition (I used 2008 cuz I'm lazy and haven't downloaded 2010 yet).
3.  Create a new WinForms project.
4.  Add a reference to SlimDX (I assume I had to choose the Framework 2.0 version since I was still with 2008).
5.  Add a button to the form, double-click, and enter this code:

using SlimDX.DirectSound;

private void button1_Click(object sender, EventArgs e)
{
    try
    {
        DirectSound directSound = new DirectSound();
        directSound.SetSpeakerConfiguration(SpeakerConfiguration.FivePointOne, SpeakerGeometry.None);
        MessageBox.Show("Done");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}
6.  You guessed it.  Run the app.  See the "Done" message box come up.  Check your control panel setting and see...


Happy happy joy joy.  Now I just needed to create a UI-free windowless version to run at startup, so I copy the code from the button handler event into the Main() method in Program.cs, get rid of the "Done" line, get rid of the line that opens the form, add a nicer error handler, delete the Form1.cs from the project, and the only code left in the project is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using SlimDX.DirectSound;

namespace ChangeTheSpeakerConfiguration
{
    static class Program
    {
        ///



        /// The main entry point for the application.
        ///



        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            try
            {
                DirectSound directSound = new DirectSound();
                directSound.SetSpeakerConfiguration(SpeakerConfiguration.FivePointOne, SpeakerGeometry.None);
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occurred trying to reset the speaker configuration: " +
                    Environment.NewLine + Environment.NewLine + ex.ToString(),
                    "ChangeTheSpeakerConfiguration");
            }
        }
    }
}

Sweeeet.  Now just add a shortcut to the executable to the Startup menu folder (for me, that's C:\Documents and Settings\Alex\Start Menu\Programs\Startup).  From now on, every day starts a 5.1 Surround Sound Speakers day.

(Disclaimer: I'm running XP, and the SlimDX docs (and others) say life is different with Vista.)

Thursday, June 9, 2011

WCF Really Doesn't Support Multiple Host-Header Applications On A Site...?

I had a situation where due to firewall NATting I had to assign a new IP address to an IIS web site, and a host header was assigned to the site as well. It appears that WCF doesn't support complexity like that; I got the following error in the Event Log:

This collection already contains an address with scheme http.  There can be at most one address per scheme in this collection.

Clear as mud.  More info (and bitter complaining) was found here:


Yeesh.  My solution was to create a new IIS web site, use only the new IP address on that site (removing it from the old one), specify that the host header should be used on the new site, apply the existing SSL certificate (this was an HTTPS web service), uninstall the web service, and reinstall it on the new IIS web site.  

I was greatly afraid this would require some kind of config file change or--worse yet--some kind of code change.  But fortunately, no.

Wednesday, May 4, 2011

A Bizarre .NET Linking Error, So Just Reconfigure LC.exe. Naturally.

To eliminate the necessity of deploying certain third-party DLL's with applications that don't need them but which link to assemblies that do, I removed my wrappers for those DLL's to a new project and only added references to that new project where necessary.

Unfortunately, after doing this, I began to get this error (with Visual Studio 2010 SP1):

Could not load file or assembly 'Dart.PowerTCP.Ftp' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)

Googling around suggested that I should press the "Unblock" button, but the assembly hadn't been downloaded, and didn't have an Unblock button.

What eventually worked for me was what I found at http://www.devexpress.com/Support/Center/p/B192717.aspx which was to do this:

The solution is to add a .config file for the license compiler which includes the element. Just create a new lc.exe.config file and include this content:
<?xml version ="1.0"?>
<configuration>
    <startup useLegacyV2RuntimeActivationPolicy="true">
        <supportedRuntime version="v4.0.30319"/>
    </startup>
   <runtime>
      <loadFromRemoteSources enabled="true"/>
   </runtime>
</configuration>

Then copy it to the folder where LC.exe resides on your machine…on Win 7 x64 that's usually:
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools
 That did it for me.  Note that my My Documents folder is on a Windows file share, so all my solutions and projects are on a remote server.  But the DLL in question was not actually remote... ah the mysteries of life.

Wednesday, February 9, 2011

Silent MessageBox.Show() Failure: Text Too Long!

I have a nifty .NET XML validation utility component in C# at work which will raise an exception if the provided XML does not conform to the provided XSD.  One of my co-workers used it, and told me that the XML file I said was invalid wasn't generating an error with that component!  Hastily testing it out, I found that it was in fact throwing an exception... but the MessageBox.Show() in the catch block wasn't doing anything!  I would trace into that statement, nothing would happen, and I'd be on the next statement.

A little paranoid googling turned this up:


It turned out there were so many errors found during the validation of the XML that the exception's message was over 900 KB, and I guess that causes a silent MessageBox.Show() failure.

...I suppose I wouldn't really like to see an error message that long, but I'd have expected MessageBox to silently truncate the message until it can be displayed.  It'd be nice if this were documented in the MSDN documentation page.  (I'm sure I've seen shortened messages appear in message boxes before.  Ah well.)