Q: My VB6 system has a lot of code files that are shared by different VBPs, How can I consolidate these into assemblies and reference them from their?
A. User the ShareFile Migration process.
Overview
The default translation process for a VBP creates a .NET version of each code file referenced by the VBP. If multiple VBPs reference the same code file, there will be multiple copies of the shared file translations: one for each VBP. Restructuring the generated code files to remove this duplication is a common upgrade feature that we call Shared Files Consolidation. Many different configurations of code files are feasible. The constraints arise from the external dependencies that are contained within each file that must still be satisfied after conversion without creating build cycles or other conflicts.
For a large-scale VB6 application with shared files, it is possible to reproduce something close to the structure of the legacy app using .NET linked files
, but linked files are still not a straight conversion: we would have to make some decisions and also deal with assigning and using namespaces. Code file linking has other disadvantages for builds and deployments so it has a higher cost of ownership. Consequently, there is some value in hosting each shared file in only one assembly and referencing it there. gmStudio can help implement this re-hosting process.
Assuming we want to go with hosting
rather than linking
, we begin with a guiding principle: each file should be referenced by at most one assembly (the host). Once in that host, the file will become a class in the namespace of the host. If a class is used by other assemblies, those others must reference the host assembly and use the shared class members through the host namespace. But, as always, the problems are in the details.
Regarding shared files, we offer these options:
Make an independent copy of the shared file for each referencing project. This is the default, and it is typically used only for the initial iterations of upgrade solution development.
Compile the shared file into one of the translated projects and reference the shared file content through that host project. This is done using the
"SharedFile
" statement described in this article.Put a single copy of the shared file in a specified location in the source directory and reference the shared file content through a link to the shared file. This can be achieved fairly easily with a few PostEdit commands in the translation script; however additional work is also needed to set a namespace for the linked file and then use that namespace in references to the contents of the file.
How To: Shared Files Consolidation
Shared Files Consolidation is a three step process:
1) Translate VBPs to produce desired VBI files
2) Prepare a ShareFile script and process it using the SharedFile utility: gmSharedFile \ABCTeam\csh\SharedFile.xml (see discussion of how to integrate this with your project below).
3) Use ShareFiles commands in a second set of translation scripts to produces consolidated translations
Example:
In this example, the shared files are into ABCCommon.VBP. Note: ABCCommon.VBP does not need to actually exist on the legacy side. It may be a VBP developed by hand, adding references to COM and Code files as needed.
SharedFile.xml
Used in Step 2: gmSharedFile \ABCTeam\csh\SharedFile.xml
Notice that two outputs are specified:
<SharedFile ReportFile="\ABCTeam\csh\SharedFile.out" RegistryFile="\ABCTeam\proj\usr\Registry_SharedFile" >
SharedFile.out is a log file for informational purposes
Registry_SharedFile.xml is a file that will contain the SharedFile commands to direct shared file consolidation in Step 3.
<gmBasic> <Storage Action="Create" Identifier="SharedFile" /> <select Target="\ABCTeam\proj\usr" /> <Select Local="\ABCTeam\proj\idf\FromCode" /> <Select System="\ABCTeam\proj\idf\FromIdl" /> <Load project="\ABCTeam\src\ABC\Applications\ABCCommon\ABCCommon.vbp" SourceCode="On" /> <Load project="\ABCTeam\src\ABC\Applications\ABCCheck\ABCCheck.vbp" SourceCode="On" /> <Load project="\ABCTeam\src\ABC\Applications\ABCClock\ABCClock.vbp" SourceCode="On" /> <Load project="\ABCTeam\src\ABC\Applications\ABCEmailReport\ABCEmailReport.vbp" SourceCode="On" /> <Load project="\ABCTeam\src\ABC\Applications\ABCKey\ABCKey.vbp" SourceCode="On" /> <Load project="\ABCTeam\src\ABC\Applications\ABCManage\ABCManage.vbp" SourceCode="On" /> <Load project="\ABCTeam\src\ABC\Applications\ABCMonitor\ABCMonitor.vbp" SourceCode="On" /> <Load project="\ABCTeam\src\ABC\Applications\ABCRead\ABCRead.vbp" SourceCode="On" /> <Load project="\ABCTeam\src\ABC\Applications\ABCReport\ABCReport.vbp" SourceCode="On" /> <Load project="\ABCTeam\src\ABC\Applications\ABCUpdate\ABCUpdate.vbp" SourceCode="On" /> <Load project="\ABCTeam\src\ABC\Applications\ABCView\ABCView.vbp" SourceCode="On" /> <Output Status="New" Filename="\ABCTeam\csh\Registry_SharedFile.xml" /> <SharedFile ReportFile="\ABCTeam\csh\SharedFile.out" RegistryFile="\ABCTeam\proj\usr\Registry_SharedFile" > <Exclude identifier="\ABCTeam\src\ABC\Applications\glbl-modShift.bas" /> <Exclude identifier="\ABCTeam\src\ABC\Applications\glbl-modSaveSensorDB.bas" /> <VbiFile identifier="\ABCTeam\csh\ABCCommon.vbi" /> <VbiFile identifier="\ABCTeam\csh\ABCCheck.vbi" /> <VbiFile identifier="\ABCTeam\csh\ABCClock.vbi" /> <VbiFile identifier="\ABCTeam\csh\ABCEmailReport.vbi" /> <VbiFile identifier="\ABCTeam\csh\ABCKey.vbi" /> <VbiFile identifier="\ABCTeam\csh\ABCManage.vbi" /> <VbiFile identifier="\ABCTeam\csh\ABCMonitor.vbi" /> <VbiFile identifier="\ABCTeam\csh\ABCRead.vbi" /> <VbiFile identifier="\ABCTeam\csh\ABCReport.vbi" /> <VbiFile identifier="\ABCTeam\csh\ABCUpdate.vbi" /> <VbiFile identifier="\ABCTeam\csh\ABCView.vbi" /> </SharedFile> <Storage Action="Close" /> </gmBasic>
SharedFile.out
This is a log file generated by Step 2. It is information only. The location of this file is set by the SharedFile@ReportFile attribute.
There were 43 Shared Files in this group of projects: Modules = 29, Forms = 8 Classes = 6 The Module file [\ABCTeam\src\ABC\Applications\glbl-Monitor.bas] is shared by 11 projects (1) \ABCTeam\src\ABC\Applications\ABCCommon\ABCCommon.vbp (2) \ABCTeam\src\ABC\Applications\ABCCheck\ABCCheck.vbp (3) \ABCTeam\src\ABC\Applications\ABCClock\ABCClock.vbp (4) \ABCTeam\src\ABC\Applications\ABCEmailReport\ABCEmailReport.vbp (5) \ABCTeam\src\ABC\Applications\ABCKey\ABCKey.vbp (6) \ABCTeam\src\ABC\Applications\ABCManage\ABCManage.vbp (7) \ABCTeam\src\ABC\Applications\ABCMonitor\ABCMonitor.vbp (8) \ABCTeam\src\ABC\Applications\ABCRead\ABCRead.vbp (9) \ABCTeam\src\ABC\Applications\ABCReport\ABCReport.vbp (10) \ABCTeam\src\ABC\Applications\ABCUpdate\ABCUpdate.vbp (11) \ABCTeam\src\ABC\Applications\ABCView\ABCView.vbp The Class file [\ABCTeam\src\ABC\Applications\glbl-Monitor.cls] is shared by 11 projects (1) \ABCTeam\src\ABC\Applications\ABCCommon\ABCCommon.vbp (2) \ABCTeam\src\ABC\Applications\ABCCheck\ABCCheck.vbp (3) \ABCTeam\src\ABC\Applications\ABCClock\ABCClock.vbp (4) \ABCTeam\src\ABC\Applications\ABCEmailReport\ABCEmailReport.vbp (5) \ABCTeam\src\ABC\Applications\ABCKey\ABCKey.vbp (6) \ABCTeam\src\ABC\Applications\ABCManage\ABCManage.vbp (7) \ABCTeam\src\ABC\Applications\ABCMonitor\ABCMonitor.vbp (8) \ABCTeam\src\ABC\Applications\ABCRead\ABCRead.vbp (9) \ABCTeam\src\ABC\Applications\ABCReport\ABCReport.vbp (10) \ABCTeam\src\ABC\Applications\ABCUpdate\ABCUpdate.vbp (11) \ABCTeam\src\ABC\Applications\ABCView\ABCView.vbp The Class file [\ABCTeam\src\ABC\Applications\glbl-Monitors.cls] is shared by 11 projects (1) \ABCTeam\src\ABC\Applications\ABCCommon\ABCCommon.vbp (2) \ABCTeam\src\ABC\Applications\ABCCheck\ABCCheck.vbp (3) \ABCTeam\src\ABC\Applications\ABCClock\ABCClock.vbp (4) \ABCTeam\src\ABC\Applications\ABCEmailReport\ABCEmailReport.vbp (5) \ABCTeam\src\ABC\Applications\ABCKey\ABCKey.vbp (6) \ABCTeam\src\ABC\Applications\ABCManage\ABCManage.vbp (7) \ABCTeam\src\ABC\Applications\ABCMonitor\ABCMonitor.vbp (8) \ABCTeam\src\ABC\Applications\ABCRead\ABCRead.vbp (9) \ABCTeam\src\ABC\Applications\ABCReport\ABCReport.vbp (10) \ABCTeam\src\ABC\Applications\ABCUpdate\ABCUpdate.vbp (11) \ABCTeam\src\ABC\Applications\ABCView\ABCView.vbp ... The Module file [\ABCTeam\src\ABC\Applications\glbl-modLocalPort.bas] is shared by 3 projects (1) \ABCTeam\src\ABC\Applications\ABCCommon\ABCCommon.vbp (2) \ABCTeam\src\ABC\Applications\ABCCheck\ABCCheck.vbp (3) \ABCTeam\src\ABC\Applications\ABCClock\ABCClock.vbp This component has no host file <ABCCommon.AppObject.SSubTimer6_GSubclass> The subprogram <ABCCommon.Monitor.ControlMonitor> is being used as a Variant Function. The defined variant <ABCCommon.Monitor.ControlMonitor.lParam> is being used as a Integer The defined Collection <ABCCommon.modABCShared.GenerateCompleteSortLabel.cmbIN> is not being changed to the using type of Object The defined Collection <ABCCommon.modABCShared.InitSortCombos.cmbIN> is not being changed to the using type of Object ... The defined Collection <ABCCommon.modABCShared.GenerateCompleteSortLabel.cmbIN> is not being changed to the using type of Object The defined variant <ABCCommon.modABCDBFunctions.CheckCloseDB.dbIN> is being used as a ADODB.Connection The defined String <ABCCommon.modABCDBFunctions.ClearBPUDisplay.lblArrayIN> is being used as a Collection. It is refactored The User Type component<frmStartup> referenced by <ABCCheck.frmStartup> is not shared This component has no host file <ABCView.AppObject.SSubTimer6_GSubclass> There is no existing GlobalSetting File selected.
Registry_SharedFile.xml
This is a rules file generated by Step 2. It contains various commands to direct the shared files consolidation. The location of this file is set by the SharedFile@RegistryFile attribute.
<GlobalImports> <Storage Action="Create" Identifier="\ABCTeam\proj\usr\Registry_SharedFile"/> <Registry type="SharedFile" Source="\ABCTeam\src\ABC\Applications\glbl-Monitor.bas" Target="\ABCTeam\src\ABC\Applications\ABCCommon\ABCCommon.vbp;ABCCommon.dll"/> <Registry type="SharedFile" Source="\ABCTeam\src\ABC\Applications\glbl-Monitor.cls" Target="\ABCTeam\src\ABC\Applications\ABCCommon\ABCCommon.vbp;ABCCommon.dll"/> <Registry type="SharedFile" Source="\ABCTeam\src\ABC\Applications\glbl-Monitors.cls" Target="\ABCTeam\src\ABC\Applications\ABCCommon\ABCCommon.vbp;ABCCommon.dll"/> <Registry type="SharedFile" Source="\ABCTeam\src\ABC\Applications\glbl-modPassword.bas" Target="\ABCTeam\src\ABC\Applications\ABCCommon\ABCCommon.vbp;ABCCommon.dll"/> <Registry type="SharedFile" Source="\ABCTeam\src\ABC\Applications\glbl-frmPassword.frm" Target="\ABCTeam\src\ABC\Applications\ABCCommon\ABCCommon.vbp;ABCCommon.dll"/> <Registry type="SharedFile" Source="\ABCTeam\src\ABC\Applications\glbl-modLocalPort.bas" Target="\ABCTeam\src\ABC\Applications\ABCCommon\ABCCommon.vbp;ABCCommon.dll"/> ... <Storage Action="Close"/> </GlobalImports>
Activating SharedFiles migration
The Registry-SharedFile commands generated by the SharedFiles utility should be added to a GlobalSettings script. Processing that GlobalSettings script stores the command in a GlobalSettings VBI file.
Loading the GlobalSettings.VBI file during translation of your VBPs will result in translations that reference shared files in the desired host project(s) rather than locally.
In addition you must Select SharedFile=on, to tell gmBasic to apply SharedFile rules to the translations:
<Select SharedFile="on" /> <Select GlobalSettings="%UserFolder%\GlobalSettings" />
The FMStocks sample demonstrates the ShareFiles migration.
Integrating a gmSharedFile task into your project
If you wish to run gmSharedFile.exe from within gmStudio, you must add a Shared File script to the project that references the SharedFile analysis script and a SharedFile.exe. For example:
Source Name = [ReportSharedFiles] Source Code Path = [C:\GM\Training\FMStocksSample\proj_csh\usr\ReportSharedFiles.xml] .NET Project Path = [\GM\Training\FMStocksSample\proj_csh\deploy\-\FMSLib_csh.csproj] .NET Project Folder = [\GM\Training\FMStocksSample\proj_csh\deploy\-] Task Tag = [std] Dialect = [csh] Source Task Type = [XML] Build Path = [] Build Type = [MULTI] Source Lines = [ 48] Internal Name = [-] Dependency Status = [ ?] Translation Status = [SUCCESS] .NET Lines = [-1] .NET Build Status = [ ?] Build Order = [_9999] Source Location = [C:\GM\Training\FMStocksSample\proj_csh\usr] Source File Name = [ReportSharedFiles.xml] Translation Script = [GMEXECSharedFile:ReportSharedFiles.xml] <--- NOTICE: GMEXECShared: prefixes the Translation Script name Task Command Script = [UserCmds.cmd] Migration Name = [FMSLib_csh] Last Message = [TRANSLATE: COMPLETED; 2024/01/24 11:20:55] Task Comment = [ADDED='2024/01/24 11:14:40'] Task Description = [] Code Bundle Path = [C:\GM\Training\FMStocksSample\proj_csh\log\FMSLib_csh-ReportSharedFiles-std-csh.bnd] TaskGuid = [DB647C65-0865-CA2D-BDBF-42F9EFD0DD90]
Where GMExecShared is specified in the project settings dialog:
Now when we run the task in gmStudio, gmSharedFile will process the SharedFile script instead of gmBasic: