Rants, rambles, news and notes from another geek

Enabling Non-Admin Shutdown on Windows Server 2003

I am in the middle of moving all of my development activities to Windows Server 2003 from Windows XP. The single biggest reason for this move is that in Windows Server 2003 you can use IIS6 application pools to enable ASP.NET debugging as a non-admin, while in Windows XP, you have to modify the machine.config file (something I would rather not do).

One thing that you will want to do if you decide to run non-admin on Windows Server 2003 is to enable it so that you (a local User) can shutdown the machine!

To do that, you need to first of all use MakeMeAdmin to get into Admin mode, then launch the Group Policy Editor (gpedit.msc). Drill down to Computer Configuration/Windows Settings/Security Settings/Local Policies/User Rights Assignment. On the right side, look for the Shut down the system policy and double click it. Add you local Users group to that list and you are all set.

One other thing that you may want to do is take a look at the article How to convert your Windows Server 2003… to a Workstation. I personally don’t do all of the things they suggest, but some of them are useful tips.

UPDATE 2005.01.20: Brian Button pointed out that my path was wrong and it has now been updated. Thanks.

Follow-up to CrossThreadTestRunner Comments

Jamie Cansdale has posed a number of interesting questions about my CrossThreadTestRunner class and the example code. Rather than address them as follow-up comments, I’ve decided to answer them in a follow up here.

Jamie wrote:

You mentioned in your post that you can’t make any promises about it working on any other runtimes. Can you be sure you’ll never want to port these tests to .NET 2.0 or Mono? If you do it would be nice to have confidence that at least your tests will work.

Can I be sure that it will work in Mono or Whidbey? No I can’t. I wrote the simplest thing that could possibly work to solve my problem. I don’t need to compile on either Whidbey or Mono, so I didn’t address them.

However, if I did need to support those other frameworks, the code is well factored so it would be very easy to do. (My guess is that .NET Remoting uses that private field in Whidbey just like it does in .NET 1.1. In fact, I would guess that a similar method is used in Mono. One quick test, or a bit of Reflector work,&nbsp_place_holder;would confirm it.)

Jamie wrote:

Try using the following code instead. I think you’ll get the effect you’re looking for.

class CrossThreadTestRunnerException : Exception
{
public CrossThreadTestRunnerException(Exception e) : base(null, e) {}
public override string ToString() { return this.InnerException.ToString(); }
}

Then just…

throw new CrossThreadTestRunnerException(e);

While that is an interesting idea, the problem is that it screws up NUnit’s Assertion reporting. So if I make that change to the code from the previous example, I will get the following output from NUnit-Console:

NUnit version 2.1.4
Copyright (C) 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole.
Copyright (C) 2000-2003 Philip Craig.
All Rights Reserved.

.F
Tests run: 1, Failures: 1, Not run: 0, Time: 0.04015 seconds

Failures:
1) NUnitHelpers.MultiThreadedTests.Test1 : NUnitHelpers.CrossThreadTestRunnerException : Exception of type NUnitHelpers.CrossThreadTestRunnerException was thrown.
&nbsp_place_holder; —-> NUnit.Framework.AssertionException : This should fail the test, right?
&nbsp_place_holder;&nbsp_place_holder; at NUnitHelpers.CrossThreadTestRunner.ThrowExceptionPreservingStack(Exception exception) in c:\documents and settings\peterpr\my documents\visual studio projects\nunithelpers\crossthreadtestrunner.cs:line 35
&nbsp_place_holder;&nbsp_place_holder; at NUnitHelpers.CrossThreadTestRunner.Run() in c:\documents and settings\peterpr\my documents\visual studio projects\nunithelpers\crossthreadtestrunner.cs:line 26
&nbsp_place_holder;&nbsp_place_holder; at NUnitHelpers.MultiThreadedTests.Test1() in c:\documents and settings\peterpr\my documents\visual studio projects\nunithelpers\multithreadedtests.cs:line 14
–CrossThreadTestRunnerException
&nbsp_place_holder;&nbsp_place_holder; at NUnitHelpers.MultiThreadedTests.Worker() in c:\documents and settings\peterpr\my documents\visual studio projects\nunithelpers\multithreadedtests.cs:line 19
&nbsp_place_holder;&nbsp_place_holder; at NUnitHelpers.CrossThreadTestRunner.MultiThreadedWorker() in c:\documents and settings\peterpr\my documents\visual studio projects\nunithelpers\crossthreadtestrunner.cs:line 42

While this does work (in that it fails the test), it doesn’t do what I wanted, which was to show the NUnit assertion failure. In other words, the message indicates an Exception was thrown instead of indicating that an Assertion failed. Sure, I could figure it out, but why should I have to?

