コード例 #1
0
 def shutdown(self):
     """Orders Steam to shutdown"""
     logger.info("Shutting down Steam")
     shutdown_command = MonitoredCommand((self.launch_args + ["-shutdown"]),
                                         runner=self,
                                         env=self.get_env(os_env=False))
     shutdown_command.start()
コード例 #2
0
ファイル: game.py プロジェクト: wberrier/lutris
    def start_xephyr(self, display=":2"):
        """Start a monitored Xephyr instance"""
        if not system.find_executable("Xephyr"):
            raise GameConfigError(
                "Unable to find Xephyr, install it or disable the Xephyr option"
            )

        xephyr_depth = "8" if self.runner.system_config.get(
            "xephyr") == "8bpp" else "16"
        xephyr_resolution = self.runner.system_config.get(
            "xephyr_resolution") or "640x480"
        xephyr_command = [
            "Xephyr",
            display,
            "-ac",
            "-screen",
            xephyr_resolution + "x" + xephyr_depth,
            "-glamor",
            "-reset",
            "-terminate",
        ]
        if self.runner.system_config.get("xephyr_fullscreen"):
            xephyr_command.append("-fullscreen")

        xephyr_thread = MonitoredCommand(xephyr_command)
        xephyr_thread.start()
        time.sleep(3)
        return display
コード例 #3
0
 def start_xephyr(self, display=":2"):
     """Start a monitored Xephyr instance"""
     if not system.find_executable("Xephyr"):
         raise GameConfigError("Unable to find Xephyr, install it or disable the Xephyr option")
     xephyr_command = get_xephyr_command(display, self.runner.system_config)
     xephyr_thread = MonitoredCommand(xephyr_command)
     xephyr_thread.start()
     time.sleep(3)
     return display
コード例 #4
0
ファイル: steam.py プロジェクト: xeddmc/lutris
 def remove_game_data(self, appid=None, **kwargs):
     if not self.is_installed():
         return False
     command = MonitoredCommand(
         [self.get_executable(), "steam://uninstall/%s" % (appid or self.appid)],
         runner=self,
         env=self.get_env(),
     )
     command.start()
コード例 #5
0
    def on_game_quit(self):
        """Restore some settings and cleanup after game quit."""

        if self.prelaunch_executor and self.prelaunch_executor.is_running:
            logger.info("Stopping prelaunch script")
            self.prelaunch_executor.stop()

        self.heartbeat = None
        if self.state != self.STATE_STOPPED:
            logger.warning("Game still running (state: %s)", self.state)
            self.stop()

        # Check for post game script
        postexit_command = self.runner.system_config.get("postexit_command")
        if postexit_command:
            command_array = shlex.split(postexit_command)
            if system.path_exists(command_array[0]):
                logger.info("Running post-exit command: %s", postexit_command)
                postexit_thread = MonitoredCommand(
                    command_array,
                    include_processes=[os.path.basename(postexit_command)],
                    env=self.game_runtime_config["env"],
                    cwd=self.directory,
                )
                postexit_thread.start()

        quit_time = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
        logger.debug("%s stopped at %s", self.name, quit_time)
        self.lastplayed = int(time.time())
        self.save(save_config=False)

        os.chdir(os.path.expanduser("~"))

        if self.antimicro_thread:
            self.antimicro_thread.stop()

        if self.resolution_changed or self.runner.system_config.get(
                "reset_desktop"):
            DISPLAY_MANAGER.set_resolution(self.original_outputs)

        if self.compositor_disabled:
            self.set_desktop_compositing(True)

        if self.screen_saver_inhibitor_cookie is not None:
            SCREEN_SAVER_INHIBITOR.uninhibit(
                self.screen_saver_inhibitor_cookie)
            self.screen_saver_inhibitor_cookie = None

        if self.runner.system_config.get("use_us_layout"):
            with subprocess.Popen(["setxkbmap"], env=os.environ) as setxkbmap:
                setxkbmap.communicate()

        if self.runner.system_config.get("restore_gamma"):
            restore_gamma()

        self.process_return_codes()
コード例 #6
0
 def start_antimicrox(self, antimicro_config):
     """Start Antimicrox with a given config path"""
     antimicro_path = system.find_executable("antimicrox")
     if not antimicro_path:
         logger.warning("Antimicrox is not installed.")
         return
     logger.info("Starting Antic")
     antimicro_command = [antimicro_path, "--hidden", "--tray", "--profile", antimicro_config]
     self.antimicro_thread = MonitoredCommand(antimicro_command)
     self.antimicro_thread.start()
