Detecting location of Visual Studio 2017 and 2019

A few years ago, I wanted to use Bazel to build an old project of mine using Visual Studio 2017 Community.

Thing is, I don't install most of MSVS on my system partition, as it's on a relatively tiny SSD. So, where do I (portably) find it? And how do I set BAZEL_VS (per their documentation) to the correct path?

As I'm much more comfortable writing Bash scripts than writing old DOS-style Batch scripts, and as I'm going to have msys64 (or at least msys32) on my machines, clearly the answer is to write the resulting launcher in Bash. There are downsides to this approach, but it's doable.

Do you even need this for Bazel?

No. I just tried running bazel-2.0.0-windows-x86_64.exe with my project. It found MSVS2019 out of the box both in cmd.exe and in the MSYS64 shell.

Unfortunately, I have a genrule that depends on bash, which didn't work in cmd.exe even if I specified BAZEL_SH (missing binary for basename). And when I didn't pass BAZEL_SH while running under MSYS64, it had trouble finding SDL/SDL.h presumably because the aforementioned genrule didn't work.

Autodetection of MSVS2019 works, just set PATH Windows envvar to include msys binaries, and set BAZEL_SH Windows envvar to the output of cygpath -w /usr/bin/bash or cygpath -w /bin/bash.

You may want this for non-Bazel uses.

Finding Microsoft Visual Studio 2017

Assuming Bazel 2.0.0 is installed in C:\bazel under the default filename from the release on Github, this does the trick:

# Based on + searching around registry.
# Finds MSVS2017.
# Slashes when invoking 'reg query' are replaced with dashes because MSYS2.
VSPATH="$(cygpath -u "$(reg query 'HKLM\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7' -v 15.0 | tail -n+3 | head -n1  | awk '{for (i=3;i<=NF;i++) {printf "%s ",$i;};}' | sed 's/ *$//')")"

export BAZEL_SH="$(cygpath -w /usr/bin/bash)"

/c/bazel/bazel-2.0.0-windows-x86_64.exe $@

Finding Microsoft Visual Studio 2019

Unfortunately this is broken as of MSVS2019. See the explanation why that registry key is not used anymore.

The new situation is better: there's a tool that does get installed in a well-known path: %ProgramFiles(x86)%/Microsoft Visual Studio/Installer/vswhere.exe.

The problem is merely that Bash doesn't like parentheses in environment variable names, so ${ProgramFiles(x86)} won't be acceptable. However, it was visible in env output! Other people have spotted the same thing, but as their writings talk about PROGRAMFILES(X86) in all caps, I've concluded that maybe it's better to add the I flag to their sed-based solution.

# Let's use VSWhere:
PROGRAMFILES_X86=$(env | sed -n s,'^PROGRAMFILES(X86)=',,pI) # because parens are not valid envvar names:$
VSWHERE=${PROGRAMFILES_X86}/Microsoft\ Visual\ Studio/Installer/vswhere.exe
VSWHERE="$(cygpath -u "${VSWHERE}")"

# Finding VC:
VSPATH=$("${VSWHERE}" -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath)

export BAZEL_SH="$(cygpath -w /usr/bin/bash)"

/c/bazel/bazel-2.0.0-windows-x86_64.exe $@


The problem with using Bazel integration into VSCode is that it wants a path to Bazel. But Bazel wants to have BAZEL_VS set.

Maybe I could work around this by writing a tool in a compilable language, then have it pass on all CLI arguments to actual bazel.exe, while also setting BAZEL_VS. Or maybe Bazel supports some settings in .bazelrc. I didn't care to check. Instead, I've used msys2_shell.cmd as the 'shell' for the integrated VSCode terminal. I'm used to manually running Bazel and I don't care enough about interactive debugging. For now, I just don't care enough to properly integrate Bazel into VSCode on Windows (though it would be neat).

Why even bother with Windows?

I need to trivially compare networking traffic between my project and a third-party program. The third-party program is written for Windows; it would likely work on other platforms under Wine, but I don't care enough to explore whether I can make a third-party binary patcher for that program work under Wine.

My program still works on Linux, built whether with Bazel or using Makefiles; but the deprecated SDL 1.2 was recently broken on macOS, my program won't work on macOS.

Getting this to work is also a nice exercise.

Anno 1404 crashing when clicking on Quickstart

Regional Settings on Windows 10

Regional Settings on Windows 10. Making the countries match fixes Anno 1404.

I finally found the solution to the issue on the forums. Nothing obvious like setting admin privileges helped.

No, it's more insidious.

Apparently when you go to regional settings, both the "Country or Region" and the "Regional Format" values must match the country.

I've had these set to "Ireland" + "English (Europe)". Before this, I likely had it set to "Ireland" + "Croatian (Croatia)".

Changing the values to "Ireland" + "English (Ireland)" resolved the issue.

I can finally play the game years after buying it. This was done on Windows 10 1903 (build 18362.10012).

Time for FOSDEM 2019

Previously I thought I would not head to Brussels this year, but it turned out I will. Let me know if you'd like to meet. I'm not sure if I'll go to the beer event.

This year I hope to meet up with people interested in fediverse-related interop. Here's a meetup thread.

I've also created an XMPP chatroom for meeting fediverse folks, in case realtime chat is needed; see There's a small web UI at and an IRC frontend3 at irc://; please join #fediverse manually. No guarantees about reliability of the XMPP server, of the HTTP proxy4, of the web UI, or of the IRC frontend. 🙂

