Tag Archives: web publishing wizard

Programming your own Web Publishing Wizard on Windows XP

Upload a bunch of pictures directly from your Windows Explorer to your webserver – a little tutorial.

Microsoft XP includes some nifty “wizards” to upload files to a web site, or to order prints of digital photos. And of course, the available choices are limited to Microsoft’s properties and partners, like MSN and xDrive.

With those options, you can select a series of files and/or folders and upload them to a website (like MSN or xDrive), or select some pictures and send them to an online photo processing service.

Well… it turns out that you can create your own wizards.

Altough Microsoft has some documentation available, it is not what you would call “complete” or “easy to understand”. It is missing some links, divided in pieces, has no examples and is definetively incomplete.

It seems like they made it available, but expect “real companies” to get some direct help from Microsoft when implementing it for real. After all, if you’re paying Microsoft to include your service in the wizard’s list, you can expect some support.

The wizards are nothing more than web pages with some specific javascript calls. And to make your “service” show up in the list, all you need is some registry entries.

Registering your service

This is the easy part. Wizards are listed on the registry, under the following keys:

For “Publish to the Web”.

HKEY_CURRENT_USER\Software\Microsoft\Windows \CurrentVersion\Explorer\PublishingWizard \PublishingWizard\Providers\{YourNameHere}

You need the following entries (all of them Strings):

DisplayName: First line of text in the listing
Description: Second line of text in the listing
Icon: URL to the icon (.ico file) for the listing
HREF: URL of the first page of the wizard
SupportedTypes: (optional) Wildcard filter for acceptable filenames (i.e. “*.jpg”)

The easiest way to create these entries is with a REG file like this one:
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\PublishingWizard\PublishingWizard\Providers\MyOwnProvider]
"Icon"="http://www.example.com/myprovider/myicon.ico"
"DisplayName"="My very own provider"
"Description"="This is my own provider, free and customized"
"HREF"="http://www.example.com/myprovider/wizard.php"

Your Service Wizard Page

This is the hard part. It involves dynamic pages on the server side (like ASP, PHP, JSP or anything you like) along with Javascript code on the client side.

The page runs inside the wizard window, and it’s expected to have 3 javascript functions, OnBack, OnNext and OnCancel, or else the wizard will not load it.

Those functions will be called whenever the user presses one of the three buttons on the bottom of the wizard.

There are two useful functions to control the wizard window (their meaning should be obvious):

window.external.SetWizardButtons(activatePrev, activateNext, isLastPage);

and

window.external.SetHeaderText(firstLine, secondLine);

And there are two functions you can call to “finish” the Wizard process:

window.external.FinalBack();

and

window.external.FinalNext();

You call FinalNext() from inside OnNext() to signal the wizard you are done asking questions and are ready to transfer the files. The next time the user clicks on “Next”, the wizard will proceed to upload the files.

And you call FinalBack() from inside OnBack() whenever you are on the “first page” of your process. (If that’s too complicated for you, simply call it all the time on OnBack()).

Uploading the files

So far, nothing is really hard. The real problem is the upload process.

See, before calling your page, the wizard created an XML file with a list of all the files to be uploaded. And you can access it through:

window.external.Property("TransferManifest")

The XML looks something like

transfermanifest> <filelist> <file id="1" source="C:\My Documents\File1.jpg" destination="File1.jpg" .../> <file id="2" source="C:\My Documents\Other File.jpg" destination="Other File.jpg" ... /> </filelist> </transfermanifest>

If you do nothing, then the wizard will not upload any file. You need to “edit” that XML document to add information about how to upload the files and where.

You have two methods: WebDAV and POST File Uploads.

I haven’t played with WebDAV, so I’ll leave it as an exersice to the reader.

For File Uploads, you need the to look like this:

<transfermanifest> <filelist> <file id="1" source="C:\My Documents\File1.jpg" destination="File1.jpg" ...> <post href=http://www.example.com/myprovider/acceptfile.php name="myfile"> <formdata name="OtherFormVar">Some Value</formdata> <formdata name="action">Save</formdata> </post> </file> <file id="2" source="C:\My Documents\Other File.jpg" destination="Other File.jpg" ... > <post href=http://www.example.com/myprovider/acceptfile.php name="myfile"> <formdata name="OtherFormVar">Some Value</formdata> <formdata name="action">Save</formdata> </post> </file> </filelist> <uploadinfo> <htmlui>http://www.example.com/myprovider/seeyourfiles.php</htmlui> </uploadinfo> </transfermanifest>

If you haven’t done POST File Uploads in regular web pages before, then you need to figure that out first.

The tags are optional and let you pass aditional form variables.

All those tags are pretty much equivalent of the following HTML page being submitted once for each file:

<form method="POST" encoding="multipart/form-data" action="http://www.example.com/myprovider/acceptfile.php"> <input type="hidden" name="OtherFormVar" value="Some Value"> <input type="file" name="myfile"> <input type="submit" name="action" value="Save"> </form>

The tag needs to be present for the upload process to begin, but you actually don’t need to put anything inside it. Anyway, the has the URL for a page that will be opened as soon as the wizard is done.

All the “editing” of the XML data has to be done using Microsoft’s XML DOM, but it’s not that hard. Here is some sample Javascript code to create the desired results:

var xml = window.external.Property("TransferManifest"); var files = xml.selectNodes("transfermanifest/filelist/file"); for (i = 0; i < files.length; i++) { var postTag = xml.createNode(1, "post", ""); postTag.setAttribute("href", "http://www.example.com/myprovider/acceptfile.php"); postTag.setAttribute("name", "myfile"); var dataTag = xml.createNode(1, "formdata", ""); dataTag.setAttribute("name", "MAX_FILE_SIZE"); dataTag.text = "2000000"; postTag.appendChild(dataTag); var dataTag = xml.createNode(1, "formdata", ""); dataTag.setAttribute("name", "action"); dataTag.text = "Save"; postTag.appendChild(dataTag); files.item(i).appendChild(postTag); } var uploadTag = xml.createNode(1, "uploadinfo", ""); var htmluiTag = xml.createNode(1, "htmlui", ""); htmluiTag.text = "http://www.example.com/myprovider/seeyourfiles.php"; uploadTag.appendChild(htmluiTag); xml.documentElement.appendChild(uploadTag);