Ryochan7 / DS4Windows

Like those other ds4tools, but sexier
https://ryochan7.github.io/ds4windows-site/
GNU General Public License v3.0
6.98k stars 808 forks source link

Auto Profile doesn't detect SeaOfThieves executable #748

Closed aemiguel closed 4 years ago

aemiguel commented 5 years ago

I am trying to get my PS4 controller working with Sea of Thieves from the Microsoft Store (I have seen that it supports PS4 controllers natively but I would rather not have to manually switch profiles when I launch the game).

I have had success with World of Warships using the same methodology but with Sea of Thieves I hit a few snags so far such as:

1) Finding the executable path (I was able to do this by running the game then checking its command line in Process Explorer)

2) Not being able to navigate to that path in the Auto Profiles -> Add Programs file dialog because the path is protected somehow (I was able to get around this by manually editing the XML file for Auto Profiles but it would be great if there was an option to just type in a path to the executable as well as navigate to it).

3) Now that the game is added, the profile doesn't detect that the game is running correctly and remains on the default profile.

Presumably (3) above means that the path is somehow not matching up when DS4Windows is trying to apply the auto profile or detect that SoT is the front active window.

I'm not sure what method or APIs DS4Windows uses to match auto profiles but I wonder if it would be possible to allow matching by other methods such as matching by just the executable name itself (SoTGame.exe) or by a substring match or similar, or even matching by some other aspect of the executable/window when its running? An additional benefit of this would be that if the path to the game changes due to versioning etc then it wouldn't matter. For reference the path to SoT is:

C:\Program Files\WindowsApps\Microsoft.SeaofThieves_2.84.2266.2_x64__8wekyb3d8bbwe\Athena\Binaries\UWP64\SoTGame.exe

which looks like it may include versioning in the path.

The manual option to type in the substring/game name/game path I mentioned in (2) would be an easy way to configure this and allow for more flexibility in matching (e.g. SoTGame).

mika-n commented 5 years ago

DS4Win auto-profile feature uses a fully qualified path name of the process running in foreground window to match a profile.

It would be possible to change it to use a wildchar search/match logic also. However, the auto-profile feature is already a bit heavy on CPU cycles, so introducing a wildchar logic would make it just even worse (the feature uses polling timer loop and thread to check the foreground process name).

Maybe the whole auto-profile feature would require a new logic by replacing the polling thread loop with an event notification queue by attaching DS4Win app to listen for "WinOS - new process created" notification channel. It would be easier for CPU cycles (ie. no need to poll and query the name of the foreground window once every few seconds) and maybe then wildchar type of logic could be included.

However, this would work only if a new profile needs to be automagically selected when a game is launched (ie. process created). As far games are considered then I guess the old game process is closed and new process is opened when people want to play a new game. If game processes are left idling bedhind and people just jump between processes then "new process created" event queue notifcation would not work.

(EDITED: Hmm.. There seems to be an event for foreground window activation changed type of event queue also. That sounds interesting as a more performance wise auto-profile feature).

Anyway, try launching DS4Windows app with "run as administrator" option in FileExplorer to see if you then can access the protected windowsApps folder.

aemiguel commented 5 years ago

Running DS4Windows as admin does let me navigate to the folder but I'm unable to select the file for opening as Windows pops up an error saying that I don't have permission to open the file, so I can't complete the process.

Wildcard matching would require more CPU work but a simple substring check or exe name check, although less flexible than wildcard, would require not much more than an equality check. Additionally if the common case for matching of auto profile entries was equality then this method might only apply to a few auto profile entries, representing just a small portion of the checks run on a poll.

Another possibility might be that if the existing matching doesn't already use one then the equality matching could add the auto profile paths to a hashmap and then dereference the map using the fully qualified name from the window which would be faster and scale better than iterating through and comparing (O(log n) rather than O(n)). That would buy extra CPU cycles for the less common substring checks.

The event based method would be the ideal option performance wise but maybe the above would allow for a more flexible method of matching without having to go to the work of implementing the event mode / debugging any issues that arose?

aemiguel commented 5 years ago

Also if there is any log that I can grab or debug version I can run that might help show why this particular game's path doesn't match its actual executable path then I'm happy to run it and provide the output.

