View RSS Feed

Development Team Blog

Inside the Studio: Reading Workspace Paths (part 2)

Rate this Entry
In the previous article I introduced the config file that the Studio generates each time it launches a Create New wizard. The name and path of this config file is passed to the launched application and the file contains information about your project that is useful to a Create New wizard application.

In this article I will talk in more detail about one particular section of data in the config file: the [Workspace] section.

Disclaimer: The information presented here describes implementation details that are undocumented and are internal to the Studio. Feel free to use this information as you require but at your own risk. Data Access does not pretend to support these techniques and reserves the right to change the way this works at their discretion.

Name=C:\Visual DataFlex 15.1 Examples\Order Entry\Order Entry.sws
The Studio Workspace File (.sws)

The first name/value pair in this section contains a reference to the current workspace's .sws file (Studio Workspace Settings). This is a config (.ini) file that is used by the Studio when it is opening a workspace. It contains information that the Studio needs to set up the workspace's environment including all of the various local workspace directory paths.

Create New wizards need to this information to know where to locate the files that are generated. Below is the .sws file for the Order Entry example workspace:

The [Properties] section contains the "version" string. This tells the Studio which version of Visual DataFlex this workspace is compatible with. The Migration Wizard updates this string after it has migrated a workspace to the current version.

The [WorkspacePaths] section contains a reference to the workspace's file. This is the file that is deployed with your application that stores all of the workspace's pathing information used by your application (e.g. the Data folder). This file also contains workspace pathing information that is relevant to the Studio and your Create New wizard. We will look at this file in closer detail below.

The [Projects] section contains the list of all project files that are registered in this workspace. You can see this list of projects when you drop down the Current Project combo list in the Studio's Workspace Explorer.

To get access to the various directory paths associated with the workspace you must open the file. The ConfigFile value contains a relative reference to the workspace's file. That means that the file reference is relative to the location of the .sws file.

In the above example the .sws file is located in C:\Visual DataFlex 15.1 Examples\Order Entry. The file is located in .\Programs relative to that which means that the full path to the file is:

C:\Visual DataFlex 15.1 Examples\Order Entry\Programs\

In the last article I gave an example of how to retrieve the name of the temporary config file that is passed to a Create New wizard via the command line. The example code below demonstrates how you can retrieve the name and path of the workspace's file from this temporary config file.

Use Winkern.pkg    // contains references to external functions (e.g. SetCurrentDirectory)

// FullPathName:

// Convert a short name or qualified name with relative references to a long name.
// Relative path is converted with respect to the current working directory. 
// (see Get_Current_Directory and SetCurrentDirectory).
// This works even if the directories don't exist - this does more a syntatical check
// e.g.  c:\MyApp\..\MyApp\appsrc ----> c:\MyApp\appsrc
//                  \MyApp\appsrc ----> c:\MyApp\appsrc  
Function FullPathName Global String sRelPathName Returns String
    String sFullPathName
    Pointer lpsFullPathName
    Pointer lpsFilePart
    Integer icChar // the number of characters returned
    Move (Repeat(character(0), 4096)) to sFullPathName
    GetAddress of sFullPathName to lpsFullPathName
    Move -1 to lpsFilePart
    Move (GetFullPathName(sRelPathName, 4096, lpsFullPathName, AddressOf(lpsFilePart))) to icChar
    Function_Return (trim(sFullPathName))
End_Function  // FullPathName

