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.
Comments
Anonymous
February 25, 2004
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.Anonymous
February 25, 2004
So now no-one's looking, how about a blog/webcast/column on Exchange scripting?Anonymous
March 24, 2004
Have not you ever experenced locks problems?Anonymous
April 20, 2004
Really, really useful. Thanks.Anonymous
May 13, 2004
Is there an enumeration of the Properties returned by the simple:
Set objDocument = objPropertyReader.GetDocumentProperties("C:ScriptsTest.doc")
Call?
That is, how can I do something like this?
<metacode>
foreach property in objDocument.Properties
print property.name
print property.value
</metacode>Anonymous
June 04, 2004
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?Anonymous
June 10, 2004
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?Anonymous
July 13, 2004
The comment has been removedAnonymous
August 04, 2004
Hi,
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 _
("C:ScriptsTest.doc")
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'.Anonymous
June 08, 2009
PingBack from http://insomniacuresite.info/story.php?id=2606Anonymous
June 15, 2009
PingBack from http://workfromhomecareer.info/story.php?id=8129