Cleaing Out the Attic: Dsofile.exe

I know that there are a lot of people who are afraid that Microsoft is going to take over the world (an issue we sort of talked about awhile back). Listen, trust me on this: it’s not gonna happen. Now, do I say this because I have some inside information, did I sit in on a meeting where we decided to drop our plans for world domination? No; I think it’s safe to say that if we ever did have such a meeting, I wouldn’t be invited. However, I do know that the amount of paperwork that we’d have to fill out and the number of planning meetings we’d have to attend prior to taking over the world would take up so much of our time that we’d never actually get around to conquest and domination. There’s no need to lock your doors and windows; Microsoft will not be invading your homes any time soon. (Which is too bad; I think I’d make a great King of Belgium.)

The truth is, we’re not so much an evil empire as we are a typical corporate bureaucracy. I’m always surprised when we release a new piece of software, because I’m used to thinking of us as a policy and procedures development company rather than a software development company. (In case you’re wondering, no, I don’t deal with structure very well.) Despite that, I suppose that when it comes to silly rules and regulations we’re no different than most companies; in fact, stories I’ve heard from friends and relatives suggest we might even be better than most. If nothing else, at least we can dress any way we want.

True story: When I started working at Microsoft a few summers ago, the first person I had to meet with was a guy wearing really short shorts, a Hawaiian shirt, black dress shoes, and long black socks. It was a bit unsettling; he looked so dorky that I couldn’t have been more uncomfortable had he been sitting there naked. (No, check that: in that case, I likely would have been a bit more uncomfortable.) Prior to that I had always thought, “Cool; if I get a job at Microsoft, I can wear shorts to work.” After seeing that guy, I decided I didn’t want to take a chance of looking like him, and I have never worn shorts to work.

This same guy also had a cell phone, and any time we had a meeting he’d always make a great show of getting the phone out and making a call before we could get the meeting started. And he’d always start the conversation by saying something like, “Yeah, I’m on my cell right now.” Always.

Needless to say, the world is in no danger.

Anyway, one of the policies we used to have was one involving the Scripting Guys. Based on something (and I don’t know what: a decision handed down by the Supreme Court in 1842; cave paintings found in Lascaux, France; an interpretation of a Nostradamus prediction), it was decided that we Scripting Guys could only deal with things found in the base operating system. Now, what exactly did that mean? Well, I’m not convinced that anyone really knew, but it did preclude us from talking about how to script Exchange, from talking about how to script Office, even from talking about how to script DNS Server. Admittedly, at first that didn’t matter much; after all, we had an awful lot of ground to cover, and we had no intention of starting with Exchange scripting anyway. A weird policy, but we had plenty of stuff within the base operating system to contend with so it was no big deal.

Of course, that doesn’t mean that this restriction didn’t prove to be an irritant at times. For example, we wrote some scripts that showed people how to retrieve summary information from files. (Summary information is all the junk you get when you right-click a file, choose Properties, and then choose Summary. Things like Title, Category, Keywords, etc.) Those were useful scripts, but they led to an obvious question: hey, if you can write a script that reads these property values, does that mean you can write a script that configures these property values?

Well, no, at least not with the base operating system. Now, you can go to the Microsoft Download Center and download a file called Dsofile.exe. When you run this executable it installs and registers a .dll that does indeed let you configure summary information values. But even though it was a .dll released by Microsoft, and even though it was available only from the Microsoft Web site, we still weren’t allowed to talk about it: it wasn’t a base operating system component. (Interestingly enough, we weren’t allowed to talk about Resource Kit tools either, even though at that time we were part of the Resource Kit.)

Fortunately, things are different now. (Or maybe not, maybe we can get away with more simply because no one ever pays any attention to us.) Now we’re able to branch out a bit, and we’ve slowly begun to touch on other areas of scripting. (For example, one of these days we’ll have hundreds of IIS scripts in the Script Center.) And so, before our policies change yet again, I’d thought I’d get out this information about Dsofile, information which has been sitting on my hard disk for over two years. (Hey, you blow the dust off it and shine it up a bit and no one will ever know how old it is.)

After you download Dsofile.exe, double-click the icon and run the setup program. When setup is done, you’ll be able to both read and write summary information. For example, here’s a script that returns summary information from a Word document. Note that we simply create an instance of the DSOleFile.PropertyReader object. We then call the GetDocumentProperties method, passing it the name of the file we want to obtain summary information from. The rest is just basic report-the-property-values code:

Set objPropertyReader = CreateObject("DSOleFile.PropertyReader")

Set objDocument = objPropertyReader.GetDocumentProperties _

    ("C:\Scripts\Test.doc")

Wscript.Echo "App name: " & objDocument.AppName

Wscript.Echo "Author: " & objDocument.Author

Wscript.Echo "Byte count: " & objDocument.ByteCount

Wscript.Echo "Category: " & objDocument.Category

Wscript.Echo "Character count: " & objDocument.CharacterCount

Wscript.Echo "Character count with spaces: " & objDocument.CharacterCountWithSpaces

Wscript.Echo "CLSID: " & objDocument.CLSID

