Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Enumproc.dll fails on WinXP (Dowload ID 9651 and 9654)
Message
 
To
All
General information
Forum:
Visual FoxPro
Category:
Troubleshooting
Title:
Enumproc.dll fails on WinXP (Dowload ID 9651 and 9654)
Miscellaneous
Thread ID:
00877070
Message ID:
00877070
Views:
67
Hi,

We've been using Enumproc.dll ( DOWNLOAD#9651 ) and also DOWNLOAD#9654 to prevent our applications to be opened twice. However, on Windows XP SP1, some errors 'Declare DLL call caused an exception. (Error 2027)' started to rise very randomly. The error is always on the line lnHandle=OpenProcList() where OpenProcList is a function of the file Enumproc.dll. I made some tests and realized the error appears when there is more than 61 process running (no, really! <s>). The error doesn't show up on Win98. I made a program to test (you'll need DOWNLOAD#9651 and possible Psapi.dll in the current path). I thought of using DOWNLOAD#9907 instead but when I issue SET LIBRARY TO Pview.fll on a Win98 machine I get the error 'Library file "name" is invalid (Error 1691)'. I really would prefer to be able to use only one procedure to do the job on all OS especially Win98 and WinXP SP1.

Anyone have an idea ? Repro-code below.
Thanks,
Sylvain Bujold
#DEFINE NACCESSRIGHT BITOR(0x100000, 0x1)
#DEFINE CR CHR(10)+CHR(13)
LPARAMETERS tnMaxProc
LOCAL lcNotePad, lnMaxProc, lnProc, lnHandle, loErr As Exception

&&DLLs needed to terminate a process
DECLARE INTEGER TerminateProcess IN kernel32 INTEGER hProcess, INTEGER uExitCode
DECLARE INTEGER OpenProcess      IN kernel32 INTEGER dwDesiredAccess, INTEGER bInheritHandle, INTEGER dwProcessId
DECLARE INTEGER CloseHandle      IN kernel32 INTEGER hObject

&&DLLs needed to find Process ID (Enumproc.dll found at levelextreme.com)
DECLARE INTEGER OpenProcList  IN Enumproc.dll
DECLARE INTEGER GetFirstProc  IN Enumproc.dll INTEGER hhandle, INTEGER @lpdwprocid, SHORT @lpwprocid16, STRING @lpzprocname
DECLARE INTEGER GetNextProc   IN Enumproc.dll INTEGER hhandle, INTEGER @lpdwprocid, SHORT @lpwprocid16, STRING @lpzprocname
DECLARE INTEGER CloseProcList IN Enumproc.dll INTEGER hHandle

lcNotePad=""
SET PATH TO (GETENV("Path"))
TRY
   lcNotePad=LOCFILE("Notepad.exe","EXE:EXE")
CATCH
   EXIT
ENDTRY

IF !FILE(m.lcNotePad)
   =MESSAGEBOX("File '"+m.lcNotePad+"' does not exists.")
   RETURN .F.
ENDIF

lnMaxProc=IIF(VARTYPE(m.tnMaxProc)#"N",61,m.tnMaxProc)
TRY
   lnProc=CountProcess()
CATCH
   lnProc=-1
ENDTRY

IF m.lnProc>0 AND m.lnProc<=m.lnMaxProc
   FOR i = 1 TO m.lnMaxProc-m.lnProc
      =EXECSCRIPT("RUN /N2 "+m.lcNotePad)
   ENDFOR
   =MESSAGEBOX("Notepad running ? "+TRANSFORM(IsProgRunning(m.lcNotePad),"Y"))
   =MESSAGEBOX("Ok, let's get to "+TRANSFORM(m.lnMaxProc+1)+" process and try to open the proclist")
   =EXECSCRIPT("RUN /N2 "+m.lcNotePad)
   lnHandle=0
   TRY
      lnHandle=OpenProcList()
   CATCH TO loErr
      =MESSAGEBOX("Error #"+TRANSFORM(loErr.ErrorNo)+CR+"Message: "+loErr.Message+CR+;
         "Now don't forget to close at least one process so that KillProcess can close all "+;
         "the notepad for you (or group them in the taskbar <s>).")
   FINALLY
      IF m.lnHandle>0
         =MESSAGEBOX("The enumproc.dll works fine on this system with "+TRANSFORM(m.lnMaxProc+1)+" processes.")
         =CloseProcList(m.lnHandle)
      ENDIF
   ENDTRY
   TRY
      DO WHILE KillProcess(m.lcNotePad)
      ENDDO
   CATCH
      =MESSAGEBOX("Unable to kill the notepads <s>")
   ENDTRY
ELSE
   IF m.lnProc>0
      =MESSAGEBOX("Already Over "+TRANSFORM(m.lnMaxProc)+" process, kill enough process to get <= to "+;
         TRANSFORM(m.lnMaxProc)+" process.")
   ELSE
      =MESSAGEBOX("Unable to determine number of process.")
   ENDIF
ENDIF

RETURN &&END

FUNCTION KillProcess
   LPARAMETERS tcProgName
   LOCAL lnProcID, lnProcHND, llReturn

   STORE 0 TO lnProcID, lnProcHND
   llReturn = .F.

   lnProcID = GetProcID(tcProgName)
   IF lnProcID # 0
      &&On an NT machine we need to open process with right access to terminate it
      lnProcHND = OpenProcess(NACCESSRIGHT, 0, lnProcID)
      IF lnProcHND > 0
         &&Try to terminate process
         IF TerminateProcess(lnProcHND, 0) > 0
            llReturn = .T.
         ENDIF
         &&Close the opened process
         =CloseHandle(lnProcHND)
      ENDIF
   ENDIF

   RETURN llReturn
ENDFUNC

FUNCTION GetProcID
   LPARAMETERS tcProgName
   LOCAL lcProcName, lnProcID, lnProcID16, lnHandle, lnReturn, lnGetProc

   STORE 0 TO lnProcID, lnProcID16, lnReturn, lnGetProc
   lcProcName = REPLICATE(CHR(0), 260)

   IF VARTYPE(m.tcProgName) = "C"
      lnHandle = OpenProcList()
      IF m.lnHandle > 0
         lnGetProc = GetFirstProc(m.lnHandle, @m.lnProcID, @m.lnProcID16, @m.lcProcName)
         DO WHILE m.lnGetProc <> 0
            IF UPPER(ALLT(m.tcProgName)) == UPPER(ALLT(LEFT(m.lcProcName, AT(CHR(0), m.lcProcName) - 1)))
               lnReturn = m.lnProcID
               lnGetProc = 0
            ELSE
               lnGetProc = GetNextProc(m.lnHandle, @m.lnProcID, @m.lnProcID16, @m.lcProcName)
            ENDIF
         ENDDO
      ENDIF
      =CloseProcList(m.lnHandle)
   ENDIF

   RETURN m.lnReturn
ENDFUNC

FUNCTION IsProgRunning
   LPARAMETERS tcProgName
   LOCAL llReturn

   llReturn = .F.

   IF VARTYPE(m.tcProgName) = "C"
      IF GetProcID(m.tcProgName) > 0
         llReturn = .T.
      ENDIF
   ENDIF

   RETURN llReturn
ENDFUNC

FUNCTION countprocess
   LOCAL lcProcName, lnProcID, lnProcID16, lnHandle, lnReturn, lnGetProc

   STORE 0 TO lnProcID, lnProcID16, lnReturn, lnGetProc
   lcProcName = REPLICATE(CHR(0), 260)

   lnHandle = OpenProcList()
   IF lnHandle > 0
      lnGetProc = GetFirstProc(m.lnHandle, @m.lnProcID, @m.lnProcID16, @m.lcProcName)
      DO WHILE m.lnGetProc <> 0
         lnReturn = m.lnReturn + 1
         lnGetProc = GetNextProc(m.lnHandle, @m.lnProcID, @m.lnProcID16, @m.lcProcName)
      ENDDO
   ENDIF

   =CloseProcList(m.lnHandle)

   RETURN m.lnReturn
ENDFUNC
Reply
Map
View

Click here to load this message in the networking platform