March 2005

SG090301

By The Scripting Guys

For a list and additional information on all Tales from the Script columns, click here.

On This Page

Dsofile: The Untold Story
What is Dsofile?
Hey, Hold On: Dsofile Isn’t New
OK, But How Do I Use Dsofile?
But That’s Not All
We’d Like to Thank the Pulitzer Prize Committee …

Dsofile: The Untold Story

When we first started writing Tales from the Script, we pictured ourselves becoming the hard-hitting, muck-raking journalists of the scripting world. Tales from the Script would scoop everyone else when it came to breaking the top scripting stories of the day, and we’d enthrall our readers with that in-depth, behind-the-scenes reporting that only the Microsoft Scripting Guys could provide. In fact, our biggest concern was how we would politely tell the Pulitzer Prize committee, “Look, guys, we appreciate it, but we win every single year. Maybe you should give this one to someone else, just for a change. Isn’t there a newspaper in New York City? Maybe you could give it to them.”

As it turned out, things didn’t go exactly as we planned. Not that we’re disappointed in Tales from the Script; we think our little column has helped a lot of people get over an initial fear of scripting and helped them see that using scripts to manage Windows is no harder (and is often easier) than using GUI tools to manage Windows. We’re very happy about that. Still, it would be nice to see the editorial board of The New York Times sitting around a table going, “Scooped by the Scripting Guys again! We just can’t compete with them!” So far, though, the Times doesn’t seem to be too worried about us.

Confession. OK, so maybe part of this is our fault. After all, one of our recent columns was titled I Married Bigfoot. That doesn’t exactly scream “Pulitzer Prize winner.”

This month, though, things are different; the March Tales from the Script has nothing to do with marrying Bigfoot. Instead, we bring you some true breaking news, the kind of high-impact story you won’t find anywhere else (well, unless you do a Google search or something). That’s right, this month we bring you Dsofile: The Untold Story.

That cry of anguish you just heard? Probably someone from The New York Times editorial board. Either that or Scripting Guy Peter Costantini just found out that his favorite type of biscotti is no longer available in the Microsoft cafeteria.

What is Dsofile?

Dsofile is actually the file name (Dsofile.dll) for the Microsoft Developer Support OLE File Property Reader 2.0 Sample. (You have to admit, Microsoft has a knack for coming up with really catchy names.) Don’t let the name throw you, however. Dsofile (which you can get for free from the Microsoft Download Center) is actually an incredibly useful tool for script writers: it provides a quick and easy way to read from and write to the summary information property set for all your files.

Your first reaction to this is probably, “This is incredible; why didn’t you guys tell us about this a long time ago?!?” Your second reaction is probably, “Um, what are summary information properties again?” If you aren’t sure what we mean by “the summary information property set for a file,” then do this. Open Windows Explorer or My Computer and find a file. (It doesn’t matter which file, although we’d recommend a Microsoft Office document, for reasons that will become clear in a minute or two). Right-click the file and click Properties. In the resulting dialog box, click the Summary tab. You should see something that looks like this (if it doesn’t look like this, click the Advanced button):

Summary Properties

This is summary information and, as you can see, there is the potential for adding a lot of very useful metadata to a file. More important, it’s then possible to make use of that metadata. For example, if you are diligent about filling in things like Subject, Category, and Keywords, you can then do finely-targeted searches that make it possible to locate files quickly and easily. As shown below, the File Search command within Microsoft Office lets you search for documents based on these summary information properties; likewise the new MSN Search tool can also search for documents based on these properties.

File Search

The truth is, this is exactly the kind of information script writers want to get their hands on; we get scores of letters from people asking how they can write scripts that access summary information, and how they can write scripts that configure this summary information. And yet the scripting tools built into the operating system can’t really do this. Granted, the Shell object has the ability to read some of these summary information fields. However, the Shell object can’t write to the summary information fields. For that matter, neither can Windows Script Host, the File System Object, WMI, or anything else built into the operating system. There’s a wealth of good stuff out there, and seemingly no way to get to it.

This is where Dsofile comes into play. Dsofile is designed to give script writers a way to get at summary information properties for a file. Dsofile comes with a set of properties built into it; these properties happen to be the same properties that come standard with Microsoft Office documents. (Not too big of a surprise there; after all, Dsofile was developed by the Office team). Using Dsofile, you can bind to a document and retrieve information for the following items:

ApplicationName

Author

ByteCount

Category

CharacterCount

CharacterCountWithSpaces

Comments

Company

DateCreated

DateLastPrinted

DateLastSaved

HiddenSlideCount

