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.)