Jamie wrote:

It behaves quite differently though, because of the Join. How would you run multiple tests in parallel using this interface? What if you want to run your tests on a STA thread?

Again, I reiterate that this was not my purpose. My purpose was to be able to run something on another thread from the main test and confirm that it behaves when run over there. I needed to confirm that it didn’t mess up the state of the code running on this thread. If I had to run threads in parallel, I certainly would have ended up with a different approach.

I want to give many thanks to Jamie for thinking hard and coming up with a number of interesting questions, but what I want to remind everyone is that as a TDD/Agile guy, I don’t make “solve-all-the-world’s-problems” frameworks unless that is actually the problem I’m trying to solve. I write exactly the code I need right here, right now and let the code tell me when it needs to evolve to be something else. At this point, for my problem, this code works.

Using CrossThreadTestRunner

So I showed you my little CrossThreadTestRunner class, but I didn’t show you how to use it.

Suppose you wanted to run a test in another thread. You would probably write something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System.Threading;
using NUnit.Framework;
namespace NUnitHelpers
{
   [TestFixture]
   public class MultiThreadedTests
   {
      [Test]
      public void Test1()
      {
         ThreadStart ts = new ThreadStart(this.Worker);
         Thread t = new Thread(ts);
         t.Start();
      }

      private void Worker()
      {
         Assert.Fail("This should fail the test, right?");
      }
   }
}

Now, as I said before, if you run this test in NUnit-Console, you will get this output:

NUnit version 2.1.4
Copyright (C) 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole.
Copyright (C) 2000-2003 Philip Craig.
All Rights Reserved.

Unhandled Exception: NUnit.Framework.AssertionException: This should fail the test, right?
Tests run: 1, Failures: 0, Not run: 0, Time: 0.0200788 seconds

As you can see, the exception does show up in the output, but you don’t actually get a failing test. If your project had hundreds or thousands of tests in it (not an uncommon occurance), that little bit of text output could easily be missed.

So, here is how you use CrossThreadTestRunner:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System.Threading;
using NUnit.Framework;

namespace NUnitHelpers
{
	[TestFixture]
	public class MultiThreadedTests
	{
		[Test]
		public void Test1()
		{
			ThreadStart ts = new ThreadStart(this.Worker);
			CrossThreadTestRunner runner = new CrossThreadTestRunner(ts);
			runner.Run();
		}

		private void Worker()
		{
			Assert.Fail("This should fail the test, right?");
		}
	}
}

And here is the new output from NUnit-Console:

NUnit version 2.1.4
Copyright (C) 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole.
Copyright (C) 2000-2003 Philip Craig.
All Rights Reserved.

.F      Tests run: 1, Failures: 1, Not run: 0, Time: 0.0401576 seconds 

Failures:      1) NUnitHelpers.MultiThreadedTests.Test1 : This should fail the test, right?  
at NUnitHelpers.MultiThreadedTests.Worker() in c:\documents and settings\peterpr\my documents\visual studio projects\nunithelpers\multithreadedtests.cs:line 19  
at NUnitHelpers.CrossThreadTestRunner.MultiThreadedWorker() in c:\documents and settings\peterpr\my documents\visual studio projects\nunithelpers\crossthread      testrunner.cs:line 41  
at NUnitHelpers.CrossThreadTestRunner.ThrowExceptionPreservingStack(Exceptionexception) in c:\documents and settings\peterpr\my documents\visual studio projects\nunithelpers\crossthreadtestrunner.cs:line 34  
at NUnitHelpers.CrossThreadTestRunner.Run() in c:\documents and settings\peterpr\my documents\visual studio projects\nunithelpers\crossthreadtestrunner.cs:line 26  
at NUnitHelpers.MultiThreadedTests.Test1() in c:\documents and settings\peterpr\my documents\visual studio projects\nunithelpers\multithreadedtests.cs:line 14 

Now we have a failing test like we wanted.

Hopefully this will help out some other poor soul who needs to deal with multithreaded testing. Many thanks to Brian and Scott for helping me work this out.

NUnit and Multithreaded Tests - CrossThreadTestRunner

NUnit 2.1 doesn’t deal well with multi-threaded code. By that I mean that if you have a test that spawns another thread and then that thread needs to Assert something, it won’t work. If you are using NUnit-GUI or NUnit-Console, you will see the exception’s message in the output window, but interestingly enough, your test will PASS! Unfortunately, TestDriven.NET (nee NUnitAddin) doesn’t give you any output at all regarding the exception. The test just passes.