コード例 #7
0
 def on_execute_script_clicked(self, _widget):
     """Execute the game's associated script"""
     manual_command = self.game.runner.system_config.get("manual_command")
     if path_exists(manual_command):
         MonitoredCommand(
             [manual_command],
             include_processes=[os.path.basename(manual_command)],
             cwd=self.game.directory,
         ).start()
         logger.info("Running %s in the background", manual_command)
コード例 #8
0
ファイル: winesteam.py プロジェクト: sonicpp/lutris
 def remove_game_data(self, appid=None, **kwargs):
     if not self.is_installed():
         logger.warning("Trying to remove a winesteam game but it's not installed.")
         return False
     self.force_shutdown()
     uninstall_command = MonitoredCommand(
         (self.launch_args + ["steam://uninstall/%s" % (appid or self.appid)]),
         runner=self,
         env=self.get_env(os_env=False),
     )
     uninstall_command.start()
コード例 #9
0
ファイル: game.py プロジェクト: sonicpp/lutris
    def on_game_quit(self):
        """Restore some settings and cleanup after game quit."""

        if self.prelaunch_executor and self.prelaunch_executor.is_running:
            logger.info("Stopping prelaunch script")
            self.prelaunch_executor.stop()

        self.heartbeat = None
        if self.state != self.STATE_STOPPED:
            logger.warning("Game still running (state: %s)", self.state)
            self.stop()

        # Check for post game script
        postexit_command = self.runner.system_config.get("postexit_command")
        if system.path_exists(postexit_command):
            logger.info("Running post-exit command: %s", postexit_command)
            postexit_thread = MonitoredCommand(
                [postexit_command],
                include_processes=[os.path.basename(postexit_command)],
                env=self.game_runtime_config["env"],
                cwd=self.directory,
            )
            postexit_thread.start()

        if self.discord_presence.available:
            self.discord_presence.clear_discord_rich_presence()

        quit_time = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
        logger.debug("%s stopped at %s", self.name, quit_time)
        self.lastplayed = int(time.time())
        self.save(metadata_only=True)

        os.chdir(os.path.expanduser("~"))

        if self.resolution_changed or self.runner.system_config.get(
                "reset_desktop"):
            DISPLAY_MANAGER.set_resolution(self.original_outputs)

        if self.compositor_disabled:
            self.set_desktop_compositing(True)

        if self.runner.system_config.get("use_us_layout"):
            subprocess.Popen(["setxkbmap"], env=os.environ).communicate()

        if self.runner.system_config.get("restore_gamma"):
            restore_gamma()

        self.process_return_codes()
        if self.exit_main_loop:
            exit()
コード例 #10
0
ファイル: game.py プロジェクト: andrewschott/lutris
 def xboxdrv_start(self, config):
     command = [
         "pkexec",
         "xboxdrv",
         "--daemon",
         "--detach-kernel-driver",
         "--dbus",
         "session",
         "--silent",
     ] + shlex.split(config)
     logger.debug("[xboxdrv] %s", " ".join(command))
     self.xboxdrv_thread = MonitoredCommand(command, include_processes=["xboxdrv"])
     self.xboxdrv_thread.stop_func = self.xboxdrv_stop
     self.xboxdrv_thread.start()
コード例 #11
0
 def start_prelaunch_command(self):
     """Start the prelaunch command specified in the system options"""
     prelaunch_command = self.runner.system_config.get("prelaunch_command")
     command_array = shlex.split(prelaunch_command)
     if not system.path_exists(command_array[0]):
         logger.warning("Command %s not found", command_array[0])
         return
     self.prelaunch_executor = MonitoredCommand(
         command_array,
         include_processes=[os.path.basename(command_array[0])],
         env=self.game_runtime_config["env"],
         cwd=self.directory,
     )
     self.prelaunch_executor.start()
     logger.info("Running %s in the background", prelaunch_command)
