WiX - How can would I hard code the default install path? - visual-studio-2013

I am trying to get the directory to be hard coded with WiX so that it can only go into one place. To prevent issues installing.
I cannot use [WindowsVolume] or [TARGETDIR] because the first is C: drive and the second defaults to the one with the most space available.
The path i need is on D: drive, how would I specifically say D: drive for my installer? Is there a variable for D or a way to get that drive letter?

set the property RootDrive.
<Property Id="ROOTDRIVE" Value="D:\"/>

Related

Environment variable is too large on Windows 10

I have recently upgraded to Windows 10 from Windows 8.1.
Now I wanted to set an environment variable for my new installation of Apache Maven.
Each time I created the user variable, things were fine. However, I also need to create the system variable where I will need to append the bin directory to the variable that I already create in the user variable to be "path".
Now, each time I do this, I get an error that says "This environment variable is too large". As a result of this, I am unable to create the path.
I have attached an image of this error.
When the PATH environment variable gets overloaded with too many values it reaches a point where you cannot add values any more. Trying the following should solve your problem.
Solution 1:
Create a new system environment variable, say 'NEWPATH'
Assign the bin directory location to 'NEWPATH'
Now append '; %NEWPATH%' to the PATH environment variable
If this still doesn't work then try to copy some part of the PATH environment variable already existing values to the 'NEWPATH' and then append the 'NEWPATH'.
Solution 2:
Check the value of the PATH environment variable if you can group and shorten the paths. For example,
C:\Program Files\Microsoft SQL Server\102\Tools\Binn;C:\Program Files\Microsoft SQL Server\102\DTS\Bin;
can be combined to
C:\Program Files\Microsoft SQL Server;
In this way, you can build more space into your fixed length PATH variable and finally adjust your bin directory location into PATH.
There are a few ways to clean up your path variable. The easiest is to use Rapid Environment Editor. This free utility will,
Remove the duplicate paths (right click → Cleanup Paths)
Remove non-existent folders (shown in red which you need to manually delete)
Replace long paths with short paths (right click → long to short path).
I do the above steps in order and use the third step only for the longest paths until the Path variable size is under control again.
If you want to go more advanced, here's a little C# tool that you can modify to whatever other logic you want to implement.
Another solution, or more a workaround to bypass the PATH environment variable length limit, is to manage your path (add, remove or update) using a PowerShell script;
Capture the current PATH variable by clicking "Edit Text" (see above screenshot) and copy it to your clipboard and save it in a text file as a backup too to avoid bad surprises. This is not mandatory, but will allow you to recover should something go wrong.
Now that it is backed up, add the following to a new PowerShell (.ps1) file (amending the first line below with the folder path(s) you want to add (the part after the + sign):
$newPath = $env:Path + '; C:\Users\....\FirstFolderToAddToPath; C:\Users\....\SecondFolderToAddToPath;'
[Environment]::SetEnvironmentVariable("Path", $newPath, "Machine")
$env:Path = $newPath
This is how I managed to get my (long) PATH variable back after playing with the Windows 10 UI, being caught by the length limitation and losing most of my path.
Try to modify by RegEdit. In my case it works when length is more than 3000.
Press Win + R and enter regedit to open RegEdit. Go to Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment, and modify the value of Path to your path. And restart the computer, and it should work.
In addition to the answer of Swapnil, note that you can modify the maximum length of the Path environment variable - which is otherwise limited to 2048 characters (while a single path has an historical limit of 206 characters).
In Windows 10, you achieve this by setting the LongPathsEnabled registry key to 1, which can be found here:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem
To access the registry editor: Windows key + R, type Regedit.
Source: Windows 10 “Enable NTFS long paths policy” option missing
Also take a look at this Super User answer: An answer to Windows 10 “Enable NTFS long paths policy” option missing
Note that the error "Environment variable is too large" is related to the whole variable, not the single path currently being added (to answer the "inaccurate advice" comment below).
Additional note: app compatibility
The text in the registry key/group policy related to LongPathsEnabled reads:
Enabling NTFS long paths will allow manifested win32 applications and Windows Store applications to access paths beyond the normal 260 char limit per node. Enabling this setting will cause the long paths to be accessible within the process.`
The caveat here is the term manifested. In general applications need to declare capabilities explicitly in a manifest file; most win32 applications since the days of Windows Vista are manifested. To use long paths, the app manifest needs a longPathAware element:
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
<ws2:longPathAware>true</ws2:longPathAware>
</windowsSettings>
</application>
More info here.
Some users complained that LongPathsEnabled is not yet supported by Windows Explorer and other apps, although in general working alternatives can be found. For example, in this forum post an user states that
The only explorer alternative that does support long paths and long file names is total commander. It also allows to edit file names and open/process the files IF the accepting application also uses the extended API function.
Notepad seems to. MKVtoolnix too. Also, very surprisingly, MPC-HC, even though it hasnt been in development for years. Not surprisingly, sucky VLC does not (seriously?) and neither does the lovely PotPlayer.
There is also an interesting SuperUser discussion on this. In particular, this answer describes two feasible alternatives to use long paths: using Cygwin (a *nix emulation layer) or splitting the long path using NTFS Junction Points (essentially a link, like a symbolic link).
I changed all the paths to variables for Program Files and programdata (this one saves like one character, though not as important).
For something like Node.js, I changed the normal path of
C:\Program Files\nodejs\
to
%ProgramFiles%\nodejs\
This can be done with "C:\Program Files (x86)" as well using "%ProgramFiles(x86)%".
It saved me a few characters, but enough that it stopped complaining, I feel.
I found you can do it via PowerShell.
[System.Environment]::SetEnvironmentVariable("PATH", "C:\Program Files (x86......etc.....", "Machine")
So I grabbed the existing system PATH, pasted into Notepad, added my new thing, and then pasted into the "C:\Program Files" bit of the above. Path was updated. Done.
Apparently Rapid Environment Editor will do this for you (from Shital Shah's answer), but you can also shorten the paths to their 8.3 filename version. You will get a lot of mileage with just these two replacements:
C:\Program Files --> C:\PROGRA~1
C:\Program Files (x86) --> C:\PROGRA~2
If you copy your current path into Notepad, first search and replace C:\Program Files (x86) and then C:\Program Files.
Workaround:
Please restart the system. After restarting the system, PATH is no longer empty, but it may get truncated to 2047 (4095) characters
If the system restart does not help, please:
Launch C:\windows\system32\regedit.exe. Go to the registry hive "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" and clean up unnecessary directories from the “Path” key. Restart the system.
Note: In some exceptional cases if the system is not able to start, please:
Login in the safe mode
Open the command prompt shell and type:
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path /t REG_EXPAND_SZ /d ^%SystemRoot^%\system32;^%SystemRoot^% /f
For more details:
Limitation to the length of the System PATH variable
In addition to other methods (e.g., PowerShell), I found a nice GUI, "Rapid Environment Editor" that can handle larger text values.
You can also try going through your variables to see if there are any irrelevant paths you could delete. This would free up some space for you to add another or more variables.
So I figured out the same problem I had, I noticed there were many duplicates pointing to the same location.
I removed the duplicates which can be done with the delete option when you go click the "edit Environment Varibles" button.
You could instead edit text, copy the text from there, remove duplicates using any popular apps like notepad, excel (use the delimiter as ; then remove duplicates), or use python (use .split(";"), convert into a set, ";".join(stringSet), copy into a notepad file, then replace \ with \ using the ctrl+ H ie find and replace).
I had exactly the same problem. Eventually I had to delete one of the existing variables to make the total length less than 2047.
Then I could add %MAVEN_HOME%\bin to the path variables.
Workaround: Use the Edit text button and edit your PATH in a text editor.
I found this AutoHotkey script useful, for editing or adding to my extremely long path (3743 chars now):
https://gist.github.com/roblogic/59898966f3ce594eb78a5b6147013194
(I'm not sure what the consequence of such a long path is; I may still have to fix it.)

Is it possible to make the eclipse workspace path change per computer

I'm trying to make my eclipse 'portable' (on a USB, workspace and program included) but, because some random guy said that drive names don't count and that the drive has to be designated as a letter given by each computer, I have to change at least 7 paths every time I use a new computer.
I'm sure it's possible but I'm just too new at programming to make a 'mod' that can do that.
My computer is a WINDOWS 7, and I'm using Eclipse with ADT.
Thanks in advance!
You can just use Eclipse's Path Variables instead of absolute path in your Eclipse settings. For example, you can reference something relative to Eclipse home folder like so:
${ECLIPSE_HOME}\..\someFolder
instead of doing
Y:\someFolder
That will work assuming someFolder and Eclipse folders are in the root of your USB stick.
This should work for most of the paths you can set in your Eclipse/project preferences.

how to add an external library to Visual Studio project RELATIVE to solution?

Is it possible to add a path to the project VC++ Directories to load a external library but have the paths relative to the solution root?
I ask this as I work off a USB that I work on at home and take to uni, and at uni I am always on different systems (witch ever is free) I would like to works wit ha external library, but every time i sit at a new computer I need to set everything up...
I am looking for a way to place the entire external library inside a dir in my solution folder, and then set the project paths relative to that.. so were ever I load the solution, on any system. it can still find the library and compile.
It is possible using subst:
Map your library dir to a virtual drive:
subst Z: C:\dev\lib\
From Visual Studio, direct references to Z:\ (e.g.: Z:\some.dll is actually C:\dev\lib\some.dll)

Proper usage of the windows user profile directory

I need to create a directory inside a windows users 'home' directory (c:\Documents and Settings\someusername\ or c:\users\someusername\). This directory will exist permanently but will only contain temporary files.
What is is the best location for this directory within the users profile if I want to be a good citizen? I should note that my program will be run by (possibly) non-admin users and will only need access to their own profile, but they must have permission to create the folder.
Using My Documents\NameOfMyApp\ is possible I guess, but that seems intrusive.
Is there a better location for this type of data, and a specific MFC call to access it?
I'd consider using the AppData directory. You can get its location with SHGetSpecialFolderLocation passing it CSIDL_APPDATA; (or a number of alternatives -- nearly every version of Windows adds a new replacement for SHGetSpecialFolderLocation, SHGetSpecialFolderPath, or (often) both).
Take a look at the following win32 calls:
GetUserProfileDirectory
GetAllUsersProfileDirectory
GetDefaultUserProfileDirectory
You probably want to use GetUserProfileDirectory and put your data in a sub-directory with your appname.
You will definitely want to use the function because there is no "\documents and settings" folder on vista and up, they changed to it "\user".
Being a good application citizen, you should use:
[drive]:\Documents and Settings[username]\Application Data[AppName] or
[drive]:\Documents and Settings[username]\Local Settings\Application Data[AppName]
(On Vista and Win7, "Documents and Settings" is replaced, most sensibly with "Users")
The environment variable USERPROFILE will provide the, you guessed it, User Profile Path.
The TEMP path provides the path to the user's individual temp directory
If the temp files aren't user-specific, you could use C:\temp
EDIT: If you are to use a user-specific location, I highly recommend that you use the environment variables (USERPATH on XP and 2000) rather than hard-coding the paths.
-Waldo
P.S. Thank you for asking this. I see bad behaviour from Waaaay too many applications. The root of the C: drive is not where you should be dumping things! At the very least, (test for the presence of, creating if necessary, and) use C:\Temp.

MoveFileEx with MOVEFILE_DELAY_UNTIL_REBOOT deleting rather than moving

I have an automatic update system that replaces my existing program files on reboot. (Suffice to say, it's a very complicated program with many drivers, services, and user level modules. There really is no other way. Trust me.)
The function MoveFileEx is used with MOVEFILE_DELAY_UNTIL_REBOOT to setup this file replacement. I'm finding that it works just fine, normally. However, if the source and target files are on different drives, the target is deleted but the source is not moved. The result is that when the user installs the software on a drive different from the system partition, an update deletes the product file rather than update them.
Now, I see in the documentation for MoveFileEx that MOVEFILE_COPY_ALLOWED should be used when moving a file from one volume to another. But it also says that flag cannot be used with MOVEFILE_DELAY_UNTIL_REBOOT.
Q: How can I move a file on reboot, overwriting an existing file, when the source and the target are not on the same volume?
Why don't you just copy the files to the drive where the user installed your program?
As far as I see there is no direct way to do what you want relying only on this function.
Finding writable location on the same drive might be a problem on Vista, but you mention you have services - if they run with LocalSystem privilleges have them write the new files.
One other simple update mechanism that I have used ( not working for drivers though) is to have dedicated update program - kill/end everything, let the update program do its work and start everything up again.

Resources