Newsletters #3

Here is my 3rd newsletter dealing with the BrowseForFolders method and other WSH topic.

How to register/unregister an OCX-file?

The power of WSH may be unleashed using other objects and their methods/properties. Many extensions are coming in OCX files. Maybe you will be soon in a situation like the author a year ago: I had a lot of OCX files, but I don't know how to install them. After playing with some development environments (like VB 5 CCE, Delphi, VS 6.0) my Windows Registry became cluttered with many sample objects which where no longer needed. In my first attempt I undertook the task to clean my Registry manually (using the Registry Editor and removes all entries of the related OCX files from HKCR/CLSID). Later on I found out that I was a bit a fool, Windows 98 comes with the program RegSvr32.exe which lets you register/unregister COM objects stored in OCX, DLL and other files. The program comes also on many Microsoft CD-ROMs and may be used also under Windows NT to do the same task. To find out more about this program, you may invoke it with a wrong command (like RegSvr32.exe /?). Then the program displays a short dialog.

To register an OCX file, copy the file into a local folder and use the following command:

REGSVR32 <path><ocx-file-name>

A program WSHExtend.ocx located in C:\MyOcx may be registered using the command:

RegSvr32 C:\MyOcx\WSHExtend.ocx

To unregister the OCX file, use the following command:

RegSvr32 /u C:\MyOcx\WSHExtend.ocx

To simplify registering/unregistering OCX controls under WIndows, you may use a small REG-file to extend your Explorer's context menu. Just store the following commands into a text file OCXRegister.reg:

REGEDIT4

[HKEY_CLASSES_ROOT\.ocx]
@="ocxfile"

[HKEY_CLASSES_ROOT\ocxfile]
@="OCX files"
"EditFlags"=hex:00,00,00,00

[HKEY_CLASSES_ROOT\ocxfile\Shell]
@=""

[HKEY_CLASSES_ROOT\ocxfile\Shell\R_OCX]
@="Register OCX"

[HKEY_CLASSES_ROOT\ocxfile\Shell\R_OCX\command]
@="RegSvr32.exe %1"

[HKEY_CLASSES_ROOT\ocxfile\Shell\Un_OCX]
@="Unregister OCX"

[HKEY_CLASSES_ROOT\ocxfile\Shell\Un_OCX\command]
@="RegSvr32.exe /u %1"

A double-click to the file updates your Registry. Afterward you get two new entries Register OCX and Unregister OCX within your shortcut menu, if you right-click an OCX file. The REG-file is also contained within the samples of the sneak preview of the WSH Tutorial.

I have used this method many times without trouble. But I should mention here a few cases where this approach fails and isn't necessary:

And I should mention here also another trap. Although you are able to register an OCX file sucessfully using RegSvr32.exe, the control won't run. Executing a script cause a run-time error in the CreateObject method during the attempt to create an object instance. The run-time error »Win32-Error 0x80040112« is reported. Trying to find out more about this error leaves you as thumb as before, because this error is not documented. I was getting realy confused after I went into this trap. The solution: Microsoft and other vendors begun to add something like a license key to their controls. And if the licence key isn't detected during the CreateObject method, the run-time error mentioned above is raised. I understand the interest of the vendors to protect their controls against unauthorized use. But there are many odds caused by the way how licensing is used: In VBA you get a different error message, indicating that there is a problem using the control. In VBScript/JScript you get the cryptic error code mentioned above. The WSH gurus told me that this is known well. But how in hell a novice shall detect this behavior? I spend days in investigating this issue, and at least a call to MS support solved the question. Why in hell the WSH script doesn't provide a clear error message like "The control xx isn't licensed"? And there is another mystery: Although you have the license to use a control, it is not always possible to use it. During updating a control from an old to a new version, the license key is not always updated properly. So you get again the error messages mentioned above. There are some articles about this behavior in Microsoft Knowledge Base. Further details about this topic may be found in my WSH Tutorial in chapter 2. The sneak preview contains this sample, and may be downloaded for free from the WSH Bazaar.

Using the BrowseForFolder method

If you have installed MS IE 4.0/5.0 on your computer, the Shell.application object may be used, and this object provides the BrowseForFolder method. You may access this method using the following (VBScript) commands:

Set objF = WScript.CreateObject("Shell.Application")
Set objF = objDlg.BrowseForFolder (&H0, title, flags)

The BrowseForFolder method requests three parameters. The first parameter is a handle and must be set alsways to &H0. The second parameter submits a string which shall be shown in the dialog window. The third parameter contains a flag value which directs the mode how the user may select entries within the Shell's namespace. Within the fourth parameter you may pass the target folder shown in the dialog's text box.

