' Stop and restart processes on your computer.
'
' Sometimes you may find your computer to work a little too slow.
' The explanation could be that it runs too many processes, some of
' which may not be necessary for the job at hand.
'
' So sometimes you may be interested to see, which processes are actually
' using the capacity of your computer, and you may be surprised to see
' how many processes are actually active. You may even discover that the same
' process is running in more than one instance.
'
' Using this program you may stop some of the unnecessary processes
' during your current session to liberate more resources for your
' job. In doing this you should take great care not to stop processes
' necessary for the proper function of the computer. Such damage will
' however only affect your current session. This may be bad enough,
' but no files are being deleted, and after a new start up the computer
' will work as previously.
'
' The program can also serve to identify programs you do not need at all.
' They may start automatically on start up, and you may not be completely
' aware of them, because they work in the background. You can delete
' such programs completely if you wish, but you can also just stop them running
' during your current session by using this program after start up.
'
' Running computer viruses, spyware etc. can in principle be discovered using
' this program and the program can be modified to also delete the files of running
' programs. However, you should know that viruses, spyware etc. may multiply,
' change their name and change their file size. Therefore it may be extremely
' difficult if not impossible to catch up with this. So do not expect this
' program to be able to effectively stop running viruses or spyware.
'
' Use this program with caution. You are responsible for how you use it.
'
' Best regards,
'
' Erik Christensen ------------- November 16, 2009
'
' P.S. Thanks to Graham McPhee and Wayne Diamond for their routines.
Code:
' Stop and restart processes on your computer.
'
' Sometimes you may find your computer to work a little too slow.
' The explanation could be that it runs too many processes, some of
' which may not be necessary for the job at hand.
'
' So sometimes you may be interested to see, which processes are actually
' using the capacity of your computer, and you may be surprised to see
' how many processes are actually active. You may even discover that the same
' process is running in more than one instance.
'
' Using this program you may stop some of the unnecessary processes
' during your current session to liberate more resources for your
' job. In doing this you should take great care not to stop processes
' necessary for the proper function of the computer. Such damage will
' however only affect your current session. This may be bad enough,
' but no files are being deleted, and after a new start up the computer
' will work as previously.
'
' The program can also serve to identify programs you do not need at all.
' They may start automatically on start up, and you may not be completely
' aware of them, because they work in the background. You can delete
' such programs completely if you wish, but you can also just stop them running
' during your current session by using this program after start up.
'
' Running computer viruses, spyware etc. can in principle be discovered using
' this program and the program can be modified to also delete the files of running
' programs. However, you should know that viruses, spyware etc. may multiply,
' change their name and change their file size. Therefore it may be extremely
' difficult if not impossible to catch up with this. So do not expect this
' program to be able to effectively stop running viruses or spyware.
'
' Use this program with caution. You are responsible for how you use it. :)
'
' Best regards,
'
' Erik Christensen ------------- November 16, 2009
'
' P.S. Thanks to Graham McPhee and Wayne Diamond for their routines.

#COMPILE EXE
#DIM ALL

#INCLUDE "WIN32API.INC"

%IDC_BUTTON2_STOP_PROCESS        = 1001
%IDC_BUTTON3_RESTART_PROCESS     = 1002
%IDC_BUTTON4_EXIT                = 1003
%IDC_LABEL4_PROCESSES_STOPPED    = 1004
%IDC_LABEL3_PROCESSES_RUNNING    = 1005
%IDC_LISTBOX1_PROCESSES_RUNNING  = 1006
%IDC_LISTBOX2_PROCESSES_STOPPED  = 1007

'------------------------------------------------------------------------------
'  Processes running . PB_Processes.inc (Provided by Graham McPhee - Thanks!)
'
DECLARE FUNCTION EnumProcesses (lpidProcess AS DWORD, BYVAL cb AS DWORD, cbNeeded AS DWORD) AS LONG
DECLARE FUNCTION GetModuleFileNameEx (BYVAL hProcess AS DWORD, BYVAL hModule AS DWORD, ModuleName AS ASCIIZ, nSize AS DWORD) AS DWORD
DECLARE FUNCTION EnumProcessModules (BYVAL hProcess AS DWORD, BYREF lphModule AS DWORD, BYVAL cb AS DWORD, cbNeeded AS DWORD) AS LONG
'
TYPE PROCESSENTRY32
   dwSize AS DWORD
   cntUsage AS DWORD
   th32ProcessID AS DWORD          ' This process
   th32DefaultHeapID AS LONG PTR
   th32ModuleID AS DWORD           ' Associated exe
   cntThreads AS DWORD
   th32ParentProcessID AS DWORD    ' This process's parent process
   pcPriClassBase AS LONG          ' Base priority of process threads
   dwFlags AS DWORD
   szExeFile AS ASCIIZ * %MAX_PATH
END TYPE
'
SUB KillByTerminate (BYVAL ProcID AS LONG) ' Provided by Wayne Diamond
    LOCAL hProc AS LONG
    hProc = OpenProcess(BYVAL %PROCESS_TERMINATE, BYVAL 0, BYVAL ProcID)
    IF hProc <> %NULL THEN TerminateProcess BYVAL hProc, BYVAL %NULL
    CloseHandle hProc