コード例 #12
0
 def start_game(self):
     self.game_thread = MonitoredCommand(
         self.game_runtime_config["args"],
         runner=self.runner,
         env=self.game_runtime_config["env"],
         term=self.game_runtime_config["terminal"],
         log_buffer=self.log_buffer,
         include_processes=self.game_runtime_config["include_processes"],
         exclude_processes=self.game_runtime_config["exclude_processes"],
     )
     if hasattr(self.runner, "stop"):
         self.game_thread.stop_func = self.runner.stop
     self.game_thread.start()
     self.emit("game-started")
     self.state = self.STATE_RUNNING
     self.heartbeat = GLib.timeout_add(HEARTBEAT_DELAY, self.beat)
コード例 #13
0
 def remove_game_data(self, appid=None, **kwargs):
     if not self.is_installed():
         installed = self.install_dialog()
         if not installed:
             return False
     appid = appid if appid else self.appid
     if appid is None:
         raise RuntimeError("No appid given for uninstallation "
                            "(game config=%s)" % self.game_config)
     logger.debug("Launching Steam uninstall of game %s", appid)
     command = [self.get_executable(), "steam://uninstall/%s" % appid]
     thread = MonitoredCommand(command,
                               runner=self,
                               env=self.get_env(),
                               watch=False)
     thread.start()
コード例 #14
0
ファイル: runner.py プロジェクト: sourcery-ai-bot/lutris
    def run(self, *args):
        """Run the runner alone."""
        if not self.runnable_alone:
            return
        if not self.is_installed() and not self.install_dialog():
            logger.info("Runner install cancelled")
            return

        command_data = self.get_run_data()
        command = command_data.get("command")
        env = (command_data.get("env") or {}).copy()

        if hasattr(self, "prelaunch"):
            self.prelaunch()

        command_runner = MonitoredCommand(command, runner=self, env=env)
        command_runner.start()
コード例 #15
0
 def start_game(self):
     """Run a background command to lauch the game"""
     self.game_thread = MonitoredCommand(
         self.game_runtime_config["args"],
         title=self.name,
         runner=self.runner,
         env=self.game_runtime_config["env"],
         term=self.game_runtime_config["terminal"],
         log_buffer=self.log_buffer,
         include_processes=self.game_runtime_config["include_processes"],
         exclude_processes=self.game_runtime_config["exclude_processes"],
     )
     if hasattr(self.runner, "stop"):
         self.game_thread.stop_func = self.runner.stop
     self.game_uuid = self.game_thread.env["LUTRIS_GAME_UUID"]
     self.game_thread.start()
     self.timer.start()
     self.state = self.STATE_RUNNING
     self.emit("game-started")
     self.heartbeat = GLib.timeout_add(HEARTBEAT_DELAY, self.beat)
コード例 #16
0
    def execute(self, data):
        """Run an executable file."""
        args = []
        terminal = None
        working_dir = None
        env = {}
        if isinstance(data, dict):
            self._check_required_params([("file", "command")], data, "execute")
            if "command" in data and "file" in data:
                raise ScriptingError(
                    "Parameters file and command can't be used "
                    "at the same time for the execute command",
                    data,
                )
            file_ref = data.get("file", "")
            command = data.get("command", "")
            args_string = data.get("args", "")
            for arg in shlex.split(args_string):
                args.append(self._substitute(arg))
            terminal = data.get("terminal")
            working_dir = data.get("working_dir")
            if not data.get("disable_runtime"):
                # Possibly need to handle prefer_system_libs here
                env.update(runtime.get_env())

            # Loading environment variables set in the script
            env.update(self.script_env)

            # Environment variables can also be passed to the execute command
            local_env = data.get("env") or {}
            env.update({key: self._substitute(value) for key, value in local_env.items()})
            include_processes = shlex.split(data.get("include_processes", ""))
            exclude_processes = shlex.split(data.get("exclude_processes", ""))
        elif isinstance(data, str):
            command = data
            include_processes = []
            exclude_processes = []
        else:
            raise ScriptingError("No parameters supplied to execute command.", data)

        if command:
            file_ref = "bash"
            args = ["-c", self._get_file(command.strip())]
            include_processes.append("bash")
        else:
            # Determine whether 'file' value is a file id or a path
            file_ref = self._get_file(file_ref)
        if system.path_exists(file_ref) and not system.is_executable(file_ref):
            logger.warning("Making %s executable", file_ref)
            system.make_executable(file_ref)
        exec_path = system.find_executable(file_ref)
        if not exec_path:
            raise ScriptingError("Unable to find executable %s" % file_ref)

        if terminal:
            terminal = system.get_default_terminal()

        if not working_dir or not os.path.exists(working_dir):
            working_dir = self.target_path

        command = MonitoredCommand(
            [exec_path] + args,
            env=env,
            term=terminal,
            cwd=working_dir,
            include_processes=include_processes,
            exclude_processes=exclude_processes,
        )
        command.start()
        GLib.idle_add(self.parent.attach_logger, command)
        self.heartbeat = GLib.timeout_add(1000, self._monitor_task, command)
        return "STOP"
