File "kill-wine-apps.bas"

Path: /kill-wine-apps/kill-wine-apps.bas
File size: 10.05 KB
MIME-type:
Charset: utf-8

#COMPILE EXE
#DIM ALL

$EXE = "Kill Wine Apps"
$VER = "v0.2"

' CHANGELOG:
' v0.2 (2026-01-21) fix for Wine 11.0 breaking 'start.exe' retrocompatibility
' v0.1 (2025-12-02) initial release

'------------------------------------------------------------------------------
'   ** Includes **
'------------------------------------------------------------------------------
#RESOURCE "kwa.pbr"
#INCLUDE ONCE "Win32Api.inc"
#INCLUDE ONCE "CommCtrl.inc"
#INCLUDE ONCE "inc\MyMsgBox.inc"
#INCLUDE ONCE "inc\exe2unix.inc"
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
'   ** Constants **
'------------------------------------------------------------------------------
%IDC_LBL_NFO  = 1001
%IDC_LVW_LST  = 1002
%IDC_CHK_SYS  = 1003
%IDC_BTN_FND  = 1004
%IDC_BTN_KL1  = 1005
%IDC_BTN_KLA  = 1006
'------------------------------------------------------------------------------
GLOBAL xd()  AS STRING
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
'   ** Functions / Subs **
'------------------------------------------------------------------------------
FUNCTION PBMAIN()

    ' Create exe icon in Unix dock and Unix file explorer
    Me2Unix 1, 1 ' askConfirmation=%TRUE, showInAppMenu=%TRUE

    ' Show main dialog
    MainShow %HWND_DESKTOP

END FUNCTION
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
FUNCTION SPLIT(BYVAL s AS STRING, BYVAL idx AS LONG) AS STRING
' Split a line from 'ps -ax' command output into its different fields
    LOCAL r AS STRING
    SELECT CASE idx
      CASE 1: r = LEFT$(s, 7)
      CASE 2: r = MID$(s,9,7)
      CASE 3: r = MID$(s,17,7)
      CASE 4: r = MID$(s,25,5)
      CASE 5: r = MID$(s,30)
    END SELECT
    FUNCTION = TRIM$(r)