Wscript.Echo "Comments: " & objDocument.Comments

Wscript.Echo "Company: " & objDocument.Company

Set colCustomProperties = objDocument.CustomProperties

For Each strProperty in colCustomProperties

    Wscript.Echo vbTab & strProperty.Name & ": " & strProperty.Value

Next

Wscript.Echo "Date created: " & objDocument.DateCreated

Wscript.Echo "Date last printed: " & objDocument.DateLastPrinted

Wscript.Echo "Date last saved: " & objDocument.DateLastSaved

Wscript.Echo "Has macros: " & objDocument.HasMacros

Wscript.Echo "Hidden slides: " & objDocument.HiddenSlides

Wscript.Echo "Icon: " & objDocument.Icon

Wscript.Echo "Is read only: " & objDocument.IsReadOnly

Wscript.Echo "Keywords" & objDocument.Keywords

Wscript.Echo "Last edited by: " & objDocument.LastEditedBy

Wscript.Echo "Line count: " & objDocument.LineCount

Wscript.Echo "Location: " & objDocument.Location

Wscript.Echo "Manager: " & objDocument.Manager

Wscript.Echo "Multimedia clips: " & objDocument.MultimediaClips

Wscript.Echo "Name: " & objDocument.Name

Wscript.Echo "Page count: " & objDocument.PageCount

Wscript.Echo "Paragraph count: " & objDocument.ParagraphCount

Wscript.Echo "Presentation format: " & objDocument.PresentationFormat

Wscript.Echo "Presentation notes: " & objDocument.PresentationNotes

Wscript.Echo "ProgID: " & objDocument.ProgID

Wscript.Echo "Revision number: " & objDocument.RevisionNumber

Wscript.Echo "Slide count: " & objDocument.SlideCount

Wscript.Echo "Subject: " & objDocument.Subject

Wscript.Echo "Template: " & objDocument.Template

Wscript.Echo "Thumbnail: " & objDocument.Thumbnail

Wscript.Echo "Title: " & objDocument.Title

Wscript.Echo "Version: " & objDocument.Version

Wscript.Echo "Word count: " & objDocument.WordCount

Pretty slick, huh? The nice thing, too, is that this is a very smart COM object. For example, if you look at the various summary information properties this baby can return, you’ll see that it’s really geared towards Office-type documents (e.g., SlideCount, which tells you the number of slides in a presentation). What’s cool, though, is that you can pass GetDocumentProperties any file name; it doesn’t have to be a fancy-schmancy Word document. Suppose you pass the name of a text file. At first you might panic: “Oh, my gosh; text files don’t have a SlideCount! My whole script is doomed!” Relax; GetDocumentProperties simply returns the property values it can find, and ignores any (like SlideCount) that it can’t find. And all without any error-handling code. (Try it; you’ll see.)

Even cooler is the fact that you can also use the DSOleFile.PropertyReader object to set the following property values (the other properties are all read-only):

  • Author
  • Category
  • Comments
  • Company
  • Keywords
  • LastEditedBy
  • Manager
  • Subject
  • Title

For example, here’s a script that sets the Category property to Scripting Documents:

Set objPropertyReader = CreateObject("DSOleFile.PropertyReader")

Set objDocument = objPropertyReader.GetDocumentProperties _

    ("C:\Scripts\Test.doc")

objDocument.Category = "Scripting Documents"

But what if you don’t like the properties built into DSOleFile.PropertyReader? Well, for file types that accept custom properties, just create your own:

Set objPropertyReader = CreateObject("DSOleFile.PropertyReader")

Set objDocument = objPropertyReader.GetDocumentProperties _

    ("C:\Scripts\Test.doc")

Set colCustomProperties = objDocument.CustomProperties

errReturn = ColCustomProperties.Add("TestProperty", "Test")

See? Now we have a new property named TestProperty, with a value of Test. If you change your mind and decide you don’t really want a custom property named TestProperty, just remove it:

Set objPropertyReader = CreateObject("DSOleFile.PropertyReader")

Set objDocument = objPropertyReader.GetDocumentProperties_

    ("C:\Scripts\Test.doc")

Set colCustomProperties = objDocument.CustomProperties

For Each strProperty in colCustomProperties

    If strProperty.Name = "TestProperty" Then

        strProperty.Remove()

    End If

Next

What’s that? Well of course you can change the value of a custom property; what fun would a custom property be if you couldn’t change it? Here’s a script that brings up the set of custom properties for a document, find the property named TestProperty, and then changes its value to New value:

Set objPropertyReader = CreateObject("DSOleFile.PropertyReader")

Set objDocument = objPropertyReader.GetDocumentProperties _

    ("C:\Scripts\Test.doc")

Set colCustomProperties = objDocument.CustomProperties

For Each strProperty in colCustomProperties

    If strProperty.Name = "TestProperty" Then

        strProperty.Value = "New value"

    End If

Next

I haven’t really given this much thought, but this has always seemed like something that could potentially be very useful. I don’t know if I’ll ever do anything else with it, but I have some vague notions concerning little utilities that could make use of it. Hey, who knows what the future might hold?

Well, OK; I mean besides Nostradamus.