@DOA said:
I've never had KFC. What's wrong with it?
I was actually curious about this, so I ate at KFC for the first time ever a while back. My verdict: most of the food is hopelessly bland, and when it isn't, you wish it were.
@DOA said:
I've never had KFC. What's wrong with it?
I was actually curious about this, so I ate at KFC for the first time ever a while back. My verdict: most of the food is hopelessly bland, and when it isn't, you wish it were.
Baked beans on toast is indeed a common snack/quick meal in England. (It's not really good for a whole meal, but for lunch, or whatever, it will do.)
OK, so I looked into the original WTF to see exactly which piece of software was screwing up.
First off, the dialog box in question looks like it was drawn using dialog(1). dialog(1) uses ncursesw(3) (a commonly used library for drawing on terminals) in order to draw lines on the screen. First WTF: you know how the picture looks like misinterpreted Unicode? Well, dialog(1) doesn't actually use Unicode to draw lines on screen, but the DEC alternate VT100 line-drawing charset (verified using ltrace). So if the terminal didn't understand it, it wouldn't look like âââââââ… but like lqqqqqqq…qqqx. (I've seen that particular bit of misencoding more than once before now.) This is interpreted correctly by PuTTY regardless of the Unicodiness or otherwise of the terminal; after all, the characters that are being sent are all ASCII, with control codes to switch between letters and line-drawing. blakeyrat, were you running inside screen by any chance? If so, my strong theory (based on a reasonably active hobby working on terminal applications) is that it's actually it that was at fault. I don't see how it'd happen otherwise; I tested running dialog(1) in a terminal that was actually set to an 8-bit codepage but which I'd told to incorrectly claim to be UTF-8, and it rendered just fine.
Next, it's typically the job of environment variables to send information about the terminal and the encoding it expects. With my TERM variable to "xterm" (what PuTTY uses by default), it renders correctly. If I set it to "screen", it renders correctly, but now starts sending, instead of DEC line-drawing characters, information depending on the charset I send. (This is further evidence in favour of the theory that screen, which wasn't mentioned, is at fault. Or perhaps some other intermediate terminal layer.) If I set LC_ALL=C and TERM=screen, it renders correctly on a terminal set to pretty much any ASCII-based encoding I tried. If I set LC_ALL=en_GB.UTF-8 and TERM=screen, it now renders incorrectly on a terminal set to ISO-8859-1 (and fine on a terminal set to Unicode). Conclusion: dialog(1) uses drawing codes as requested by the TERM and LC_ALL variables. So dialog(1) is not the WTF. (Note: the programs I work on on my hobby are in the same position as dialog(1), and often have to do unreasonable things in order to work around WTFs elsewhere, so I was guessing this conclusion.)
Next step: what's setting those environment variables? Well, the shell can, but ssh should be setting them up. And a bit of testing reveals that, in fact, ssh is transmitting the TERM environment variable. That's reasonable. Also, that it's transmitting the LC_ALL environment variable. That's how it's meant to work, and here's how it looks in practice:
ais523@mycomputer:~$ export LC_ALL=en_GB.UTF-8
ais523@mycomputer:~$ ls /blakeyrat
ls: cannot access /blakeyrat: No such file or directory
ais523@mycomputer:~$ export LC_ALL=fr_FR.UTF-8
ais523@mycomputer:~$ ls /blakeyrat
ls: impossible d'accéder à /blakeyrat: Aucun fichier ou dossier de ce type
ais523@mycomputer:~$ ssh anothercomputer
ais523@anothercomputer:~$ ls /blakeyrat
ls: impossible d'accéder à /blakeyrat: Aucun fichier ou dossier de ce type
Now, it's pretty easy to accidentally customize your startup scripts to set the locale, and if you do, you accidentally blow away your encoding information in the process. (In fact, I'd done it on one of my systems before running these tests, and got confusing results for a while.) I'd recommend looking in .profile or .bash_profile or .bashrc or .login or .bash_login or whatever it's called nowadays to see if there's any locale setting done. (Yes, there are far too many of those files. It probably seemed like a good decision at the time…)
So, why would dialog be sending UTF-8 to a terminal configured to use ISO-8859-1? There are two possibilities, and possibly both apply.
The first is that PuTTY isn't bothering to set LC_ALL at all. (blakeyrat can test this via "echo $LC_ALL" in his remote terminal.) In this case, programs he runs have no information about what encoding he's expecting (or, fwiw, about what language he's expecting; most likely, this wouldn't show up as an obvious problem to an English-speaker, because it's the language most programs are going to default to). I've tested what dialog(1) and ncursesw(3) do with a blank LC_ALL: they assume C.UTF-8 as the language and encoding. ("C" is a sort of default language used by programmers when they want portable output; text is in English, things like numbers and dates follow typical programming conventions.) This wouldn't be noticeable with the TERM set to "xterm"; but with TERM set to "screen", ncursesw assumes Unicode and outputs that. (After all, it's the Unicode version of ncurses, right?) So this is an arguable bug #1: given no information about encoding, ncursesw assumes UTF-8 rather than falling back to a lowest common denominator.
The other is that PuTTY is sending LC_ALL correctly (something along the lines of "en_US.ISO-8859-1", assuming that blakeyrat likes the USA variant of English best). Why wouldn't this render correctly (again with TERM set to "screen")? Because, the .ISO-8859-1 encoding isn't actually implemented for English in Ubuntu! At least, not with the default set of locale packages (and I haven't found which package it's actually in). Presumably someone removed it on the basis that with Unicode awareness everywhere nowadays, it wasn't necessary. The result of that would be that the shell wouldn't understand the locale it was given and would fall back to a default instead, which might well reasonably be C.UTF-8. So this is arguable bugs #2 and #3.
And the reason that the bugs weren't caught is most likely that they were tested directly, rather than via screen (or some other bizarre terminal type that doesn't just use line-drawing commands). The bug only comes up if two things are unusual.
The best fix to all this is, IMO, to react to missing or impossible encoding declarations by sending back only ASCII in ncursesw. Oh, and to adjust PuTTY to start up in Unicode mode by default, and tell the other end of the connection that that's what it expects. (I'd also love it if the default Ubuntu terminal capability files TERM=screen used the actual standard VT100 codes for everything they could be used for, rather than randomly doing things differently from xterm just to be perverse, but hey, you can't have everything. And arguably that would hide genuine bugs, although I doubt blakeyrat would care if it made the screen render correctly.)
(BTW, I can confirm that the terminals I tested do indeed treat an instruction to render something as ISO-8859-1, to render it as ISO-8859-1. Not as Windows-1252. So only the âs of the misencoding are visible, because the other characters aren't valid in that character set.)
I bet after all the time I put into diagnosing this, my post will largely be ignored and people won't care about it.
@ender said:
@blakeyrat said:Programs store their read-only data files in Program Files, generally.Actually, the recommended directory for data is the common AppData folder, which (by default) is read-only to normal users, and writeable to administrators (but some installers make this folder read-write for everybody, to be able to store per-machine data while running as unprivileged users).
Huh, so I was right the first time, and blakeyrat was just telling me I was wrong?
What's the directory for common files that are writeable to normal users?
As a bonus question (one that's quite close to my usecase, but not that important), is there any way to set permissions on a file so that normal users can only read and write it via using a specific executable? (On Linux, this is both possible, and sufficiently difficult and nonintuitive to set up that some major distros have screwed it up.)
@morbiuswilters said:
Are you running it chrooted? Otherwise, that sounds really bizarre and hack-y.
Yes.
@morbiuswilters said:
@HardwareGeek said:I think that was the point. This login is allowed to run/foo/bar/baz -option blat
and absolutely nothing else. I'm guessing it can't even give that command line to a shell to process any metacharacters in-option blat
.But it still needs to read libraries in /usr, unless the whole thing is statically-linked. And statically-linking with C/C++ on glibc is a big no-no, so the only way this would work is if the application was written in Go.
I put copies of all the libraries it needs, and only those libraries, in a folder it can read (and tell it where to find them). It can't read /usr.
@blakeyrat said:
You gotta look at it the other way around. The Windows folder system is MUCH more comprehensive than the Linux one-- there are tons of Windows named folders that don't have Linux equivalents, and at least one that's used entirely differently (the user's "home" folder.) If you insist on equating every Windows known folder to one in Linux, you're going to produce buggy, broken, awful software-- the better solution is to do what Mono does, and artificially impose Windows' system on Linux.
I wasn't insisting that they had to be the same. I was simply pointing out that the fact that they were different was the reason for my confusion. (There is, indeed, a greater range of known folders on Windows than Linux.)
@blakeyrat said:
The whole idea of putting all .exes in a directory divorced from any contextual information about what program they are, or what associated files they have, is such a terrible idea I can't imagine that even Linux users are a fan of it.
It can be a problem, indeed; there's even been Linux distros that aim to change it even though it means fighting the expectations of every program in existence. The package managers try to work around that problem (I can type "dpkg -S /usr/bin/cat", be told it belongs to "coreutils", then type "dpkg -L coreutils" and get a list of all the files associated with it), but that's no help when the program you want isn't in the repositories. It does mean you rarely have the wrong value for $PATH, but that's about the best thing you can say about it.
Incidentally, just for fun, I tried to do the same thing through the package manager's GUI, and couldn't figure out how. This might say something about the relative discoverability of interfaces, or possibly not. Most likely they didn't implement it, on the grounds that the functionality was available through the CLI already and most people would look for it there rather than the GUI. Meanwhile, both those commands were on the first page of help output from the CLI.
@blakeyrat said:
AppData isn't below Documents, assuming by "below" you mean "inside". At least not by default.
I meant "outside", and used entirely the wrong word. And I was talking about the default locations, indeed. My point is that the Windows default hierarchy, in which we have /Users/blakeyrat/AppData and /Users/blakeyrat/Documents, is more sensible than the Linux default hierarchy, in which we have /home/ais523/.share and /home/ais523, with the convention of using a dot on the filename to imply that it isn't "really" part of the home directory. (And that convention came about because the earliest versions of ls, the equivalent of dir from DOS, ignored files starting with dots in order to not list the . and .. entries that referred to the current and parent directories, so people thought it'd be a great name for directories that weren't really user-visible. As I said, quite something of a WTF.) Interestingly, Ubuntu has now created a /home/ais523/Documents. I'm not sure what their intended use is for it.
@blakeyrat said:
Windows has admittedly poor support for running CLI programs over a network without using something like Remote Desktop to set up a graphical remote first. Windows wasn't built to support CLI programs well, because they were rightly considered arcane and obsolete even in 1995 when this UI was first being designed.
Going back in time and telling them about the current Linux developer holdouts still building these shitty UIs in 2014 would probably cause all their monocles to pop out.
My program actually has a GUI as well as a CLI, but the users who want to use it remotely wanted to use a CLI, so there we are.
@blakeyrat said:
... unless the user's problem is, "I want to install a program that the package manager group hasn't heard of yet". Which is basically the most important problem that needs solving. (Given, the Windows solution sucks also, but.)
Yeah, this is definitely a problem. The common answer is "you run the installer by hand, setting it to install into /usr/local, and hope that a) the installer works, and b) you don't have to install so much manually that you get things like filename clashes in /usr/local/lib when two programs both try to install the same library". Oh, and "c) oh, we forgot to mention that you have to download and manually install all the dependencies first". This seems to be strictly worse than Windows, which suffers from problems a) and b) but normally doesn't suffer so much with c).
There are a bunch of workarounds for a) (there are programs that sandbox installers to make sure that they're behaving correctly, for instance), but b) and c) are entirely left to the team managing the package manager (those sandboxing programs can detect the existence of filename clashes, but can't do anything to solve them), and you're in trouble if the program you want to install isn't there. Incidentally, the existence of problem a), on Linux and Windows, is part of the reason I'm trying so hard to get my installer to work correctly.
@blakeyrat said:
My point is that each user who logged in and ran the program would have generated files in their own user folders that simply deleting the folder containing the application wouldn't be able to remove.
Often no; it rather depends on what the program is. I once had to find, download, and install a program to concatenate PDFs within 15 minutes to meet a deadline (thankfully, it was in the package manager, although I probably wouldn't have made it). That program doesn't write anything to my user folder (apart from the resulting concatenated PDF, if you ask it to put it there, and you probably will), because it has no reason to; it's not like it has any per-user configuration to worry about. Incidentally, it's usual for Linux uninstallers to not delete configuration files by default anyway (often they have an option to do so, but it's not the default). Often I choose to leave the configuration around in case I ever install the program again. When the option's there, this isn't a problem, but some don't support this at all, and in general, uninstalling things is really hard on Linux because people don't test their uninstallers. (I'm annoyed about this. That said, I haven't had time to write the matching uninstaller to my installer yet, but when I do, I'll make sure it works.)
@blakeyrat said:
Sounds like overcomplicated crap. But there's no law that said the Linux version of your portable install needs to run the same way as the Windows version.
Indeed. I'd like to make them work similarly, if possible; it means you only have to maintain one set of documentation, that if a bug appears on one system you know to look for it on the other system too, and so on. However, conforming to the expectations of the OS is more important than that, at least in a default setup.
@blakeyrat said:
@ais523 said:I thought only Administrators could write there? Or did I pick the wrong folder? I was talking about the known folder in which programs store their read-only data files.What huh?
Programs store their read-only data files in Program Files, generally. You want them in a place where every user can access them, and since they're read-only it's harmless to have them in Program Files.
Roaming AppData is for read-write configuration files. (Roaming means these files can "roam" over an active directory to another physical PC if needed.) Each user has their own Roaming AppData
Normal AppData is for read-write caching, basically files which if deleted won't impact your program. (The perfect example of this is a web browser's cache. You don't want it to roam over the network, and deleting the files is harmless.) Each user has their own AppData
Ah right, sorry, in that case I just got the folders muddled. The reason for the confusion is that on Linux, there are separate known-location-equivalents for executables (which depend on the architecture), and read-only data files (which don't), both of which are read-only and centralized. The reason is that if you, say, have a 64-bit and 32-bit version of the same program, they can then share their data. Or you can share the read-only data files over NFS even if you have a bunch of programs running different architectures.
I agree with your clarification, and am sorry about the disconnect. I assumed that AppData was the equivalent of /usr/share, when it seems it's actually the equivalent of /home/username/.cache (non-roaming) or /home/username/.share (roaming). And /usr/share and /usr/bin are both lumped together as Program Files, it seems.
@blakeyrat said:
@ais523 said:
Most commonly, over a remote-desktop-like functionality, except that the target user is highly locked down and doesn't have permissions to anything other than the files used by one application.What does this MEAN!
So it's Remote Desktop-like, but it's not Remote Desktop. So what is it? Knowing that is kind of critical to being able to answer the question. For example, if you're using VNC instead of Remote Desktop, then the remote user does not get their own individual user account, and all remote users would be sharing the same settings.
In my case, this is a command-line program, and the program in question is a service that accepts commands from arbitrary people over the Internet, provides them to the program's command line, and then sends the results back across the Internet. This is effectively a command-line Remote Desktop. (You could even use telnet for the purpose, in fact. Just imagine it's telnet except vaguely secure.) The service has the same permissions as the program; it runs under an account that basically doesn't have permissions to access anything, all it can do is run one program. (I know that Windows' permissions system is entirely capable of implementing this.) Being a service, it's running from boot time, so has no separate "log in" stage, and thus the login process doesn't need to be able to complete normally.
@blakeyrat said:
@ais523 said:(Sometimes it'll be a web interface instead, that's in a separate executable written for the purpose.)Now I'm even more confused. If it's running in a web server, it's a completely different app you need to handle like any other web application.
A service with a web interface is just a webserver. So it's much the same as a service with a network interface.
@blakeyrat said:
Right, and Windows has System/System32 which is used by the OS and Program Files which is for stuff installed by the user/admin. The difference is that you can't install into System/System32 because why the fuck would you be able to? Why would this be something you need to tell the OS at install time? If the OS manages the programs in /usr doesn't it already fucking know that? It can just set the permissions when the OS is installed to disallow it! (And also: why the fuck would the "programs managed by the admin/user" be in a subfolder of "programs managed by the OS"... how does that make any sense?
I think there's been a communication problem here again. On Linux distributions, you normally install via package managers (which, basically, download and run the installer for you), which is part of the distribution (which corresponds to the OS; Linux the kernel has no concept of package managers, but it's only one component of the distribution). These install into the main /usr hierarchy. You can also install programs by either running the installer by hand, or (if you feel like it) copying files into the /usr/local hierarchy manually; in both cases, the files end up in /usr/local (which is important, because otherwise the package manager might overwrite them).
As for why /usr/local is a subdirectory of /usr, this is indeed a WTF (although not as much of a WTF as the reason the directory is called /usr in the first place). It's worked around in practice (the package manager knows that /usr/local is special and doesn't touch it), but it would definitely be possible to do better. (There was something of a campaign to use /opt for the purpose instead, but that lead to some sort of bureaucratic process with the result that nobody really knows what /opt is for, and in my experience, it normally seems to be used for programs that were ported directly from Windows and nothing else.) The way in which the home file directories start with dots is also a WTF, and again for stupid historical reasons (Windows' approach, in putting things like AppData in the directory below Documents, is a lot more sensible).
@blakeyrat said:
So if you know it's broken, fix it.
I'm talking about other people's installers here, which are broken on Windows. (What this thread is notionally about, in fact.)
@blakeyrat said:
Hey answer a riddle for me. If you go into your stupid-ass Linux build process and set the dash-dash-prefix to something like "my app" does it fail there too? I bet it does. I bet it's fucking broken on its native OS. But I'm too lazy to get a VM and try it.
I did just try. The installer in autoconf/automake is the most commonly used one on Linux; it handles spaces in directory names just fine (I just installed a program to a directory with spaces in). However, the programs that are actually installed often themselves have problems in such a configuration (for instance, failing to escape them correctly in command-line arguments when invoking other programs via the equivalent of Windows' CreateProcess). That said, it did fail when I tried a double quote in the directory name instead (although double quotes are illegal in filenames on Windows, so all Windows programs are either perfect or terrible at handling them depending on your point of view), and it's easy for programs using the installer to misconfigure it in a way that it fails to handle spaces (by not telling it how it wants them escaped).
My own system that I'm working on did indeed fail (it handles the spaces itself just fine, so it works in simple cases, but cannot correctly communciate them to custom build steps defined by the application; this is close, but not perfect, and not good enough). I view this as a bug that needs fixing; thank you for drawing it to my attention. It makes sense to fix this at the same time as implementing Windows support.
@blakeyrat said:
Linux doesn't even have installers. You're the first Linux user I've ever seen to even talk about installers, in a way other than telling me how much better package managers are and how I'm so stupid for not appreciating package managers and package managers solve all problems ever.
The package managers work via either a) downloading and running the installer; or b) running the installer on the distributor's system, recording the results, then downloading the results and copying them into the appropriate places. (The latter method is why you'd want to install in directory X, telling the program you're actually installing in directory Y; directory X is used to record the results of the installation.) So Linux users rarely deal with installers directly. People doing packaging for Linux, however, have to write the installers (if the installer is well-behaved, the package managers don't need much information from there, you can just tell it "this installer works like every other installer, do what you normally do" and it will work).
WRT package managers solving every problem ever, they don't; however, what they do do, is cause those problems to become someone else's (the team who administers the package database). In a way, this is solving problems from the user's point of view. Having seen what happens when they go wrong (so far, twice in seven years), they're no magical tool for making the problems not exist in the first place, and recovering from such a problem is almost as hard as it would be on Windows (slightly easier, in that all the source information is on someone else's server and so there's a limit to how badly you can screw things up).
@blakeyrat said:
@ais523 said:Or, if you installed it into a directory of its own, you can (if the installer was correctly written) just delete that directory instead, because it didn't touch anything outside that directory.Really? How is that possible, if Linux is a multi-user system? And doesn't have any kind of non-filesystem based way of saving configuration?
The configuration would be installed into the same "directory of its own", in that situation.
@blakeyrat said:
@ais523 said:OK, I think this almost works. The main way in which I see it failing is that it requires the executable to be on a writable disk, but systems on which people want executables on non-writable disks are rare on Windows(?) and so it probably won't be a problem in practice?If someone goes out of their way to make a portable install, you pretty much just have to assume they kind of know what they're doing. I mean, you are 100% correct.
I don't use it myself, but apparently several people use a W^X system for disks on Linux (W^X normally refers to the practice of making sure that memory is never simultaneously writable and executable, which I believe is called DEP on Windows?); each disk either contains executable files, or writable files, but never both (and this is enforced at the filesystem level). You temporarily overwrite the "writable" flag on the executables disk to do an install, but otherwise leave it the same. Obviously, in such a case, the configuration would be on a different disk to the executable, in which case it would be awkward to put them in parallel directories (you could do it with Linux bind mounts or Windows junctions, but probably wouldn't want to). It's that sort of configuration I had in mind when I made my comment. (As well as just --prefix, most installers allow you to specify specific directories for executables, configuration, etc., so as to be able to support that practice, although that's not as ubiquitous as --prefix.)
@blakeyrat said:
@ais523 said:They don't have permission to write AppDataThis guy's computer is broken. No point supporting him.
I thought only Administrators could write there? Or did I pick the wrong folder? I was talking about the known folder in which programs store their read-only data files.
@blakeyrat said:
@ais523 said:They're installing the application for other people
to access remotely; and they also want to use the application locally.
The remote use is heavily locked down, for security reasons; it doesn't
have permission to even read any of the known folders, and thus cannot
be installed in any of them. The local use is not locked down, it's just
a "normal install". Both are the same version of the software.I don't even know what this one means. Access remotely how? Over a network share?
Most commonly, over a remote-desktop-like functionality, except that the target user is highly locked down and doesn't have permissions to anything other than the files used by one application. (Sometimes it'll be a web interface instead, that's in a separate executable written for the purpose.) I wouldn't want random people to be able to potentially read any registry entry in HKLM if they found an exploit in the application, or see the files used by the other programs I have installed, etc.. The idea is to be able to host a system that lets other people use your application remotely (basically, SaaS/cloud usage of it), while maintaining some sort of security.
@blakeyrat said:
If you mean access remotely as in "using Remote Desktop", then there's no issue-- the remoter has their own user account which works like any other independent user account.
I guess this is the fundamental disconnect between our points of view. The remoter has an account that has very, very low permissions. Not even enough to make any sort of basic use of the system. When such systems are set up on Linux, they frequently don't have read access to such fundamental folders as /usr or /etc. Are you saying that on Windows, I can't lock down an account so far that it cannot read Program Files or the registry, perhaps for the purpose of allowing people to remote into it to run one specific program?
@blakeyrat said:
@ais523 said:And I guess the real reason is that this functionality is standard in installers, or at least I thought it was.And the basis of this thinking is... what? Have you ever actually tried it?
Yes, but only on Linux, which is my primary system, and it works as I expected there. --prefix is the #1 most commonly used option to the configure/make/make install process for an install from source, and usually the very first feature request on any install system that doesn't have it. (DESTDIR is also quite common; that's used for a workflow of "install into directory X, but tell the executable that it's installed in directory Y", which has various uses for build system automation.) Part of the reason is that standard Linux systems have two hierarchies into which programs are commonly installed: /usr which is managed by the operating system, and /usr/local that is managed by the system administrator (and never touched via the equivalent of Add/Remove programs), so the ability to specify which one you want to install into is kind-of critical.
I assumed that the functionality would also be standard on Windows.
@blakeyrat said:
Typically if you run an installer for an application that's already installed, the only options you get are "repair" or "remove". Have you seriously never actually tried this? And you write software? Do you... do you even own a computer? Or do you just write software on a legal pad and fax it to Bermuda for someone to type in?
I own a computer, but rarely boot it into Windows, which is partly why I'm asking about common Windows practice; the situation of actually installing a program on Windows has come up incredibly rarely for me (and the few times it has, the installer often clearly isn't well-behaved for a standard Windows installer, e.g. one of them couldn't handle paths with spaces even though "Program Files" has a space in specifically to ensure that installers handle paths with spaces in).
On Linux, if you run an installer on an application that's already installed, it'll do a repair; if you change the installation directory, it will do a second install, into that chosen directory (while leaving the original directory intact). If you want to uninstall it, you run the uninstaller instead (which is normally the same program as the installer, but run a different way, either with different command-line options or using the "uninstall" command in a GUI whose purpose is to run installers and uninstallers. Or, if you installed it into a directory of its own, you can (if the installer was correctly written) just delete that directory instead, because it didn't touch anything outside that directory.
If you're unlucky, and have a badly written installer, it'll get the path handling wrong and touch things in directories it's not supposed to. This is, ofc, a fun source of WTFs in its own right (e.g. there is a program whose purpose is to attach a debugger to an installer in order to log every path it touches, and uses the information to generate a matching uninstaller; the WTF is not the program itself, but the fact that it's necessary).
@blakeyrat said:
Look. Your installer has a fucking check box. The check box reads "portable install". If the user selects that when the application is installed, the installer writes a folder called "myapp_settings" into the same folder as the .exe.
When your .exe boots, the first thing it does it look for "myapp_settings". If it finds it, it creates its own virtual AppData and virtual Registry inside this path and uses those virtual paths instead of the real AppData or Registry. (Making a compatible wrapper to write Registry entries to either place I leave as an exercise to you.) If the "myapp_settings" folder isn't present, the app uses the normal AppData or Registry path like a normal app written by a normal person normally.
OK, I think this almost works. The main way in which I see it failing is that it requires the executable to be on a writable disk, but systems on which people want executables on non-writable disks are rare on Windows(?) and so it probably won't be a problem in practice?
@blakeyrat said:
@joe.edwards said:He's trying to support "portable installations" I think (where you install on a USB drive and the settings are carried along with it). Most applications I've seen that support this scenario ask the user at installation if they want a normal or portable installation.Oh. Then his insane rambling makes some tiny sort of sense. Imagine how less confused we'd all be if he's typed like 4 words to actually COMMUNICATE WHAT PROBLEM HE WAS TRYING TO SOLVE.
My problem is: allow the user to install the application wherever they want, and have it still work, with multiple installs in independent locations being 100% independent of each other.
Reasons a user might want to do this (all of which have actually come up):
Reasons that haven't come up for me, but are plausible (and have been mentioned by others upthread):
And I guess the real reason is that this functionality is standard in installers, or at least I thought it was. Are you implying that when I use one of those installers that allows editing of the install path, if I install the application a second time in a second location, the first installation will stop working? That removes most of the point of customizing the install path in the first place.
BTW, when I was talking about writing the paths into the executable, I meant that the installer modified the executable to know where it had been installed. DEP has nothing to do with that, because the executable isn't running while it's being modified. And when I was talking about running two versions of the application, I mean two different versions; it's also supported, and entirely normal, to open the same executable twice.
@blakeyrat said:
Anyway, the best/only way to handle this is to get the path to your own executable (not as trivial as it seems) and have a folder called something like "thisapp_config" at the same level in the filesystem and create your own little mini-AppData and mini-Registry in there in the form of files.
@joe.edwards said:
Each user account has its own HKCU subtree. This is layered on top of HKLM.
I was aware of that (which is why I said "the same user"); not having HKCU would mean that you couldn't have two different users each install for their own use, which would be such a mistake in designing a configuration system that it's hard to imagine any OS making it.
That said, all this thinking about corner cases is mostly just an attempt to make sure I don't do something stupid, like half the programs on here do. (That said, doing better than the average installer doesn't seem to be hard, given how bad the average installer is.)
@Buttembly Coder said:
The generally accepted way is to use the registry.
Then how could the same user possibly install two copies of the application at once? Half the reason you'd want to customize the install paths is to do that.
@Scarlet Manuka said:
@anotherusername said:
@Scarlet Manuka said:I changed its installation path to the standard place for programs to be installed, running elevated (as one does to install software) so that it could put its important files there where they could be safe. And yes, I expected it to work just fine because that's how Windows software is supposed to work. It clearly knew what AppData is since it suggested to install there, so I'd expect that regardless of the program installation directory, user-specific files would be created in AppData where they belong.Slightly bemused, I changed it to Program Files.You changed its installation path to a location with drastically different permissions and you expected it to work just fine? You are TRWTF.
@ais523 said:
(discussion of general issues porting Linux software to Windows)As has been pointed out, porting issues should not have been relevant in this case because the software is Windows-only. However:This isn't so much a problem with doing the security properly, as problems finding the appropriate directories. {...} The problem is, on Linux, you can correctly and safely hardcode all the pathsThe usual "solution" in my experience is the same one used by lazy Windows devs: hardcode all the paths regardless of correctness. And if that was the only issue, it would have worked for me too. If the installer had hardcoded C:\Program Files rather than looking it up from CSIDL or KnownFolder values I wouldn't even have known.
I've actually been trying to work out just how you're supposed to create an installer for Windows that allows users to customize the install location (this is something I actually want to do, and I'm hoping that the "bitch about shortcomings of Linux until a bunch of Linux fanboys turn up and tell you 10 different ways to do it in Linux to prove its superiority" works for Windows too). Say a user wants to install to their Documents folder (maybe they're just trying out the program and don't want to give it admin rights); how does it know to look there for its data, rather than in the normal place on Windows (which I assume is an application-specific subdirectory under FOLDERID_ProgramData, formerly CSIDL_COMMON_APPDATA)? Getting the installer to write the path into the executable would be awkward, but I think it's wrong anyway; it should convert the path to a relative path to FOLDERID_Documents, in case the documents folder moves. (This is something that my installer gets wrong under Linux at the moment, actually; it would be nice to fix that at the same time.) I guess one possibility is for the application to determine the path to its own executable, see if it's in FOLDERID_ProgramFiles, use the known folders mechanism if it is, and otherwise assume that the user is doing something weird and custom and just use files relative to the directory containing the executable, on the basis that if the user is installing it somewhere weird, they should know what they're doing. You'd write the actual relative paths to use into the executables, in case the user wants to customize the locations of some things but not others (e.g. they want to move the data files but not the executables, for just the one program; this is a scenario I've actually seen people ask about).
OK, that wasn't so bad. I should try rubber-ducking on forums more often.