// GetConfigWSFile:
Function GetConfigWSFile String sTempFile Returns String
    Handle hoTempFile hoSWSFile
    String sSWSFile sRelativePath sConfigWSFile 
    String sCurDirectory sOldCurDirectory 
    Boolean bOK
    Get Create (RefClass(cIniFile)) to hoTempFile
    Get Create (RefClass(cIniFile)) to hoSWSFile
    // Get Create U_cIniFile to hoTempFile  <- pre VDF 15.1 you must write it this way
    // Get the .sws filename...
    Set psFileName of hoTempFile to sTempFile
    Get ReadString of hoTempFile "Workspace" "Name" "" to sSWSFile
    // open the .sws file and get the relative path to the config file...
    Set psFileName of hoSWSFile to sSWSFile
    Get ReadString of hoSWSFile "WorkspacePaths" "ConfigFile" "" to sRelativePath
    // convert the relative path to an absolute path....
    Get_Current_Directory to sOldCurDirectory
    Move (ExtractFilePath(sSWSFile)) to sCurDirectory    // must set the current directory to location of,
    Move (SetCurrentDirectory(sCurDirectory)) to bOK    // the .sws file before calling FullPathName
    Move (FullPathName(sRelativePath)) to sConfigWSFile  // converts relative path to absolute path
    Move (SetCurrentDirectory(sOldCurDirectory)) to bOK  // restore the previous current directory setting
    Send Destroy to hoTempFile  // remove these objects from memory
    Send Destroy to hoSWSFile
    Function_Return sConfigWSFile
End_Function  // GetConfigWSFile
The first line in this code is a Use WinKern.pkg. This compiles in two important external_function declarations:

  • GetFullPathName - This function merges the name of the current directory with the passed directory path to produce a full absolute directory path.
  • SetCurrentDirectory - This function sets the current directory that is used by the call to GetFullPathName.

The first function declaration FullPathName is a wrapper to the GetFullPathName Windows API function. The next function GetConfigWSFile is passed the name and path to the temporary config file which generated for the Create New Wizard and returns the name and path of the workspace's file.

Below is a copy of the file for the Order Entry sample workspace:

Description = Order Entry Example
This data represents the workspace directory information that was specified in the Create New Workspace wizard when this workspace was first created. Each workspace path is specified by its own name/value pair in the file's [Workspace] section. You can read about the various workspace paths and what they mean in the online help under the following table of contents topic: Development Tools, Studio, Studio Concepts, Workspaces and Libraries.

Each of these paths can be specified either as an absolute directory path (e.g. c:/projects/orders/AppSrc) or a relative path (e.g. ../AppSrc). Normally, the paths are relative as this makes the workspace more versatile and portable.

The AppSrc path can contain a semicolon (;) delimited chain of directories. The first AppSrc directory is know as the primary AppSrc directory. The other paths in this list normally only contain a reference to one directory.

The key to decoding any relative path references is the "Home" value. The Home value is the path to the workspace's root folder. All relative pathing in the remaining paths are relative to the Home directory. The Home value is itself normally expressed as a relative path. In this case it is the path to the root folder relative to the location of

The following code demonstrates how to extract the absolute path to the primary AppSrc directory from a workspace's file:

Function GetPrimaryAppSrcPath String sConfigSWFile Returns String
    String sRelativePath sHome sAppSrc
    String sCurDirectory sOldCurDirectory 
    Handle hoConfigSWFile
    Boolean bOK
    Get Create (RefClass(cIniFile)) to hoConfigSWFile
    Get_Current_Directory to sOldCurDirectory

    Set psFileName of hoConfigSWFile to sConfigSWFile
    // Get the Home directory...
    Move (ExtractFilePath(sConfigSWFile)) to sCurDirectory
    Move (SetCurrentDirectory(sCurDirectory)) to bOK     // set the current dir to location of the config file
    Get ReadString of hoConfigSWFile "Workspace" "Home" "" to sRelativePath
    Move (FullPathName(sRelativePath)) to sHome          // converts relative path to absolute path
    // Get the full AppSrc Path....
    Move (SetCurrentDirectory(sHome)) to bOK            // set the current directory to the Home dir
    Get ReadString of hoConfigSWFile "Workspace" "AppSrcPath" "" to sRelativePath
    Move (FullPathName(sRelativePath)) to sAppSrc       // converts relative path to absolute path
    // Extract the first directory from the full path....
    Get PathAtIndex  of (phoWorkspace(ghoApplication)) sAppSrc 1 to sAppSrc

    // clean up....
    Move (SetCurrentDirectory(sOldCurDirectory)) to bOK  // restore the previous current directory setting
    Send Destroy to hoConfigSWFile
    Function_Return sAppSrc
End_Function  // GetPrimaryAppSrcPath
In part three of this series we will look at the DDClassList xml file that is passed to each Create New wizard and look at how this can be used to choose the correct data dictionary class for any table.