PxPlus User Forum

Twitter Twitter Twitter

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - PxPlus

Pages: 1 ... 4 5 [6] 7
76
Tips and Techniques / Correcting duplicate Unique keys
« on: May 31, 2018, 10:47:14 AM »
If during the course of building a key tree for a data file the system detects that a duplicate key exists, the system will display the following message.

    Duplicate key found at NNNNN

The value displayed in NNNNN is the logical record address or index which can be used to locate and read the effected record.

To correct this problem read the record using an IND=NNNNN clause, change/correct the key field(s) and issue a WRITE to update the record. The system will remove the incorrect key pointer and insert the appropriate new key pointer.

For Example lets create a file which ultimately will have duplicate keys:

    ->keyed "keyfle",[1:1:6]
    ->open (1) "keyfle"
    ->write (1) "000001","123456"
    ->write (1) "000002","123456"
    ->close (1)

Add the index which will cause the problem:

    ->add index [2:1:6:"U"] to "keyfle"
    Duplicate key found at index 2050
    Done - loaded key number 1 with 2 keys

During the addition of the new key the system will attempt to load the key trees. Any errors will be reported both on the screen and, on PxPlus, the system logfile (see below).

To repair the records read by the record index and change the key:

    ->open (1) "keyfle"
    ->read (1,ind=2050) a$,b$
    ->print a$,b$
    000002123456
    ->b$="999999"
    ->write (1) a$,b$

A reload of the keys is not required but can be uses to verify the correction.

    ->keyed load (1)
    Done - loaded key number 0 with 2 keys
    Done - loaded key number 1 with 2 keys

-----------------------------
Note: In PxPlus (build 9180.3 and beyond), whenever a key table is loaded a log is sent of the rebuild process (including errors) to the logfile specified in the INI file for the system. The contents of this logfile can be used to keep track of any records with keys that need to be corrected. On the windows version the output is also sent to the Trace window which itself could be saved to a disk file if necessary.

77
Tips and Techniques / Changing FKEYS in Nomads
« on: May 31, 2018, 10:45:44 AM »
You can override the function keys used.

 %NOMAD_FKEY_HELP
   - Function key to use for HELP
 %NOMAD_FKEY_QRY
   - Function key to use for Query

Setting the above variables to values outside the range of 1 -> 15 will effectively disable the builtin help/query function key recognition.

78
Tips and Techniques / Recovering damaged files and KEYED LOAD
« on: May 31, 2018, 10:43:54 AM »
One of the best/fastest ways to recover a damaged file is to use the KEYED LOAD directive. See https://manual.pvxplus.com/PXPLUS/directives/keyed_load.htm

The KEYED LOAD directive removes the existing key tables for a file then reads through the file physically rebuilding the key tables based on the records it finds.