END FUNCTION
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
SUB ListWineApps(BYVAL hDlg AS DWORD)
' Populate listview with output from 'ps -ax' command restricted to .exe progs
    LOCAL e     AS STRING
    LOCAL i, n  AS LONG
    LOCAL hsys  AS LONG

    e = GetUnixRet("/bin/ps -ax")
    LISTVIEW RESET hDlg, %IDC_LVW_LST
    REDIM xd(PARSECOUNT(e, $LF))
    PARSE e, xd(), $LF
    CONTROL GET CHECK hDlg, %IDC_CHK_SYS TO hsys

    FOR i = UBOUND(xd) TO LBOUND(xd) + 1 STEP -1
        e = SPLIT(xd(i), 5)
        IF INSTR(e, ".exe") > 0 THEN
            IF hsys AND INSTR(e, "\system32\") > 0 THEN ITERATE FOR
            LISTVIEW INSERT ITEM hDlg, %IDC_LVW_LST, 1, %NULL, SPLIT(xd(i), 1)
            LISTVIEW SET TEXT    hDlg, %IDC_LVW_LST, 1, 2,     SPLIT(xd(i), 3)
            LISTVIEW SET TEXT    hDlg, %IDC_LVW_LST, 1, 3,     SPLIT(xd(i), 4)
            LISTVIEW SET TEXT    hDlg, %IDC_LVW_LST, 1, 4,     UCASE$(LEFT$(e,1)) + MID$(e,2)
            LISTVIEW SET TEXT    hDlg, %IDC_LVW_LST, 1, 5,     SPLIT(xd(i), 2)
            INCR n
        END IF
    NEXT

    IF n >= 1 THEN
        CONTROL ENABLE hDlg, %IDC_BTN_KL1
        CONTROL ENABLE hDlg, %IDC_BTN_KLA
    ELSE
        CONTROL DISABLE hDlg, %IDC_BTN_KL1
        CONTROL DISABLE hDlg, %IDC_BTN_KLA
    END IF

    CONTROL SET TEXT hDlg, %IDC_LBL_NFO, FORMAT$(n) _
        + " Wine App" + IIF$(n>1,"s","") + " detected"
    DIALOG REDRAW hDlg
END SUB
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
SUB ConvertEOL(BYVAL file AS STRING)
    LOCAL ff AS LONG
    LOCAL buf AS STRING
    ff = FREEFILE
    OPEN file FOR BINARY ACCESS READ LOCK SHARED AS #ff
    GET$ #ff, LOF(#ff), buf
    CLOSE #ff
    KILL file
    ff = FREEFILE
    OPEN file FOR BINARY ACCESS WRITE AS #ff
    PUT$ #ff, REMOVE$(buf, $CR)
    CLOSE #ff
END SUB
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
SUB KillWineApps(BYVAL hDlg AS DWORD, BYVAL killall AS LONG)
    LOCAL i, nrow, nk, ff, sel AS LONG
    LOCAL r, pid AS STRING

    ' Check wine version
    IF wine_ver = "" THEN wine_ver = GetWineVer()

    ' Create shell script
    LISTVIEW GET COUNT hDlg, %IDC_LVW_LST TO nrow
    ff = FREEFILE
    OPEN UNIX_HOME + "kwa.sh" FOR OUTPUT AS #ff
    PRINT #ff, "#!/bin/bash"

    ' Take each Wine app and decide if kill or not
    FOR i = 1 TO nrow
        LISTVIEW GET STATE hDlg, %IDC_LVW_LST, i, 1 TO sel
        IF ISTRUE sel OR ISTRUE killall THEN
            LISTVIEW GET TEXT hDlg, %IDC_LVW_LST, i, 1 TO pid
            PRINT #ff, "kill -9 " + pid
            INCR nk
        END IF
    NEXT

    ' Make script executable and run it
    CLOSE #ff
    ConvertEOL(UNIX_HOME + "kwa.sh")
    r = "/home/" + ENVIRON$("USERNAME") + "/kwa.sh"
    SHELL "start /"+IIF$(wine_ver>="11","unix","exec")+" /bin/chmod +x " + r, 0
    SHELL "start /"+IIF$(wine_ver>="11","unix","exec")+" /bin/sh " + r, 0

    'Clean-up (listview, script) & display result msg
    ListWineApps hDlg
    CONTROL SET TEXT hDlg, %IDC_LBL_NFO, FORMAT$(nk) _
        + " Wine App" + IIF$(nk>1,"s","") + " killed !"
    KILL UNIX_HOME + "kwa.sh"

END SUB
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
'   ** CallBacks **
'------------------------------------------------------------------------------
CALLBACK FUNCTION MainProc()

    SELECT CASE AS LONG CB.MSG

        ' Initialization handler
        '--------------------------
        CASE %WM_INITDIALOG
            IF NOT IsOnUnix() THEN
                CONTROL DISABLE CB.HNDL, %IDC_BTN_FND
                SetTimer CB.HNDL, 1, 1000, %NULL ' timer to show DlgMsg on top of dialog
            ELSE
                ListWineApps CB.HNDL
            END IF

        ' Timer to display DlgMsg
        '--------------------------
        CASE %WM_TIMER
            KillTimer CB.HNDL, 1
            MyMsgBox  CB.HNDL, "This program needs to be run from a Unix system.", "", %MB_ICONINFORMATION

        ' Double-click on listview item to kill Wine App
        ' -----------------------------------------------
        CASE %WM_NOTIFY
            LOCAL pLV AS LVUNION PTR
            pLV = CB.LPARAM
            IF %IDC_LVW_LST = @pLV.NMHDR.IDFROM _
                AND %NM_DBLCLK = @pLV.NMHDR.CODE THEN
                KillWineApps CB.HNDL, 0
            END IF

        ' Process control notifications
        '-------------------------------
        CASE %WM_COMMAND
            SELECT CASE AS LONG CB.CTL

                CASE %IDC_BTN_FND       ' Find Wine Apps
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        ListWineApps CB.HNDL
                    END IF

                CASE %IDC_BTN_KL1       ' Kill Selected
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        KillWineApps CB.HNDL, 0
                    END IF

                CASE %IDC_BTN_KLA       ' Kill All
                    IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                        KillWineApps CB.HNDL, 1
                    END IF

            END SELECT
    END SELECT
END FUNCTION
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
'   ** Dialogs **
'------------------------------------------------------------------------------
FUNCTION MainShow(BYVAL hParent AS DWORD) AS LONG
    LOCAL hDlg   AS DWORD
    LOCAL lStyle AS LONG

    DIALOG NEW PIXELS, hParent, $EXE+$SPC+$VER, , _
        , 460, 250, %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
    DIALOG SET ICON         hDlg, "AICO"

    CONTROL ADD LABEL,      hDlg, %IDC_LBL_NFO, "0 Wine App detected", 10, 6, 270, 16

    CONTROL ADD LISTVIEW,   hDlg, %IDC_LVW_LST, "", 8, 28, 440, 172
    LISTVIEW INSERT COLUMN  hDlg, %IDC_LVW_LST, 1, "PID", 50, %SS_LEFT
    LISTVIEW INSERT COLUMN  hDlg, %IDC_LVW_LST, 2, "Stat", 40, %SS_LEFT
    LISTVIEW INSERT COLUMN  hDlg, %IDC_LVW_LST, 3, "Time", 50, %SS_LEFT
    LISTVIEW INSERT COLUMN  hDlg, %IDC_LVW_LST, 4, "Command", 240, %SS_LEFT
    LISTVIEW INSERT COLUMN  hDlg, %IDC_LVW_LST, 5, "TTY", 35, %SS_LEFT
    LISTVIEW GET STYLEXX    hDlg, %IDC_LVW_LST TO lStyle
    LISTVIEW SET STYLEXX    hDlg, %IDC_LVW_LST, lStyle OR %LVS_EX_FULLROWSELECT OR %LVS_EX_GRIDLINES OR %LVS_EX_INFOTIP OR %LVS_EX_LABELTIP

    CONTROL ADD CHECKBOX,   hDlg, %IDC_CHK_SYS, "Hide system services", 8, 210, 170, 24
    CONTROL SET CHECK       hDlg, %IDC_CHK_SYS, 1

    CONTROL ADD BUTTON,     hDlg, %IDC_BTN_FND, "Find Apps", 185, 210, 80, 24, _
        %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_TEXT _
        OR %BS_PUSHBUTTON OR %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR _
        %WS_EX_LTRREADING
    CONTROL ADD BUTTON,     hDlg, %IDC_BTN_KL1, "Kill Selected", 276, 210, 80, 24, _
        %WS_CHILD OR %WS_VISIBLE OR %WS_DISABLED OR %WS_TABSTOP OR %BS_TEXT _
        OR %BS_PUSHBUTTON OR %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR _
        %WS_EX_LTRREADING
    CONTROL ADD BUTTON,     hDlg, %IDC_BTN_KLA, "/!\ Kill All", 368, 210, 80, 24, _
        %WS_CHILD OR %WS_VISIBLE OR %WS_DISABLED OR %WS_TABSTOP OR %BS_TEXT _
        OR %BS_PUSHBUTTON OR %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR _
        %WS_EX_LTRREADING

    DIALOG SHOW MODAL hDlg, CALL MainProc

END FUNCTION
'------------------------------------------------------------------------------