CLEAR ACTIVATE SCREEN _screen.windowstate=2 _screen.visible=.T. clear IF FILE('printers.txt') dele file printers.txt ENDIF SET PRINTER TO GETPRINTER() set PRINTER FONT 'COURIER NEW',8 set PRINTER TO printers.txt set DEVICE TO print LOCAL ARRAY myprinters(1,2) LOCAL lcDeviceList, lnBufLen, lcUncBuffer,; lnLength, i, iv, lcLocalDevice,; lnResult, lcPrinter, lcTargetDevice FOR i = 1 TO APRINTERS(gaprinters) gaprinters[i,1]=SPACE(1) +; gaprinters[i,1] DIMENSION validport(i,2) validport(i,1)=gaprinters[i,1] IF LEN(gaprinters(i,2))>=5 .and. SUBSTR(gaprinters(i,2),5,1)=":" validport(i,2)=LEFT(gaprinters(i,2),4) ELSE validport(i,2)=gaprinters(i,2) ENDIF ENDFOR DECLARE SHORT QueryDosDevice IN KERNEL32.DLL ; STRING @ lpDeviceName, ; STRING @ lpTargetPath, ; INTEGER ucchmax * pass null device name to get a list of DOS Devices lcDeviceList = REPL(CHR(0),2048) lnResult = QueryDosDevice(0,@lcDeviceList,2047) * result is in lcDeviceList; you have to parse it - null char separators * Get info on one device assignment lcTargetDevice = REPL(CHR(0), 262) lnBufLen = 261 DECLARE INTEGER WNetGetConnection IN WIN32API ; STRING @ lpLocalName, ; STRING @ lpRemoteName, ; INTEGER @ lplnLength lcUncBuffer = REPL(CHR(0),261) lnLength = LEN(lcUncBuffer) * i=1 iv=ALEN(gaprinters,1) FOR i = 1 TO 20 lcLocalDevice="LPT"+ALLTRIM(STR(i)) lnResult = QueryDosDevice(lcLocalDevice,@lcTargetDevice, lnBufLen) && note - no : IF !lnResult = 0 cTargetName = LEFT(lcTargetDevice, lnResult-2) IF WNetGetConnection(lcLocalDevice, @lcUncBuffer, @lnLength) = 0 * lcPrinter=lcLocalDevice+LEFT(lcUncBuffer,AT(CHR(0),lcUncBuffer)-1) lcPrinter=LEFT(lcUncBuffer,AT(CHR(0),lcUncBuffer)-1) iv=iv+1 DIMENSION validport(iv,2) validport(iv,1)=lcPrinter validport(iv,2)=lcLocalDevice * ? lcLocalDevice IF UPPER(TYPE('myprinters(ALEN(myprinters,1),2)'))!="L" DIMENSION myprinters(ALEN(myprinters,1)+1,2) ENDIF myprinters(ALEN(myprinters,1),2)=lcLocalDevice myprinters(ALEN(myprinters,1),1)=lcPrinter ELSE IF UPPER(TYPE('myprinters(ALEN(myprinters,1),2)'))!="L" DIMENSION myprinters(ALEN(myprinters,1)+1,2) ENDIF IF UPPER(TYPE('myprinters(i,2)'))!="L".and.UPPER(LEFT(myprinters(i,2),3))<>"LPT" .and. UPPER(LEFT(myprinters(i,2),3))<>"COM" myprinters(ALEN(myprinters,1),2)=LEFT(gaprinters(i,2),4) myprinters(ALEN(myprinters,1),1)=gaprinters(i,1) ENDIF ENDIF ENDIF lcLocalDevice="COM"+ALLTRIM(STR(i)) lnResult = QueryDosDevice(lcLocalDevice,@lcTargetDevice, lnBufLen) && note - no : IF !lnResult = 0 cTargetName = LEFT(lcTargetDevice, lnResult-2) IF WNetGetConnection(lcLocalDevice, @lcUncBuffer, @lnLength) = 0 *lcPrinter=lcLocalDevice+LEFT(lcUncBuffer,AT(CHR(0),lcUncBuffer)-1) lcPrinter=LEFT(lcUncBuffer,AT(CHR(0),lcUncBuffer)-1) iv=iv+1 DIMENSION validport(iv,2) validport(iv,1)=lcPrinter validport(iv,2)=lcLocalDevice IF UPPER(TYPE('myprinters(ALEN(myprinters,1),2)'))!="L" DIMENSION myprinters(ALEN(myprinters,1)+1,2) ENDIF myprinters(ALEN(myprinters,1),2)=lcLocalDevice myprinters(ALEN(myprinters,1),1)=lcPrinter ELSE IF UPPER(TYPE('myprinters(ALEN(myprinters,1),2)'))!="L" DIMENSION myprinters(ALEN(myprinters,1)+1,2) ENDIF IF UPPER(TYPE('myprinters(i,2)'))!="L".and.UPPER(LEFT(myprinters(i,2),3))<>"LPT" .and. UPPER(LEFT(myprinters(i,2),3))<>"COM" myprinters(ALEN(myprinters,1),2)=LEFT(gaprinters(i,2),4) myprinters(ALEN(myprinters,1),1)=gaprinters(i,1) ENDIF ENDIF ENDIF ENDFOR ************* FOR i =1 TO ALEN(myprinters,1) IF UPPER(TYPE('myprinters(i,1)'))<>"L" lcshort=ALLTRIM(myprinters(i,1)) lcthisprinter=getprinterdrivername(lcshort) IF UPPER(TYPE('lcthisprinter'))="C" .and. !EMPTY(lcthisprinter) myprinters(i,1)=lcthisprinter ENDIF ENDIF ENDFOR FOR i =1 TO ALEN(validport,1) IF UPPER(TYPE('validport(i,1)'))<>"L" lcshort=ALLTRIM(validport(i,1)) lcthisprinter=getprinterdrivername(lcshort) IF UPPER(TYPE('lcthisprinter'))="C" .and. !EMPTY(lcthisprinter) validport(i,1)=lcthisprinter ENDIF ENDIF ENDFOR RELEASE myprinter =ASORT(validport,2,-1,0,1) FOR i =1 TO ALEN(validport,1) @ i, 1 SAY validport(i,2) @ i,10 SAY validport(i,1) ENDFOR set DEVICE TO screen set PRINTER to MODIFY COMMAND printers.txt ************** *SET STEP ON *DISPLAY MEMORY LIKE myprinters *!* FOR i = 1 TO ALEN(validport,1) *!* validport(i)=LTRIM(validport(i)) *!* ? validport(i) *!* ENDFOR *DISPLAY MEMORY LIKE validport IF APRINTERS(gaprinters) > 0 && If there are installed printer drivers * DISPLAY MEMORY LIKE gaprinters && Display the printers and ports ELSE && Otherwise, no printer are installed WAIT WINDOW 'No printers installed.' ENDIF DISPLAY MEMORY LIKE validport DISPLAY MEMORY LIKE gaprinters DISPLAY MEMORY LIKE myprinters RETURN ************************ FUNCTION getprinterdrivername LPARAMETERS tcPrinterName * API Declarations DECLARE INTEGER OpenPrinter IN Winspool.drv; STRING @pPrinterName, INTEGER @phPrinter,; STRING @pDefault DECLARE INTEGER ClosePrinter IN Winspool.drv; INTEGER hPrinter DECLARE INTEGER GetPrinterDriver IN Winspool.drv; INTEGER hPrinter, STRING @pEnvironment,; INTEGER dLevel, INTEGER pDriverInfo,; INTEGER cbBuf, INTEGER @pcbNeeded DECLARE INTEGER HeapCreate IN Win32API; INTEGER dwOptions, INTEGER dwInitialSize,; INTEGER dwMaxSize DECLARE INTEGER HeapAlloc IN Win32API; INTEGER hHeap, INTEGER dwFlags, INTEGER dwBytes DECLARE lstrcpy IN Win32API; STRING @lpstring1, INTEGER lpstring2 DECLARE INTEGER HeapFree IN Win32API; INTEGER hHeap, INTEGER dwFlags, INTEGER lpMem DECLARE HeapDestroy IN Win32API; INTEGER hHeap LOCAL lcresult, lcprinter, lnheaphandle, lnhandle,; lnsize, lnheap, lnptr, lcstruct lcprinter = tcPrinterName lnhandle = 0 lcresult = "" IF OpenPrinter(@lcprinter, @lnhandle, 0) # 0 * Create space on the heap lnheaphandle = HeapCreate(0, 4096, 0) IF lnheaphandle # 0 * Get the required size of the DRIVER_INFO_2 structure lnsize = 0 GetPrinterDriver(lnhandle, 0, 2, 0, 0, @lnsize) * Get a pointer to an address lnheap = HeapAlloc(lnheaphandle, 0, lnsize) * Get the information into the structure GetPrinterDriver(lnhandle, 0, 2, lnheap, lnsize, @lnsize) * Copy the structure to VFP memory * In order to get the pointer to the string lcstruct = SYS(2600, lnheap, lnsize) lnptr = StringToInteger(SUBSTR(lcstruct, 5, 4)) * Initialize the buffer to receive the driver * to MAX_PATH lcresult = SPACE(260) = lstrcpy(@lcresult, lnptr) * Remove the trailing CHR(0) lcresult = LEFT(lcresult, AT(CHR(0), lcresult) - 1) * Free the heap = HeapFree(lnheaphandle, 0, lnheap) * Clean up by destroying the handle * to the heap = HeapDestroy(lnheaphandle) ENDIF * Close the printer = ClosePrinter(lnhandle) ENDIF RETURN lcresult ENDFUNC FUNCTION StringToInteger LPARAMETER pcstring, plsigned LOCAL lnresult, lnlast, lni, llsigned,; lnmsb, lnmax lnresult = 0 lnlast = LEN(pcstring) * Return Signed Integer? IF PCOUNT() = 2 llsigned = plsigned ELSE llsigned = .F. ENDIF FOR lni = 1 TO lnlast lnresult = lnresult + ASC(SUBSTR(pcstring, lni, 1)) * (256 ^ (lni - 1)) NEXT IF llsigned lnmsb = (lnlast * 8) - 1 IF BITTEST(lnresult, lnmsb) lnmax = (2 ^ (lnmsb + 1)) lnresult = lnresult - lnmax ENDIF ENDIF RETURN lnresult ENDFUNC