How to deal with .lnk files in wine?

Questions about Wine on Linux
Locked
caetydid
Level 1
Level 1
Posts: 6
Joined: Sat Sep 01, 2018 2:35 am

How to deal with .lnk files in wine?

Post by caetydid »

Hello everyone,

I am the developer of Dolmades - a solution to package particular windows applications into wine containers.
My goal is to automate custom setups as much as possible.

Win installers commonly create .lnk files which pretty much describe everything needed to know to properly run their targets.
I've read somewhere that wine could execute lnk files natively but it never worked for me (I've just tried wine 3).
So far I've found a couple of external tools which can deal with .lnk files:
I'd clearly prefer using a native wine tool or a trusted script.
Is there a native wine tool for creating lnk files and dumping their meta data?
Could someone please report their experiences on how they do this?
Best regards Stefan
User avatar
Bob Wya
Level 12
Level 12
Posts: 3068
Joined: Sat Oct 16, 2010 7:40 pm

Re: How to deal with .lnk files in wine?

Post by Bob Wya »

caetydid wrote: I'd clearly prefer using a native wine tool or a trusted script.
Is there a native wine tool for creating lnk files and dumping their meta data?
Could someone please report their experiences on how they do this?
Best regards Stefan
@Stefan

Code: Select all

wine start *.lnk
Will correctly launch an application, using a standard MS binary format .lnk file.
This assumes that the target executable, of the .lnk binary link file, actually exists in your current WINEPREFIX!
See: WineHQ Wiki: Start

Since .lnk are yet another MS binary abomination I usually replace references to them, in the auto-generated Wine .desktop launchers. :roll:

The native Linux strings tool is handy in this regard.
It is simple file parser, that extracts and prints 4(+) (default) character printable strings from binary file(s).
E.g.

Code: Select all

strings 'Open Office Document.lnk' | grep '^C:'

C:\Program Files\Microsoft Office\OFFICE11\OSA.EXE
Then you can launch the application directly with:

Code: Select all

wine start 'C:\Program Files\Microsoft Office\OFFICE11\OSA.EXE'
This is the "officially recommended" way to start Windows applications, with Wine.
See: WineHQ User's Guide: 3 Using Wine


Bob
caetydid
Level 1
Level 1
Posts: 6
Joined: Sat Sep 01, 2018 2:35 am

Re: How to deal with .lnk files in wine?

Post by caetydid »

Thanks for supplying help, Bob,

however, this is odd: In case of MS Office 2013 it behaves like this for me:

Code: Select all

wine /wineprefix/drive_c/Program\ Files/Microsoft\ Office/Office15/ONENOTE.EXE
# WORKS

Code: Select all

strings '/wineprefix/drive_c/users/stefan/Start Menu/Programs/Microsoft Office 2013/OneNote 2013.lnk' | grep 'C:'
C:\Program Files\Microsoft Office\Office15\ONENOTE.EXE
file /wineprefix/drive_c/Program\ Files/Microsoft\ Office/Office15/ONENOTE.EXE 
/wineprefix/drive_c/Program Files/Microsoft Office/Office15/ONENOTE.EXE: PE32 executable (GUI) Intel 80386, for MS Windows

Code: Select all

wine /wineprefix/drive_c/users/stefan/Start\ Menu/Programs/Mi
crosoft\ Office\ 2013/OneNote\ 2013.lnk 
wine: Bad EXE format for C:\users\stefan\Start Menu\Programs\Microsoft Office 2013\OneNote 2013.lnk.
# no matter if I escape or quote it
Apart from that another problem affecting this is .lnk files often not resolving to their targets due to wrong casing (Linux is case sensitive)
Is there a way to tell wine to ignore casing in file names?

cheers Stefan
User avatar
Bob Wya
Level 12
Level 12
Posts: 3068
Joined: Sat Oct 16, 2010 7:40 pm

Re: How to deal with .lnk files in wine?

Post by Bob Wya »

caetydid wrote:Thanks for supplying help, Bob,
...

Code: Select all

wine /wineprefix/drive_c/users/stefan/Start\ Menu/Programs/Mi
crosoft\ Office\ 2013/OneNote\ 2013.lnk 
wine: Bad EXE format for C:\users\stefan\Start Menu\Programs\Microsoft Office 2013\OneNote 2013.lnk.
# no matter if I escape or quote it
That should be:

Code: Select all

wine start /unix '/wineprefix/drive_c/users/stefan/Start Menu/Programs/Microsoft Office 2013/OneNote 2013.lnk'
caetydid wrote: Apart from that another problem affecting this is .lnk files often not resolving to their targets due to wrong casing (Linux is case sensitive)
Is there a way to tell wine to ignore casing in file names?
You are generally best to use winepath to mangle path names between Unix and Windows.
  • Windows paths are case insensitive under Wine.
  • Unix paths are case sensitive under Wine.
Hint: try to stick to the former!!

Bob
caetydid
Level 1
Level 1
Posts: 6
Joined: Sat Sep 01, 2018 2:35 am

Re: How to deal with .lnk files in wine?

Post by caetydid »

Thanks a big deal, Bob!

this is working! It essentially helps me a lot :)

Stefan
User avatar
Bob Wya
Level 12
Level 12
Posts: 3068
Joined: Sat Oct 16, 2010 7:40 pm

Re: How to deal with .lnk files in wine?

