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 _


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


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 _


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 _


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_


Set colCustomProperties = objDocument.CustomProperties

For Each strProperty in colCustomProperties

    If strProperty.Name = “TestProperty” Then


    End If



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 _


Set colCustomProperties = objDocument.CustomProperties

For Each strProperty in colCustomProperties

    If strProperty.Name = “TestProperty” Then

        strProperty.Value = “New value”

    End If



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.


Comments (11)

  1. Paul Tyng says:

    Do you have the script that read those properties without using the Dsofile.exe? I’m trying to do just this in .Net and I found all the stuff on the API but the example that exists on MSDN chooses not to work for me, so a script example would probably help me out a lot.

  2. Steven Griffiths says:

    So now no-one’s looking, how about a blog/webcast/column on Exchange scripting?

  3. Jaime Miramontes says:

    Have not you ever experenced locks problems?

  4. webauk says:

    Really, really useful. Thanks.

  5. simpleton says:

    Is there an enumeration of the Properties returned by the simple:

    Set objDocument = objPropertyReader.GetDocumentProperties("C:ScriptsTest.doc")


    That is, how can I do something like this?


    foreach property in objDocument.Properties


    print property.value


  6. Nethers says:

    It’s just a pity they didn’t build it in to .NET 🙂

    I’m sure there’s a very good reason – backed up with the minutes from several very important meetings – thet would explain why a ‘get’ function is put in to .NET without the corresponding ‘set’ function.

    I know it’s always ‘more complicated’ but why put in System.Diagnostics.FileVersionInfo and not System.IO.File.SetProperties?

  7. mich says:

    DSOFile throws an exception when I try to read or write a extended file properties from ASP.NET application if the another aplication ( ie. word, excel, explorer (via properties|summary) ) has not initially written to the extended properties structure.

    The exception is thrown in GetDocumentProperties.

    GetDocumentProperties references STG_E_FILENOTFOUND even though the file path is correct and the file exists and permissions on the file allow for access.

    If I edit any of the properties in the file explorer in the summary information it seems to work on the next pass through.

    Has anyone else experienced this?

    IS there a way to initialize the Extended file Porperties Structure from an ASP.NET application?

  8. Nicki says:

    I experienced locking problems when using it in conjunction with the FileSystemObject from an ASP page on an intranet site.

    I wanted to take the processing out of the actual page and serve up a flat page which is generated by a script running at night when no-one is using the intranet. However I can’t get the DLL to work from WSH although it was fine in ASP.

    I get this error: ActiveX component can’t create object: ‘DSOleFile.PropertyReader’

    The DLL registered ok, and I could use it from ASP so what’s the problem in WSH?

    Anyone come across this?

  9. Marc says:


    The code is just great. But how can I change the type of custom document property?

    This code works fine for customproperties of type ‘text’

    Set objPropertyReader = CreateObject("DSOleFile.PropertyReader")

    Set objDocument = objPropertyReader.GetDocumentProperties _


    Set colCustomProperties = objDocument.CustomProperties

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

    How can I create customproperties of type ‘Date’?

    I’m creating a tool with types ‘Text’ and ‘Date’.