Is there a Property that resolves to the public folder? I don't want to hard code "c:\users\public" in the Directory structure, obviously, but I can't find a predefined Property that resolves to this. Is there an accepted way of specifying files to be installed here and/or removed on uninstall?
If there is a CSIDL for the directory then the OSInfo CustomActions probably have it. That's an extension to the properties supported by Windows Installer. There isn't support for the Vista only RefKnownFolder(), yet.
When you target your setup to be for all users then some folders will me mapped to the all users folder (DesktopFolder, StartMenuFolder, ProgramMenuFolder, more info here) but there is no permanent property that will point to the all users folders on all types of setups.
You can use the CommonAppDataFolder which is where you should put data that will be relevant to all users of the application (but it requires admin right to modify).
You can try to write a custom action (Sample here) that will replace the value of [YourFolder] with [%PUBLIC] (The Public environment variable, I don't know if it exits on XP and down)
Related
I'm creating installer using wix, and in my deferred custom action File.Exists return false on existing temporary file. How can I make C:\Users\<me>\AppData\Local\Temp visible for my custom action?
You should show the actual code. It might work fine in code run from the interactive user's desktop, but it's being called from an msiexec process running impersonated (or with the system account) from the system folder, and you don't even say if it's a Dll call or an executable.
However, the issue is that you can't just look in that folder from a custom action. If you are running deferred with the system account and looking at Environment.SpecialFolder to get the user's temp folder you'll get the system account's temp folder. If you run with impersonation you still won't get the right location because impersonation does not load up the entire user profile that would give you access to user profile locations like the user's temp folder.
Without knowing exactly what you're trying to do this may not help, but WiX and Windows Installer have searches which will do exactly what you want. Just do a file search for that file in TempFolder, which is the property name location you need. You need this kind of thing searching TempFolder, ignoring the version checks:
http://wixtoolset.org/documentation/manual/v3/howtos/files_and_registry/check_the_version_number.html
I'm creating a WIX installer for a C# application.
In the application I use System.Configuration.ConfigurationManager.AppSettings[Setting1] to get settings.
My question is, where must I place the program.exe.config file on the machine in order for it to work?
I can't place it with the program in ProgramFiles directory, since those files are read-only.
I tried:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
config.AppSettings.Settings[Config1].Value = "Value1";
config.Save();
Unfortunately I don't know where it's looking.
Thanks your replies, Trevy
It should be in the same folder of the program.exe. Use wix to copy both program.exe and program.exe.config to the required folder.
If you need to edit the configuration file during the installation you will need to do it using a custom action in wix. Make sure you pass the file path to the custom action and write the code to read the configurations in that file and edit.
The problem isn't that the files there are readonly - the problem is that you are trying to update files in the Program Files folder with your config.Save, and you can't do that if you are a limited user, and you are always limited (even if you are admin) unless you elevate. The short answer is that:
If your app routinely updates files in restricted areas then it probably needs elevation, so give it an elevation manifest.
If however you require you app to be used by limited users and allow them to update that config file then don't install to Program Files. Choose User Appdata folder, for example. Windows is probably using your config file during program startup, so you can't separate it from the exe.
When I was creating an installer for my app, I found I couldn’t save my settings.
The reason is because the Program Files repository, from a practical point of view, is read-only (Applications should never run with elevated permissions). When installing a program, the only time we modify the MyApp.exe.config file is at installation/upgrade/repair time.
The config file has many sections. One of them is userSettings. This is where we store any data we need to modify during the lifetime of the application. When run for the first time, Windows creates a hidden file in the user’s AppData folder. That is why we can save user settings, even though the config file is in the same directory as the MyApp.exe
So the answer is, if we run into permission errors when trying to save our settings it means we are writing our settings to the wrong section of the config file. We need to place it in the userSettings section and nowhere else.
For convenience, Visual Studios has a settings editor (the settings tab of the properties page). It allows you to create strongly typed user and application settings. The generated class lets you save user settings, but not application settings for the above reasons.
As part of my WiX-based installation, I need to ask the user to enter the value for a property, JAVA_LOC, which I'm going to store as a registry value (it is NOT a directory I want to create on the install.) However, if I use the Publish Event="SetTargetPath", the linker says that I must declare JAVA_LOC as a directory in the component hierarchy. If I do that, things I can record the path okay. However, it turns out that if I run a 'Change' install afterward, the new path value is ignored, and JAVA_LOC is reset to the location of the JAVA_LOC directory I was forced to create.
How does one validate a path the user has entered that isn't for the install
directory? Remember, I'm just trying to store it in the registry, not really create a dir for it.
Dave
The SetTargetPath control event can only take a primary key from the Directory table as an argument. You would have to define the directory to be able to use this. Nothing says that the dirctory has to have a CreateFolder entry and/or any File resources. I'd think you could nest your component with the registry data under this directory and it should all work without creating the directory.
On linux, we have LIBRARY_PATH and LD_LIBRARY_PATH environment variables in order for programs to search for libraries. Do we have similar thing on windows? Particularly Windows 7?
Also, I would like to know best practices for DLL use (where to put them, use envs or not, etc.), since I want to work on windows like everyone does, and not to sloth myself on workarounds :)
Edit: As explained by Bob, this answer describes the Alternate Search Order, which is not what most applications would see. The full rules are quite complex. I don't think I can summarize them here. Instead, read the Microsoft docs - https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order
My original answer was:
This MSDN article explains the default search order. I quote:
The directory specified by lpFileName.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The current directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.
In (1), if you statically linked against the DLL's stub library, I think "the directory specified by lpFileName" is the process's exe's path.
Take a look at the help for the LoadLibrary and CreateProcess functions. These describe the paths used to locate DLLs, and how you can modify them.
It looks on currentDir first then WinDir and SystemDir also in your path
According to what #andrew has mentioned in his answer, the order of folders that are used on Windows to search a DLL may be different from one configuration to another. I think the simplest way to check this order on Windows is to use the Dependency Walker tool. After opening the tool, and pressing the "Configure Module Search Order" button on the toolbar, you will see a window like this:
This window shows you the current search order on your machine. The interesting part is that by pressing "Expand", you can see the whole folders in the search path one by one. You may also change the order if you want, to be used for loading an specific module.
I'm using WiX, and would like to know the .wxs necessary to take a file and install it to every available sub-directory of a particular location. This could mean 0 or more final installation locations, determined at install time based on the currently existing directory structure. For example, if I started the install with:
\target
\subdir-1
\subdir-2
Then at the end of the installation my file would be in \subdir-1 and \subdir-2. If on the other hand these directories did not exist on the system when the install was started, my file would not be installed at all and no sub directories would be created.
Afaik this is not possible with WiX (because it is basically against the nature of MSI to install a component into several locations).
You could either
create a different component for each subfolder, or
use a custom action to copy the component to all subfolders.
In the latter case you should also provide a corresponding CA for uninstallation which removes all the files from the subfolders again.
EDIT: Seems my above answer is not totally correct. MSI supports duplicating files using the DuplicateFile tables and WiX 3.0 also provides a mechanism called "smart cabbing". Both are mentioned in a blog post by Aaron Stebner.
Not without a custom action, you need to write a custom action that will do that.
The latest and greatest in custom actions is the DTF (and here) framework that comes with Wix3.
If you are targeting Vista (or Win2k8, not sure about Win2k3), you can use mklink.