コード例 #17
0
    def configure_game(self, prelaunched, error=None):
        """Get the game ready to start, applying all the options
        This methods sets the game_runtime_config attribute.
        """

        if error:
            logger.error(error)
            dialogs.ErrorDialog(str(error))
        if not prelaunched:
            logger.error("Game prelaunch unsuccessful")
            dialogs.ErrorDialog("An error prevented the game from running")
            self.state = self.STATE_STOPPED
            self.emit("game-stop")
            return
        system_config = self.runner.system_config
        self.original_outputs = DISPLAY_MANAGER.get_config()

        gameplay_info = self.runner.play()
        if "error" in gameplay_info:
            self.show_error_message(gameplay_info)
            self.state = self.STATE_STOPPED
            self.emit("game-stop")
            return
        logger.debug("Launching %s: %s", self.name, gameplay_info)
        logger.debug("Game info: %s", json.dumps(gameplay_info, indent=2))

        env = {}
        sdl_gamecontrollerconfig = system_config.get(
            "sdl_gamecontrollerconfig")
        if sdl_gamecontrollerconfig:
            path = os.path.expanduser(sdl_gamecontrollerconfig)
            if system.path_exists(path):
                with open(path, "r") as controllerdb_file:
                    sdl_gamecontrollerconfig = controllerdb_file.read()
            env["SDL_GAMECONTROLLERCONFIG"] = sdl_gamecontrollerconfig

        sdl_video_fullscreen = system_config.get("sdl_video_fullscreen") or ""
        env["SDL_VIDEO_FULLSCREEN_DISPLAY"] = sdl_video_fullscreen

        restrict_to_display = system_config.get("display")
        if restrict_to_display != "off":
            if restrict_to_display == "primary":
                restrict_to_display = None
                for output in self.original_outputs:
                    if output.primary:
                        restrict_to_display = output.name
                        break
                if not restrict_to_display:
                    logger.warning("No primary display set")
            else:
                found = False
                for output in self.original_outputs:
                    if output.name == restrict_to_display:
                        found = True
                        break
                if not found:
                    logger.warning("Selected display %s not found",
                                   restrict_to_display)
                    restrict_to_display = None
            if restrict_to_display:
                turn_off_except(restrict_to_display)
                time.sleep(3)
                self.resolution_changed = True

        resolution = system_config.get("resolution")
        if resolution != "off":
            DISPLAY_MANAGER.set_resolution(resolution)
            time.sleep(3)
            self.resolution_changed = True

        if system_config.get("reset_pulse"):
            audio.reset_pulse()

        self.killswitch = system_config.get("killswitch")
        if self.killswitch and not system.path_exists(self.killswitch):
            # Prevent setting a killswitch to a file that doesn't exists
            self.killswitch = None

        # Command
        launch_arguments = gameplay_info["command"]

        optimus = system_config.get("optimus")
        if optimus == "primusrun" and system.find_executable("primusrun"):
            launch_arguments.insert(0, "primusrun")
        elif optimus == "optirun" and system.find_executable("optirun"):
            launch_arguments.insert(0, "virtualgl")
            launch_arguments.insert(0, "-b")
            launch_arguments.insert(0, "optirun")
        elif optimus == "pvkrun" and system.find_executable("pvkrun"):
            launch_arguments.insert(0, "pvkrun")

        xephyr = system_config.get("xephyr") or "off"
        if xephyr != "off":
            if not system.find_executable("Xephyr"):
                raise GameConfigError(
                    "Unable to find Xephyr, install it or disable the Xephyr option"
                )

            xephyr_depth = "8" if xephyr == "8bpp" else "16"
            xephyr_resolution = system_config.get(
                "xephyr_resolution") or "640x480"
            xephyr_command = [
                "Xephyr",
                ":2",
                "-ac",
                "-screen",
                xephyr_resolution + "x" + xephyr_depth,
                "-glamor",
                "-reset",
                "-terminate",
            ]
            if system_config.get("xephyr_fullscreen"):
                xephyr_command.append("-fullscreen")

            xephyr_thread = MonitoredCommand(xephyr_command)
            xephyr_thread.start()
            time.sleep(3)
            env["DISPLAY"] = ":2"

        if system_config.get("use_us_layout"):
            setxkbmap_command = [
                "setxkbmap", "-model", "pc101", "us", "-print"
            ]
            xkbcomp_command = ["xkbcomp", "-", os.environ.get("DISPLAY", ":0")]
            xkbcomp = subprocess.Popen(xkbcomp_command, stdin=subprocess.PIPE)
            subprocess.Popen(setxkbmap_command,
                             env=os.environ,
                             stdout=xkbcomp.stdin).communicate()
            xkbcomp.communicate()

        if system_config.get("aco"):
            env["RADV_PERFTEST"] = "aco"

        pulse_latency = system_config.get("pulse_latency")
        if pulse_latency:
            env["PULSE_LATENCY_MSEC"] = "60"

        vk_icd = system_config.get("vk_icd")
        if vk_icd and vk_icd != "off" and system.path_exists(vk_icd):
            env["VK_ICD_FILENAMES"] = vk_icd

        fps_limit = system_config.get("fps_limit") or ""
        if fps_limit:
            strangle_cmd = system.find_executable("strangle")
            if strangle_cmd:
                launch_arguments = [strangle_cmd, fps_limit] + launch_arguments
            else:
                logger.warning(
                    "libstrangle is not available on this system, FPS limiter disabled"
                )

        prefix_command = system_config.get("prefix_command") or ""
        if prefix_command:
            launch_arguments = (
                shlex.split(os.path.expandvars(prefix_command)) +
                launch_arguments)

        single_cpu = system_config.get("single_cpu") or False
        if single_cpu:
            logger.info("The game will run on a single CPU core")
            launch_arguments.insert(0, "0")
            launch_arguments.insert(0, "-c")
            launch_arguments.insert(0, "taskset")

        terminal = system_config.get("terminal")
        if terminal:
            terminal = system_config.get("terminal_app",
                                         system.get_default_terminal())
            if terminal and not system.find_executable(terminal):
                dialogs.ErrorDialog("The selected terminal application "
                                    "could not be launched:\n"
                                    "%s" % terminal)
                self.state = self.STATE_STOPPED
                self.emit("game-stop")
                return

        # Env vars
        game_env = gameplay_info.get("env") or self.runner.get_env()
        env.update(game_env)
        env["game_name"] = self.name

        # Prime vars
        prime = system_config.get("prime")
        if prime:
            env["__NV_PRIME_RENDER_OFFLOAD"] = "1"
            env["__GLX_VENDOR_LIBRARY_NAME"] = "nvidia"
            env["__VK_LAYER_NV_optimus"] = "NVIDIA_only"

        # LD_PRELOAD
        ld_preload = gameplay_info.get("ld_preload")
        if ld_preload:
            env["LD_PRELOAD"] = ld_preload

        # Feral gamemode
        gamemode = system_config.get("gamemode")
        if gamemode:
            env["LD_PRELOAD"] = ":".join([
                path for path in [
                    env.get("LD_PRELOAD"),
                    "libgamemodeauto.so",
                ] if path
            ])

        # LD_LIBRARY_PATH
        game_ld_libary_path = gameplay_info.get("ld_library_path")
        if game_ld_libary_path:
            ld_library_path = env.get("LD_LIBRARY_PATH")
            if not ld_library_path:
                ld_library_path = "$LD_LIBRARY_PATH"
            env["LD_LIBRARY_PATH"] = ":".join(
                [game_ld_libary_path, ld_library_path])

        include_processes = shlex.split(
            system_config.get("include_processes", ""))
        exclude_processes = shlex.split(
            system_config.get("exclude_processes", ""))

        self.game_runtime_config = {
            "args": launch_arguments,
            "env": env,
            "terminal": terminal,
            "include_processes": include_processes,
            "exclude_processes": exclude_processes,
        }

        if system_config.get("disable_compositor"):
            self.set_desktop_compositing(False)

        prelaunch_command = system_config.get("prelaunch_command")
        if system.path_exists(prelaunch_command):
            self.prelaunch_executor = MonitoredCommand(
                [prelaunch_command],
                include_processes=[os.path.basename(prelaunch_command)],
                env=self.game_runtime_config["env"],
                cwd=self.directory,
            )
            self.prelaunch_executor.start()
            logger.info("Running %s in the background", prelaunch_command)
        if system_config.get("prelaunch_wait"):
            self.heartbeat = GLib.timeout_add(HEARTBEAT_DELAY,
                                              self.prelaunch_beat)
        else:
            self.start_game()