(I’ve read that NUnit 2.2 has fixed this problem, but since we are using NUnit 2.1 on our project I ran into it headlong. Also, the 2.2 implementation apparently doesn’t work when the exception isn’t serializable.)

I did a little bit of digging and&nbsp_place_holder;came up with an approach that works. Catch the exception on the other thread and pass it back to the main thread through a local member variable. I had it done and working as&nbsp_place_holder;couple of helper methods in my&nbsp_place_holder;test fixture, but I wasn’t really happy with it. It seemed to me that I should be able to make it a little bit more reusable.

So I grabbed Brian Button this morning and we started refactoring. (Have I mentioned how much I love Resharper?) A little extract method here, a little extract class there… a rename or two… and viola, I had the following class.

Once little caveat: The code on lines 32-34 require you to have Reflection permissions (hence the demand attribute). While this isn’t absolutely essential, it is nice because it means you will get a good stck trace in your failing test. If you don’t like that, get rid of it. Oh and that “remoteStackTraceString” stuff works in ,NET 1.1… I can’t make any promises about any other runtimes. YMMV.

My next post will have a sample that shows how to use it.

Enjoy!

.csharpcode{ font-size: 10pt; color: black; font-family: Courier New , Courier, Monospace; background-color: #ffffff; /white-space: pre;/}.csharpcode pre { margin: 0px; }.rem { color: #008000; }.kwrd { color: #0000ff; }.str { color: #006080; }.op { color: #0000c0; }.preproc { color: #cc6633; }.asp { background-color: #ffff00; }.html { color: #800000; }.attr { color: #ff0000; }.alt { background-color: #f4f4f4; width: 100%; margin: 0px;}.lnum { color: #606060; }

     1: using System;



     2: using System.Reflection;



     3: using System.Security.Permissions;



     4: using System.Threading;



     5: &nbsp_place_holder;



     6: namespace NUnitHelpers



     7: {



     8:     public class CrossThreadTestRunner



     9:     {



    10:         private ThreadStart userDelegate;



    11:         private Exception lastException;



    12: &nbsp_place_holder;



    13:         public CrossThreadTestRunner(ThreadStart userDelegate)



    14:         {



    15:             this.userDelegate = userDelegate;



    16:         }



    17: &nbsp_place_holder;



    18:         public void Run()



    19:         {



    20:             Thread t = new Thread(new ThreadStart(this.MultiThreadedWorker));



    21: &nbsp_place_holder;



    22:             t.Start();



    23:             t.Join();



    24: &nbsp_place_holder;



    25:             if (lastException != null)



    26:                 ThrowExceptionPreservingStack(lastException);



    27:         }



    28: &nbsp_place_holder;



    29:         [ReflectionPermission(SecurityAction.Demand)]



    30:         private void ThrowExceptionPreservingStack(Exception exception)



    31:         {



    32:             FieldInfo remoteStackTraceString = typeof (Exception).GetField("_remoteStackTraceString", 



    33:                 BindingFlags.Instance | BindingFlags.NonPublic);



    34:             remoteStackTraceString.SetValue(exception, exception.StackTrace + Environment.NewLine);



    35:             throw exception;



    36:         }



    37: &nbsp_place_holder;



    38:         private void MultiThreadedWorker()



    39:         {



    40:             try



    41:             {



    42:                 userDelegate.Invoke();



    43:             }



    44:             catch (Exception e)



    45:             {



    46:                 lastException = e;



    47:             }



    48:         }



    49:     }



    50: }

Geek Notes 2004-11-02

It is Election Day! Will we actually know who our president is tomorrow? Will we know who has a majority in the House and Senate? Somehow I doubt it.

Hopefully you all went out and voted by now. If not, please do. If you are one of those people who thinks that voting is a waste of time, then please go vote for me (I’m Canadian and can’t vote).

  • Living Brain in a Jar - Well… not really. But it is an interesting idea. [via BoingBoing]
  • Has Blogging Gone Too Far - This one made me laugh out loud.
  • Segway Centaur - From the guys who brought you the over-prices walking machine, now you can have an overpriced quad-cycle/walking/thingy. The video is cool though. [via iamwill]
  • NClassifier - Want Bayesian (or some other) text classification for your .NET app? Look no further. (I can’t find a license file though… so if you are license-concerned, ask the project maintainer first.) [via The Daily Grind 486]
  • Cat Tossing in Zero-G - Man oh man… another hilarious tidbit. There is a little ten-year old boy deep down inside of me that thinks this is the funniest thing in the world.
  • Hypo-Allergenic Cats - Speaking of cats, Allerca is taking pre-orders for genetically modified cats that may help those who are allergic but want to own a cat. I wonder how many people actually fall into that category? NewScientist.com doesn’t think it will work however, so you may want to carefully consider before you fork over your dough. [via BoingBoing]

Non-Admin Development in VS.NET 2003

Because all of you are good developers who don’t run as administrator anymore, I’m sure that you have all read most of these articles before. But so that I have them documented here, I wanted to list the things I found useful when I made the switch.

It really isn’t that hard. You should be doing it.

As a side note, I do all of my development in a Virtual PC environment. While that doesn’t make it any easier per se, it does mean that on my development machine I’m rarely troubled with strange desktop applications that don’t work. (Those problems are relegated to my host OS… where I also run non-admin.)

Here is the list of the ones I found the most useful.

MakeMeAdmin - If you are running on a corporate domain, you really need this tool by Aaron Margosis.&nbsp_place_holder;If you are running XP on a workgroup, read this post instead. If fact, go read all of of Aaron’s non-admin post categories: Non-Admin and Non-Admin for Home Users.

PrivBar - Once you’ve made the switch, you really should be running PrivBar to help you know which explorer (and IE) windows you have open as admin. I was very happy to see this running on a number of presenter’s machines at Win-Dev last week.

Running VS.NET as non-Admin - This MSDN article is a must read; in particular the part about debugging ASP.NET applications. (And that bit about messing with the machine.config file has convinced me to repave using Server 2003 ASAP.)

TestDriven.NET - The most recent builds (RC6 and later I think) of TestDriven.NET (formerly known as NUnitAddin) support running as non-admin.

How to Secure Your Developer Workstation - Another must read from MSDN.

Running As Non-Admin - Brad Wilson (aka The .NET Guy) has an article that lists applications that work and don’t work when running non-admin.

Arrived at Win-Dev

It took too long (flew through Phoenix) but I’m finally here at Win-Dev in Boston.

I landed just as the 6th inning was finishing and got to the hotel just in time to have a couple of Guinness while watching the last two innings. Congrats to the Bo-Sox, but I know Brian and Jim are very disappointed. Haven’t seen anyone I know yet, but I’m sure I will. (Keith is here somewhere.)&nbsp_place_holder;If you see me, please grab me and say hi.

Tomorrow (Thursday) I give my first talk during the last C#/CLR track: Refactoring Support in the Whidbey IDE. Friday I do Effective Unit Testing with NUnit in the same timeslot. That is the last session of the track, so hopefully there will still be a few people around to participate.

I’m really looking forward to this as it is my first “real” conference speaking gig. I’ve spoken a fair amount at local events in Colorado (MS DevDays and others), but this is the first time I’ve ever been paid as a speaker!! Gotta love that. Many thanks to Keith Brown and Mike Woodring for getting me involved.

Geek Notes 2004-10-26

Since my new laptop hasn’t arrived, it looks like I’m going to have to head to Boston tomorrow with a borrowed system: a Toshiba Portege 3500 TabletPC. Unfortunately it doesn't have USB 2.0, so I’m gonna have to buy one to run my VPC images.

UPDATE: My good friend and former boss Joe Shirey IMed me to tell me that the USB on the Portege is USB 2.0. So I tried it and it is. Now I can return that CardBus adapter. Thanks Joe!

Win-Dev This Week

Win-Dev is this week, and as a reminder to my regular readers, I will be giving two talks in the CLR/C# track:

  • Refactoring Support in the Whidbey IDE (Thursday 3:30pm-5:00pm)
  • Effective Unit Testing in C# (Friday 3:30pm-5:00pm)

If you’re going to be in Boston for this, drop by and say hello. I don’t arrive until Wednesday evening, though, so if you’re there already have fun!

DirecTV TiVo + Lingo VoiP == Not Good

We decided, after much negotiating between me and my wife, to put a second TV in our bedroom. Since we are a DirecTV TiVo family downstairs, we decided that we would do the same upstairs.

This afternoon the installer showed up and got us all hooked up.

Or so we thought.

It turns out that DirecTV TiVo can’t dial out over my Lingo VoiP line. I did a bunch of research and discovered all kinds of secret TiVo codes (“,#019” and all that) that were supposed to help, but they didn’t. I also tried a USB ethernet adapter, but apparently my TiVo software is not new enough.

The good thing is that I know from experience with my other reciever that I don’t actually need the phone connection once I get it all setup. All of the guide information comes from the satellite (unlike a traditional TiVo where it get it over the phone every other night or so).

So now I just need to find a friendly co-worker who has a landline to let me come over and plug my TiVo into their phone jack. Once it finishes its setup and activation, I’m good to go.