The method allows not only to select a true folder, it can be used also to retrieve printers and other shell namespace objects. Within my first experiements I found out a few values which may be passed for the flag parameter (allowing me to use BrowseForFolder to select folders of the file system). After all I found some additional information provided from Jan Herman Scheffer (Email_Address: jh.scheffer@hccnet.nl). Jan Herman provided a sample script (downloadable from C. Washington's Website http://washington.netreach.net) with some extra information about the constants which may be passed to the method. The constant definition from his sample (and some comments I have added) are shown below:

Const BIF_returnonlyfsdirs = &H0001    ' allow the user to select only folders
Const BIF_dontgobelowdomain = &H0002   ' prevent the user to go below a given domain
Const BIF_statustext = &H0004          ' ???
Const BIF_returnfsancestors = &H0008   ' only file system entries
Const BIF_editbox = &H0010             ' disply a text box to enter a path
Const BIF_validate = &H0020            ' OK will be enabled only, if a valid entry is selected
Const BIF_browseforcomputer = &H1000   ' show the computer branch in the tree
Const BIF_browseforprinter = &H2000    ' show the printer branch in the tree
Const BIF_browseincludefiles = &H4000  ' allow files to be selected

'******************************************************************************
' Gordon Ali provided me with the following information:
' There is an additional optional parameter.
' This fourth parameter gave the following experimental options.
' Any other value starts the function with the desktop, but with My Computer 
' expanded.
'
' When you pass a textstring instead of the numeric BSF-constants, the root
' will be this specific folder or drive.
'
' Jan Herman Scheffer March 30 1999
'******************************************************************************

Const BSF_desktop = 0          'Desktop is the root directory. 
                               'With BIF_returnonlyfsdirs circumvents 
                               'problem with OK-button
Const BSF_internetexplorer = 1 'Internet Explorer is the root
Const BSF_programs = 2         'Programs folder of the start menu is the root
Const BSF_controlpanel = 3     'Control Panel is the root. Needs BIF_browseincludefiles
Const BSF_printers = 4         'Printers folder is the root. Needs BIF_browseincludefiles
Const BSF_documents = 5        'Documentsfolder is the root
Const BSF_favorites = 6        'Favorites is the root
Const BSF_startup = 7          'Startup-folder of the startmenu is the root. Needs BIF_browseincludefiles
Const BSF_recent = 8           'Recentfolder is the root. Needs BIF_browseincludefiles
Const BSF_sendto = 9           'Sendto-folder is the root. Needs BIF_browseincludefiles
Const BSF_recyclebin = 10      'Recycle Bin is the root. Needs BIF_browseincludefiles
Const BSF_startmenu = 11       'Start Menu is the root
Const BSF_desktopdirectory = 16 'The Desktopdirectory is the root directory
Const BSF_drives = 17          'The drives (My computer) folder is the root
Const BSF_network = 18         'The networkneighbourhood is the root
Const BSF_nethood = 19         'The nethoodfolder is the root
Const BSF_fonts = 20           'The fontsfolder is the root
Const BSF_templates = 21       'The templatesfolder is the root

It is worth to experiment a bit with this method, especially with the constants documented from Jan Herman Scheffer. The BrowseForFolder method is a powerful (but also dangerous) tool to access all entries within the Shell's name space. The following short VBScript sample takes this know how and displays the BrowseForFolder dialog. Enjoy!

'************************************************
' File:    Dialog.vbs (WSH sample in VBScript) 
' Author:  Günter Born
'
' Demonstrates, how the Shell-Dialog may be used
' to select a folder.
'
' In no way shall the author be liable for any
' losses or damages resulting from the use of this
' program. Use AS-IS at your own risk.
'
' The code is the property of the author. You may
' use the code and modify it, as far as this header
' remains intact. Further updates and other samples
' may be found on the WSH Bazaar at:
' http://www.borncity.de
'************************************************
Option Explicit

' Flags for the options parameter
Const BIF_returnonlyfsdirs   = &H0001
Const BIF_dontgobelowdomain  = &H0002
Const BIF_statustext         = &H0004
Const BIF_returnfsancestors  = &H0008
Const BIF_editbox            = &H0010
Const BIF_validate           = &H0020
Const BIF_browseforcomputer  = &H1000
Const BIF_browseforprinter   = &H2000
Const BIF_browseincludefiles = &H4000

Dim wsh, objDlg, objF

' get Application object of the Windows-Shell
Set objDlg = WScript.CreateObject ("Shell.Application")

' use the BrowseForFolder method
' for instance: Set objF = objDlg.BrowseForFolder _
'     (&H0, "Select the folder to copy", &H10, "C:\Born")

Set objF = objDlg.BrowseForFolder (&H0, _
    "Select the folder to copy", _
    BIF_editbox + BIF_returnonlyfsdirs)

If TypeName(objF) = "Folder" Then
 MsgBox "Selected folder: " & objF.Title
Else
 MsgBox "Canceled"
End if

' End

One of my German readers of the WSH book has informed me that the sample won't run after installing MS IE 5.0 on his Windows NT workstation. Because the automation interface is provided from the file Shodocvw.dll we solved his problem with the following trick: Rename the original IE 4 file shdocvw.dll and copy it to c:\winnt.Then register the control using the command:

regsvr32.exe /n /i c:\winnt\shdocvw4.dll c:\winnt\shdocvw4.dll

Afterward, the Shell.Application object was accesseable. But during installing MS IE 5.0 on one of my test machines I detected also an option which let you to install both browsers MS IE 4 and MS IE 5 on your machine. I haven't tried it, but maybe this is also a solution, if you run into trouble using the Shell.Application object, after installing MS IE 5.0.

Further samples and details may be found also in my WSH Bazaar. Have a look at the sample page and at the WSHExtend Programmers Reference.

Other topics I mentioned in my last newsletters (like shell access) are already described in my WSH Bazaar as ordinary samples. So check out the WSH Bazaar.

Planned topics for newsletter #4 and future newsletters:

If I had time, I will investigate also WSH 2.0, WMI and more. But first I have to dig a bit more into Linux and XML<g>. To all of you living on the northern hemisphere of this globe, I wish you a nice and relaxing summer with a lot of fun. The fellows living on the southern hemisphere may have a nice winter season, till the next newsletter arrives...


(c) G. Born