Repository: voxel51/fiftyone

Issue:
[BUG] Unable to run desktop applications by using desktop flag
### System information

-   **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: Windows 11 Family Chinese version 21H2
-   **FiftyOne installed from (pip or source)**: both pip and source
-   **FiftyOne version (run `fiftyone --version`)**: FiftyOne v0.15.0.1, Voxel51, Inc.
-   **Python version**: 3.10.4

### Describe the problem

When I started the Fiftyone desktop application in Python, the application raised a `FileNotFoundError` exception and said that the system could not find the specified file, causing the desktop application to fail to start.

### Code to reproduce issue

```python
import fiftyone as fo
import fiftyone.zoo as foz

if __name__ == '__main__':
    dataset = foz.load_zoo_dataset(
        "coco-2017",
        split="validation",
        dataset_name="evaluate-detections-tutorial")
    dataset.persistent = True
    session = fo.launch_app(dataset, desktop=True)
    session.wait()
```

### Other info / logs

First, attach the log output to the terminal when running the program

```                              shell
Downloading split 'validation' to 'C:\Users\batu\fiftyone\coco-2017\validation' if necessary        
Found annotations at 'C:\Users\batu\fiftyone\coco-2017\raw\instances_val2017.json'
Images already downloaded
Existing download of split 'validation' is sufficient
Loading existing dataset 'evaluate-detections-tutorial'. To reload from disk, either delete the existing dataset or provide a custom `dataset_name` to use
Desktop App launched.
Uncaught exception
Traceback (most recent call last):
  File "D:\Develop\Python\FiftyOne_test\PIPENV_VENV_IN_PROJECT\FiftyOne_test-EhvB1Jtk\lib\site-packages\fiftyone\service\main.py", line 257, in <module>
    child = psutil.Popen(
  File "D:\Develop\Python\FiftyOne_test\PIPENV_VENV_IN_PROJECT\FiftyOne_test-EhvB1Jtk\lib\site-packages\psutil\__init__.py", line 1358, in __init__   
    self.__subproc = subprocess.Popen(*args, **kwargs)
  File "F:\Python\3.10.4\lib\subprocess.py", line 966, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "F:\Python\3.10.4\lib\subprocess.py", line 1435, in _execute_child
    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
FileNotFoundError: [WinError 2] 系统找不到指定的文件。
```

Then I found the problem through the search in the afternoon, and the wrong place is located in the first 447 line of `fiftyone/core/service.py` . The `os.path.join()` function is called to return the merged path to the full executable file, but instead of passing in the argument and adding a slash in the middle, it uses the plus to merge the two strings directly, rather than passing in the argument and adding slashes in the middle, resulting in the path being `fiftyone\\desktop\\binFiftyOne 0.19.4.exe`.

The solution is to replace the 447 line of the `fiftyone/core/service.py` file with this:

```pyhton
return [os.path.join(pre + path)]  # before

return [os.path.join(pre, path)]     # after
```

I'm not very good with Github's pull request feature, so I'll just write it here. I was hoping you could help me fix the bug.

P.S. My English is not very good, so I used translation software to write this issue. I would be glad to provide more information if THERE is any unclear expression.

### What areas of FiftyOne does this bug affect?

-   [x]  `App`: FiftyOne application issue
-   [ ]  `Core`: Core `fiftyone` Python library issue
-   [ ]  `Server`: Fiftyone server issue

### Willingness to contribute

The FiftyOne Community encourages bug fix contributions. Would you or another
member of your organization be willing to contribute a fix for this bug to the
FiftyOne codebase?

-   [x] Yes. I can contribute a fix for this bug independently.
-   [ ] Yes. I would be willing to contribute a fix for this bug with guidance
          from the FiftyOne community.
-   [ ] No. I cannot contribute a bug fix at this time.


Discussion:

Resolving patch:
diff --git a/fiftyone/core/service.py b/fiftyone/core/service.py
--- a/fiftyone/core/service.py
+++ b/fiftyone/core/service.py
@@ -393,10 +393,7 @@ def find_app(self):
 
         pre = foc.FIFTYONE_DESKTOP_APP_DIR
         for path in etau.list_files("./"):
-            if path.endswith(".exe"):
-                return [os.path.join(pre + path)]
-
-            if path.endswith(".AppImage"):
+            if path.endswith(".AppImage") or path.endswith(".exe"):
                 return [os.path.join(pre, path)]
 
         if os.path.isdir("./FiftyOne.app"):


Test patch: