I have a Visual Studio Setup project which includes a .SQL file from my project which should always overwrite the existing file if I run the installer on the same machine to update to a new version. The problem is that doesn't always seem to happen. Under File System > Application Folder > File Installation Properties, which property would tell the installer to always overwrite the existing .SQL file on an install?
The upgrade is an install of the new files on top of the older files, during which file overwrite rules are followed. The rule for data files is that they will not be overwritten if they've been updated since they were installed. If you've installed a database that's now full of customer data it's usually a bad idea to just replace it with a new empty database:
https://learn.microsoft.com/en-us/windows/desktop/msi/neither-file-has-a-version
Among the ways to solve your problem are:
Update the existing file with the new data using a custom action.
Avoid the problem in the first place by having the installed file copied to a location where it can be used, updated etc by the application. The original can then be overwritten by the upgrade, and the application detect that there is a new one to use, that it copies to replace the previous copy. It maybe too late for this.
Have the application make the creation date and modify date of the file have identical values so that the upgrade will think it's not been updated.
Install the new file to a different location (and use 1. from now on). The older file will be removed by the upgrade.
Edit the MSI file (with a tool like Orca) to move the location of RemovePreviousVersions (in the InstallExecuteSequence) so that it is immediately after InstallInitialize. This will completely remove all of the old files before installing the new ones, so it won't help if you have that database full of customer data mentioned in the opening paragraph.
Related
I have a fairly large application (~750k LOC) that I distribute using the Package and Deployment Wizard. I fully understand that it would be nice to migrate to .NET (that ain't happening - see the code size above), and that the PDW is deeply flawed. However, for the most part I've made it work well for my end users, by customizing the Setup1 application, writing a menu-driven wrapper for the Setup application, and by running it in silent mode. (Note that the problem I'm about to describe occurred even before I started using silent mode.)
The issue I'm having is that my application requires quite a few auxiliary files, which I've added to the PDW project in the "Included files" section. When a user does a clean installation (either from scratch, or after un-installing a previous installation), everything works fine. However, if they simply run the installer to update the existing installation, the executable file and any OCXs I've updated get copied over the previous versions just fine, but my auxiliary files don't - I have to have the user manually delete them, and then the Setup1 program will re-install them as it should.
I've checked in the Setup.lst file, and all of the files are listed there, with their current date stamps. In fact, in my "BuildAll.bat" file, I do the Windows equivalent of a "touch" (copy /b "TheFile.dat" +,,) to force the date stamp to be current. However, if the file exists on the target machine, it won't be over-written even though it's older. There are no errors reported, either visibly or in the .LOG file (which is required if using the silent option).
A couple of additional points: Some of the auxiliary files are themselves VB6 applications - just the .exe files. Those do get copied correctly if they're newer than the existing files. Other than being files with internal versioning information, there's no difference between them and the other auxiliary files (which are things like media files, or text-based .txt or .dat files).
So, what's going on, and how do I fix it (besides moving to Inno or some other solution that won't work for me...)? Thanks in advance for any help!
~~
Mark Moulding
I have a visual studio installer (vs2015) that installs an application. I want it to also install a set of configuration files, the contents of which vary by physical install location, that will be delivered as a cab file in the same directory as the msi. The cab has a known set of files that will be distributed across 2 folders in the install location and is created by a different project than the installer. How do I get the msi to install both its internal contents and the contents of the external cabinet file?
Wise Package Studio
I actually successfully updated MSI files with new files to install using Wise Package Studio back in the day. It added a CAB file to the Cabs table (I don't know if this table is actually a Wise "view" or a real MSI table - it seems missing from Orca if all CABs are embedded in the MSI). There is a corresponding entry in the Media table where the LastSequence value (in the Media table) describes which CAB contains what files. In the File table you will find a field called Sequence which specifies the "order" of the files listed. Essentially your new files will be at the end of the "order" and hence in a new CAB. A bit involved the whole thing.
However, I successfully got Wise Package Studio to both embed a new CAB file, and to use an external CAB file to install the new files during installation, but I don't have the procedure documented and don't recall all the steps. Moreover I don't recommend the procedure - in fact I would never use this approach now. It was just used at the place I worked at the time. In most cases we used a transform to add this content to the main package, rather than hacking the MSI itself.
MSI SDK: Including a Cabinet File in an Installation
The procedure to add a CAB file to your MSI is documented in the MSI SDK here: Including a Cabinet File in an Installation. Quite involved - as I said, but definitely possible. As you will see the lack of a # flag at the start of the CAB name in the Media table indicates an external CAB file.
So I suppose, in short:
Add a new entry to the file table, set the Sequence number to +1 from the highest sequence File entry already there. I would add a new, corresponding entry in the Component table as well.
Add a new row to the Media table, specify the number you set for the file in the LastSequence column. Add the name of your cabinet file to Cabinet. Make sure to not prefix the CAB name with #.
Wise would also add entries in the MsiFileHash table. Not sure if this is required or not. Pretty sure it is not required to add entries here.
As you will see in the linked MSI SDK article, you can embed the whole cab following the last few steps listed in the linked MSDN content.
I wish I had time to test all this, but I don't. Which brings me to the next point:
Default / Instantiate Your Settings?
When I see questions like these I invariably ask myself: what is in these files? Are they "trivial settings" that could actually be defaulted instead of hard coded in config files? This has saved me a lot of work, many times.
The deployment of settings and data files have always been problematic with both MSI and legacy style installers. My philosophy of deployment for such files is to treat what you install as "read-only" and then you copy them to per-user locations or set them in HKCU on application launch, using some sane process of obtaining appropriate values (from settings written to HKLM during installation, retrieved from the user, retrieved from the Internet, etc...). Please see this longer answer on the subject: Create folder and file on Current user profile, from Admin Profile. The best approach, in my opinion, is to retrieve settings on launch from an online database (as you will see if you read that linked content), but that is involved.
It's not clear precisely what you mean, but you cannot alter the MSI to unpack all the files in your separate CAB as if they were in the MSI as the other files are. There is too much internal data on the files inside the MSI file, in the file table, component table, and so on.
So if the CAB file is in the same location as the MSI file then you could create a custom action to copy it to the target system, and unpack if you want. The copy can be told where the MSI location is by using the [SourceDir] property or the [OriginalDatabase] property OriginalDatabase property
You'd parse that location to get the path and then do the copy to the TARGETDIR location.
We have different dev environments between developers here. When I build, I want my compiled files to be copied to a bin folder located in C:\Web\bin\. Another developer may want those files dropped in C:\Web_2011\bin\.
Using Visual Studio 2010, the way we work this now is to run a BAT file with the directories defined as parameters that need to be changed if pulling from another developer's branch.
Is it possible to store a solution-wide parameter, (in a .user or .suo file maybe,) to define where a developer wants to drop his builds?
You could do it through the project file (.vcxproj for C++ project for example).
The simplest solution would be to add a Custom Build Step that runs some batch file. This batch file could check the current user name and copy the files based on that.
(An even simpler solution would be to run a user specific batch file from his local disk)
If you really want the fully fledged solution that will allow you to save this data to the user file, you can do it by editing the project file and adding a PropertyPageSchema element that extends VS property pages with another parameter (your destination directory). You can define the Persistence attribute of DataSource element as "UserFile" and the data will be saved on your .user file. You will need to add some target that actually uses this data (copies files to the directory specified).
For more information, read about msbuild and PropertyPageSchema.
I am developing a package using Installshield 2008 Primer Edition and Project type is Installscript MSI project.
The problem I am facing is during installation I am installing some of the files to the following location C:\Program Files\Company\SystemFiles from this location I am copying and adding the set of files into System32 folder, it contains DLLs and OCX files, copying into the System32 folder has been done using Installscript.
Due to this during uninstallation, the installed file is getting removed from System32 due to this other dependent application which requires the same set of DLLs have stopped working.
I have approached Installscript to copy files from ProgramFiles to System32 Folder rather than using built-in options because we have an issue during the upgrade in order to avoid that I am using Installscript.
Even I have tried several workarounds like setting the file attributes after file copies to System32 using Installscript like FILE_ATTR_SYSTEM which sets the system attribute but still files are getting removed during uninstallation.
Any idea how to give file attributes as PERMANENT or SHARED; will this help, and if it will, then how can I set it using Installscript?
I have 2 ideas
1)I think you can use SHARED option as this wont remove the files while uninstallation.
2)Also when i was facing similar issue , what i did was putting all the required files in the installation directory itself so that while uninstalling only the installed files will be removed.(I know this is not a best solution)
(NOTE:I have worked on Install shield some 6 years back and so remember only certain things)
You can also disable logging from Install Script. This will make the installer "forget" that it installed specific files groups or features.
You should make sure to enable logging once again after you have copied the files that you want to permanently leave on the system.
If you don't remember to enable logging after you have disabled it, your uninstall process may not work correctly.
Syntax is as follows:
Disable(LOGGING);
//Add code to copy your permanent files here
Enable(LOGGING);
For InstallScript projects:
To prevent the files in a particular Component from being removed during uninstall:
1-Select the Components view from within the Organization folder.
2-Select the component that contains the files you do not wish to remove during uninstall.
3-Change the "Uninstall" property in the right pane to a value of "No."
For MSI Projects:
To prevent the files in a particular Component from being removed during uninstall:
1-Select the Components view from within the Organization folder.
2-Select the component that contains the files you do not wish to remove during uninstall.
3-Change the "Permanent" property in the right pane to a value of "Yes".
I see this is an old question but I just came across this. Seems to be a common problem. One good solution is to stage the files to a private directory mostly program files and then have a custom action do the copy and register (ocx etc). Installshield remembers what it copied so it tends to remove them. Do not disturb anything else like logging (my recommendation). Set conditions on the custom action so that it doesn't run during Uninstall.
Although sometime back I did another weird implementation which only programmers are used to doing.. Packed the files as resources and created my own code to extract and deploy (Something that Process Explorer kind of tool does). There were certain use cases that warranted this kind of implementation. But again this is complicated and obviously reinventing the wheel. Unless you are good with C/C++ and Windows API this would be difficult. I would still suggest you stay away from this kind of implementation because it is also considered a "virulent behavior". Yet, so far I never got warnings from the Anti-malware products.
I've got a Setup & Deployment Project in VS2005. One of the files that i'm installing is a SQLite data file.
I'm about to release a new version for the software, but i found that if i run the update on existing installation it overwrites the data file.
I've got an updated data file in the setup project so it's newer than already installed, but i don't want to overwrite it.
I've tries setting the Permanent property for that file to True, but to no avail.
Any suggestions?
Ok, here's a workaround that i've used:
In my setup project I've renamed my blank database file from Database.db to Database-blank.db.
In my app i'm checking if Database.db is missing and copying Database-blank.db to Database.db if it is.
then just load existing Database.db
This way i can ensure the local copy of the data file (Database.db) does not get replaced by newer versions of the software.
In MSI, the best way would be to make a record in the Upgrade table, determining whether this is an upgrade installation, and setting a property if it is. Then put the data file in a component, and place a condition on the component. Alternatively, make an entry in the AppSearch table, checking for the presence of the file (through the DrLocator table).
I don't know whether a Setup & Deployment project supports any of this. So as a fallback, install the file with a different name, and then create a custom action that copies over the file conditionally.
Because VS2005 setup when upgrading a program first it remove the original installed instance
and then install a new one, so for that the file will be removed every time.
to avoid replacing or overwriting the file I suggest the following:
1- mark the file as readonly in the setup project.
2- mark the file as permanent in the setup project.
now after upgrading the file it will not be overwriten, but your application can't deal with this file because it's readonly, so in the startup of your application check if the datafile is readonly uncheck it.