If the file is VLR the records are all kept in pages/blocks thus the system reads each block from the file, validates that it looks correct (block header intact, record offsets valid, etc..) and if a data block processes all the records found. Now if a block has been overwritten or cannot physically be read then the records that existed on that block are lost (after all they data isn't on disc anymore...) and the file should be recovered from a backup.

EFF files are similar however the system has to use the file inventory to make sure that it uses the 'Active' data pages instead of 'Old/Shadow' data pages. Other than this, the logic is much the same as VLR.

For FLR files the process is quite a bit different because the records aren't stored in pages whose integrity can be verified. In this case the file is read record by record and each record is checked to see if the record length (and any external key) make sense relative to the file description. If so the system assumes the data found is a valid record.

Because FLR does not employ a record blocking mechanism there is more potential for having garbage data (or old key blocks) misinterpreted as data records.

Now when the KEYED LOAD ends normally then the value is TCB(67) is a sanity check. Basically if not -1 then we were able to read all the data blocks from a file. In the cause of FLR files which multiple keys it does attempt to validate that the number of records found when processing each the key trees match.

If the KEYED LOAD fails with an error then file generally cannot be recovered since there are defective areas (blocks) within the file.

If TCB(67) is not -1 then the record count on each of the key trees matched thus generally the file is fine. If the value is -1 then there was a mismatch however if you had NULL key suppression the -1 is not meaninful (this will be addressed in a future version).

Regardless of the value in TCB(67) though, for VLR and EFF files, its unlikely any other process could retrieve the data due to nature of the file design. For FLR it may be possible to write a program to better examine the records and determine the record validity -- this is where *UFAR and its 'Assumptions' may be useful.   

There is also another VLR file recover program available at:

https://www.pvxplus.com/downloads/misc/fixvlr2

This program can be used to copy the data out of a corrupted data file into a new file (it also supports for multi-segmented files). It reads the file physically and copies any records it finds into the output file.

In many cases this process is faster than *UFAR and can handle data files with major problems including the loss of file header information.

The data dictionary is not preserved and should be reloaded using the Data Dictionary utility.

79
Tips and Techniques / Applying Temporary installation keys
« on: May 31, 2018, 10:37:39 AM »
If you want to simplify the process for your users to install and register your software, the following program can be used to allow them the highlight and copy their registration keys into the clipboard and have the system apply them.

0010 PRINT 'DIALOGUE'(0,0,40,11,"Registration Utililty",'B?',OPT="^"),'SR','CS','OPTION'("CenterWdw"),
0020 CLIP_BOARD WRITE ""
0030 PRINT 'PICTURE'(20,20,120,120,"!SYS_INFO",1),
0040 PRINT ""
0050 PRINT " Please select and ",'BLUE',"COPY",'RM'," the keys"
0060 PRINT " you have been sent."
0070 PRINT
0080 PRINT " Press ESCAPE to cancel"
0090 LET CUR_STS$=""
0100 WHILE 1
0110 LET KEY1$="",KEY2$=""
0120 CLIP_BOARD READ X$
0130 LET STS$="No keys selected"
0140 LET O=MSK(X$,".....-.....-.....-.....-.....")
0150 IF O=0 THEN GOTO SHOW_STS
0160 LET STS$="Only one key selected"
0170 LET KEY1$=X$(O,29),X$=X$(O+29)
0180 LET O=MSK(X$)
0190 IF O=0 THEN GOTO SHOW_STS
0200 LET KEY2$=X$(O,29)
0210 BREAK
0220 SHOW_STS:
0230 IF CUR_STS$<>STS$ THEN PRINT 'IMAGE'(DELETE "STS"),'IMAGE'("STS"),'FONT'("*guifont",2,"BC"),'TEXT'(@X(0),@Y(7),@X(MXC(0)+1),@Y(9),STS$),; LET CUR_STS$=STS$
0240 OBTAIN (0,TIM=.5,BSY=*CONTINUE)*
0250 IF EOM=ESC OR CTL=4 OR CTL=-1999 THEN BREAK
0260 WEND
0270 IF KEY2$="" THEN STOP ! No keys
0280 !
0290 ! Keys have been copied
0300 !
0310 LET X$=ARG(0)
0320 LET X$=X$(1,POS("\/:"=X$,-1))+"pxpreg"
0330 IF POS(" "=X$) THEN LET X$=QUO+X$+QUO
0340 !
0350 ! Get name
0360 !
0370 CALL "*fl.nme",F$
0380 LET N$="Unknown name"
0390 INVOKE WAIT HIDE ENV("COMSPEC")+" /c "+X$+" -v >"+F$
0400 SELECT R$ FROM F$ WHERE POS("Registe"=R$)
0410 LET N$=STP(R$(POS(":"=R$)+1),2)
0420 BREAK
0430 NEXT RECORD
0440 ERASE F$,ERR=*NEXT
0450 PRINT 'POP',
0460 LET N$=SUB(N$,$0D$,"")
0470 !
0480 ! If a demo key we want to init the file
0490 !
0500 IF TCB(33)=799999 THEN LET INIT$=" -i" ELSE LET INIT$=""
0510 !
0520 ! Apply keys
0530 !
0540 INVOKE HIDE WAIT X$+INIT$+" -k "+KEY1$+" -n "+QUO+N$+QUO
0550 INVOKE HIDE WAIT X$+" -k "+KEY2$
0560 MSGBOX "Your registration keys have been applied."+SEP+SEP+"The registration will take effect when you run the program the next time.",N$,"INFO,TOP"
0570 END

It assumes that if the system is running a demo key the file must be re-initialized otherwise it just applies the keys.

There is limited error checking in the above but it should be able to serve as a basis for an activation utility.

80
The default behaviour in the system when issuing the 'CP' mnemonic is to take the current font (which normally is a 12 point font) and multiply by 5/8 rounding up. This results in a 8 point font thus you get:

->open (1) "*pdf*;file=c:\junk.pdf"
->print mxc(1)
 79
->print (1) 'cp',
->print mxc(1)
 119
->end

If however you want, you can override the 'CP' font (and the 'EP' font) using the MNEMONIC directive as in:

->open (1) "*pdf*;file=c:\junk.pdf"
->print mxc(1)
 79
->mnemonic (1) 'cp'="Courier,-7":132,60
->print (1) 'cp',
->print mxc(1)
 136
->

Using a point size of -7 will give you 136 columns.   

81
When you pass is the SMTP Server Name add + ";;" + user$ + ";" + pswd$

Example:

  CALL "*web/email",ERR=SEND_HTML_ERR,FROMADDRESS$,
     "",TOADDRESS$,CCADDRESS$,BCCADDRESS$,SUBJECT$,
     MESSAGE$,ATTACHMENTS$,OPTIONS$,SMTPSERVER$+";;"+user$+";"+pswd$,
     0,0,BODYENCODING$,ERASEIT,ERRORMESG$,SENTDIRECTORY$,SAVEDFILENAME$

This will pass the userid and password specified to the SMTP server.

82
Tips and Techniques / Walking a directory structure
« on: May 31, 2018, 10:34:58 AM »
When reading a directory, subdirectory entries can be identified if the system parameter 'SD' is enabled. When 'SD' is set each subdirectory in a directory will have a trailing directory delimiter ('\' for Windows, '/' for Unix and Linux).

The following logic uses this in order to walk and process a directory structure:

0010 LET SV_SD=PRM('SD')
0020 SET_PARAM 'SD'
0030 LET D$=LWD ! Starting point
0040 GOSUB DO_DIR
0050 SET_PARAM 'SD'=SV_SD; END
0060 !
0070 DO_DIR:
0080 PRINT 'BLUE',D$
0090 SELECT F$ FROM D$ WHERE F$(1,1)<>"."
0100 IF MID(F$,-1)<>DLM THEN GOSUB DO_FILE ELSE GOSUB DO_SUBDIR
0110 NEXT RECORD
0120 RETURN
0130 !
0140 DO_SUBDIR:
0150 LET D1$=D$
0160 LOCAL D$
0170 LET D$=D1$+DLM+STP(F$,1,DLM)
0180 GOSUB DO_DIR
0190 RETURN
0200 !
0210 DO_FILE:
0220 PRINT D$+DLM+F$
0230 RETURN

Note: We also have a routine "dirtree" which can be used, for more information please visit:
https://manual.pvxplus.com/PXPLUS/utilities/dirtree.htm

83
Tips and Techniques / Returning error values/messages
« on: May 31, 2018, 10:31:19 AM »
Often when writting generic routines it is desirable to not only return an error code but also an error message.

A simple technique that can be used to return a error condition and message to a calling application is to use one of the unused system error codes. Within PxPlus, error codes are in the range of from 0 to 255 however most errors code/message are below 200.

To return an application error; select one of these error codes (we suggest 250) and use it in an EXIT nnn directive to report an error to the user. To return an associated error message simply issue a DEF MSG(250)="My Error test" prior issuing the exit then the programmer can use MSG(250) to determine what the cause of the error was.

This has the added advantage that should the error cause the system to return to command mode, the error message will be displayed automatically.

For Example:

-:list
0010 ENTER TYPE$
0020 IF TYPE$<>"A" THEN GOTO BAD_TYPE
0030 ! ...
8000 BAD_TYPE:
8010 DEF MSG(250)="Unable to process Order - Wrong type"
8020 EXIT 250
-:save "tstord
C:\Pvxsrc\tstord
->call "tstord","B"
Unable to process Order - Wrong type
->print err
 250

This approach can be used for called sub-programs and objects.

84
Tips and Techniques / Check_box Write values
« on: May 31, 2018, 10:29:35 AM »
When issuing a WRITE to a Check_box (or Tristate_box) the value written will be interpreted are as follows:

- If the value is one of the translation table values, it's position in the table defines the state (First=off, Second=on, Third=Other for Tristate)
- If the value is "0", "N" or NULL ("") set off
- If the value is "1" set on
- If the value is "2" set to other state (Tristate only)
- Any other value sets the check box on

85
FAQs / Does PxPlus SQL ODBC driver trigger Embedded IO
« on: May 31, 2018, 10:22:29 AM »
Embedded I/O Programs, are PxPlus programs and require a PxPlus environment in which to run.

The ODBC Driver does not require PxPlus, and can be installed on a workstation that has no PxPlus whatsoever therefore the ODBC driver does not use embedded I/O procedures.

If you want/need to have your embedded IO procedure to run against files which are being access by ODBC, we suggest you create a 'View' of the file which will accessible by the ODBC interface and runs within a PxPlus environment thus will honour your embedded IO settings.

86
FAQs / How to configure a Windows Server running CS
« on: May 31, 2018, 10:10:46 AM »
When running PxPlus as a service on Windows systems the system will limit the amount of memory that it will allow the service to use.  This is caused by the fact that Windows has pre-set hard boundaries defined for 'service' memory and 'user/application' memory.

This can often lead to problems trying to connect to a Windows server running the PxPlus Simple CS, Application server, or NTHost/Slave as a service.  You can confirm this is the problem often by instead of running as a service you can run as a desktop application.  If this solves the issue and allows more users to connect, then the problem is with the Windows memory settings.

The problem can often be rectified by changing the default Windows memory settings found in the system registry.

Category:HKEY_LOCAL_MACHINE
Key:\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems[\td]
Entry:Windows

This registry entry will look something like this:

%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16

The values you need to change are found in the SharedSection parameter string which uses the following format to specify heap size:

SharedSection=xxxx,yyyy,zzzz

Where:
  • xxxx specifies the maximum size of the system-wide heap (in kilobytes)
  • yyyy specifies the size of each desktop heap
  • zzzz specifies the size of the desktop heap that is associated with a non-interactive Windows processes

In newer systems, like Windows 10, these are something like:

    SharedSection=1024,20480,768

In older systems, like Win 2003, the standard is:

    SharedSection=1024,3076,512

The values in these settings will dictate the number of concurrent sessions you can have running in the service.  In particular the last value (desktop Heap for non-interactive sessions) will need to be increased to support more than about 40 PxPlus tasks.

Increasing this value will generally allow more users to connect.

    SharedSeciion=1024,20480,2048

We suggest only increasing it by about 512 at a time as setting it too high can cause Windows not to start.  Generally values under 4096 can support most installations.

87
Sometimes it is desirable to know if the user input from a VARDROP_BOX (or VARLIST_BOX) came from user input or selection from the list.

You can determine whether it was user input versus selection by issuing a
   
    VARDROP_BOX READ nnn,X
 
X will return 0 if the user entered the data or be non-zero with the item number from the drop down list.

The 'CurrentItem property has been added to both the VARDROP_BOX and VARLIST_BOX controls with build 9162 of PxPlus which can be used to determine whether the input was from the list or not.   

88
Tips and Techniques / Converting to Graphical Reporting
« on: May 31, 2018, 10:02:17 AM »
Within PxPlus, there is a built-in logic to allow you to leave your print statements pretty much as is and output using a proportional font.

Take the following simple example:

0010 BEGIN
0020 OPEN (1)"*winprt*;normal"
0030 PRINT (1)'FONT'("Courier New",1),'DF',
0040 WHILE 1
0050 READ DATA COMPANY$,CUSTNO$,NAME$,ADDR$,OWES,END=*BREAK
0060 IF LINESLEFT<1 OR COMPANY$<>CURCOMP$ THEN GOSUB NEWPAGE
0070 PRINT (1)CUSTNO$,@(10),NAME$,@(40),ADDR$,@(70),OWES:"-$###,##0.00"
0080 LINESLEFT--
0090 WEND
0100 END
0110 !
0120 NEWPAGE:
0130 IF PAGENO<>0 THEN PRINT (1)'FF',
0140 PAGENO++
0150 PRINT (1)"Page:",PAGENO:"###0",@(30),"Client list for "+COMPANY$
0160 PRINT (1)
0170 PRINT (1)"Client",@(10),"Name",@(40),"Address",@(70),"Balance"
0180 PRINT (1)"------",@(10),DIM(20,"-"),@(40),DIM(20,"-"),@(70),"------------"
0190 PRINT (1)
0200 LET LINESLEFT=50
0210 LET CURCOMP$=COMPANY$
0220 RETURN
0230 DATA "ABC","000047","Cyclops Car Dealer","6675 Cherry",3.12
0240 DATA "ABC","000122","Global Undergarments","823 Maple Lodge Court",99.54
0250 DATA "ABC","000192","The Hungry Incorporated","5582 2nd Avenue",.55
0260 DATA "ABC","000295","The Hungry Magazine","8576 Major Mackenzie",71.74
0270 DATA "ABC","000310","New Dimensions Company","8052 Center Avenue",5.93
0280 DATA "ABC","000332","Cyclops Computing","7723 Fantasy Island",7.61
0290 DATA "DEF","000355","Kitty Kay Undergarments","2124 Major Mackenzie",4.55
0300 DATA "DEF","000385","New Age Importers","1743 Allstate Parkway",73.84
0310 DATA "DEF","000461","SOTA Golf club","4377 Major Mackenzie",63.66
0320 DATA "DEF","000555","Mike was here","8450 Buga-Buga Drive",11.43
0330 DATA "DEF","000598","Yorktown Body Shop","5674 One-way Street",8.53
0340 DATA "DEF","000874","Elephant Importers","8656 Main",74.63
0350 DATA "DEF","000899","Silly Walks Computing","3920 North Tacoma",60.31
0360 DATA "DEF","000978","Crimson Magazine","2303 Steep Hill Drive",86.16
0370 DATA "DEF","001072","Flagship Trading Limited","2782 Aurora Road",90.15
0380 DATA "DEF","001081","Snap Dragon Grocers","3682 East West Street",49.51

Basically the above is a simple print routine using a standard fixed width font. In order to pretty this report up you probably will want to use a proportional text.

Normally this would cause a problem because names and address in a proportional text occupy different widths but with PxPlus and if you are using the normal @(..) positioning the system will take care of this.

So change line 40 to

0030 PRINT (1)'FONT'("Arial",1),'DF',

The columns remain lined up. What's more is that PxPlus even detects the fact that you are printing numeric data for the balance column thus it right justifies aligning the data on the decimal point.

Now if you look at the output from the above you will notice that the dashed lines don't line up because a dash in Arial is not wide enough. You can fix this by adding a PRINT '+S' which replaces fields consisting of dashes, underscores, or equal signs with solid lines of the proper width, so line 30 becomes:

0030 PRINT (1)'FONT'("Arial",1),'DF','+S',

Internally the PxPlus logic is to re-position the output based on the CPI or average default character width whenever an @(..) is found. If the output is numeric the field will be right justified (aligned to last digit or decimal point) -- this will assure alignment if all numeric output contains a consistent format mask.

Another thing -- this logic supports 'BB'/'EB' to control BOLD print and 'BU'/'EU' for underscores. So try:

0150 PRINT (1)"Page:",PAGENO:"###0",@(30),'BU','BB',"Client list for "+COMPANY$,'EU','EB'

0170 PRINT (1)'BB',"Client",@(10),"Name",@(40),"Address",@(70),"Balance",'EB'

Using these built in features means you can clean up many of your reports -- perhaps just then having to change the page header to use a "Fancy" font.

89
Tips and Techniques / Printing PDF files using Windows system help
« on: May 31, 2018, 09:59:10 AM »
If you want to print a PDF file when running under Windows (or via Windx), one of the easiest techniques is to use the Windows Shell to determine how to print the file.

The following program invokes the Windows shell to print all PDF files in a directory using Adobe:

0010 ! Utility to print all PDF's in a directory
0020 ! Developed by PVX Plus Technologies
0030 ! Written by: Mike King - Nov 2005
0040 !
0050 SELECT F$ FROM "." WHERE LCS(MID(F$,-4))=".pdf"
0060 LET TRU_PATH$=LWD+DLM+F$+$00$
0070 LET A=DLL("SHELL32.DLL","ShellExecuteA",0,"print"+$00$,TRU_PATH$,0,0,0)
0080 WAIT 1
0090 NEXT RECORD
0100 !
0110 ! Find Adobe and terminate it
0120 !
0130 LET WINAPI=NEW("*obj/winapi")
0140 !
0150 FOR I=1 TO 20
0160 WAIT 1 ! give it a second to complete
0170 LET WDWHDL=WINAPI'FINDWINDOW("Adobe Reader"+$00$,"")
0180 IF WDWHDL<>0 THEN WINAPI'SENDMESSAGE(WDWHDL,16,0,0); BREAK
0190 NEXT
0200 !
0210 DROP OBJECT WINAPI
0220 END

The logic consists of passing the full pathname of each PDF file to the Shell and asking it to print. Once done, the system looks for a window titled "Adobe Reader" and if found sends it a Window Close request.

90
For the "location" of a Windows printer you need to read the following registry entry

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\<printer name>\Location

Where <printer name> is the name of the printer.

You can use the following logic in your programs to get this value:

 LET OBJ_WINAPI=NEW("*obj/winapi")
 LET REGKEY$="HKEY_LOCAL_MACHINE"
 LET REGSUBKEY$="SOFTWARE\Microsoft\Windows NT\" +
      "CurrentVersion\Print\Printers\"
!
! Add the printer name you got from WINPRT_SETUP LIST
!
 LET REGSUBKEY$+="hp psc 1200 series"
 LET NAME$="Location"
 OBJ_WINAPI'GETREGISTRYVALUE(REGKEY$,REGSUBKEY$,NAME$,VALUE$)
!
 PRINT "Location is:",VALUE$
!
 DROP OBJECT OBJ_WINAPI 

Pages: 1 ... 4 5 [6] 7