Delphi - Configure tools menu with VB scripts
- Date:
- Author: Stefan Cruysberghs
The Tool Properties dialog box is used to customize the Delphi Tools menu. In this article I will show a way how to create some powerful extensions for this Tools menu. Most Delphi developers like to add some extra tools like resource editors, database managers, report designers, ... I have created some Visual Basic scripts (VBScripts, VBS) to open a help file or PDF document, to open an URL in your web browser, to create a zipped backup file, to create a list of PAS files, compile your project with the .NET CF compiler, ... Hopefully this article can serve as a guideline when you start writing your own VBScripts. |
Tools Properties dialog
In the Tool Properties dialog you can specify the title (this is the caption of the new menu item), the location of the program, a working directory and a list of parameters.
The location of the program should include the full path to the program. The browse button can be used to search drives and directories to locate the path and file name of the program. Only EXE, COM, PIF and BAT files are allowed, other files will produce an "Unable to execute (error 2)" error upon execution.
Adding a seperator can be done by creating a new menu item and typing "-" in the title field. At first glance it seems impossible to add more then one seperator because the IDE enforces every title to be unique ("Tool called - already exists" error). This is a bug because it, clearly, doesn't count for separators. It only happens when you create a new item, not when you edit an existing one. So in order to create multiple seperators, create a new item with a non-existing title and change it afterwards.
Macros
The parameters field can be used to pass some specific parameters to the program at startup. Delphi supports 16 macros which can be used to pass some Delphi information. In Delphi 2005 the $PROJECT parameter has been added. This is interesting because now you can pass the project name to another compiler, e.g. the .NET Compact Framework compiler.
Here a list of all macros. This list is copied from the Delphi help files.
Macro | Description |
$COL | Expands to the column number of the cursor in the active Code editor window.For example, if the cursor is in column 50, at startup the product passes 50 to the program. |
$ROW | Expands to the row number of the cursor in the active Code editor window.For example, if the cursor is in row 8, at startup the product passes 8 to the program. |
$CURTOKEN | Expands to the word at the cursor in the active Code editor window. For example, if the cursor is on the word Token, at startup the product passes Token to the program. |
$PATH | Expands to the directory portion of a parameter you specify. When you insert the $PATH macro, the product inserts $PATH() and you specify a parameter within the parentheses. For example, if you specify $PATH($EDNAME), at startup the product passes the path for the file in the active Code editor window to the program. |
$NAME | Expands to the file name portion of a parameter you specify. When you insert the $NAME macro, the product inserts $NAME() and you specify a parameter within the parentheses. For example, if you specify $NAME($EDNAME), at startup the product passes the file name for the file in the active Code editor window to the program. |
$NAMEONLY | Expands to the file name portion of a parameter you specify, without an extension. When you insert the $NAMEONLY macro, the product inserts $NAMEONLY() and you specify a parameter within the parentheses. |
$EXT | Expands to the file extension portion of a parameter you specify. When you insert the $EXT macro, the product inserts $EXT() and you specify a parameter within the parentheses. For example, if you specify $EXT($EDNAME), at startup the product passes the file extension for the file in the active Code editor window to the program. |
$EDNAME | Expands to the full file name of the active Code editor window. For example, if you are editing the file C:\PROJ1\UNIT1.PAS, at startup the product passes C:\PROJ1\UNIT1.PAS to the program. |
$EXENAME | Expands to the full file name of the current project target. For example, if you are working on the project PROJECT1 in C:\PROJ1, at startup the product passes C:\PROJ1\PROJECT1.EXE to the program. If you are working on a package project PACKAGE1 in C:\PACKAGE, at startup the product passes C:\PACKAGE\PACKAGE1.BPL to the program. |
$HOSTNAME | Expands to the full file name of the executable which is run for the current project. For .executable projects, this macro is equivalent to the $EXENAME macro. For package and DLL projects, this macro expands to the project's host application as defined on the Run|Parameters dialog box. For example, if you are working on the project PROJECT1 in C:\PROJ1, at startup the product passes C:\PROJ1\PROJECT1.EXE to the program. If you are working on a package project called PACKAGE1 in C:\PACKAGE, and the host application is set to C:\HOST\HOSTAPP.EXE at startup the product passes "C:\HOST\HOSTAPP.EXE" to the program (rather than the package name "C:\PACKAGE\PACKAGE1.BPL"). |
$PARAMS | Expands to the command-line parameters specified in the Run Parameters dialog box. |
$PROJECT | NEW IN DELPHI 2005. Expands to the file name of the current project. |
$PROMPT | Prompts you for parameters at startup. When you insert the $PROMPT macro, the product inserts $PROMPT() and you specify a default parameter within the parentheses. |
$SAVE | Saves the active file in the Code editor. |
$SAVEALL | Saves the current project. |
$TDW | Sets up your environment for running Turbo Debugger. For example, this macro saves your project, ensures that your project is compiled with debug info turned on, and recompiles your project if it is not compiled with debug info turned on. Be sure to use this macro if you add Turbo Debugger to the Tools menu. |
Some examples :
Open resource file of current .NET WinForms unit
I like the tool Resourcer (Lutz Roeder, http://www.aisto.com/roeder/dotnet) and I'm utilizing it to take a look at .NET resource files. By using a combination of some macros the resource file of the current WinForms unit can be opened.
Program | C:\Program Files\Developer tools\Resourcer.exe |
Parameters | $SAVEALL $NAMEONLY($EDNAME).resx |
Open resource file of current Win32 project
For openening the Win32 resource file of a Delphi project I'm using an older tool called ResourceHacker (Angus Johnson, http://www.angusj.com/resourcehacker).
Program | C:\Program Files\Developer tools\ResHacker.exe |
Parameters | $SAVEALL $NAMEONLY($PROJECT).res |
VB scripts
The program field only allows EXE, COM, PIF and BAT (which is not visible in filter combobox) files. That is a pitty, because you can't create a link to another type of file. But by passing an unit name ($EDNAM) or project name ($PROJECT) to a VB script you can create some powerful extensions for Delphi. Some examples :
Open given file (help, pdf, ...) or URL
I've created a very small VB script to open a help file, PDF document, Word document, image or URL. The filename or URL will be passed to the script and by using the Windows Shell Run method the associated program will be started.
Program | C:\WINDOWS\system32\wscript.exe |
Parameters | "C:\Program Files\Borland\BDS\3.0\Scripts\OpenFileURL.vbs" "C:\Program Files\Developer Express.VCL\ExpressQuantumGrid 5\Help\EXPRESSQUANTUMGRID.HLP" |
Program | C:\WINDOWS\system32\wscript.exe |
Parameters | "C:\Program Files\Borland\BDS\3.0\Scripts\OpenFileURL.vbs" "D:\Books\Dr Bob - Delphi OplossingsCourant 5-2.pdf" |
Program | C:\WINDOWS\system32\wscript.exe |
Parameters | "C:\Program Files\Borland\BDS\3.0\Scripts\OpenFileURL.vbs" "http://www.scip.be" |
OpenFileURL.vbs
Dim WshShell, Args
Set WshShell = CreateObject("WScript.Shell")
Set Args = WScript.Arguments
If Args.Count = 0 Then
MsgBox "No file given", 16, "Error"
Else
WshShell.Run(Chr(34) & Args(0) & Chr(34))
End If
Open DFM from given unit
Sometimes a DFM file gets corrupted. Then you have to open it with an external editor. This small script will open the DMF file of the current PAS file.
Program | C:\WINDOWS\system32\wscript.exe |
Parameters | "C:\Program Files\Borland\BDS\3.0\Scripts\OpenFormOfUnit.vbs" $EDNAME |
OpenFormOfUnit.vbs
Dim WshShell, Fso, Args
Set WshShell = CreateObject("WScript.Shell")
Set Fso = CreateObject("Scripting.FileSystemObject")
Set Args = WScript.Arguments
If Args.Count = 0 Then
MsgBox "No unit given", 16, "Error"
Else
q = Chr(34) 'quote
strUnitName = Fso.GetBaseName(Args(0))
strUnitFolder = Fso.GetParentFolderName(Args(0))
' Set DFM filename from given PAS filename
strForm = strUnitFolder & "\" & strUnitName & ".dfm"
If Not Fso.FileExists(strForm) Then
MsgBox "Unit has no form (" & strUnitName & ")", 16, "Error"
Else
WshShell.Run("notepad " & q & strForm & q)
End If
End If
Create list of all PAS files in given project folder
This script will create a listing of all PAS files in the project folder. This list will be created by executing the DOS DIR command. The result will be redirected to a log file and at the end this file will be opened with the associated editor (notepad, ultraedit, ...)
Program | C:\WINDOWS\system32\wscript.exe |
Parameters | "C:\Program Files\Borland\BDS\3.0\Scripts\ListPASFiles.vbs" $PROJECT |
ListPASFiles.vbs
Dim WshShell, Fso, Args
Set WshShell = CreateObject("WScript.Shell")
Set Fso = CreateObject("Scripting.FileSystemObject")
Set Args = WScript.Arguments
If Args.Count = 0 Then
MsgBox "No project given", 16, "Error"
Else
q = Chr(34) 'quote
strProjectFolder = Fso.GetParentFolderName(Args(0))
strLogFileName = strProjectFolder & "\ListPasFilesLog.txt"
strCommandLine = "cmd /c > " & q & strLogFileName & q & " dir /b " & q & strProjectFolder & "\*.pas"
' Execute dir command and save result in log file
WshShell.Exec(strCommandLine)
' Open log file
WshShell.Run(strLogFileName)
End If
Create backup ZIP file of given project folder
Sometimes it can be useful to create a temporary backup of your source code, even if you are using a version control system. So I needed a small script which will backup my sources in a ZIP file and store it with a unique name (with date and time) in my backup folder.
For creating ZIP files within a VB script, I'm using the Winzip command line add-on. This is a small executable with the name WZZIP.EXE. It can be started with a lot of command line parameters. Because the command window is closed after executing, you can't see the result. So I always redirect the command (DOS) output to a log file.
Program | C:\WINDOWS\system32\wscript.exe |
Parameters | $SAVEALL "C:\Program Files\Borland\BDS\3.0\Scripts\BackupProject.vbs" $PROJECT |
BackupProject.vbs
Dim WshShell, Fso, Args
Set WshShell = CreateObject("WScript.Shell")
Set Fso = CreateObject("Scripting.FileSystemObject")
Set Args = WScript.Arguments
Function GetDateTimePart(strPart)
GetDateTimePart = DatePart(strPart,Now())
If Len(GetDateTimePart) < 2 Then
GetDateTimePart = "0" & GetDateTimePart
End If
End Function
' Create datetime string yyyymmdd_hhnn
Function GetFormattedDateTime
GetFormattedDateTime = GetDateTimePart("yyyy") & GetDateTimePart("m") & GetDateTimePart("d")
& "_" & GetDateTimePart("h") & GetDateTimePart("n")
End Function
If Args.Count = 0 Then
MsgBox "No project given", 16, "Error"
Else
q = Chr(34)
' Set paths and filenames
strProjectName = Fso.GetBaseName(Args(0))
strProjectFolder = Fso.GetParentFolderName(Args(0))
strZipExe = "C:\Program Files\Winzip\WZZIP.exe"
strBackupFolder = "D:\Backup"
strZipLogFileName = strBackupFolder & "\BackupProjectLog.txt"
' Set name of zip file with project name and date and time
strZipFileName = strBackupFolder & "\" & strProjectName & "_" & GetFormattedDateTime & ".zip"
' Create backup folder if it does not exists
If Not Fso.FolderExists(strBackupFolder) Then
Fso.CreateFolder(strBackupFolder)
End If
' Create ZIP file in backup folder and save log file
strCommandLine = "cmd /c > " & q & strZipLogFileName & q & " " & q & strZipExe & q
& " -r -p " & q & strZipFileName & q & " " & q & strProjectFolder & q
WshShell.Exec(strCommandLine)
End If
Compile application with DCCIL.exe (.NET CF preview compiler)
In David Cleggs Delphi for .NET Compact Framework Preview Quickstart Guide he shows a batch file to compile a Delphi .NET application with the Borland .NET Compact Framework Preview Compiler (DCCIL.EXE). The result of the compilation will be shown in a command window.
Nice, but it would be better if the result is saved in a log file. So I have written a VB script which does the same but the output is redirected to a log file and afterwards this log file will be opened. I have chosen to use the "PAS" extension for the log file so it will open in my Delphi IDE. This makes it easier to solve the errors which are outputted by the .NET CF compiler.
Program | C:\WINDOWS\system32\wscript.exe |
Parameters | $SAVEALL "path\CompileNETCF.vbs" $NAMEONLY($PROJECT) $PATH($PROJECT) |
CompileNETCF.vbs
' CompileNETCF.VBS
' Compile project with Delphi 2005/2006 .NET Compact Framework Compiler (DCCIL)
' August 2005 / February 2006 - Stefan Cruysberghs
' Delphi tools properties
' * Program : C:\WINDOWS\system32\wscript.exe
' * Parameters : $SAVEALL "path\CompileNETCF.vbs" $NAMEONLY($PROJECT) $PATH($PROJECT)
Dim WshShell, Fso, Args, Exec, i
Set WshShell = CreateObject("WScript.Shell")
Set Fso = CreateObject("Scripting.FileSystemObject")
Set Args = WScript.Arguments
If Args.Count = 0 Then
MsgBox "No Delphi project given", 16, "Error"
Else
strProjectName = Args(0)
strProjectFolder = ""
For i = 1 To Args.Count-1
strProjectFolder = strProjectFolder & " " & Args(i)
Next
strProjectName = Trim(Fso.GetBaseName(strProjectName))
strProjectFolder = Trim(Fso.GetParentFolderName(strProjectFolder))
strProject = strProjectFolder & "\" & strProjectName & ".dpr"
If Not Fso.FileExists(q & strProject & q) Then
MsgBox strProject & " does not exist", 16, "Error"
Else
q = Chr(34) 'quote
' Set paths Delphi 2006
strDCCIL = "C:\Program Files\Borland\BDS\4.0\Bin\dccil.exe"
strCFUnits = "C:\Program Files\Borland\BDS\4.0\lib\cf"
' Set paths Delphi 2005
' strDCCIL = "C:\Program Files\Borland\BDS\3.0\CFPreview\Bin\dccil.exe"
' strCFUnits = "C:\Program Files\Borland\BDS\3.0\CFPreview\Lib"
strLogFileName = strProjectFolder & "\CompileCFNETLog.pas"
' Extra compiler options. If .NET CF assemblies are not available/needed, set it to ""
strCompilerOptions = ""
'strCompilerOptions = " -lu" & q & "C:\NETCFAssemblies\Microsoft.WindowsCE.Forms.dll"
' & q & " -lu" & q & "C:\NETCFAssemblies\System.Windows.Forms.DataGrid.dll" & q
' Delete all .dcuil files
On Error Resume Next
Fso.DeleteFile strProjectFolder & "\*.dc?il", True
strCommandLine = "cmd /c > " & q & strLogFileName & q & " " & q & strDCCIL & q & " "
& q & strProject & q & " -u" & q & strCFUnits & q
& " -luSystem.Windows.Forms -luSystem.Data " & strCompilerOptions
' Compile the project with the DCCIL.exe
Set Exec = WshShell.Exec(strCommandLine)
' Wait for application to exit
Do While Exec.Status = 0
WScript.Sleep 1
Loop
' Show the log file (when extention of log is PAS, it will be opened in Delphi)
WshShell.Run(q & strLogFileName & q)
End If
End If
Remove the enters in the command line rule because this should be one source line !
Registry
If you like to take a backup of your customized tools menu, then you have to export the Transfer keys in the Windows registry.
Delphi 7
- HKEY_CURRENT_USER\Software\Borland\Delphi\7.0\Transfer
Delphi 2005
- HKEY_CURRENT_USER\Software\Borland\BDS\3.0\Transfer
Delphi 2006
- HKEY_CURRENT_USER\Software\Borland\BDS\4.0\Transfer
Afterwards you can import the REG file on other Delphi developer PC's or on your own PC after a clean install.