Keywords

LastSavedBy

LineCount

Manager

MultimediaClipCount

NoteCount

PageCount

ParagraphCount

PresentationFormat

RevisionNumber

SharedDocument

SlideCount

Subject

Template

Title

TotalEditTime

Version

WordCount

Like we said, these are the properties found in Microsoft Office documents. But you aren’t limited to retrieving information from Office documents. You can also bind to other types of files using Dsofile; for example, you can bind to your .vbs files or your .mp3 files or whatever. The only caveat is that Dsofile won’t be able to get at any properties other than the ones listed above. For example, .jpg files have properties like Width, Height, and Bit Depth. Useful properties, but you can’t access those properties using Dsofile.

Hey, Hold On: Dsofile Isn’t New

A few of you skeptics out there might be saying, “Wait a second. This is old news; Dsofile has been out for years.” Well, that’s true: not only has Dsofile been out for years, but we even have some sample scripts in the Script Center that show you how to use the utility. However, a new version of Dsofile was released without fanfare in early December; hence the reason for this column, and hence our claim to be bringing you late-breaking news. (Assuming that two months later still counts as late-breaking.) Before you ask, this new version of Dsofile was designed for use with the .NET programming languages and, as far as we know, it doesn’t add any capabilities not found in the previous version.

What does differ between the two are the scripts that take advantage of Dsofile’s capabilities. Suppose you have the old version of Dsofile, and you download and install the new version. Your old Dsofile scripts (the same ones found in the Script Center) won’t work with the new version of Dsofile; that’s due to a number of changes in the script code required to use the old version vs. the script code required to use the new version.

For example, here’s a script that retrieves the name of a document’s author using the older version of Dsofile:

Set objPropertyReader = CreateObject("DSOleFile.PropertyReader")
Set objDocument = objPropertyReader.GetDocumentProperties _
    ("C:\Scripts\New_users.xls")
Wscript.Echo "Author: " & objDocument.Author


Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open("C:\Scripts\New_users.xls")
Wscript.Echo "Author: " & objFile.SummaryProperties.Author

And here’s the same script rewritten to work with the new version of Dsofile:

Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open("C:\Scripts\New_users.xls")
Wscript.Echo "Author: " & objFile.SummaryProperties.Author

As you can see, both scripts return the document author, but that’s about the only similarity. Even the ProgIds – DSOleFile.PropertyReader and DSOFile.OleDocumentProperties – are different. Unfortunately, the minimal documentation released with Dsofile doesn’t really make that clear; if you aren’t careful you might – like at least one of the Scripting Guys – install the new version and spend hours trying to figure out why your old scripts no longer seem to work.

Those of you who are really skeptical might also be thinking, “Big deal; couldn’t I just create an instance of an Office application and get at this same information?” Yes, you could. However, the value of using Dsofile doesn’t lie in its ability to get at unique information other applications, such as Microsoft Office, can’t get at; instead, the value of Dsofile is the fact that it does just this one thing. Scripts that use Dsofile return information faster than scripts that use Microsoft Office; that’s because you don’t have to create an instance of Word or Excel just to determine the author of a document. Dsofile can get the same information quicker, easier, and without the overhead of starting up an Office application. That’s what makes Dsofile such a useful tool.

OK, But How Do I Use Dsofile?

Good question: if we hope to get the Pulitzer Prize for scripting this year it might help if we showed you some code. (It would also help if they actually had a Pulitzer Prize for scripting.) So let’s take a closer look at our script that returns the author of a document:

Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open("C:\Scripts\New_users.xls")
Wscript.Echo "Author: " & objFile.SummaryProperties.Author

As you can see, we begin by creating an instance of the DSOFile.OleDocumentProperties object. We then use the Open method to “open” the file. (We put quotation marks around the word “open” because we aren’t opening the file in the sense of starting up an application like Microsoft Excel and then loading up the document. Instead all we’re really doing is binding to the summary information metadata attached to the file.)

After we’ve made this connection we simply echo the values of the desired summary information properties. Nothing too fancy here; the only thing to watch out for is the fact that we need to reference the SummaryProperties object; thus we have objFile.SummaryProperties.Author rather than objFile.Author. But that’s the only tricky part; there are no arrays, no weird date conversions, none of those things we’ve all grown to … love … about scripting.

Here’s a more complete script, one that retrieves all the summary information values for the file C:\Scripts\New_users.xls. Another nice thing about Dsofile: no error is generated if you try to echo a property (such as SlideCount) for a file that doesn’t have anything to do with slides. Instead, you simply get back a Null value (or a 0 in the case of a numeric property) and the script continues on its merry way. This is true even if you’re retrieving information from a text file, a Windows Media file, or any other non-Microsoft Office document.