END SUB
'
FUNCTION StopProcess(strProcessName AS STRING) AS LONG
'
    DIM Reply AS STRING
    DIM lngR AS INTEGER
    DIM strModule AS STRING
    DIM strEXE AS STRING
    DIM ProcID AS LONG
    CALL EnumModules(Reply)  ' pick up the processes in a string
    '
    FUNCTION = 0
    FOR lngR = 1 TO PARSECOUNT(Reply,$CRLF)
        strModule = PARSE$(Reply,$CRLF,lngR)
        strExe = PARSE$(strModule,"|",2) ' path and filename
        IF INSTR(strExe,strProcessName) > 0 THEN
            ProcID = VAL(PARSE$(strModule,"|",1))
            KillByTerminate(ProcID)
            EXIT FOR : FUNCTION = lngR
        END IF
    NEXT lngR
'
END FUNCTION
'
FUNCTION ListAllProcesses(BYVAL hDlg AS DWORD) AS LONG
'
    DIM Reply AS STRING
    DIM lngR AS INTEGER
    DIM strModule AS STRING
    DIM strExe AS STRING
    DIM f AS STRING
    DIM DirDataVar AS DIRDATA
    '
    CALL EnumModules(Reply)  ' pick up the processes in a string
    '
    LISTBOX RESET hDlg, %IDC_LISTBOX1_PROCESSES_RUNNING
    '
    FOR lngR = 1 TO PARSECOUNT(Reply,$CRLF)
        strModule = PARSE$(Reply,$CRLF,lngR)
        strExe = PARSE$(strModule,"|",2) ' path and filename
        f = DIR$(strExe, TO DirDataVar)  ' get file data including file size
        IF DirDataVar.FileSizeLow > 0 THEN LISTBOX ADD hDlg, %IDC_LISTBOX1_PROCESSES_RUNNING, strExe + "     Size ="+STR$(DirDataVar.FileSizeLow) + " Bytes"
    NEXT lngR
    '
    FUNCTION = 1
'
END FUNCTION
'
SUB EnumModules(Reply AS STRING) ' Provided by Graham McPhee
  LOCAL Proc AS PROCESSENTRY32
  LOCAL cb AS DWORD, cbNeeded AS DWORD
  LOCAL i AS LONG, j AS LONG, nModules AS LONG, nProcesses AS LONG, hProcess AS DWORD, lResult AS LONG
  LOCAL hPsApiDll AS DWORD, hEnumProcesses AS DWORD, hGetModuleFileNameEx AS DWORD, hEnumProcessModules AS DWORD
  LOCAL SizeOfFile AS DWORD
  hPsApiDll = GetModuleHandle("psApi.dll")
  IF hPsApiDll = 0 THEN hPsApiDll = LoadLibrary("psApi.dll")
    hEnumProcesses = GetProcAddress(hPsApiDll, "EnumProcesses")
    hGetModuleFileNameEx = GetProcAddress(hPsApiDll, "GetModuleFileNameExA")
    hEnumProcessModules = GetProcAddress(hPsApiDll, "EnumProcessModules")
    cb = 100
    DO
      REDIM ProcessIDs(1 TO cb / 4) AS DWORD
      CALL DWORD hEnumProcesses USING EnumProcesses (ProcessIDs(1), cb, cbNeeded) TO lResult
      IF cb > cbNeeded THEN EXIT DO
      cb = cb * 2
    LOOP
    '
    Reply = ""
    nProcesses = cbNeeded / 4
    FOR i = 1 TO nProcesses
       hProcess = OpenProcess(%PROCESS_QUERY_INFORMATION OR %PROCESS_VM_READ OR _
                              %PROCESS_CREATE_THREAD OR %PROCESS_VM_OPERATION OR _
                              %PROCESS_VM_WRITE, %False, ProcessIDs(i))
      IF hProcess THEN
        LOCAL CmdLine AS STRING
        '
        cb = 100
        DO
          REDIM Modules(1 TO cb / 4) AS DWORD
          CALL DWORD hEnumProcessModules USING _
          EnumProcessModules (hProcess, Modules(1), cb, cbNeeded) TO lResult
          IF lResult = 0 THEN cbNeeded = 0: EXIT DO
          IF cb > cbNeeded THEN EXIT DO ELSE cb = cb * 2
        LOOP
        IF cbNeeded >= 4 THEN
          CALL DWORD hGetModuleFileNameEx USING GetModuleFileNameEx _
            (hProcess, Modules(1), Proc.szExeFile, SIZEOF(Proc.szExeFile)) TO lResult
            IF lResult THEN Reply = Reply + STR$(ProcessIDs(i))+ "|" + Proc.szExeFile + "|" + $CRLF
        END IF
       CloseHandle hProcess
     END IF
  NEXT nProcesses
