Somehow I didn't run into this with testing *this* invocation of
`win32gui.EnumWindows()`, but then I did over in EDMarketConnector.py. So,
as I had to handle the exception there, let's also do it here.
This is something the old code *didn't actually do*.
Tested with a 'pseudo ed' process (same MainWindowTitle) running as myself
(test matches), and via `runas` as another user (doesn't match).
Both the current `develop` code and this PR's new code share this behaviour.
What the code does is look for windows/processes *in the current Windows
session*, no matter if they're owned by the session user or not.
Neither version will find a process, that would match, if it's running in
another session, i.e. you'd need to switch to it via the windows Login screen.
* All of the implementation of the EnumWindows callback.
The documentation for pywin32 isn't great, in terms of finding the call
convention and necessary form of parameters, but once you do this is *much*
cleaner than using ctypes directly.
I'm not 100% certain that `win32api.OpenProcess()` has the same semantic as
the previous `GetProcessHandleFromHwnd()`, i.e. only getting the `handle`
back if the process is owned by the current user. If the user has
Windows Administrator rights they can probably kill other users' processes ?
After over an hour's struggle trying to get the win32/user32
`GetWindowTextW()` prototyped properly, and running into problem after problem:
1. Once you properly prototype this, including defining the 2nd `lpString`
parameter as 'out', ctypes wants to just *return* that.
2. This leads to then implementing a `.errcheck` property so that you
can *also* check the INT result for errors.
3. But then you just run into another error.
I finally found <https://stackoverflow.com/a/10905155> which pointed out
you can simply use `win32gui.GetWindowText()` from `pywin32`. Tested, it
simply works, no errors/exceptions.
This is actually to do with a reported issue around the ctypes code in
`EDLogs.gamerunning()` causing:
```python
exception ignored on calling ctypes callback function: <function EDLogs.game_running.<locals>.callback at 0x0000020E9C9D0EA0>
Traceback (most recent call last):
File "monitor.pyc", line 2041, in callback
File "monitor.pyc", line 2034, in WindowTitle
ctypes.ArgumentError: argument 1: OverflowError: int too long to convert
```
Although I can't personally get this to trigger at all under 64-bit python,
either in PyCharm *or* with the 5.7.1-alpha1 64-bit pre-release.
`game_running()` is only used in a few places, and the key things it
malfunctioning might cause are lack of the synthetic `ShutDown` (already
has an INFO logging) and `StartUp` events.
This is to allow restart of EDMarketConnector whilst the game is running
to have `state['NavRoute']` hold data when the synthetic `StartUp` event
is passed to plugins.
NB: Probably need to note this in PLUGINS.md
* Adds `monitor.is_live_galaxy()` for general use.
* Assumes Update 14 starts after 2022-11-29T09:00:00+00:00. That's the
currently schedule day, and recently the servers have been down by the time.
Likelihood of them coming back *up* quickly seems slim to none.
* If we couldn't parse the `gameversion` from Journal using
`semantic_version.Version.coerce()` this will fail, and assume we're on
the Legacy galaxy.
* This is cleaner than starting to track it in `plugins/eddn.py` specifically.
* This is literally only about if we're piloting a ship that is docked, so
not even trying to resolve "on-foot, in a station, 'Location' said not
docked though".
No need to log at INFO for the retry counts, as this appears to be working,
make it DEBUG instead.
This was making the EDMC.py output needlessly noisy.
Using os.path.getctime for the order, not the filename. This addresses the
changed Journal filenames in Odyssey Update 11, whilst keeping compatibility
with the Horizons Update 11 old-name-style filenames.
1. We need StarPos (as well as StarSystem)
2. Adding more state tracking in this plugin is misguided.
3. So added it in monitor instead, putting *copies* of data in the
monitor.state dictionary.
4. So we reference those, but only available in journal_entry() itself, else
we'd need to pass the whole of `state` in.
5. So instead pass in the bits of `state` only when we need them.
We can't just use `EDLogs.live` here as it'll get set `true` when the
`Commander` event is seen *during the catch up*. We need that catchup
to have finished before we'll try processing a `NavRoute` event and
file.
The order of Journal events changed from:
1. LoadGame
2. Rank
3. Progress
to:
1. Rank
2. Progress
3. LoadGame
in Odyssey, and in at least current 'base game' and Horizons clients as
well. Also 'Reputation' event is before 'LoadGame' now. So simply
allow those events to have populated the data, don't re-init on
LoadGame.
Yes, I'm preferring to leave the lines in, but commented, so it's clear
why those aren't being init'd, *and* why 'Statistics' still is, and as
of what game version.
The old code did this, and without it we enter a loop of:
1. CAPI says unauthorized
2. We call login()
3. But companion.session.state == STATE_OK, so do nothing
4. Re-scheduled CAPI request goes back to 1.