Here’s the code:

Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open("C:\Scripts\New_users.xls")

Wscript.Echo "Application name: " & objFile.SummaryProperties.ApplicationName
Wscript.Echo "Author: " & objFile.SummaryProperties.Author
Wscript.Echo "Byte count: " & objFile.SummaryProperties.ByteCount
Wscript.Echo "Category: " & objFile.SummaryProperties.Category
Wscript.Echo "Character count: " & objFile.SummaryProperties.CharacterCount
Wscript.Echo "Character count with spaces: " & objFile.SummaryProperties.CharacterCountWithSpaces
Wscript.Echo "Comments: " & objFile.SummaryProperties.Comments
Wscript.Echo "Company: " & objFile.SummaryProperties.Company
Wscript.Echo "Date created: " & objFile.SummaryProperties.DateCreated
Wscript.Echo "Date last printed: " & objFile.SummaryProperties.DateLastPrinted
Wscript.Echo "Date last saved: " & objFile.SummaryProperties.DateLastSaved
Wscript.Echo "Hidden slide count: " & objFile.SummaryProperties.HiddenSlideCount
Wscript.Echo "Keywords: " & objFile.SummaryProperties.Keywords
Wscript.Echo "Last saved by: " & objFile.SummaryProperties.LastSavedBy
Wscript.Echo "Line count: " & objFile.SummaryProperties.LineCount
Wscript.Echo "Manager: " & objFile.SummaryProperties.Manager
Wscript.Echo "Multimedia clip count: " & objFile.SummaryProperties.MultimediaClipCount
Wscript.Echo "Note count: " & objFile.SummaryProperties.NoteCount
Wscript.Echo "Page count: " & objFile.SummaryProperties.PageCount
Wscript.Echo "Paragraph count: " & objFile.SummaryProperties.ParagraphCount
Wscript.Echo "Presentation format: " & objFile.SummaryProperties.PresentationFormat
Wscript.Echo "Revision number: " & objFile.SummaryProperties.RevisionNumber
Wscript.Echo "Shared document: " & objFile.SummaryProperties.SharedDocument
Wscript.Echo "Slide count: " & objFile.SummaryProperties.SlideCount
Wscript.Echo "Subject: " & objFile.SummaryProperties.Subject
Wscript.Echo "Template: " & objFile.SummaryProperties.Template
Wscript.Echo "Title: " & objFile.SummaryProperties.Title
Wscript.Echo "Total edit time: " & objFile.SummaryProperties.TotalEditTime
Wscript.Echo "Version: " & objFile.SummaryProperties.Version
Wscript.Echo "Word count: " & objFile.SummaryProperties.WordCount

Of course, retrieving summary information is really only half the battle; as a script writer you’d also like to be able to configure these property values. Boy, are you in luck. Want to assign a title to a document? Then just use a script like this one:

Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open("C:\Scripts\New_users.xls")

objFile.SummaryProperties.Title = "New title added via a script"
objFile.Save

Again, we create an instance of the OleDocumentProperties object, and then we call the Open method to open the file. We assign the title New title added via a script to SummaryProperties.Title, and then call the Save method. That’s it. If we ever decide to remove the document Title all we have to do is set the property value to an empty string, like so:

Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open("C:\Scripts\New_users.xls")

objFile.SummaryProperties.Title = ""
objFile.Save

One drawback to Dsofile is the fact that it can write to the summary information fields only for a Microsoft Office document; a script that tries to assign a title to, say, a text file (a .txt file) will fail. One of the sad facts of life. And note, too, that not all the properties are writeable; some are read-only. You can use Dsofile to change the Title or Subject of a document; you can’t – for obvious reasons – use Dsofile to change the ByteCount or DateCreated properties.

But That’s Not All

Your typical scripting journalist – like those who work for all the major scripting news organizations – would probably quit at this point, confident that he or she had told you everything there is to know about Dsofile. But do you think the Scripting Guys are the type to give up so easily?

Well, actually we are. But then our editor said, “Um, what about the custom document properties? Don’t you think people would be interested in knowing about those?” And because she’s nearly 11-feet tall and shoots fire out of her eyes, we said, “Sure, anything you say.” (We might point out, too, that, seeing as how she didn’t edit out the part about being nearly 11-feet tall and shooting fire out of her eyes, then it obviously must be true.)