END SUB
'------------------------------------------------------------------------------
CALLBACK FUNCTION ShowDIALOG1Proc()
    STATIC txtv AS STRING, datav AS LONG, k AS DWORD
    SELECT CASE AS LONG CBMSG
        CASE %WM_INITDIALOG
            ' Initialization handler
            ListAllProcesses(CBHNDL)

        CASE %WM_NCACTIVATE
            STATIC hWndSaveFocus AS DWORD
            IF ISFALSE CBWPARAM THEN
                ' Save control focus
                hWndSaveFocus = GetFocus()
            ELSEIF hWndSaveFocus THEN
                ' Restore control focus
                SetFocus(hWndSaveFocus)
                hWndSaveFocus = 0
            END IF

        CASE %WM_COMMAND
            ' Process control notifications
            SELECT CASE AS LONG CBCTL

                CASE %IDC_BUTTON2_STOP_PROCESS
                    IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                        LISTBOX GET SELECT CBHNDL, %IDC_LISTBOX1_PROCESSES_RUNNING TO datav
                        IF datav > 0 THEN
                            LISTBOX GET TEXT CBHNDL, %IDC_LISTBOX1_PROCESSES_RUNNING TO txtv
                            LISTBOX DELETE CBHNDL, %IDC_LISTBOX1_PROCESSES_RUNNING, datav
                            LISTBOX ADD CBHNDL, %IDC_LISTBOX2_PROCESSES_STOPPED, txtv
                            txtv = TRIM$(LEFT$(txtv, INSTR(txtv, "Size =") - 1))
                            StopProcess(txtv)
                            SLEEP 500 ' allow time for stopping of process to be registered by the system
                            ListAllProcesses(CBHNDL)
                        END IF
                    END IF

                CASE %IDC_BUTTON3_RESTART_PROCESS
                    IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                        LISTBOX GET SELECT CBHNDL, %IDC_LISTBOX2_PROCESSES_STOPPED TO datav
                        IF datav > 0 THEN
                            LISTBOX GET TEXT CBHNDL, %IDC_LISTBOX2_PROCESSES_STOPPED TO txtv
                            LISTBOX DELETE CBHNDL, %IDC_LISTBOX2_PROCESSES_STOPPED, datav
                            LISTBOX ADD CBHNDL, %IDC_LISTBOX1_PROCESSES_RUNNING, txtv
                            txtv = TRIM$(LEFT$(txtv, INSTR(txtv, "Size =") - 1))
                            k = SHELL(txtv, 4)
                            SLEEP 500 ' allow time for starting of process to be registered by the system
                            ListAllProcesses(CBHNDL)
                        END IF
                    END IF

                CASE %IDC_BUTTON4_EXIT
                    IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN DIALOG END CBHNDL

            END SELECT
    END SELECT
END FUNCTION
'------------------------------------------------------------------------------
FUNCTION PBMAIN()
    LOCAL lRslt AS LONG
    LOCAL hDlg  AS DWORD

    DIALOG NEW PIXELS, %HWND_DESKTOP, "Stop And Restart Processes On My Computer", _
        105, 114, 767, 512, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR _
        %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR %WS_CLIPSIBLINGS OR _
        %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
        %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
        %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
    CONTROL ADD LISTBOX, hDlg, %IDC_LISTBOX1_PROCESSES_RUNNING, , 18, 26, 732, 188, %WS_CHILD _
        OR %WS_VISIBLE OR %WS_TABSTOP OR %WS_HSCROLL OR %WS_VSCROLL OR _
        %LBS_SORT OR %LBS_NOTIFY OR %LBS_DISABLENOSCROLL, %WS_EX_CLIENTEDGE _
        OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
    CONTROL ADD LISTBOX, hDlg, %IDC_LISTBOX2_PROCESSES_STOPPED, , 18, 280, 732, 188, %WS_CHILD _
        OR %WS_VISIBLE OR %WS_TABSTOP OR %WS_HSCROLL OR %WS_VSCROLL OR _
        %LBS_SORT OR %LBS_NOTIFY OR %LBS_DISABLENOSCROLL, %WS_EX_CLIENTEDGE _
        OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
    CONTROL ADD LABEL,   hDlg, %IDC_LABEL3_PROCESSES_RUNNING, "Processes Running:", 18, 8, 732, _
        18, %WS_CHILD OR %WS_VISIBLE OR %SS_CENTER, %WS_EX_LEFT OR _
        %WS_EX_LTRREADING
    CONTROL ADD LABEL,   hDlg, %IDC_LABEL4_PROCESSES_STOPPED, "Processes " + _
        "Stopped:", 18, 260, 732, 20, %WS_CHILD OR %WS_VISIBLE OR _
        %SS_CENTER, %WS_EX_LEFT OR %WS_EX_LTRREADING
    CONTROL ADD BUTTON,  hDlg, %IDC_BUTTON2_STOP_PROCESS, "&Stop Selected " + _
        "Process", 288, 216, 186, 26
    CONTROL ADD BUTTON,  hDlg, %IDC_BUTTON3_RESTART_PROCESS, "&Restart " + _
        "Selected Process", 288, 471, 186, 26
    CONTROL ADD BUTTON,  hDlg, %IDC_BUTTON4_EXIT, "E&xit", 660, 471, 90, 26

    DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt

    FUNCTION = lRslt
END FUNCTION
'------------------------------------------------------------------------------