3

My current script looks like this:

cd ~/.wine/drive_c/
echo "test123" > foo$$.txt
wine start "C:\foo$$.txt"
wineserver -w
echo "Wine is done!"

which works fine when only one program is running in wine at a time. However if I run this a second time, before the first program is done, both scripts will wait for each others programs to exit.

This does not work:

cd ~/.wine/drive_c/
echo "test123" > foo$$.txt
$(wine start "C:\foo$$.txt") &
wait ${!}
echo "Wine is done!"

as it will exit before you close the text editor.

I need to use the start command, because I want a file to be run with its default editor/viewer.

Tyilo
  • 28,998
  • 40
  • 113
  • 198

4 Answers4

3

To wait for the process started by wine to exit, you can pipe its output to another program. On my system, the following achieves the desired effect:

wine "program.exe" | cat
echo "program.exe has finished"

If you want to wait asynchronously:

wine "program.exe" | cat & pid=$!
# ...
wait $pid
echo "program.exe has finished"
coldfix
  • 6,604
  • 3
  • 40
  • 50
  • Note: the `| cat` part of this command does nothing. `cat` finishes when the `wine` command exits. However, **`wine` itself waits until the program exits**. `wine start` (what OP is using) does not wait. So the solution is simply to use `wine` instead of `wine start`. – Merlijn Sebrechts Apr 05 '20 at 21:04
  • 1
    @MerlijnSebrechts The pipe (`|cat` part) changes buffering and the result of `isatty()` and can therefore influence wine. At the time of writing it was needed to make wine behave as desired. It's possible that wine has changed in the meantime and the pipe is no longer required. – coldfix Jan 08 '21 at 23:15
  • Thanks for the explanation! From my unscientific testing, the Wine command did not wait longer with `| cat`. I did find this comment, However, saying some programs might need this to prevent them from misbehaving: https://stackoverflow.com/questions/1401002/how-to-trick-an-application-into-thinking-its-stdout-is-a-terminal-not-a-pipe#comment91870873_1402389 – Merlijn Sebrechts Jan 11 '21 at 22:04
3

wineserver has a --wait flag which can be used to do exactly that.

However if you run multiple programs at once, it will wait for all of them to finish.

Tyilo
  • 28,998
  • 40
  • 113
  • 198
3

wine <program> waits until the program exits. wine start program does not.

A summary:

  • wine <program> starts the program and waits until it is finished. I recommend using this method.
  • wine start <program> starts the program and immediately exits without waiting. The program will keep running in the background.
  • wine start \wait <program> starts the program and waits until it is finished. This is the same behavior as wine <program>.
  • wineserver --wait waits until all programs and all services in Wine are finished. This command does not launch any program itself but waits for existing programs and services.

Services like services.exe, plugplay.exe, and winedevice.exe keep on running a few seconds after the last program finishes, and wineserver --wait also waits until these services exit.

Some of these services hold state and write their state (and the registry) to disk when they exit. So if you want to backup or remove your wine prefix, make sure to wait until these services have exited.

Merlijn Sebrechts
  • 545
  • 1
  • 5
  • 16
  • Where did you find this summary? From the command line there is no such description and I can't find it on the internet, where did you get it from? – Mario Palumbo Jan 31 '23 at 20:06
  • 1
    @MarioPalumbo I created this summary myself, it doesn't really exist. A lot of the info on the internet was conflicting, so I tested it myself. I needed to know the difference for developing sommelier-core: https://github.com/snapcrafters/sommelier-core – Merlijn Sebrechts Feb 01 '23 at 09:41
0

What happens is that wine just asks wineserver to start the program and exits, and I have found no good mechanism to get notifications from wineserver about the processes that it spawns.

My suggestion would be to wait for the completion of the process started by wineserver using one of the methods in How to wait for exit of non-children processes, but you need to know its PID. Possible ideas: run wineserver -f -d | grep init_thread( and get PIDs from there, but I can see no easy way to find out which is which, to avoid race conditions, and to ignore noise; or try to find your process in the output of ps, but it's ugly, and definitely not robust.

If nothing better surfaces, you might want to suggest the addition of such a feature to the Wine devs (probably as a flag to wine).

Community
  • 1
  • 1
a3nm
  • 8,717
  • 6
  • 31
  • 39