Making Tivo Server Run as a Service

3
Filed under Tivo

I love Tivo. If you have a cable company DVR, my heart goes out to you. My 4 year old daughter can operate our Tivo to watch her favorite show. And she can easily pause the action to take those all important potty breaks! That’s not to say she watches a lot of TV, but hey, Mr. Roger’s rocks!

I don’t even mind the 13$ a month for the service (although now, I SOOOO wish I’d taken the blue pill gone with that lifetime subscription.

But one thing that has annoyed me since I first got the thing networked is the fact that the dang server software has to be run from a logged-in user account. Tivo sets up its “Beacon” service as a legitimate Windows Service, but there are three other programs that get run via the RUN key in HKCU, and, of course, those only get fired off after a user logs in.

Since my Tivo server software is actually running on a server, it’s a tad annoying to actually HAVE to login just to get the Tivo stuff running.

It hasn’t been a huge pain, but I finally got some time to experiment, and I’m happy to report, there does appear to be a solution.

The Goal

I should reiterate that the goal of all this is to get things set up such that powering up the “server” machine is enough to get the Tivo Server running and able to communicate with the Tivo. If you want to actually use the Tivo Desktop from the PC, then you’ll still have to login.

The Disclaimer

Before you start, be warned that mucking with your registry and with services can be dicey, especially when your setting up programs to run as services that weren’t originally intended for that purpose.

However, in reality, there’s really no need to directly fiddle with the registry using this technique. And converting an app to a service can be done for free, or done much more easily for the reasonably low cost of a simple utility.

What’s needed

  • A Tivo, and it really has to be networked for there to be much of a point in all this.
  • A “server” PC that is already running the Tivo Desktop and Server software. You absolutely MUST already have the Tivo software running and verify that it can connect to your Tivo, download shows, share music etc before even attempting any of this process.
  • A way to convert a standard app into a Windows Service. I use FireDaemon for this, simply because I already bought it for other purposes, and it’s a bargain at 40$, but there are free alternatives out there. One in particular is SRVANY.EXE. A good article about that approach is here, but just google for more.

First things First

As mentioned above, make sure that your Tivo Desktop software is already installed, running and can connect to your Tivo and at least download the list of recording available.

image

You’ll also want to share at least one MP3 track or one photo, so you can see them from the Tivo box. Using Tivo Desktop, setup music or photo sharing here:

image

You do this so that, once everything’s reset and running as a service, you can easily check, from the Tivo, whether it can still see your PC and the Tivo Server running on it.

Stopping the autoRun of the Tivo Background Apps

Technically, this step isn’t really necessary, but I’ll detail it anyway, for those interested parties out there.

As I said earlier, the Tivo Beacon is already configured as a service, so we don’t have to do anything to it.

However, a quick glance through the registry will reveal these keys:

image

To be technically correct, you should probably remove these keys from the registry (backing them up first!). Actually, you wouldn’t really want to remove the TivoNotify entry, since it really should be run when a user logs in. But the TivoTransfer and TivoServer entries could be removed.

However, from experiments I’ve done, it doesn’t seem hurt to leave them in place. If these programs are started as services, then running them again when you actually do login doesn’t appear to have any effect.

Setting Up the Tivo Transfer app as a Service

Open FireDaemon and select Services – New to create a new service definition. This one will be for the Tivo Transfer Service.

You’ll get the Edit Service Definition Dialog as below. Fill it in appropriately. Typically, if you perform a standard Tivo Desktop install, these paths will be the same for you.

image

Pay particular attention to the Executable name and the Parameters.

On the Setting page, make sure the Logon Account is set to a user with appropriate permissions and that you will normally logon to the machine as (usually, it’s the user under which you installed and setup the Tivo Desktop).

Also, make sure the Startup Mode is Automatic and disable program exit monitoring.

image

And finally, on the Dependencies Page, add a dependency to the “Tivo Beacon” service. Mine just happens to be named “Tivo Beacon2”. This guarantees that the Windows Service Manager won’t start this service until after the Tivo Beacon is running.

image

Setting Up the Tivo Server app as a Service

Create another Service Definition in FireDaemon.

image

Make sure the logon account, Startup Mode and program exit monitoring are set as in the Tivo Transfer Service above.

And finally, set the dependencies as above, but in this case, include both the TivoBeacon and the Tivo Transfer service (that you just created).

What About That Tivo Notify App?

Good question. It handles the little system tray icon, and as such, doesn’t need to be started as a service.

Restart

At this point, you should have created 2 services, one for the Transfer app, one for the Server app.

Use the TaskManager to kill off the two processes (TivoServer.exe and TivoTransfer.exe) if they’re running.

Then, use FireDaemon or the Windows Service Control panel to start the two services you just created. If everything went right, you should see them running in the Task Manager.

image

Restart your machine and DO NOT LOGIN.

The Wrap Up

Once your PC has restarted, use your Tivo to check that it can see your shared Music or Photos (from the Now Playing screen, select Music, Photos and More, and scroll down to find your PC’s shared music in the list (in my case, My Tivo Server runs as the Administrator and my server’s name is Olympus).

 image

If your Tivo can see those, and can browse through your music or photos, you know that the Tivo Server and Transfer services started properly without you actually logging into your PC, which is the whole point of this twisted exercise!

If not, go back and check to verify that everything is setup as above and that there are no errors logged in the Application Event Log.

Things to Watch Out For

From what I can tell, the Transfer Process, and to a lesser extent, the Server process, do some peculiar things when they start up (I believe they actually start up a second instance, then terminate the initially loaded instance).

Because of this, FireDaemon’s “Process Exit Monitoring” function really made a mess of things. Basically, the idea is that FireDaemon can monitor the process that it starts as a service. If that process terminate for some reason, FireDaemon can automatically restart it.

Under normal circumstances, this is a good thing because you’d want to service to be constantly available. This won’t work with the Tivo processes though. That’s why I disable this feature when setting these services up (see above).

It might be possible instead to increase the load delay or otherwise tweak FireDaemon’s settings, but I haven’t tried that yet.

I do know that if you don’t do something, though, the Tivo processes will just enter an endless cycle of starting, stopping, and FireDaemon restarting them, only for them to stop again, ad nauseam.

And yeah, my TV’s a 36″ tube set, hence the old school sexy curves in the Tivo screen shots<G>

Fire and Brimstone! Office 2000, XP, 2003 and 2007 living together!

0
Filed under Uncategorized

This is truly old testament stuff…. Ok, enough with the Ghostbusters….

If you’ve ever had to support multiple Office environments, you’ve probably already discovered the sheer joy and wonderment that is VMWare.

But, if you have to develop against them, sometimes, it’s awfully nice to have the Office version you need right there on your main box.

It’s not terribly common knowledge, but you can actually install various versions of Office side by side (with the sole exception of Outlook, which only tolerates a single version on a machine, for dark and unholy reasons).

However, if you’ve tried, you’ve most likely snagged yourself on a rather irritating burr.

You start Word 2000, say, and you get an MSI (Windows Installer) prompt saying it’s got to repair something. You click OK, and let it do it’s thing. But then, later, when you start Word 2007, you get a similar prompt, this time for the newer version. Back in Word 2000, same prompt again. Grrr.

There’s a few KB articles out there about this annoyance, but nothing that really resolves it completely satisfactorily.

After some experimenting, however, it looks like it is possible to make various Office versions coexist more or less peacefully, without bashing each other over the head with a virtual tire iron every time one or the other fires up.

The key is registration, esp with Word. Each time it starts, Word checks certain registry entries to make sure they point to that version of Word. If not, you get that “repairing” prompt and the long delay while Word resets everything.

This is great for Joe User who accidentally scrambled his registry and just needs Word to work right again, but it sucks for Pauline Power User who has 3 versions of Office on her machine, and switches back and forth between them constantly.

The trick is to prevent Word from reregistering itself when it starts.

Details of how to do just that are in one KB article on the Microsoft site, but they only go so far as to detail how to do this for Word 2007.

The problem is, what if you want DOC files to normally open with Word 2007, but still have Word 2000 on the “Open With” list via the right click menu? I’d imagine this is a pretty typical scenario.

Take the following REG script, save it to a REG file, and dbl click it to merge it into your registry (it shouldn’t require any special privileges because it only deals with the user hive).

Basically, creating the NoReReg value for each version of Word will prevent the reregistration from happening when you start Word.

Windows Registry Editor Version 5.00

;This will keep Word 2007 from reregistering itself each time you run it
[HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Word\Options]
"NoReReg"=dword:00000001

;The same trick works for Word 2000
[HKEY_CURRENT_USER\Software\Microsoft\Office\9.0\Word\Options]
"NoReReg"=dword:00000001

;for Word xp
[HKEY_CURRENT_USER\Software\Microsoft\Office\10.0\Word\Options]
"NoReReg"=dword:00000001

;and for Word 2003
[HKEY_CURRENT_USER\Software\Microsoft\Office\11.0\Word\Options]
"NoReReg"=dword:00000001

Be sure to have run the version of Word you want to use actively as the LAST THING YOU DO before running this script; ie, if you really want Word 2000 to be the default editor for DOC files, run it, let it register itself fully, and THEN run this script.

Of course, setting the NoRegReg value back to 0 (via REGEDIT) will revert things back to the way they were and allow that specific version of Word to reregister itself.

Furthermore, the newer versions of Word support a “repair” option on the HELP menu that will perform the reregistration as well.

One note; the Word 2000 and 2007 versions I’ve tested explicitly. The XP and 2003 versions I haven’t checked explicitly yet, so YMMV. However, I was utterly surprised that this trick (which was documented for 2007), actually worked with Word 2000.

And finally, neither Excel nor Powerpoint appear to need any of these shenanigans, hence their MIA status in the above script.

Properly reading the EDITTIME structure in an OLE Structured Storage file (ie just about any Office Document)

0
Filed under Uncategorized

There’s lots of articles out there about reading the properties of an OLE Structured Storage file (which is the format used for all Office apps before 2007 and with continued support in Office 2007).

Eduardo Morcillo probably has about the best implementation for VB6 that I’ve come across. Check here for tons of great VB6 code for opening/reading structured storage files, and lots of other very advanced stuff.

.NET likely makes much of this dramatically easier, but I haven’t delved into that yet so I can’t say for sure.

What I do know, however, is that Eduardo’s code doesn’t quite handle a few elements of OLE document properties. One in particular is the EDITTIME property.

EDITTIME normally tracks how long a particular file has been “edited” within a given application, be it Word, Excel, or PowerPoint.

The field itself is stored as a 64bit FILETIME structure, but it’s not actually a FILETIME structure. Instead, the EDITTIME is stored as a direct 64bit number of milliseconds that the document has been edited.

Check out here for all the details, and a good sampling of some C code to convert the EDITTIME element to a number of seconds and back again.

It’s not terribly difficult code, but it’s also virtually undocumented as to the layout of that structure.

I won’t repeat the code here, but I have to give credit to Rolandas Rudomanskis and the Shareaza team for researching the issue and making the code available.

Just kick it

0
Filed under Uncategorized

imageHopefully, this might save someone else from trading in a “dead” machine.

I picked up an AMD based generic box about 6 months ago for my wife. It’s got an ABIT-NF8 mobo, 2 gb ram, and several HD’s, plus a Vista capable graphics card. It worked great for about 3 months till the powersupply went bits up.

So, a trip to Frys, 40$ and all was well, at least for another 3 months.

Then, just a few days ago, it died again. There was definitely power to the motherboard, but the thing wouldn’t power up.

Suspecting the el-cheapo PS I’d picked up, I yanked it and trekked back down to Frys. I’ve got to get one of those PowerSupply tester units (they sell them there but they are perpetually sold out<sigh>).

At any rate, yep, the new PS had gone south too.

Hrmm. So I picked up an decent supply (this time an Antec), come home and wired it all up.

Hit the on button and up she came, for all of about 30 seconds. Grrr…

Lather, rinse, repeat, same thing.

Doesn’t seem like the power supply, but what the heck?

I disconnected everything, all the way down to the fans inside the box, still the same behavior.

But the unit would boot up, it’d just immediately power down. I started suspecting a possible short on the motherboard, but then that’d usually result in an almost instance crowbar.

Without any other ideas, I googled the ABIT NF8 motherboard for any interesting bits.

Lo and behold, I turn up at least three stories of similar behavior.

Basically, with these motherboards, if the CPU fan/heatsink gets jostled just right, it can result in a “bad connection” between the two. The end game is that the MOBO believes the CPU is overheating almost immediately and shuts down to prevent any damage.

Of course the CPU isn’t  overheating but no matter.

I unhitch the heatsink, dab on a little extra thermal grease and reseat it. Power up… Shutdown. Arrrgggghhh!

Ok. Grab the heatsink and shove it down with a good thwack.

image

Power up. Golden. Been running solid for 3 days now.

Sledgehammers aren’t just for railroads anymore.

Getting Consistent Results with Find.Execute in Word

0
Filed under Uncategorized

If you’ve ever written a Word addin, at some point you’ve probably had to use the Find object. It’s quite powerful, allowing you to find (and replace) text based on wildcards, formatting, etc.

However, it can also be an exercise in frustration getting consistent results from Find, especially when “finding” in the same document across several versions of Word (in my case, Word 2000, XP, 2003, and 2007, surely we can ignore ’97 by now<g>).

The problem comes from at least two places that I know of.

The first is that to really execute the find everywhere,  you need to execute it against the range objects of all the storyranges in the document, NOT just the main body.

Fortunately, that’s relatively easy to do:

For each Story in Document.StoryRanges    'Handle the Story here
Next

However, that doesn’t quite get you there. This is because you won’t necessarily enumerate through all the ranges for all the headers and footers in the document if you just use the above loop.

To see the section headers and footers, you have to do something like:

   For Each Section In Document.Sections
      For Each Header In Section.Headers
         'Handle this Header range
      Next
      For Each Footer In Section.Footers
         'Handle this Footer range
      Next
   Next

And finally, simply enumerating through the headers and footers, you may end up with multiple references to the same header/footer. Gah! How? There’s an unobtrusive little Word feature for headers and footers called “Link to Previous”. Here it is lurking in Word 2007.

image

When that’s set, a single header or footer might show up in several different sections, causing you to search the same place twice. Just filter those with the “LinkToPrevious” property set and you’re gold.

The bigger problem is that Word has a way of fouling its internal search state such that when your code executes its find, it simply doesn’t work.

This is a much nastier problem because it’s not consistent. Things will work fine at one point, then fail inexplicably later.

Fortunately, I happened to stumble across an article by MVP Bill Coan that addressed this issue directly. The article is about “Flushing the bad karma from Word’s search“, and how he came up with the solution is nothing short of bayou voodoo, but it’s exactly what I needed to get my search consistent across all Word versions.

Essentially, you perform a dummy search to clear out whatever internal state information Word is holding onto. This allows your real search to execute properly.

The dummy search is simply:

WordDocObject.Content.Find.Execute "^p", MatchWildcards:=False

Even better, it doesn’t appear to negatively impact performance of my search to any perceptible degree.

And finally, even though it looks like this article was written for Word 2000 (and maybe XP), I found that it’s still very much valid for the latest SP releases of 2000, XP, and Word 2003.

The good news is that Word 2007 doesn’t appear to be effected by the bug anymore, but using the dummy search doesn’t have any negative impact here either.

Merry Christmas!

0
Filed under Uncategorized

I rendered a special Apophysis flame just for the occasion.

Sorry it’s shrunken. If you’d like a full render or the flame file, just shoot me an email.

I call it “Snowflakes”

Snowflakes

Have a great holiday and a happy New Year!

When a good application won’t leave (or the brother-in-law app)

0
Filed under Uncategorized

I have an InstallShield-authored MSI installation for an application I work on.

In testing one of the recent interations, I ran into a peculiar problem.

It installed perfectly fine, and after an uninstall, virtually everything was removed properly, except for one particular component.

It didn’t go away.

I turned verbose MSI logging on (see here for details how), and reran the install/uninstall.

For the install, somewhere toward the top of the log, you should see a block that looks like this:

MSI (s) (9C:D8) [16:43:17:376]: Feature: Some Feature; Installed: Absent;   Request: Local;   Action: Local
MSI (s) (9C:D8) [16:43:17:376]: Feature: Some other feature; Installed: Absent;   Request: Local;   Action: Local
MSI (s) (9C:D8) [16:43:17:376]: Component: InstallMSXML6; Installed: Absent;   Request: Null;   Action: Null
MSI (s) (9C:D8) [16:43:17:376]: Component: InstallSQLSMO; Installed: Absent;   Request: Null;   Action: Null

Notice the Installed state is absent and the action is local, meaning that the feature/component doesn’t already exist on the machine and it’s going to be installed locally (the normal installation type).

After an uninstall, the log will contain a similar block, but just reversed:

MSI (s) (9C:B8) [17:00:19:887]: Feature: Some Feature; Installed: Local;   Request: Absent;   Action: Absent
MSI (s) (9C:B8) [17:00:19:887]: Feature: Some Other feature; Installed: Local;   Request: Absent;   Action: Absent
MSI (s) (9C:B8) [17:00:19:887]: Component: InstallMSXML6; Installed: Absent;   Request: Null;   Action: Null
MSI (s) (9C:B8) [17:00:19:887]: Component: InstallSQLSMO; Installed: Absent;   Request: Null;   Action: Null

Note the Installed state of Local but the action is now absent (at least on the two features noted above).

However, my problem component looked like this

MSI (s) (9C:B8) [17:00:19:887]: Component: ProblemComponent; Installed: Local;   Request: Absent;   Action: Null

And what stumped me was, why a null action? The Request was absent, so why wasn’t the action?

I researched the problem a little and got nowhere, then tried tweaking the install several different ways; still no joy.

I finally broke down and put a call into Macrovision. Ended up talking to one of their guys (Thanks, Cary!) and the first thing he asked was, “Search for Disallow” in the log starting at the top and see if there’s anything mentioned.”

Ok. And sure enough, I had several lines like this.

MSI (s) (9C:B8) [17:00:19:626]: Disallowing uninstallation of component: {997FA962-E067-41D1-9396-00A0C90F27F9} since another client exists

After a little GUID spelunking (you can find GUIDs easily in InstallShield by opening the direct editor

image

clicking on the component table and sorting by the component ID)

image

I was able to determine that the problem component, was indeed one of those whose uninstallation was disallowed.

(You might see a number of “Disallowing” lines in your log, often as a result of including Merge modules of standard libraries, like the COM libraries or the VB runtime files, so you have to just ignore them).

So I figured, just search the registry for the GUID in question and remove whatever junk was left over, probably from an aborted install.

No dice. The component information used to track reference counting (which is how MSI knows to “disallow uninstallation since another client exists”) is locked up in a binary registry entry, from what I can tell.

In the end, you’ll generally have two options.

  1. Change the Component GUID. Only do this if you know that component won’t need the same GUID (for upgrading in later releases, for instance).
  2. Pave your test machine or try the install on a different machine.

Not fun, but not too bad.

Application Blocks and Exception Handling

0
Filed under Uncategorized

I have some pretty in-depth experience working with the VB6 exception handling mechanism. I still get an occasional email about my article on Try-Catch exception handling in VB6 in the Sept 2001 Visual Basic Programmer’s journal.

So when I finally got a chance to crack open the Enterprise Application Block and check out the Exception Handling App Block, I was hoping for some pretty nice stuff, or at least something to give me a few ideas.

But what’s there seems pretty underwhelming.

The good news is that most of the stack tracing and related informational-type things that you really had to work very hard at with VB6, are part and parcel to VB.NET. The bad news is that the exception handling application block doesn’t seem to contain much at all to actually make handling exceptions any easier than piling mountains of Try-Catch lines into your source.

Hmm, Try…Catch…Finally, or On Error Goto Handler…Handler: …Resume next

Under the covers, I know they’re very different, but seriously, what I see is just syntactic shuffling.

I’ve always believed that virtually all exception handling in an app should be attributable to individual routines. That’s the way my exception handler for VB6 worked, just without all the syntactic niceties of .NET.

For instance, why shouldn’t I be able to attribute a routine as to how exceptions within it ought to be handled?

<HandleExceptionsByContinuing> _
Public Sub MySub(arg1, arg2, arg3)
    x = 1 / 0
End Sub

In this case, I’ve declared that for this particular method, exceptions ought to be handled by simply continuing execution of the code.

Other cases might raise a specific error, reraise the original error, reraise the original error wrapped in an outer exception, etc. Granted, my example may not be great here.

Most routines are supposed to be so small that having more than one TRY statement would be lame anyway, right? And most of the code I’ve looked at containing Try Catch blocks only contain one in a method anyway.

For those routines where you definitely need to handle specific exception in specific ways, you still have the Try statement to fall back on, but even then, I tend to believe that every exception in an app should be routed through a single handler that can be configured to do certain things, be it emailing the exception, logging it, or (and I’m not recommending this, mind you!) ignoring it altogether.

Littering the workings of your code with boilerplate Try Catch filler strikes me as equally onerous as those comments like:

'Increase the count variable by one
Count = Count + 1

Ugh.

But, just like a well placed comment, when the workings of the code are better explained with inline exception handling, TRY away!

Might be time for my own Enterprise Exception Handling Block…

Steam Punk Laptop

0
Filed under Uncategorized

If you’re not familiar with steampunk, it’s the illegitimate offspring of retro-futurism, a mid-1800’s Sears catalog, The Jetsons, and This Old House.

That god awful Will Smith movie, Wild Wild West, is probably the most, er, public, of examples. Kenneth Branagh surely should have known better.

image

image

But a guy calling himself Datamancer has to have created one of the nicest examples I’ve ever seen, the steampunk laptop, complete with winding key for an off/off switch, brass lions claw feet, and a watch-gears guts under a hardwood framed glass viewing window. According to the site, the thing actually works.

This is just one picture, and it doesn’t really do it justice. Check out his site for lots more, plus some unbelievable steampunk keyboards he sells.