TMGPAT1 ;TMG/kst/Patching tools ;09/17/08 ;;1.0;TMG-LIB;**1**;09/17/08 ; ;"Kevin Toppenberg MD ;"GNU General Public License (GPL) applies ;"9/17/08 ;"======================================================================= ;" API -- Public Functions. ;"======================================================================= ;"DONEXT -- Ask for package, and install next appropriate patch ;"DONEXTPJ -- do next patch within the same project ;"FIXMISEQ -- allow fixing a missing patch, based on sequence order ;"FIXMISPT -- allow fixing a missing patch, based on patch number ;"DONEXTPK(PckInit,Ver)-- a common entry point ;"GO(Option,Info,Msg) -- Entry point to allow automatic loading and installation of a patch. ;"LOAD -- Entry point to allow manual loading of a patch (like old way, but using new code) ;"======================================================================= ;"Private Functions ;"======================================================================= ;"Logo ;"FixMissing(Mode) allow fixing a missing patch, even if it is out of sequence order ;"FixMisInit(PckInit,Ver,Mode) -- Based on PckInit, and Version, allow fixing a missing patch, even if it is out of sequence order ;"DoFixMissing(IENS,Mode) -- fix a missing patch, even if it is out of sequence order ;"DoIENS(NextIENS,NextPatch,PckDirFName) -- install patch, given IENS to it's entry in 22709.11 ;"GetPckVer(PckInit,Ver) -- query user for package, and desired version ;"GetLastPackage(PckInit,Ver) -- for given package initials, return the last patch applied ;"GetPVIEN(PckInit,Ver,IEN9d4,IEN9d49) -- convert PckInit and Ver into IEN's for file 9.4 ad 9.49 ;"GetLastInst(PckInit,Ver,InstIEN) -- for given package initials, return the last patch applied in INSTALL file ;"GetVers(PckInit,VerArray) --for given package initials, return possible versions ;"PickFile(pArray) -- Pick a filename from a list, in a menu ;"======================================================================= Logo write !!,"===================",! write "TMG Patcher Helper",! write "===================",! quit DONEXT ;"Purpose: Ask for package, and install next appropriate patch do Logo new PckInit,Ver do GetPckVer(.PckInit,.Ver) if Ver="^" goto DNDone do DONEXTPK(PckInit,Ver) goto DONEXT DNDone quit DONEXTPJ ;"Purpose: to do next patch within the same project do Logo new PckInit,Ver new s set s=$get(^TMG("KIDS","PROJECT")) if s'="" do . set PckInit=$piece(s,"^",1) . set Ver=$piece(s,"^",2) else do . do GetPckVer(.PckInit,.Ver) . set s=PckInit_"^"_Ver . set ^TMG("KIDS","PROJECT")=s if Ver="^" goto DNDone do DONEXTPK(PckInit,Ver) DNPJDone quit FIXMISEQ ;"Purpose: to allow fixing a missing patch, based on sequence order do FixMissing(1) quit FIXMISPT ;"Purpose: to allow fixing a missing patch, based on patch number do FixMissing(2) quit FixMissing(Mode) ;"Purpose: to allow fixing a missing patch, even if it is out of sequence order ;" This will prepare, then call DoFixMissing() ;"Input: Mode -- 1: search by SEQ#, 2: search by Patch# do Logo write "Fix missing patches, regardless of order",! new PckInit,Ver do GetPckVer(.PckInit,.Ver) goto:(Ver="^") FMIDone ;"set IENS=$$AskIENS^TMGDBAPI(22709.01) goto:(IENS="") FMIDone do FixMisInit(.PckInit,.Ver,.Mode) FMDone quit FixMisInit(PckInit,Ver,Mode) ;"Purpose: Based on PckInit, and Version, allow fixing a missing patch, even if it is out of sequence order ;" This will prepare, then call DoFixMissing() ;"Input: Mode -- 1: search by SEQ#, 2: search by Patch# set PckInit=$get(PckInit) goto:(PckInit="") FMIDone set Ver=$get(Ver) goto:(Ver="") FMIDone new IENS set IENS=$$GetIENS2^TMGPAT2(PckInit_"*"_Ver) goto:(IENS="") FMIDone do DoFixMissing(IENS,.Mode) FMIDone quit DoFixMissing(IENS,Mode) ;"Purpose: fix a missing patch, even if it is out of sequence order ;"Input: IENS -- should be IENS from file 27709.01 ;" i.e. 'IEN22709d01,IEN22709,' ;" Mode -- 1: search by SEQ#, 2: search by Patch# new PckInit,Ver,Y,PatchName,Msg,PckDirFName new IEN1 set IEN1=+$piece(IENS,",",2) goto:(IEN1'>0) FMSDone new IEN2 set IEN2=+$piece(IENS,",",1) goto:(IEN2'>0) FMSDone new IEN9d4 set IEN9d4=$piece($get(^TMG(22709,IEN1,0)),"^",1) goto:(IEN9d4'>0) FMSDone set PckInit=$piece($get(^DIC(9.4,IEN9d4,0)),"^",2) set Ver=$piece($get(^TMG(22709,IEN1,1,IEN2,0)),"^",1) goto:(Ver="") FMSDone new saveIENS set saveIENS=IENS set Mode=+$get(Mode,1) do MAKFRESH^TMGPAT2(PckInit,.Msg,.PckDirFName) FMLoop new SrchNum,DIR set DIR(0)="N^1:9999:0" if Mode=1 set DIR("A")="Enter missing patch SEQUENCE NUMBER" else set DIR("A")="Enter missing PATCH NUMBER" do ^DIR write ! if $get(DIRUT) goto FMSDone set SrchNum=+Y ;"Search for specified Patch/Seq # new found set found=0 new IEN3 set IEN3=0 new PatchNum set PatchNum=0 new SeqNum set SeqNum=0 for set IEN3=$order(^TMG(22709,IEN1,1,IEN2,1,IEN3)) quit:(IEN3'>0)!found do . set PatchNum=$piece($get(^TMG(22709,IEN1,1,IEN2,1,IEN3,0)),"^",1) . set SeqNum=$piece($get(^TMG(22709,IEN1,1,IEN2,1,IEN3,0)),"^",2) . if (Mode=1),(SeqNum=SrchNum) set found=IEN3 . else if (Mode=2),(PatchNum=SrchNum) set found=IEN3 . if found do . . set IENS=IEN3_","_IENS . . set PatchName=PckInit_"*"_Ver_"*"_PatchNum_" SEQ #"_SeqNum if found=0 do goto FMSDone . write "Sorry. Can't find that Patch/Seq Number in downloaded info from ftp.va.gov",! write "Found: ",PatchName," on ftp.va.gov server.",! ;"Now see if already installed new DIC,X,Y,IEN9d49 ;"set IEN9d49=+$order(^DIC(9.4,IEN9d4,22,"B",Ver,"")) set DIC="^DIC(9.4,"_IEN9d4_",22," set DIC(0)="M" set X=Ver do ^DIC set IEN9d49=+Y if IEN9d49'>0 do goto FMSDone . write "?? Can't find that version in the PACKAGE file",! set found=0 new i set i="" for set i=$order(^DIC(9.4,IEN9d4,22,IEN9d49,"PAH","B",i)) quit:(i="")!found do . new onePatchNum set onePatchNum=$piece(i," ",1) . ;"write onePatchNum,! . if onePatchNum=PatchNum set found=$order(^DIC(9.4,IEN9d4,22,IEN9d49,"PAH","B",i,"")) if found do goto FMSMore . new newIENS set newIENS=found_","_IEN9d49_","_IEN9d4 . write "Sorry, that patch is already installed. IENS='",newIENS,"'",! . do ForceP2^TMGPAT2(PckInit,Ver,PatchNum,SeqNum) new % set %=1 write "Do you want to work on this patch now (out of sequence order)" do YN^DICN write ! if %'=1 goto FMSDone if $$DoIENS(IENS,PatchName,.PckDirFName) ;"actually process patch FMSMore set %=1 write "Fix others in this same Package-Version" do YN^DICN write ! if %=1 do goto FMLoop . set IENS=saveIENS FMSDone quit DONEXTPK(PckInit,Ver) ;"Purpose: a common entry point ;"Input: PckInit -- package initials ;" Ver -- version e.g. '22.0' ;"Result: None new LastPck,NextIENS,NextPatch,LastInst,PckDirFName new Info,Msg,Option,result,restart,InstIEN,abort,chgVer set (abort,restart,chgVer)=0 do MAKFRESH^TMGPAT2(PckInit,.Msg,.PckDirFName) DNP1 set LastPck=$$GetLastPackage(PckInit,Ver) if LastPck="" do goto AllDone . write "Sorry, can't find any installed packges in that version.",! set LastInst=$$GetLastInst(PckInit,Ver,.InstIEN) write "The last patch installed into PACKAGE file was: ",?50,LastPck,! if LastInst="" goto DNP2 write "The last patch loaded into the INSTALL file was: ",?50,LastInst," (FYI)",! if +$piece(LastPck,"SEQ #",2)<+$piece(LastInst,"SEQ #",2) do goto:(restart) AllDone . new % set %=2 . write !,"Undelete entry in INSTALL FILE" do YN^DICN write ! . if %=1 do quit . . do EN1^TMGXPDIU(InstIEN) . . set restart=1 . set %=1 . write "Try to continue with existing files" do YN^DICN write ! . if %'=1 set restart=1 quit if restart goto AllDone DNP2 set NextIENS=$$GetNextIENS^TMGPAT2(LastPck,.NextPatch) new pendingCt set pendingCt=$$Rpt1Avail^TMGPAT3(LastPck) if pendingCt>0 write "Number of pending patches for this package:",?50,pendingCt,! else do goto:(chgVer) DNP1 . if $$RptAvail^TMGPAT3(PckInit)=0 set chgVer=0 quit . do AskVer(PckInit,.Ver) . set chgVer=1 if $$DoIENS(NextIENS,NextPatch,.PckDirFName)=0 goto AllDone More set %=1 write "Do more patch installations in this package" do YN^DICN write !! if %=1 goto DNP1 AllDone quit DoIENS(NextIENS,NextPatch,PckDirFName) ;"Purpose: install patch, given IENS to it's entry in 22709.11 ;"Input: NextIENS -- IENS for entry in 22709.11 ;" NextPatch -- Patch Name of patch to be applied. ;"Results: 1 if OK, 0 if problem. new abort set abort=0 if NextPatch'="" do . write "Next patch to install is: ",?50,NextPatch,! else do goto DNPDone . write "No more patches available for this package.",! . set abort=1 . quit; ;"//kt fix below later... . write "View list of all patches for this package on ftp server" . set %=2 . do YN^DICN write ! . if %=1 if $$EditHFSFile^TMGKERNL(PckDirFName) . if %=-1 set restart=1 quit new Option set Option("VERBOSE")=1 set result=$$EnsureLocal^TMGPAT2(NextIENS,.Info,.Msg,.Option) if result=0 do goto DNPDone . do AddMsg^TMGPAT2("Unable to find patch on local file system.",1,Msg) . if $$ShowMsg^TMGPAT2(.Msg) new % set %=1 if $get(Info("KID FILE"))'="" do PAnalyze^TMGPAT4(.Info,.Option) if $get(Info("TEXT FILE"))'="" do goto:(abort=1) DNPDone . do Analyze^TMGPAT4(.Info,.Option) . new tempMsg . do ShowAnalysis^TMGPAT4(.Info,.tempMsg) . if $$ShowMsg^TMGPAT2(.tempMsg,1) . kill tempMsg . new FilePathName set FilePathName=$get(Info("PATH"))_$get(Info("TEXT FILE")) . set %=1 . write "View INFO FILE for patch" do YN^DICN write ! . if %=-1 quit . if %=1 if $$EditHFSFile^TMGKERNL(FilePathName) . if $get(Info("KID FILE"))="" do . . new FName set FName="" . . if $get(Info("MULTI-PATCH","FILENAME"))'="" do . . . set Info("KID FILE")=Info("MULTI-PATCH","FILENAME") . . else if ($$ListCt^TMGMISC($name(Info("PATCH CATEGORY")))=1)&($data(Info("PATCH CATEGORY","Informational"))) quit . . else if $data(Info("MISC KID FILES")) do . . . write !,"No typical KIDS file found for this patch. However, one or more filenames",! . . . write "were scraped from the TEXT file. Having read the TEXT file, see if one of these",! . . . write "names is correct.",!! . . . set Info("KID FILE")=$$PickFile($name(Info("MISC KID FILES"))) . . if $get(Info("KID FILE"))'="" set Info("TEXT ONLY")=0 . . set FName=$get(Info("KID FILE")) . . if FName="" quit . . set %=2 . . write !,"Attempt to download ",FName," from ftp.va.gov?",! . . write "NOTE: if this file doesn't exist on the server, then the process will HANG.",! . . write "If this happens, then use a utility to abort process #",$J," from OS prompt.",! . . write "Download '",FName,"'" do YN^DICN write ! . . if %'=1 quit . . if $$DownloadPatch^TMGPAT2(FName,"ftp://",.Option,.tempMsg,.Info)=0 . . . write "ERROR: Can't download file: ",Info("KID FILE")," from ftp server.",! . . . do PressToCont^TMGUSRIF . . . ;"handle error here... . . if $$ShowMsg^TMGPAT2(.tempMsg,1) if %=-1 goto DNPDone if $data(Info("STILL NEEDED")) do goto:(abort=1) DNPDone . new pArray set pArray=$name(Info("STILL NEEDED")) . do StoreMissing^TMGPAT3(PckInit,pArray) . write "It seems that the system is not ready for this patch.",! . write "(However, sometimes this can be ignored and one can proceed anyway.)",! . set %=1 . write "Quit this patch and try another" do YN^DICN write ! . if %'=2 set abort=1 if $get(Info("TEXT ONLY"))=1 do goto DNPDone . write "This 'patch' doesn't have a corresponding KID file.",! . write "Perhaps it was informational only. I'm not smart enough to figure that out.",! . write "If you didn't read the INFO FILE, then answer NO, and loop back and read it.",! . set %=2 . write "Ready to consider the patch 'installed'" do YN^DICN write ! . if %'=1 quit . if $$MakePatchEntry^TMGPAT2(NextPatch,.Msg) if $get(Info("KID FILE"))="" do goto DNPDone . write "?? No name for KID file ??",! set %=1 write "Ready to load patch "_Info("KID FILE")_" into system" do YN^DICN write ! if %'=1 set %=-1 goto DNPDone new result set result=$$GO(.Option,.Info,.Msg) quit result GO(Option,Info,Msg) ;"Purpose: Entry point to allow automatic loading and installation of a patch. ;"Input: Option -- PASS BY REFERENCE. Can be an empty array. ;" Info -- PASS BY REFERENCE. ;" Msg -- PASS BY REFERNCE. ;"Results: 1 if OK, 0 if problem. new abort set abort=0 set Option("HFSNAME")=$get(Info("PATH"))_Info("KID FILE") set Option("FORCE CONT LOAD")=1 set Option("DO ENV CHECK")=1 do EN1^TMGXPDIL(.Option,.Msg) new errorFound set errorFound=$$ShowMsg^TMGPAT2(.Msg,1) if errorFound goto DNP3 new InstallName set InstallName=$get(Option("INSTALL NAME")) if InstallName="" do goto DNPDone . write "No installation name found. Aborting.",! . set abort=1 new % set %=1 write "Proceed with installation" do YN^DICN write ! kill Msg new Option ;"... FINISH..., add presets to avoid user interactivity later... set Option("Want to DISABLE Scheduled Options, Menu Options, and Protocols","DEFAULT")="NO" set Option("Want KIDS to INHIBIT LOGONs during the install","DEFAULT")="NO" set Option("Want KIDS to Rebuild Menu Trees Upon Completion of Install","DEFAULT")="NO" if %=1 do EN^TMGXPDI(InstallName,.Option,.Msg) if $$ShowMsg^TMGPAT2(.Msg,1) DNP3 new tempNull if $data(PckInit) do . do StoreMissing^TMGPAT3(PckInit,"tempNull") ;"clear out pending patches... else goto DNPDone set %=1 write "Clean up local files for this patch" do YN^DICN write ! if %=-1 goto DNPDone if %=1 do . new path set path=$get(Info("PATH")) . new fileName set fileName=$get(Info("KID FILE")) . if fileName'="" if $$DelFile^TMGIOUTL(path_fileName) . set fileName=$get(Info("TEXT FILE")) . if fileName'="" if $$DelFile^TMGIOUTL(path_fileName) DNPDone quit (abort=0) LOAD ;"Purpose: Entry point to allow manual loading of a patch (like old way, but using new code) do Logo^TMGPAT1 write ! new FPName,FPath,FName,Msg,Option,Info set FPName=$$GetFName^TMGIOUTL("Select Patch to Load",,,,.FPath,.FName) if (FPName'="")&(FPName'="^") do . set Info("PATH")=FPath,Info("KID FILE")=FName . new result set result=$$GO(.Option,.Info,.Msg) quit GetPckVer(PckInit,Ver) ;"Purpose: query user for package, and desired version ;"Input: PckInit - PASS BY REFERENCE. An OUT PARAMETER. The package initials, e.g. 'DI' in the case of filemant ;" Ver -- PASS BY REFERENCE. An OUT PARAMETER. The version of the package to match. ;"results: none; (if user aborted, Ver="^") set Ver="^" new DIC,X,Y set DIC=9.4,DIC(0)="MAEQ" ;"ask for package name do ^DIC write ! if +Y'>0 goto GPVDone new Package set Package=$piece(Y,"^",2) set PckInit=$piece($get(^DIC(9.4,+Y,0)),"^",2) if PckInit="" do goto GPVDone . write "Error. Unable to obtain package prefix.",! do AskVer(PckInit,.Ver) GPVDone quit AskVer(PckInit,Ver,Package) ;"Purpose: query user for desired version from specified package ;"Input: PckInit - The package initials, e.g. 'DI' in the case of filemant ;" Ver -- PASS BY REFERENCE. An OUT PARAMETER. The version of the package to match. ;" Package -- OPTIONAL. Name of Package. Default is same as PckInit ;"results: none; (if user aborted, Ver="^") new VerArray do GetVers(PckInit,.VerArray) if $data(VerArray)=0 do goto AVrDone . write "Error. No version number available.",! if $get(Package)="" set Package=PckInit ; new Menu,i,Usr set Menu(0)="Select Version of "_Package set Ver="",i=0 for set Ver=$order(VerArray(Ver)) quit:(Ver="") do . set i=i+1 . new tempPatch set tempPatch=PckInit_"*"_Ver_"*1" . new count set count=+$$Rpt1Avail^TMGPAT3(tempPatch) . set Menu(i)="Version "_Ver_" ("_count_" patches pending)"_$C(9)_Ver if i=1 set Ver=$order(VerArray("")) ;"must be only one option, so skip menu else do . set Ver=$$Menu^TMGUSRIF(.Menu,"^") ; AVrDone quit GetPVIEN(PckInit,Ver,IEN9d4,IEN9d49) ;"Purpose: to convert PckInit and Ver into IEN's for file 9.4 ad 9.49 ;"Input: PckInit - . The package initials, e.g. 'DI' in the case of filemant ;" Ver -- The version of the package to match. ;" IEN9d4 - PASS BY REFERENCE. The IEN in 9.4 to return ;" IEN9d49 -- PASS BY REFERENCE. The IEN in 9.49 to return ;"result: 1 if OK, 0 if not found. new result set result=0 ; set IEN9d4=+$order(^DIC(9.4,"C",PckInit,"")) if IEN9d4'>0 goto GPVIDne new DIC,X,Y set DIC="^DIC(9.4,"_IEN9d4_",22," set DIC(0)="M" set X=Ver do ^DIC set IEN9d49=+Y if IEN9d49'>0 goto GPVIDne set result=1 ; GPVIDne quit result GetLastPackage(PckInit,Ver) ;"Purpose: for given package initials, return the last patch applied ;" This searches the PACKAGE file ;"Input: PckInit - the package initials, e.g. 'DI' in the case of filemant ;" Ver -- the version of the package to match. ;"Results: returns e.g. 'DI*22.0*140 SEQ# 123' ;" or "" if problem or not found. new result set result="" set Ver=$get(Ver) set PckInit=$get(PckInit) if (PckInit="")!(Ver="") goto GLPDone new IEN9d4,IEN9d49 set IEN9d4=+$order(^DIC(9.4,"C",PckInit,"")) if IEN9d4'>0 goto GLPDone set IEN9d49=+$order(^DIC(9.4,IEN9d4,22,"B",Ver,"")) if IEN9d49'>0 goto GLPDone new i,array set i="" for set i=$order(^DIC(9.4,IEN9d4,22,IEN9d49,"PAH","B",i)) quit:(i="") do . new patchNum set patchNum=$piece(i," ",1) . new seqNum set seqNum=$piece(i,"SEQ #",2) . new tempName set tempName=i . if seqNum="" do . . set tempName=PckInit_"*"_Ver_"*"_patchNum . . set tempName=$$GetSeq^TMGPAT4(tempName) . . set seqNum=$piece(tempName,"SEQ #",2) . . if seqNum="" quit . . new IEN9d4901 set IEN9d4901=$order(^DIC(9.4,IEN9d4,22,IEN9d49,"PAH","B",i,"")) . . ;"write "The PACKAGE file entry for patch "_PckInit_"*"_Ver_"*"_patchNum_" doesn't have a SEQ #",! . . ;"write "By comparing this to patch files available on ftp.va.gov network site, it",! . . ;"write "appears that this patch should be SEQ #",tempName,! . . ;"new % set %=1 . . ;"write "Shall I correct this in the PACKAGE file" do YN^DICN write ! . . ;"if %'=1 quit . . new TMGFDA,TMGMSG . . set TMGFDA(9.4901,IEN9d4901_","_IEN9d49_","_IEN9d4_",",.01)=patchNum_" SEQ #"_seqNum . . do FILE^DIE("K","TMGFDA","TMGMSG") . . ;"do ShowIfDIERR^TMGDEBUG(.TMGMSG) . ;"if seqNum is still "" at this point, it won't find the patch, could be bug... . set seqNum=$$RJ^XLFSTR(seqNum,6,"0") . if tempName["*" set tempName=$piece(tempName,"*",3) . set array(seqNum)=tempName set i=$order(array(""),-1) if i'="" set result=PckInit_"*"_Ver_"*"_$get(array(i)) else set result=PckInit_"*"_Ver_"*0 SEQ #0" ;"else set result=$piece($get(^DIC(9.4,IEN9d4,0)),"^",1)_" SEQ #0" GLPDone quit result GetLastInst(PckInit,Ver,InstIEN) ;"Purpose: for given package initials, return the last patch applied ;" This searches the INSTALL file ;"Input: PckInit - the package initials, e.g. 'DI' in the case of filemant ;" Ver -- the version of the package to match. ;" InstIEN -- Optional. Pass by Reference, an OUT PARAMETER. ;"Results: returns last patch + 'SEQ# 123' (123 is example) ;" or "" if problem or not found. new result set result="" new array set Ver=$get(Ver) new i set i=$get(PckInit) if (i="")!(Ver="") goto GLIDone new done set done=0 for set i=$order(^XPD(9.7,"B",i)) quit:(i="")!done do . if $piece(i,"*",1)'=PckInit set done=1 quit . if $piece(i,"*",2)'=Ver quit . new patch set patch=$piece(i,"*",3) . set patch=$$RJ^XLFSTR(patch,6,"0") . new IEN set IEN=$order(^XPD(9.7,"B",i,"")) . if IEN=0 quit . new seq set seq=$$GET1^DIQ(9.7,IEN_",",42001) . if seq="" quit . ;"write "SEQ #"_seq_" "_i,! . set array(seq)=i_" SEQ #"_seq_"^"_IEN set i=$order(array(""),-1) set result=$get(array(i)) set InstIEN=$piece(result,"^",2) set result=$piece(result,"^",1) if result'="" do . new PatIEN set PatIEN=+$order(^XPD(9.7,"B",result,"")) . if PatIEN=0 quit . new Seq set Seq=$$GET1^DIQ(9.7,PatIEN_",",42001) . if Seq="" quit . set result=result_" SEQ #"_Seq GLIDone quit result GetVers(PckInit,VerArray) ;"Purpose: for given package initials, return possible versions ;"Input: PckInit - the package initials, e.g. 'DI' in the case of filemant ;" VerArray -- PASS BY REFERENCE -- an OUT PARAMETER. Format ;" VerArray("22")="" ;" VerArray("23")="" ;"Results: none new ver kill VerArray if $get(PckInit)="" goto GVDone new done set done=0 new ien9d4 set ien9d4=+$order(^DIC(9.4,"C",PckInit,"")) goto:(ien9d4'>0) GVDone set ver="" for set ver=$order(^DIC(9.4,ien9d4,22,"B",ver)) quit:(ver="")!done do . if ver'="" set VerArray(ver)="" GVDone quit ;"Discard below later ============================================ for set i=$order(^XPD(9.7,"B",i)) quit:(i="")!done do . if i["*" do . . if $piece(i,"*",1)'=PckInit set done=1 quit . . set ver=$piece(i,"*",2) . else do . . new ien set ien=+$order(^XPD(9.7,"B",i,"")) . . write i,! . . write "From the above name, please enter version number" . . new DIR set DIR(0)="N^0:999:2" do ^DIR write ! . . if $data(DIRUT) set ver="" quit . . set ver=X ;"why doesn't Y return decimals??? . . set done=1 . if ver'="" set VerArray(ver)="" ;"Discard above later ============================================ PickFile(pArray) ;"Purpose: Pick a filename from a list, in a menu ;"Input: pArray -- PASS BY NAME. format: ;" @pArray@(name)="" ;" @pArray@(name)="" ;"Result: the chosen name, or "" if problem. new menu set menu(0)="Select IF one of the following files is the patch file." new count set count=1 new name set name="" for set name=$order(@pArray@(name)) quit:(name="") do . set menu(count)=name_$C(9)_name . set count=count+1 set menu(count)="(None of these / Cancel)"_$C(9)_"@" set count=count+1 set result=$$Menu^TMGUSRIF(.menu) if "@^"[result set result="" quit result