mika-n commented 5 years ago

Here is a special version of DS4Windows.exe (backup the existing EXE and replace it with this one) to send the name of the foreground process to DS4Windows Logs tabpage. Hopefully you can figure out that way what is the process name. If the name is empty string then it means that for some reason DS4Windows app fails to acquire the process name (some permission issue?)

DS4Windows_AutoProfileMonitoringDebug.zip

aemiguel commented 5 years ago

The name of the window seems to be:

C:\Windows\System32\ApplicationFrameHost.exe

This seems to be a common executable used by many windows store apps (e.g. Calculator) which would make targeting it not very useful. I wonder if there is any other information that can be had like the name of the window/HWND or something?

mika-n commented 5 years ago

Technically there would be window title and window class name attributes available also. Window title might work with WinStore apps also.

The bad news is that at the moment DS4Win auto-profile logic doesn't use those attributes to match a profile.

For now maybe assigning a gamepad key to change a profile or cycle through a number of difference profiles as a "linked special action LoadProfile list" as explained in the following page (option 2). If you have different lightbar color for each of the profiles then you know in which profile you are at the moment. This is a quick way to change profiles without clicking any mouse keys in properties screens. https://github.com/Ryochan7/DS4Windows/wiki/Settings#how-to-change-a-profile-on-the-fly-via-a-certain-gamepad-button

aemiguel commented 5 years ago

Switching profiles and matching them to a light colour seems like a nice idea, thanks. I can also switch manually for now since it is just this one game.

If you have a debug version that dumps the window title, class etc that I can run at any point then I'd be happy to run that for SoT and Calculator too so you can see if there is any way to distinguish windows store apps and games.

Ryochan7 commented 5 years ago

This type of issue has existed for a long time. Many newer Windows apps (UWP) run using a shared executable so the older method of application detection does not work. I experienced this first with the desktop Netflix app. I don't know of any properties that could be used for app detection outside window title and program filename/path.

I don't use the Auto Profile system in DS4Windows. That functionality will likely not get changed by me.

teeedubb commented 5 years ago

I have run into a similar issue with UWP, but with steam not displaying the game I am playing. I have resorted to using a AHK launcher for these games. The launcher will launch the game via the "shell:" protocol, wait for the game window to appear, then loop until the game window is closed and once the window is closed, it exits. This works well for steam and it would probably work here too.

ForzaLauncher.ahk

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force
MouseMove, 3840, 2160
NoMousy = "e:\emulation\programs\nomousy\nomousy.exe"
Run, %NoMousy% /hide
If 1 = fm6
{
    GC := "shell:appsFolder\Microsoft.ApexPG_8wekyb3d8bbwe!forzamotorsportapex"
    WD := "Forza Motorsport 6: Apex ahk_class ApplicationFrameWindow"
}
else if 1 = fm7
{
    GC := "shell:appsFolder\Microsoft.ApolloBaseGame_8wekyb3d8bbwe!forzamotorsport7"
    WD := "Forza Motorsport 7 ahk_class ApplicationFrameWindow"
}
else if 1 = fh3
{
    GC := "shell:appsFolder\Microsoft.OpusPG_8wekyb3d8bbwe!OpusReleaseFinal"
    WD := "Forza Horizon 3 ahk_class ApplicationFrameWindow"
}

RunLoop:
Run, %GC%,, UseErrorLevel
if ErrorLevel != 0
{
    Sleep, 1000
    Goto RunLoop
}
WinWait, %WD%
Loop 10
{
   WinActivate, %WD%
   Sleep, 1000
}
WinWaitClose
Run, %NoMousy%
Exit

You can get the window name via the AHK window spy. You can compile the script to a exe also. To get the shell: command I had to do some googling + trial and error.

mika-n commented 5 years ago

The new V1.7.13 version with an improved auto-profile rule sets should solve this issue. Take a look at the "auto-profile" documentation page for more info. https://github.com/Ryochan7/DS4Windows/wiki/Profile-selection-using-auto-profile-rules

aemiguel commented 5 years ago

This seems to be working perfectly now, thanks for the addition!