Got FIOS everything (TV, internet, phone) installed at the new place on Friday. I've had some friends do "custom" installs, so I figured it wouldn't be a problem. The Verizon pre-install guy called me a week before, and asked if I had any special requests for the location of the box. I really want my ONT in the furnace room in my basement- it's the best place for central wiring, and doesn't require stapling a bunch of crap to the outside of the house. Unfortunately, the furnace room is basically under the garage, and the fiber was on the wrong side of the driveway to get there. I didn't really want them tunneling under the driveway, nor did I want the fiber entry on the front of the house. So, I had the fiber crew leave about 60' of extra fiber on the side of the house to accomodate my special placement (which they did- great!). Then I'd just need to bust a few small holes in the basement ceiling to help get the fiber fished over to the soon-to-be network closet.
Fast-forward to Friday morning- installer dude shows up and is kinda grumbly ("What the hell did they leave all this extra fiber for? That's not gonna fit in my box!"). Side note- he was also a Verizon contractor. All my other friends that have gotten FIOS have had genuine Verizon installers. Cue "uneasy feeling in pit of stomach". I told him this would probably be the easiest job he'd done in awhile- all we had to do was fish the fiber, hook up and test the ONT, and we're done. I would handle all interior wiring from there. His response: "I'm not allowed to fish, and I have to hook up to the existing wiring and test all the outlets. Besides, you'd probably break the fiber trying to fish it through there." Further sinking feeling ensues- all the other service demarcs are on the other end of the house by the garage. That means a lot of cables stapled to the side of the house- NOOO!
Luckily, he couldn't find a suitable place to stick the ONT and power connections anyway (the garage is best, but the fiber's not handy there), so he started to warm to my ideas. Next, he said he'd have to run all the fiber through conduit, and that I'd have to bust up the entire 50' section of ceiling from the side of the house to the furnace room. Uhh, not happening. Couple more minutes of arguing, and I get him to concede that it doesn't need to be in conduit if it's in the ceiling. So I started busting little holes, and we started stringing fiber with some Fish Stix that he had in his truck. Side note #2: if you're not allowed to fish fiber, why do you have Fish Stix?
Once we started getting the fiber running in the right direction, installer dude's attitude improved dramatically. We started chatting more casually, and had some high-fives when the fiber hit it's destination. He had the ONT on the wall in a matter of minutes, and all was looking good until ... "I think we broke it". Aww, crap.
Apparently fiber installers have something similar to the tone generator used by wired network installers to locate a particular node. It's basically just a light they attach to the end of the fiber, then go look for the light over at the hub. If there's no light, there's a break in the fiber somewhere, and a splice has to be made by a Verizon tech before the break (which would likely be in my ceiling somewhere, since it worked before going in). Not good, since we're doing a forbidden install here- don't want the installer to get in trouble, and also don't want crap on the side of my house!
Installer dude came back and said, "It's broken- tear it all out". Double crap. Then, "Just kidding- they gave me the wrong port number at the hub. It's all working fine". Yes! He had everything hooked up and working in a few minutes.
I was told at order time that there were no HD DVRs available, and would have to live a few months with SD DVR service (all the while polling customer service for boxes- there was no "I want HD, call me when available" procedure). Installer dude just happened to have an HD DVR box on the truck. Did I want it? Heh. Is a bear Catholic? This dude's getting a good tip.
So, everything's installed exactly as I want, and bonus, I got HD DVR service months before I expected it. I haven't spent much time playing with it (and what little I have was on a 20" TV- I haven't moved the beast over yet), but the FIOS TV UI kicks the ever-loving crap out Comcast's. It's cool to see, because FIOS TV uses pretty much exactly the same hardware as the Comcast DVR boxes- that really mean's there's no excuse for Comcast's lame ad-ridden UI beyond corporate greed. Time to get back on the ball Comcast- Verizon's gonna eat your lunch with FIOS TV just like you ate theirs when cable modem squashed DSL.
Ahh, fiber-y goodness. Can't wait to enjoy it on a daily basis- we'll see how much I miss running my own webserver. Cheers, installer guy Steve- enjoy the tip, and cut the next guy some slack when he's got a plan.
Sunday, March 2, 2008
Personal update
Well, my Bell's Palsy took several weeks to subside, but it finally did. One day I noticed that I could flare both nostrils again (very important, for someone who makes as many faces as I do). Right up there with being able to make symmetric faces- I can make non-pathetic razberry noises, which means I can play again!
Work progresses well on the home fronts (both of them). We're ticking projects off the list left and right at the old place- probably within a couple of weeks of being ready to put it on the market. It's looking GOOD- why didn't I do this stuff years ago??? Meanwhile, we closed on the new house and took possession on 2/29. FIOS TV/internet/phone was immediately installed, and we're hatching plans to de-popcorn ceilings, rip down paneling and strategically place our sparse furniture into this monster of a house. Stories and pictures to follow, I'm sure.
Work progresses well on the home fronts (both of them). We're ticking projects off the list left and right at the old place- probably within a couple of weeks of being ready to put it on the market. It's looking GOOD- why didn't I do this stuff years ago??? Meanwhile, we closed on the new house and took possession on 2/29. FIOS TV/internet/phone was immediately installed, and we're hatching plans to de-popcorn ceilings, rip down paneling and strategically place our sparse furniture into this monster of a house. Stories and pictures to follow, I'm sure.
Windows services as console apps
During my PADNUG talk, I mentioned that we do self-hosted WCF services, and that our service host can be run either as a console app or a Windows Service. Since then, I've had several questions about how that works.
I've been using this pattern since .NET 1.0- it makes debugging service startup failures in production a snap, since you can just stop the Windows service and run it as a console app. When we're developing, we run in console mode almost exclusively.
I'll write a description of the process- if I get time (ha!) I'll try to post a basic sample.
The most important thing that many people don't understand is that there is no magical voodoo behind Windows services; they're just console apps that use RPC APIs and callbacks to talk/listen to the global service control manager. The ServiceBase class wraps up those API calls and callbacks into a nice little base class where you can wire up event handlers for start/stop/whatever, but there's no special behavior provided by the runtime or the OS for running in a service. This means that your Main method can behave just like any normal console app.
The trick to making this work is to dissociate your startup and shutdown behavior into methods that don't care whether you're running in service or console mode. Then you just add a "/console" command line parser to the beginning of Main. If someone passed /console to you on the command-line, you skip all the ServiceBase.Run stuff, call your startup methods directly, and do the "Press any key to exit" behavior. If you don't see /console, call ServiceBase.Run and pass an instance of your service class. The service class' OnStart event handler should call your startup methods. The service installer behaves exactly the same, so what gets generated is fine. As an aside- you could go the other way (require "/service" to run as a service), but command-line args aren't a first-class entity for the managed Windows service installer, so you'd have to hack the registry afterward to stuff the command-line args into the image path. Much easier to go the other way, IMHO, but whatever.
To debug in VS, just go to the "Debug" tab in your project properties and add "/console" to your command-line args- you should be off to the races.
I've taken this pattern much further on various projects. We currently use a generic WCF ServiceHost "host" (oy, overloaded terms galore!) that implements this pattern and knows how to load multiple WCF ServiceHosts based on the "service" entries in an app.config's system.serviceModel section. All of our different service setups on different machines use this same generic "host" binary- what WCF service impls get loaded depends on the services defined in the WCF config section. If we have one service entry, one ServiceHost- if we have ten, ten ServiceHosts.
A couple of other little tips:
- Long-running service startup/shutdown is generally a Bad Thing- the SCM will give up on you if you take more than 30s to respond to a startup/shutdown request. This isn't fatal, but it makes for a bad administrative experience. In the past, I'd end up doing long-running stuff on another thread to avoid that. That's equally sucky if you have a fatal error during startup, though, since you can't report the error through the Services panel- the service process appears to start successfully, then silently dies. However, .NET 2.0 added the ability to request more time from the SCM (ServiceBase.RequestAdditionalTime)- makes it much nicer on both fronts.
- Tag your service and installer class definitions with [System.ComponentModel.DesignerCategory("Code")] to disable design view on double-click in the solution explorer. I find Design View pretty much useless with Windows services- it's maddening to remember to right-click->View Code when opening. This tip works for any other code with designer support as well (including Service Installers, where designer mode is nearly as useless). You have to leave the attribute fully qualified, or it won't work- that parser's apparently built for speed, not intelligence.
Hope this helps. Don't hold your breath for sample code, but if I get enough requests, I might whip something up.
I've been using this pattern since .NET 1.0- it makes debugging service startup failures in production a snap, since you can just stop the Windows service and run it as a console app. When we're developing, we run in console mode almost exclusively.
I'll write a description of the process- if I get time (ha!) I'll try to post a basic sample.
The most important thing that many people don't understand is that there is no magical voodoo behind Windows services; they're just console apps that use RPC APIs and callbacks to talk/listen to the global service control manager. The ServiceBase class wraps up those API calls and callbacks into a nice little base class where you can wire up event handlers for start/stop/whatever, but there's no special behavior provided by the runtime or the OS for running in a service. This means that your Main method can behave just like any normal console app.
The trick to making this work is to dissociate your startup and shutdown behavior into methods that don't care whether you're running in service or console mode. Then you just add a "/console" command line parser to the beginning of Main. If someone passed /console to you on the command-line, you skip all the ServiceBase.Run stuff, call your startup methods directly, and do the "Press any key to exit" behavior. If you don't see /console, call ServiceBase.Run and pass an instance of your service class. The service class' OnStart event handler should call your startup methods. The service installer behaves exactly the same, so what gets generated is fine. As an aside- you could go the other way (require "/service" to run as a service), but command-line args aren't a first-class entity for the managed Windows service installer, so you'd have to hack the registry afterward to stuff the command-line args into the image path. Much easier to go the other way, IMHO, but whatever.
To debug in VS, just go to the "Debug" tab in your project properties and add "/console" to your command-line args- you should be off to the races.
I've taken this pattern much further on various projects. We currently use a generic WCF ServiceHost "host" (oy, overloaded terms galore!) that implements this pattern and knows how to load multiple WCF ServiceHosts based on the "service" entries in an app.config's system.serviceModel section. All of our different service setups on different machines use this same generic "host" binary- what WCF service impls get loaded depends on the services defined in the WCF config section. If we have one service entry, one ServiceHost- if we have ten, ten ServiceHosts.
A couple of other little tips:
- Long-running service startup/shutdown is generally a Bad Thing- the SCM will give up on you if you take more than 30s to respond to a startup/shutdown request. This isn't fatal, but it makes for a bad administrative experience. In the past, I'd end up doing long-running stuff on another thread to avoid that. That's equally sucky if you have a fatal error during startup, though, since you can't report the error through the Services panel- the service process appears to start successfully, then silently dies. However, .NET 2.0 added the ability to request more time from the SCM (ServiceBase.RequestAdditionalTime)- makes it much nicer on both fronts.
- Tag your service and installer class definitions with [System.ComponentModel.DesignerCategory("Code")] to disable design view on double-click in the solution explorer. I find Design View pretty much useless with Windows services- it's maddening to remember to right-click->View Code when opening. This tip works for any other code with designer support as well (including Service Installers, where designer mode is nearly as useless). You have to leave the attribute fully qualified, or it won't work- that parser's apparently built for speed, not intelligence.
Hope this helps. Don't hold your breath for sample code, but if I get enough requests, I might whip something up.
Subscribe to:
Posts (Atom)