Why doesn't Chocolatey install packages into `C:\Program Files\`? - installation

According to the Windows installation rules, programs should be installed to
C:\Program Files (64-bit program / x86-64) or C:\Program Files (x86) (32-bit program / x86). The program is copied into a sub-sub-folder containing the vendor name and the program name.
But why doesn't Chocolatey install packages into C:\Program Files\<Vendor>\<Program>\?
10. Apps must install to the correct folders by default
Users should have a consistent and secure experience with the default installation location of files, while maintaining the option to install an app in the location of their choice. It is also necessary to store app data in the correct location to allow several people to use the same computer without corrupting or overwriting each other's data and settings. Windows provides specific locations in the file system to store programs and software components, shared app data, and app data specific to a user
10.1 Your app must be installed in the Program Files folder by default
For native 32-bit and 64-bit apps in %ProgramFiles%, and %ProgramFiles(x86)% for 32-bit apps running on x64. User data or app data must never be stored in this location because of the security permissions configured for this folder.
Source: Certification requirements for Windows desktop apps
Version: 10 (July 29, 2015)

It depends on your version of Chocolatey, it's settings and the packages themselves.
To start, see Tools vs Applications and Chocolatey's distinction (
https://github.com/chocolatey/chocolatey/wiki/ChocolateyFAQs at the
bottom).
If the package does not use a native installer (a tool), it depends on
if the package author has used the bin_root concept that is up and
coming in a future version.
For example, SysInternals will go to c:/sysinternals right now unless
you have a defined $env:chocolatey_bin_root variable. The concept in
the code will change as well as right now this requires it to be a
subfolder of the system drive and I don't see us developing the final
feature with that limitation.
If the package doesn't have that concept yet, one can always ask the
package author to incorporate it.
If the package uses a native installer (an application), one can use
installArgs to pass arguments to the native installer
(https://github.com/chocolatey/chocolatey/wiki/CommandsInstall) and
tell it the directory to install the application to. This does require
you to know what you need to pass to the native installer. If you want
your applications in a custom directory, there is an assumption that
you are already an advanced user so it is expected that you would know
what to pass the installer if you were doing a silent install.
Slightly paraphrased from: https://groups.google.com/forum/#!msg/chocolatey/uucAz8GxebA/HEPAKp69d90J
Also,
NOTICE: As of 0.9.8.24, Chocolatey's default install location is
C:\ProgramData\Chocolatey
This reduces the attack surface on a local installation of chocolatey
and limits who can make changes to the directory.
Source: https://github.com/chocolatey/chocolatey/wiki/DefaultChocolateyInstallReasoning
And from personal experience I can attest that that concept is an excellent line of defense (when properly configured, used and understood).
PS:
As you already added to your answer, technically the requirement is %ProgramFiles% and %ProgramFiles(x86)% environment variable(s where applicable).
For example, %ProgramFiles(x86)% could as well point to P:\Software\Programs\x86\ (instead of C:\Program Files (x86)\).
There is obviously a lot of legacy software (now (re-)packaged) that never used a <vendor> section in the path-name.
Hope this helps!

Related

Comprehensive list of programs on different operating systems

How would I get a list of EVERY program into a text file for windows 95-windows 10. The uninstall programs in control panel doesn't have the version and publisher for the older operating systems, and wmic does not display every program. Even the uninstall registry, which I thought would be my savior, does not list every program. I can see discrepancies between that and the uninstall programs tab. Powershell and the like are off the table since it is relatively new.
Some combination of the following:
Enumerate registry for HKEY_CURRENT_USER\Software\Microsoft\CurrentVersion\Uninstall and HKEY_LOCAL_MACHINE\Software\Microsoft\CurrentVersion\Uninstall. And probably HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall on 64-bit os (might be duplicated). These are the list of installed programs that appear in the Control Panel's "Program and Features" section. Notice that some of the entries are straight-forward and have most of the data you want. Others are a GUID - this corresponds to an MSI installation.
For all the entries obtained in #1 that reference a GUID, use the MSI API to find the installation information you seek. Start with MsiEnumProducts. From there you can get at version info of installed applications.
Brute force search for EXEs installed in C:\Program Files and C:\Program Files (x86). For each EXE found, you can use this method to get the version information.
You want a list of applications installed from the Windows Store? Ask me for a code sample if that's important too.
The registry uninstall registration requirements in the 90's was just the display name and the command to start the uninstallation. Windows 2000 added support for more values and exposed them in the new UI but they were still optional. In recent years a couple of them became a requirement to pass the Windows Logo tests but they are still optional for non-certified applications so the uninstall key is not guaranteed to contain version/publisher information for every entry. Portable applications are not listed in the registry so if you need a inventory of everything then you need to inspect all exe files and ignore the registry.
Supporting everything back to Win95 RTM is going to be tough since you have nothing except batch files as a scripting option. VBScript is a optional component that normally gets installed with IE 4 and I don't even remember if it is possible to get Powershell on these systems.
I don't think it is possible to extract the version information with a simple batch file, you probably need the help of a 3rd-party tool. The issue with 3rd-party tools is that a lot of them depend on the Microsoft CRT run-time .DLLs and Windows 95 RTM does not have them out of the box, not even msvcrt.dll.
If you can raise your requirement for Win95 to have Windows Scripting Host installed (redistributable or part of IE4) then you could write a VB/Jscript file that uses the FileSystemObject to both walk the entire directory tree on every drive and to get version information from .exe files.
If that is unacceptable then you need to try to find a tool that can extract version information. There is a Microsoft tool named filever.exe listed here but I don't know if it works on Win95 and a NirSoft tool here but I'm not sure if it supports stdout redirection from the commandline (but it is open source so you could fix that if needed). Even if you find a suitable tool you would still need to walk the directory tree looking for .exe files and that is not going to be fun when you are limited to command.com and its DOS compatible batch handling.
My recommendation is to write a new application. I can't recommend writing it in a .NET language because you would be dealing with versions 1-4 and it is not installed on XP and older by default.
The way I see it, you have 3 options if you are writing it yourself: Visual Basic 6, Delphi (something old, v3 or older perhaps) or C/C++.
For C/C++ any version of Microsoft Visual C++ or MinGW/GCC will do but the older the better and you must not link to or use any C run-time library stuff (you might get away with static linking with MinGW but not recent versions of Visual Studio). If I was doing this I would use Visual Studio 6 or 2003 and build with /Zl & /NODEFAULTLIB. There are multiple small standalone CRT libraries if you need them. If you use any recent version of Visual Studio you will manually have to hex-edit the file to make it run on anything older than XP.
The actual implementation needs to call FindFirstFileA (and friends) on Windows 95/98/ME and FindFirstFileW on other systems to walk the directory tree and GetFileVersionInfoA/W (and friends) to get version info.
If you are feeling fancy you could perhaps filter out files in %WinDir% signed by Microsoft. Good luck...

Pitfalls when deploying/installing legacy software outside program folders on Win 7 and 8

I’ve been given the task of changing all our legacy software installation packages to conform to Win 7 and 8. Previously our software would run on XP and Win Server 2003 and would simply be installed into the “program files” folder and run without any worry.
Nowadays, or since the introduction of UAC, installing into the program files opens up some issues regarding privileges when it comes to file creation, changing and deletion. Furthermore the whole wow64 redirection thing, where our legacy applications would be run from a different folder than the actual installation folder (Program files x86).
Cut to the chase:
Our legacy software is running on dedicated computers, only used for running our SW. I’ve previously bypassed the whole problem with UAC and WOW64 redirection (as a hot-fix-hack) by simply installing the software outside the program files folders.
Now we are looking for a permanent solution, and I was actually thinking of making my previous hot-fix the solution. So simply install our software on for example: c:\software\ and by doing so bypass the whole issue with UAC and WOW64.
Question: What are (if any) the pitfalls when installing legacy x86 software outside the program files folder?

%HOMEDRIVE% vs. %ProgramFiles% vs. %HOMEPATH%: When should an Application choose which installation directory?

Some cross-platform packages like Ruby or Qt prefer %HOMEDRIVE% as the default installation path, Google Chrome uses something in %HOMEPATH%. What's the advantage and disadvantage of each choice? What's the best choice for a simple private application (i.e. a game, where the installation should work without administrator rights)? On the other end: What would be the best choice for an industrial application (i.e. a software that controls an industrial device, running on a computer that merely exists for that purpose)?
If you want to ensure your app can be installed without Admin privs, install under %LOCALAPPDATA% - if you want to install system-wide, use %ProgramFiles%. Whatever you do, don't use %ProgramFiles(x86)%.
As a general rule I find it hard to believe that a single installation will work for multiple operating systems. From my understanding it seems that you would need multiple different installation files to handle each of the different file systems (not just installation directory, but the actual file system). This will span not just private, and industrial systems, but all business systems as well. Go to the download page for any software that is available for multiple OS and they will have a link for each one.

Install usb device without manager prompt

We have a usb device and the drivers (.inf, libusb.dll, libusb.sys) and can install it using Windows' Device Installation Wizard (by pointing to the .inf file). However, we need to install the drivers without using the wizard (passively, so the user doesn't need to do anything). Does anyone know how this can be achieved?
You added the "installer" tag, so I'm assuming you're talking about some kind of installation package, like Windows Installer, InstallShield InstallScript, etc.
If that's the case, you should probably use Microsoft's DIFx framework.
DIFx makes it easier for you to create
high-quality driver packages,
customize the installation of driver
packages, allow the installation of
driver packages in combination with
application software, and use the
standard Windows APIs and installation
tools. DIFx also makes it easier for
end users to diagnose device and
driver problems. End users can be
confident that, if necessary, drivers
can be uninstalled or rolled back.
I've used DIFx from both Windows Installer-based installs and InstallScript installs. Very user-friendly, easy to debug, and effective.
My colleague came up with an answer that is working very well. It appears that, unless you hardware/driver combination is WHQL signed, the Add New Hardware Wizard will always appear in Win XP. However, with the following method it is possible to have the "Search" button in the wizard find your driver automatically. In Windows 7, there is no prompt and the device installs just fine. You'll need to watch out on 64-bit machines, though, as they have much stricter signing enforcement.
So here is the relevant excerpt from the whole document:
Use the DIFxAPi merge module. (Read a good introduction to drivers in Windows, the use of INF files, and DIFxAPP.) The DIFxAPI merge module is included in the WDK in the ‘WDDK//redist\DIFx\DIFxApp\MergeModule\’ directory. The merge module can be included in an MSI package and can be set to install multiple device drivers. Here are the steps to create an MSI with the DIFxAPP merge module:
In the setup folder, create a separate directory in the Application Folder for the driver package and add the driver files to the folder.
Add the DIFxApp.msm to the setup project.
Build the setup
Use Orca to edit the MSI database table and add the INF component to the DIFxAPP merge modules table.
The Orca installation is included in the Windows SDK in the ‘C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin’ directory. (The Windows SDK can be downloaded from Microsoft)
Run Orca and select the MSI package that needs to be modified.
Read part 5 for automation.
In the ‘File’ table, locate the INF file of the driver package you would like to install and copy the Component value.
Create a new row in the MsiDriverPackages table. Add the Component value into Component field. The following flags can be used (although some are ignored by Windows 7):
0 - Not set (default)
1 – Force installation of driver, even if it the currently installed drivers is
a better match than the driver being installed
2 – Suppress message box telling user to plug in devices after the driver
has been installed.
4 – Suppress adding an entry in Add/Remove Programs for driver.
Driver will be uninstalled when main application is uninstalled.
8 – Install unsigned driver packages
16 – Remove driver binaries during uninstall.
Save the MSI. In order to automate the process, the editing of the MSI database can be recorded to a Transform and then the Transform can be applied in a post build process.
Open the MSI in Orca.
Select Transform->New Transform
Complete steps 3 and 4 in the above directions.
Select Tranform->Generate transform and save the transform.
Add the following line to the post build of the Setup Project
MsiDb.exe -t transform.mst -d $(TargetDir)\DriverInstall.msi
Note: MsiDB.exe comes with the Microsoft SDK and is located in
C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin
If you get an error installing from the MSI (e.g. I got error code 2356 which ended up being due to an invalid Flag value), use Orca's Validate function to see if there are any errors. EDIT: Fixing these errors still has not gotten rid of the error. I remember reading that inf files should be in their own sub-directory, but that didn't fix my problem either.

