Example 1:
For example, to load the runtime DLL file PBORC190.dll from where PowerBuilder IDE is installed, you write code differently between 2019 R3 and 2019 R2.
Also note that the file name PBORC190.dll in 2019 R2 has been changed to PBORC.dll in 2019 R3.
Original code in 2019 R2:
hORCALibrary = AfxLoadLibrary("PBORC190.dll"))
Modified code in 2019 R3:
This code example hard-codes the path of IDE and runtime, if you want to read the directory from the registry, use the next example.
//First, defines the AddEnvironmentPath method BOOL AddEnvironmentPath(LPCTSTR lpAddPath) { TCHAR szSysPath[1024 * 8] = { 0 }; TCHAR szNewPath[1024 * 8] = { 0 }; if(0 == GetEnvironmentVariable(_T("path"), szSysPath, 1024 * 8)) return FALSE; _tcscpy_s(szNewPath, lpAddPath); _tcscat_s(szNewPath, _T(";")); _tcscat_s(szNewPath, szSysPath); if(0 == SetEnvironmentVariable(_T("path"), szNewPath)) return FALSE; return TRUE; } //Adds the path of runtime file before loading the runtime DLL //The path needs to be updated when PB is upgraded AddEnvironmentPath(_T("C:\\Program Files (x86)\\Appeon\\Common\\PowerBuilder\\Runtime 19.2.0.2566")); AddEnvironmentPath(_T("C:\\Program Files (x86)\\Appeon\\PowerBuilder 19.0\\IDE\\")); (hORCALibrary = AfxLoadLibrary("PBORC.dll")
Or you can write code like this in 2019 R3 which reads the path of IDE and runtime from the registry instead of the hard-coded path:
//First, defines the AddEnvironmentPath method //AddEnvironmentPath(_T("19.2.0.1080"), _T("19")); //AddEnvironmentPath(_T("19.2.0.1080"), NULL); BOOL AddEnvironmentPath(LPCTSTR lpRuntimeVersion, LPCTSTR lpIDEShortVersion) { LONG lRet = 0; HKEY hkReg = NULL; TCHAR szIDEPath[MAX_PATH] = { 0 }; TCHAR szRTPath[MAX_PATH] = { 0 }; TCHAR szIDEName[MAX_PATH] = { 0 }; TCHAR szTmpRTPath[MAX_PATH * 2] = { 0 }; TCHAR szTmpIDEPath[MAX_PATH * 2] = { 0 }; TCHAR szSysPath[1024 * 8] = { 0 }; TCHAR szNewPath[1024 * 8] = { 0 }; TCHAR szRegPath[MAX_PATH] = { 0 }; DWORD cbLen = MAX_PATH * sizeof(TCHAR); DWORD dwType = REG_SZ; //Reads runtime path from registry if (NULL == lpRuntimeVersion) return FALSE; wsprintf(szRegPath, _T("%s\\%s"), _T("Software\\Sybase\\PowerBuilder Runtime"), lpRuntimeVersion); lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegPath, 0, KEY_QUERY_VALUE, &hkReg); if ((ERROR_SUCCESS != lRet) || (NULL == hkReg)) return FALSE; lRet = RegQueryValueEx(hkReg, _T("Location"), 0, &dwType, (LPBYTE)szRTPath, &cbLen); RegCloseKey(hkReg); if (_tcslen(szRTPath) <= 0) return FALSE; wsprintf(szTmpRTPath, _T("%s;%s\\X64;"), szRTPath, szRTPath); //Reads IDE path from registry if (lpIDEShortVersion && _tcslen(lpIDEShortVersion) > 0) { hkReg = 0; wsprintf(szRegPath, _T("%s\\%s.0"), _T("Software\\Sybase\\PowerBuilder"), lpIDEShortVersion); lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegPath, 0, KEY_QUERY_VALUE, &hkReg); if ((ERROR_SUCCESS != lRet) || (NULL == hkReg)) return FALSE; cbLen = MAX_PATH * sizeof(TCHAR); lRet = RegQueryValueEx(hkReg, _T("Location"), 0, &dwType, (LPBYTE)szIDEPath, &cbLen); cbLen = MAX_PATH * sizeof(TCHAR); lRet = RegQueryValueEx(hkReg, _T("IPS Name"), 0, &dwType, (LPBYTE)szIDEName, &cbLen); RegCloseKey(hkReg); if (_tcslen(szIDEPath) <= 0 || _tcslen(szIDEName) <= 0) return FALSE; wsprintf(szTmpIDEPath, _T("%s\\%s\\IDE;%s\\%s\\IDE\\X64;"), szIDEPath, szIDEName, szIDEPath, szIDEName); } if (0 == GetEnvironmentVariable(_T("path"), szSysPath, 1024 * 8)) return FALSE; _tcscpy_s(szNewPath, szTmpRTPath); _tcscat_s(szNewPath, szTmpIDEPath); _tcscat_s(szNewPath, szSysPath); if (0 == SetEnvironmentVariable(_T("path"), szNewPath)) return FALSE; return TRUE; }
In summary, you need to write code in two steps in version 2019 R3:
Step 1: Define a method that can add a path to the PATH environment variable.
Step 2: Call the method to add the PowerBuilder Runtime and PowerBuilder IDE directories to the PATH environment variable and then load the DLL file.
Note that if the path of IDE or runtime is hard-coded in the scripts, make sure to update the path accordingly if PowerBuilder Runtime and IDE are upgraded to a new version.
Example 2:
If you have source code like below which determines the PowerBuilder versions according to the class name, you will need to change the code accordingly.
Original code in 2019 R2:
Environment le_env GetEnvironment(le_env) //Determines position of window within microhelp bar ii_width = st_time.x + st_time.width + 25 this.width = ii_width //Sets object class name choose case le_env.PBMajorRevision case 10, 11, 12 choose case le_env.PBMinorRevision case 5 is_classname = "FNHELP" + & String(le_env.PBMajorRevision) + "5" case 6 is_classname = "FNHELP" + & String(le_env.PBMajorRevision) + "6" case else is_classname = "FNHELP" + String(le_env.PBMajorRevision * 10) end choose case else is_classname = "FNHELP" + String(le_env.PBMajorRevision * 10) end choose //Sets parenthood this.wf_setparent()
Modified code in 2019 R3:
choose case le_env.PBMajorRevision case 10, 11, 12 choose case le_env.PBMinorRevision case 5 is_classname = "FNHELP" + & String(le_env.PBMajorRevision) + "5" case 6 is_classname = "FNHELP" + & String(le_env.PBMajorRevision) + "6" case else is_classname = "FNHELP" + String(le_env.PBMajorRevision * 10) end choose case 17 is_classname = "FNHELP" + String(le_env.PBMajorRevision * 10) case 19 if le_env.PBMinorRevision > 1 then // pb2019 R3 or later: is_classname = "FNHELP" else //pb2019 R2 or earlier: is_classname = "FNHELP" + String(le_env.PBMajorRevision * 10) end if case IS > 19 is_classname = "FNHELP" end choose
Function long GetClassName ( & longptr hWnd, & Ref string lpClassName, & long nMaxCount & ) Library "user32.dll" Alias For "GetClassNameW"
public subroutine wf_setparent ()
String ls_name
LongPtr ll_hWnd
Integer li_rc
//Gets the microhelp handle
ll_hWnd = GetWindow(Handle(gw_frame), 5)
DO UNTIL ll_hWnd = 0
ls_name = Space(25)
li_rc = GetClassName(ll_hWnd, ls_name, Len(ls_name))
If ls_name = is_classname Then
ll_hWnd = SetParent(Handle(this), ll_hWnd)
ll_hWnd = 0
Else
ll_hWnd = GetWindow(ll_hWnd, 2)
End If
LOOP