File "exe2unix.inc"
Path: /exe2unix/inc/exe2unix.inc
File size: 11.53 KB
MIME-type:
Charset: utf-8
'--------------------------------------------------------------------------------
' 'exe2unix.inc' v0.4 for PBWin9 - Facilitates the usage of Windows .exe in Linux
'--------------------------------------------------------------------------------
DECLARE FUNCTION Exe2Unix(BYVAL src AS STRING, BYVAL showInAppMenu AS LONG, _
OPTIONAL BYVAL dkpName AS STRING) AS LONG
' - extract exe icon, convert it to png, copy it to ~/.local/share/icons
' - create a .desktop entry in ~/.local/share/applications to show icon in dock
' - if 'showInAppMenu' is true, add the program in the XDG Desktop Menu
' - use 'gio set' to apply the icon to the exe in the Linux file explorer
DECLARE SUB Me2Unix(BYVAL askConfirmation AS LONG, BYVAL showInAppMenu AS LONG, _
OPTIONAL BYVAL dkpName AS STRING)
' - exact same as Exe2Unix() but applied to ourselves when compiled into an exe
DECLARE FUNCTION Exe2UnixConfirm(BYVAL src AS STRING) AS LONG
' - ask user confirmation to register the exe in the Linux App Menu,
' result is either %IDYES or %IDNO
DECLARE FUNCTION IcoStrip2Unix(BYVAL src AS STRING) AS STRING
' - extract an exe icon, convert it to png, copy it to ~/.local/share/icons
DECLARE SUB FileIco2Unix(BYVAL src AS STRING, BYVAL png AS STRING)
' - apply an icon (png) to a file in the Linux file explorer
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
#INCLUDE ONCE "Gdiplus.inc" ' from JoseRoca includes
#INCLUDE ONCE "GdipUtils.inc" ' from JoseRoca includes
#INCLUDE ONCE "inc/icostrip.inc"
#INCLUDE ONCE "inc/unix.inc"
'--------------------------------------------------------------------------------
MACRO UNIX_SHARE = UNIX_HOME + ".local\share\"
'--------------------------------------------------------------------------------
MACRO UNIX_XPATH = UnixPath(LTRIM$(EXE.PATH$, "\"))
'--------------------------------------------------------------------------------
MACRO UNIX_DESKTOP(x) = UNIX_SHARE+"applications\wine-"+UnixSafeName(x)+".desktop"
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION Exe2Unix(BYVAL src AS STRING, BYVAL showInAppMenu AS LONG, _
OPTIONAL BYVAL dkpName AS STRING) AS LONG
' Register a windows executable as a Linux App:
' - extract its icon, convert it to png, copy it to ~/.local/share/icons
' - create a .desktop entry in ~/.local/share/applications to show and launch
' the program from the XDG Desktop Menu
' - customize the .exe itself to display its icon in Linux file explorer
LOCAL ff AS LONG
LOCAL lRes AS LONG
LOCAL png AS STRING
LOCAL wmc AS STRING
LOCAL xec AS STRING
LOCAL dkp AS STRING
FUNCTION = 0 ' by default
' Extract exe icon and convert to png in ~/.local/share/icons
png = IcoStrip2Unix(src)
' Set the program icon to the executable itself in Linux file explorer
FileIco2Unix src, png
' Create the .desktop fields
IF LEN(dkpName) THEN
dkp = UNIX_DESKTOP(dkpName)
ELSE
dkp = UNIX_DESKTOP(src)
END IF
wmc = LCASE$(PATHNAME$(NAMEX, src))
xec = "env WINEPREFIX=" + $DQ
xec += "/home/" + ENVIRON$("USERNAME")
xec += "/.wine" + $DQ + " wine "
xec += UnixProtect(src)
' Create .desktop file for the exe in ~/.local/share/applications
ff = FREEFILE
OPEN dkp FOR OUTPUT AS #ff
PRINT #ff, "[Desktop Entry]"
PRINT #ff, "Name=" + PATHNAME$(NAME, src)
PRINT #ff, "StartupWMClass=" + wmc
IF ISTRUE showInAppMenu THEN
PRINT #ff, "Exec=" + xec
ELSE
PRINT #ff, "NoDisplay=true"
END IF
PRINT #ff, "Type=Application"
PRINT #ff, "Terminal=false"
PRINT #ff, "StartupNotify=true"
PRINT #ff, "Icon=" + PATHNAME$(NAME, png)
CLOSE #ff
' Set the program icon to the .desktop file too, for user friendliness
FileIco2Unix dkp, png
' Done!
FUNCTION = 1
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB Me2Unix(BYVAL askConfirmation AS LONG, BYVAL showInAppMenu AS LONG, _
OPTIONAL BYVAL dkpName AS STRING)
LOCAL ff, lRes AS LONG
LOCAL xPath AS STRING
LOCAL dPath AS STRING
LOCAL zText AS ASCIIZ * 255
' No need to go further if we're not on Unix
IF NOT IsOnUnix() THEN EXIT SUB
' In any case, reveal the exe icon in Nautilus
FileIco2Unix EXE.FULL$, IcoStrip2Unix(EXE.FULL$)
' Check any existing .dekstop file
IF LEN(dkpName) THEN
dPath = UNIX_DESKTOP(dkpName)
ELSE
dPath = UNIX_DESKTOP(EXE.FULL$)
END IF
IF EXISTS(dPath) THEN EXIT SUB
' Ask user confirmation if needed
xPath = EXE.FULL$
IF ISTRUE askConfirmation THEN
lRes = MyMsgBox(0, "Do you want to register this program as a Linux App?" + $CRLF _
+ "(it will be listed in the XDG Desktop Menu for quick access)" _
, EXE.NAME$, %MB_ICONQUESTION + %MB_YESNO)
IF lRes = %IDNO THEN EXIT SUB
IF LCASE$(EXE.PATH$) <> "c:\apps\" THEN
lRes = MyMsgBox(0, "We recommend to have Windows executables stored in the " _
+ "'~/.wine/drive_c/Apps' folder. Would you like to move this " _
+ "program there, or do you prefer to launch it from " _
+ "'" + UNIX_XPATH + "' ?" + $CR _
+ "(beware that in this case, moving it in the future will break " _
+ "the Linux App shortcut in the Desktop Menu)." + $CR + $CR _
+ "- Click Yes to move to '~/.wine/drive_c/Apps'" + $CR + $CR _
+ "- Click No to keep in '" + UNIX_XPATH + "'" + $CR + $CR _
+ "- Click Cancel to abandon registration as a Linux App." _
, EXE.NAME$, %MB_ICONQUESTION + %MB_YESNOCANCEL)
IF lRes = %IDCANCEL THEN EXIT SUB
IF lRes = %IDYES THEN
MKDIR "C:\Apps"
FILECOPY EXE.FULL$, "C:\Apps\" + EXE.NAMEX$
xPath = "C:\Apps\" + EXE.NAMEX$
END IF
END IF
END IF
' Register!
lRes = Exe2Unix(xPath, showInAppMenu, dkpName)
IF askConfirmation AND lRes <= 0 THEN
MyMsgBox(0, "An error occured." + $CRLF _
+"Registration failed." + $CRLF + $CRLF _
+"Click OK to continue the program." _
, EXE.NAME$, %MB_ICONWARNING)
EXIT SUB
END IF
' Special case: exe moved, create batch file to delete old exe and restart in C:\Apps
IF askConfirmation AND xPath <> EXE.FULL$ THEN
ff = FREEFILE
OPEN ENVIRON$("TEMP") + "\" + EXE.NAME$ + ".bat" FOR OUTPUT AS #ff
PRINT #ff, "TimeOut 1"
PRINT #ff, "del " + $DQ + EXE.FULL$ + $DQ
PRINT #ff, "start " + $DQ+$DQ + $SPC + $DQ+xPath+$DQ
CLOSE #ff
ff = SHELL(ENVIRON$("TEMP") + "\" + EXE.NAME$ + ".bat", 0)
ExitProcess(12345) ' Close ourselves
END IF
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION Exe2UnixConfirm(BYVAL src AS STRING) AS LONG
' Ask user confirmation to register the exe in the Linux App Menu
' Result is either %IDYES or %IDNO
LOCAL lRes AS LONG
lRes = MyMsgBox(0, "Would you like to register " _
+ $DQ + PATHNAME$(NAMEX,src) + $DQ _
+ " as a Linux App and launch it from " _
+ PATHNAME$(PATH,src) + " ?", EXE.NAME$ _
, %MB_ICONQUESTION + %MB_YESNO)
FUNCTION = lRes
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION IcoStrip2Unix(BYVAL src AS STRING) AS STRING
' - extract an exe icon, convert it to png, copy it to ~/.local/share/icons
LOCAL ico AS STRING
LOCAL png AS STRING
LOCAL hIcon AS DWORD
LOCAL pImage AS DWORD
LOCAL i, j AS LONG
' Does the executable icon in png format already exist in ~/.local/share/icons?
ico = UNIX_SHARE + "icons\" + UnixSafeName(src) + ".ico"
png = LEFT$(ico, -4) + ".png"
IF EXISTS(png) THEN FUNCTION = png : EXIT FUNCTION
' If not, extract exe's main icon
IF NOT EXISTS(ico) THEN
IF IcoStrip(src, 1, ico) <= 0 THEN ' extraction failed
FUNCTION = ""
EXIT FUNCTION
END IF
END IF
' Convert executable icon to png
' UnixShell "convert " _
' + "~/.local/share/icons/"+UnixSafeName(src)+".ico " _
' + "~/.local/share/icons/"+UnixSafeName(src)+".png"
hIcon = LoadImage(0, BYVAL STRPTR(ico), %IMAGE_ICON, gsIcoRes, gsIcoRes, %LR_LOADFROMFILE)
GdipCreateBitmapFromHICON hIcon, pImage
GdipConvertToPng pImage, png
' Conversion to png worked (single resolution icon)
IF EXISTS(png) THEN FUNCTION = png : EXIT FUNCTION
' Conversion produced several resolution png's
IF EXISTS(LEFT$(png,-4)+"-0.png") THEN
DO
INCR i
LOOP UNTIL NOT EXISTS(LEFT$(png,-4)+"-"+FORMAT$(i)+".png")
DECR i ' final index for highest resolution png
NAME LEFT$(png,-4)+"-"+FORMAT$(i)+".png" _
AS LEFT$(png,-4)+".png"
FOR j = 0 TO i-1
KILL LEFT$(png,-4)+"-"+FORMAT$(j)+".png"
NEXT
FUNCTION = png
EXIT FUNCTION
END IF
' Conversion didn't produce any png > use ico instead
FUNCTION = ico
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB FileIco2Unix(BYVAL src AS STRING, BYVAL png AS STRING)
' - customize a file in Linux file explorer to display an icon (png)
LOCAL xec AS STRING
xec = "gio set -t 'string' '" + UnixPath(src) + "' "
xec += "'metadata::custom-icon' "
xec += "'file://" + UnixPath(png) + "'"
UnixShell xec
END SUB
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
#IF NOT %DEF(%FN_EXISTS)
%FN_EXISTS = -1
FUNCTION EXISTS(BYVAL f AS STRING) AS LONG
LOCAL i AS LONG
i = GETATTR(f)
FUNCTION = (ERRCLEAR = 0)
END FUNCTION
#ENDIF
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION UnixSafeName(BYVAL xpath AS STRING) AS STRING
' Define a safe filename for a windows executable, for use in unix
LOCAL r AS STRING
r = PATHNAME$(NAME, xpath)
r = LCASE$(REMOVE$(r, " "))
FUNCTION = r
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
FUNCTION UnixProtect(BYVAL str AS STRING) AS STRING
LOCAL r AS STRING
r = str
REPLACE "\" WITH "\\\\" IN r
REPLACE " " WITH "\\ " IN r
FUNCTION = r
END FUNCTION
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
SUB GdipConvertToPng(BYVAL pImage AS DWORD, BYVAL srcImg AS STRING)
LOCAL hStatus AS LONG
LOCAL token AS DWORD
LOCAL StartupInput AS GdiplusStartupInput
' Initialize GDI+
StartupInput.GdiplusVersion = 1
hStatus = GdiplusStartup(token, StartupInput, BYVAL %NULL)
IF hStatus THEN
' ?"Error initializing GDI+",%MB_ICONERROR,EXE.NAME$
EXIT SUB
END IF
' Call conversion function
GdiPlusSaveImageToPng pImage, srcImg
' Shutdown GDI+
GdiplusShutdown token
END SUB
'--------------------------------------------------------------------------------