Is AppData now the 'correct' place to install user-specific apps (which modify their own data)?

I'm probably just being very thick here, but it's not clear to me where I'm supposed to install 'new' user-specific programs on Windows 7 (and presumably Vista too, though I've not specifically looked at that scenario yet).
Under Windows XP (rightly or wrongly) we always installed our programs into folders under 'Program Files' and accepted that they'd be kind-of available to everyone. From what I can gather under Windows 7 I'm supposed to install my software under the user's AppData folder (possibly AppData\Local\MyApp). That makes a degree of sense, but the fact that this folder is 'hidden' by default means that we're going to have 'fun' talking our users through support stuff.
I want to install our software so that it's user specific (the Users bit in Windows 7 makes perfect sense) but I do want the user to be able to access it if required. Our program also includes a 'data' subdirectory which it needs to write into while it's running (embedded database), but as the program is intended to be single-user/standalone, the data folder being inside a user-specific folder isn't going to be a problem.
My problem is just that whole 'hidden folder' aspect of AppData. As much as I've trawled the MSDN, I can't work out where else I'm supposed to install user-specific programs. Taken one way it would seem to be something like AppData\Local\MyApp, and another way it would seem to be just as valid under the user's My Documents\MyApp equivalent.
Has anyone got a clear guide for where all this stuff goes? I found the MSDN docs confusing. :-)
Not really.
The directory that serves as a common
repository for application-specific
data for the current roaming user.
AppData is, surprisingly, for application data, not for installation (Click Once/Silverlight applications aside). You can, and should still install into Program Files, just don't expect to write into that folder.
You can install software into AppData if you want it to follow a user about in an Active Directory environment, which happens if you put it in AppData\Roaming (the SpecialFolder.ApplicationData location).
You can also install into AppData if you want the software to be available to just the user that installs it. This can be useful if, for example, you have multiple users on the same machine, who all want to run different versions of the software in complete isolation.
If you want settings to only apply on the local machine then you use AppData\Local, which is SpecialFolders.LocalApplicationData - this will make AD administrators very happy as the roaming profile size won't suddenly jump up 50Mb or whatever the size of your software is.
If you wanted to create settings which apply to all users then you're looking at SpecialFolders.CommonApplicationData
You should remember never to rely on the actual name of the directory - localisation issues mean this can change and the location does change with OS versions two. You should be using the special folder enumeration in your software, or the equivalent in your installer.
Could you not install into Program Files, but use AppData as it's supposed to be used, and store your database in there?
Windows 7 added the FOLDERID_UserProgramFiles known folder and by default this maps to %LOCALAPPDATA%\Programs. This is used by MSI when ALLUSERS=2 & MSIINSTALLPERUSER=1.
On Vista and earlier there is no canonical per-user application folder but just using %LOCALAPPDATA% is pretty common. Sadly MSI will just use %ProgramFiles% on these systems.
It's 2019, and I just installed Visual Studio Code (a Microsoft product) in the default folder of
%userprofile%\AppData\Local\Programs\Microsoft VS Code
This is probably for getting around the requirement to have an administrator or UAC prompt authorise the installation
Windows 7 folder structure is deeply inspired on Unix structure:
/usr/ -> C:\Program Files\ -> binaries: executables and dynamically linked
/etc/ -> C:\ProgramData\ -> global settings
/home/ -> C:\Users\ -> a folder for each user
~/.* -> C:\Users\Hikari\AppData\Roaming\ -> settings for each user
Windows has more folder, like My Documents for files with content produced by user, AppData Local and Roaming (which Unix usually handles with NFS).
It's about time for us developers to start using these structures. We must separate at least binary files that don't need to be replicated, global and user settings.
When a setup is installing an app, this setup should expect to have permission to write on Program Files. Once the setup is finished, Program Files should be writable only for other setups aiming to update binaries to other versions.
Please install executable files to the %programfiles% folder in Windows - a simple MSI based install package can perform an active setup for any new user who logs onto the machine to create the user specific files and folders in their profiles %appdata% folder. You see this behaviour for Internet Explorer, Adobe reader, etc. - It's the little MSI installer window that pops up the first time you log onto a machine which has those applications installed. - Thanks - a system admin :)
My opinion, for what it's worth, is that user-specific program files is just asking for trouble and is a damn stupid thing to do.
A much more sensible approach is to install different versions of your program to:
\Program Files\Your Program\Program_v0.1\Program.exe
\Program Files\Your Program\Program_v0.2\Program.exe
\Program Files\Your Program\Program_v0.3\Program.exe
\Program Files\Your Program\Program_v0.4\Program.exe
I would then place a bootstrapping launcher at:
\Program Files\Your Program\ProgramLauncher.exe
Then, the user application data folder will only contain data, including an INI/XML/Settings file that indicates the version of the program that this user is working with.
Such an approach satisfies the core tenant of keeping data and executing code separate, allows every user to run a specific version of the code, and offers a small amount of de-duplication by ensuring the same executable code is not copied multiple times across user folders.
Otherwise, go right ahead with installing programs to AppData and undoing the years it has taken us to achieve clean separation of code and data. I found this thread because I noticed that Chromium and DropBox are installing code to AppData. I'm going to uninstall those program, and change the permissions on my AppData folder to exclude execution to ensure I can easily spot other programs attempting the same BS.

Resources