コード例 #18
0
ファイル: wine.py プロジェクト: Patryk-Jaroszczyk/lutris
def wineexec(
    executable,
    args="",
    wine_path=None,
    prefix=None,
    arch=None,  # pylint: disable=too-many-locals
    working_dir=None,
    winetricks_wine="",
    blocking=False,
    config=None,
    include_processes=[],
    exclude_processes=[],
    disable_runtime=False,
    env={},
    overrides=None,
):
    """
    Execute a Wine command.

    Args:
        executable (str): wine program to run, pass None to run wine itself
        args (str): program arguments
        wine_path (str): path to the wine version to use
        prefix (str): path to the wine prefix to use
        arch (str): wine architecture of the prefix
        working_dir (str): path to the working dir for the process
        winetricks_wine (str): path to the wine version used by winetricks
        blocking (bool): if true, do not run the process in a thread
        config (LutrisConfig): LutrisConfig object for the process context
        watch (list): list of process names to monitor (even when in a ignore list)

    Returns:
        Process results if the process is running in blocking mode or
        MonitoredCommand instance otherwise.
    """
    executable = str(executable) if executable else ""
    if isinstance(include_processes, str):
        include_processes = shlex.split(include_processes)
    if isinstance(exclude_processes, str):
        exclude_processes = shlex.split(exclude_processes)
    if not wine_path:
        wine = import_runner("wine")
        wine_path = wine().get_executable()
    if not wine_path:
        raise RuntimeError("Wine is not installed")

    if not working_dir:
        if os.path.isfile(executable):
            working_dir = os.path.dirname(executable)

    executable, _args, working_dir = get_real_executable(
        executable, working_dir)
    if _args:
        args = '{} "{}"'.format(_args[0], _args[1])

    # Create prefix if necessary
    if arch not in ("win32", "win64"):
        arch = detect_arch(prefix, wine_path)
    if not detect_prefix_arch(prefix):
        wine_bin = winetricks_wine if winetricks_wine else wine_path
        create_prefix(prefix, wine_path=wine_bin, arch=arch)

    wineenv = {"WINEARCH": arch}
    if winetricks_wine:
        wineenv["WINE"] = winetricks_wine
    else:
        wineenv["WINE"] = wine_path

    if prefix:
        wineenv["WINEPREFIX"] = prefix

    wine_config = config or LutrisConfig(runner_slug="wine")
    disable_runtime = disable_runtime or wine_config.system_config[
        "disable_runtime"]
    if use_lutris_runtime(wine_path=wineenv["WINE"],
                          force_disable=disable_runtime):
        if WINE_DIR in wine_path:
            wine_root_path = os.path.dirname(os.path.dirname(wine_path))
        elif WINE_DIR in winetricks_wine:
            wine_root_path = os.path.dirname(os.path.dirname(winetricks_wine))
        else:
            wine_root_path = None
        wineenv["LD_LIBRARY_PATH"] = ":".join(
            runtime.get_paths(
                prefer_system_libs=wine_config.
                system_config["prefer_system_libs"],
                wine_path=wine_root_path,
            ))

    if overrides:
        wineenv["WINEDLLOVERRIDES"] = get_overrides_env(overrides)

    wineenv.update(env)

    command_parameters = [wine_path]
    if executable:
        command_parameters.append(executable)
    command_parameters += shlex.split(args)
    if blocking:
        return system.execute(command_parameters, env=wineenv, cwd=working_dir)
    wine = import_runner("wine")
    command = MonitoredCommand(
        command_parameters,
        runner=wine(),
        env=wineenv,
        cwd=working_dir,
        include_processes=include_processes,
        exclude_processes=exclude_processes,
    )
    command.start()
    return command