So what about these custom document properties? As we showed you earlier, Microsoft Office documents come with a couple dozen built-in document properties. But what if those document properties don’t quite satisfy your needs? Hey, no problem: you can add your own properties to Microsoft Office documents.

For example, suppose you’d like to keep track of the date on which a document was last reviewed. The built-in document properties don’t include a property called Date Reviewed. But that’s all right; we’ll just create our own such property:

Const msoPropertyTypeDate = 3

Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open("C:\Scripts\New_users.xls")

objFile.CustomProperties.Add "Date Reviewed", msoPropertyTypeDate 
objFile.Save

Here we start out by defining a constant named msoPropertyTypeDate and assigning it the value 3; this tells Dsofile that the custom property we want to add is a date field. Custom properties can be one of the following types:

Constant

Data type

Value

msoPropertyTypeNumber

Number

1

msoPropertyTypeBoolean

Boolean (Yes/No)

2

msoPropertyTypeDate

Date

3

msoPropertyTypeString

String

4

In other words, if we wanted to add a Document Reviewed property, in which we simply indicated whether or not the document had been reviewed, we could add a Boolean property, like so:

Const msoPropertyTypeBoolean = 2

Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open("C:\Scripts\New_users.xls")

objFile.CustomProperties.Add "Document Reviewed", msoPropertyTypeBoolean
objFile.Save

But back to the Date Reviewed property. We then bind to the document, access the CustomProperties collection, and then call the Add method, passing two parameters: the name we’re giving our new property (Date Reviewed) and the data type (msoPropertyTypeDate) for this new property. We then call the Save method and save the new property to the CustomProperties collection.

When we run a script that creates a new custom property, what we’re really doing is setting aside a place where we can store information; by default, though, no information is actually stored there. (In other words, we have a place where we can stash the Date Reviewed, but that place will be blank.) In addition, this new property won’t appear in the Properties dialog box, at least not until you assign it a value. So maybe we’d better show you how to assign a value to this new property.

To assign a value we need to use a script similar to this:

Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open("C:\Scripts\New_users.xls")

Set objProperty = objFile.CustomProperties.Item("Date Reviewed")
objProperty.Value = #2/16/2005#
objFile.Save

Here we start off by binding to the file C:\Scripts\New_users.xls. We then create a property reference to our custom property; that’s what this line of code does:

Set objProperty = objFile.CustomProperties.Item("Date Reviewed")

We set the Value for the property, and then call the Save method to save our changes. That’s it; the Date Reviewed property will now house the value 2/16/2005. Now that we’ve assigned the property a value we can go check the Properties dialog box for New_users.xls; when we do that we should see something that looks like this:

Data Reviewed

By the way, the two pound signs (#) bracketing the date are a standard VBScript method for ensuring that a date is passed as a date and not as a string or as some sort of mathematical expression (i.e., 2 divided by 16 divided by 2005).

You know, you’re right: this does seem more like a Nobel Prize than it does a Pulitzer Prize. But it gets even better. (Those of you who wonder, “What can be better than winning the Nobel Prize?” have obviously never thought much about Dsofile, have you?) You don’t need to use Windows Explorer to retrieve the values of all the custom properties attached to a document; instead you can use a script like this one:

Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open("C:\Scripts\New_users.xls")

For Each objProperty in objFile.CustomProperties
    Wscript.Echo objProperty.Name, objProperty.Value
Next

Because CustomProperties is a collection, we use a For Each loop to walk through all the items in that collection, echoing back the property name and the value assigned to it. Pretty easy, huh?

And what if you want to get rid of this custom property? Well, bind to the document, set an object reference to the property you want to get rid of, and then call the Remove method:

Set objFile = CreateObject("DSOFile.OleDocumentProperties")
objFile.Open("C:\Scripts\New_users.xls")

Set objProperty = objFile.CustomProperties.Item("Date Reviewed")
objProperty.Remove
objFile.Save

Again, make sure you call the Save method to save the changes to the custom property set.

We’d Like to Thank the Pulitzer Prize Committee …

…but we aren’t going to; that’s because they haven’t actually awarded us a Pulitzer yet. We do hope, however, that you find Dsofile useful. One thing we’re trying to do is help broaden your scripting horizons a little; as you might recall, last month we introduced Log Parser, another tool that doesn’t ship with the operating system but is incredibly useful to script writers. Give Dsofile a try, and let us know what you think of it (as always, you can write to us at scripter@microsoft.com (in English, if possible)).

And if you do find it useful, well, maybe you could mention the Scripting Guys the next time you’re talking to someone on the Pulitzer Prize committee. Hey, we have to do something with these tuxedos we all foolishly rushed out and bought.