Post by Bob Wya »

@caetydid

On a tangential note...

I often recommend to use native Windows tools, when extracting archives for Windows applications, running under Wine.
This might seem a bit odd, because there are excellent native Linux tools to do this job!
The issue is again because only Wine will correctly mangle case insensitivity on a case sensitive Linux filesystem (e.g. ext4, xfs, ZFS, etc.)

An example of this the WineHQ AppDB entry for the game Deus Ex.

See the section:
How To / Notes
Install Kentie Launcher

This gives an example of how to use the native Windows 7-Zip tool to extract an archive, using Wine.
I use a bit of winepath mangling in this example as well...

Bob
Riky92
Newbie
Newbie
Posts: 2
Joined: Fri Apr 09, 2021 6:02 am

Re: How to deal with .lnk files in wine?

Post by Riky92 »

Bob Wya wrote: Sat Sep 01, 2018 7:51 pm
caetydid wrote: I'd clearly prefer using a native wine tool or a trusted script.
Is there a native wine tool for creating lnk files and dumping their meta data?
Could someone please report their experiences on how they do this?
Best regards Stefan
@Stefan

Code: Select all

wine start *.lnk
Will correctly launch an application, using a standard MS binary format .lnk file.
This assumes that the target executable, of the .lnk binary link file, actually exists in your current WINEPREFIX!
See: WineHQ Wiki: Start

Since .lnk are yet another MS binary abomination I usually replace references to them, in the auto-generated Wine .desktop launchers. :roll:

The native Linux strings tool is handy in this regard.
It is simple file parser, that extracts and prints 4(+) (default) character printable strings from binary file(s).
E.g.

Code: Select all

strings 'Open Office Document.lnk' | grep '^C:'

C:\Program Files\Microsoft Office\OFFICE11\OSA.EXE
Then you can launch the application directly with:

Code: Select all

wine start 'C:\Program Files\Microsoft Office\OFFICE11\OSA.EXE'
This is the "officially recommended" way to start Windows applications, with Wine.
See: WineHQ User's Guide: 3 Using Wine


Bob
This answer does not answer Stefan's question "How to create an .lnk file" but explains how to call an .lnk file.
I'm also interested in how to create it.
madewokherd
Level 4
Level 4
Posts: 143
Joined: Mon Jun 02, 2008 5:03 pm

Re: How to deal with .lnk files in wine?

Post by madewokherd »

Wine has no builtin tools for creating lnk files.

You would need to run a Windows program that creates them. AutoHotKey has a command for this: https://www.autohotkey.com/docs/command ... ortcut.htm
User avatar
Bob Wya
Level 12
Level 12
Posts: 3068
Joined: Sat Oct 16, 2010 7:40 pm

Re: How to deal with .lnk files in wine?

Post by Bob Wya »

Riky92
Newbie
Newbie
Posts: 2
Joined: Fri Apr 09, 2021 6:02 am

Re: How to deal with .lnk files in wine?

Post by Riky92 »

I invented the right solution that guarantees perfect compatibility with wine:

Code: Select all

lnk () {
    cat <<EOF > /tmp/shortcut.vbs
TargetPath = WScript.Arguments(0)
Pos = InStrRev(TargetPath, "\") - 1
If Pos > 0 Then WorkingDirectory = Left(TargetPath, Pos) Else WorkingDirectory = "."
Set lnk = CreateObject("WScript.Shell").CreateShortcut(WScript.Arguments(1))
    lnk.TargetPath = TargetPath
    lnk.WorkingDirectory = WorkingDirectory
    lnk.Save
EOF
    wine wscript '//b' 'Z:\tmp\shortcut.vbs' "$@" 2> /dev/null
    local exit_code=$?
    rm -f /tmp/shortcut.vbs
    return $exit_code
}
I was able to call the function cleanly:

Code: Select all

lnk 'C:\Program Files (x86)\Rufus\rufus.exe' 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Rufus.lnk'
This is the installation function of a program in my case:

Code: Select all

update_rufus () {
    local old_version="$(cat ~/'.wine/dosdevices/c:/Program Files (x86)/Rufus/version.txt' 2> /dev/null)"
    local link="$(wget -q 'https://api.github.com/repos/pbatard/rufus/releases/latest' -O - | grep '"browser_download_url":' | grep -o -m 1 -E '[^"]+/rufus-[0-9.]+\.exe')"
    wget -q "$link" -O rufus.exe
    local exit_code=$?
    if [[ $exit_code -eq 0 ]]; then
        mkdir -p ~/'.wine/drive_c/Program Files (x86)/Rufus'
        echo "$link" | perl -lpe 's|^.*/rufus-([0-9.]+)\.exe$|\1|' > ~/'.wine/drive_c/Program Files (x86)/Rufus/version.txt'
        mv rufus.exe ~/'.wine/drive_c/Program Files (x86)/Rufus'
        lnk 'C:\Program Files (x86)\Rufus\rufus.exe' 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Rufus.lnk'
        local new_version="$(cat ~/'.wine/dosdevices/c:/Program Files (x86)/Rufus/version.txt')"
        if [[ "$new_version" == "$old_version" ]]; then
            echo "Rufus is already the newest version ($new_version)."
        else
            echo "Rufus has been successfully updated ($new_version)."
        fi
    else
        echo 'An error has occurred.'
    fi
    return $exit_code
}
Locked