On a related note, it's disappointing that there's a social fragmentation between Matrix, fediverse and XMPP, but eh. It would have been nice if ActivityPub was (like OStatus protocol suite before it) based around XML and Atom; it would have made pushing for supplanting the under-utilized XEP-0277 and its urn:xmpp:microblogging:0 with something that had a model of favoriting and commenting similar to fediverse.

Alas, to be useful now would probably require imagining ActivityPub 2.0's model and vocabulary over XML, and use Atom for posts and activities. shrug

  1. This is running Prosody
  2. This is using Converse.js
  3. This is running the ultra-tiny MUC2IRC, written in Objective-C using ObjFW
  4. This is the Punjab BOSH connection manager running behind Haproxy running behind nginx running in a Mesos cluster managed by Marathon. 🙂 

Using PostgreSQL row commit IDs and live stats

Once again, it's time to write down some notes for personal use. Let me know if what I'm jotting down here is particularly wrong.

PostgreSQL can tell you what are the commit IDs that touched a particular table. You query the system column named xmin.

prosody=> select xmin from prosody limit 5;
(5 rows)

You can also ask for the timestamp when this commit was created; however, that requires you to start tracking timestamps for each commit ID.

prosody=> select pg_xact_commit_timestamp(xmin), * from prosody;

ERROR:  could not get commit timestamp data
HINT:  Make sure the configuration parameter "track_commit_timestamp" is set.

This seems to be rather useful for built-in tracking of the modification timestamp and for etags. If the database backend is well structured, it may be possible to structure queries in such a way to quickly check when the results were last modified, and help the web frontend avoid serving and requesting the results. I don't have a clear way to do it yet, but while I don't think impact on the database will be significant, it may help shave off some serving bytes or requests to other backends.

Commit IDs also roll over after 32bit, so their use on a high traffic site needs to be closely considered. Then again, by the time you have over four billion writes, your caches will probably otherwise expire anyway.

Table pg_stat_activity is interesting and lets you see the transactions and even queries in flight. This'll be slightly messy, but click 'view raw code' to see the original formatting, and scroll around a bit.

$ sudo -u postgres psql
psql (10.1, server 9.6.10)
Type "help" for help.

postgres=# SELECT pid, query FROM pg_stat_activity;
 pid  |                                                                                                                                                                                                              query                                                                                                                                                            
 8968 | SELECT o0."id", o0."token", o0."refresh_token", o0."valid_until", o0."user_id", o0."app_id", o0."inserted_at", o0."updated_at" FROM "oauth_tokens" AS o0 WHERE (o0."token" = $1)
 9869 | SELECT pid, query FROM pg_stat_activity;
(12 rows)
postgres=# SELECT * FROM pg_stat_activity;
 datid  |   datname   | pid  | usesysid | usename  | application_name | client_addr | client_hostname | client_port |         backend_start         |          xact_start           |          query_start          |         state_change          | wait_event_type | wait_event |        state        | backend_xid | backend_xmin |                                                                                                                                                                                                              query                       
 146762 | yyyyyyy_dev | 8968 |   146761 | yyyyyyy |                  |   |                 |       47545 | 2018-11-08 23:44:52.761448+00 |                               | 2018-11-08 23:50:33.742608+00 | 2018-11-08 23:50:40.75014+00  |                 |            | idle                |             |              | SELECT u0."id", u0."bio", u0."email", u0."name", u0."nickname", u0."password_hash", u0."following", u0."ap_id", u0."avatar", u0."local", u0."info", u0."follower_address", u0."last_refreshed_at", u0."inserted_at", u0."updated_at" FROM "users" AS u0 WHERE (u0."id" = $1)
  16391 | prosody     | 8833 |    16386 | prosody  |                  | 10.0.AA.AAA |                 |       51490 | 2018-11-08 23:44:30.819644+00 | 2018-11-08 23:50:28.826344+00 | 2018-11-08 23:50:28.826344+00 | 2018-11-08 23:50:28.826362+00 |                 |            | idle in transaction |             |              | BEGIN
  12409 | postgres    | 9869 |       10 | postgres | psql             |             |                 |          -1 | 2018-11-08 23:48:29.262371+00 | 2018-11-08 23:50:41.487958+00 | 2018-11-08 23:50:41.487958+00 | 2018-11-08 23:50:41.487961+00 |                 |            | active              |             |      1606549 | SELECT * FROM pg_stat_activity;
(12 rows)

On Mastodon and the "fediverse"

I do like the freedom from lock-in. That's why I run my own federated XMPP server (though a domain whitelist applies due to spam – contact me if you want to interop).

I do want to regain control over my social postings. I don't use Facebook; I'm mainly on Twitter. I don't mind Twitter as much, but it would be nice to host my own posts.

That's why I will not be signing up for a Mastodon instance. Allegedly migration to another instance is easy. But permalinks to posts would still be stored on a domain owned by someone else. Thank you – but then I might as well stay on Twitter.

What about running my own? I have a test deployment I can spin up, but I don't want to pay for the resources that would be required to make it a permanent thing. Mastodon's minimum requirements are huge.

Why not GNU Social? I am trying to reduce my consumption of PHP.

Why not Pleroma? Maybe I'll do that. I need to check it out, however, I'm not well versed in Erlang and fediverse stuff seems like something I may want to customize.

Customize in what way? Bridging to XMPPs microblogging seems like an interesting possibility. And sharing more than just "notes" (Twitter's tweets, Mastodon's toots) seems like a good way of weaning myself off of WordPress. ActivityStreams vocabulary (which makes an appearance in OStatus and is basis for ActivityPub) has more than just Notes.