How to setup Installer project with conditional file copying - visual-studio-2010

I am building a VS 2010 installer, and I want to copy files to app folder depending on what options I select in UI (UI is not simple, so the only option is to show custom dialogs in Install custom action).
The problem is that custom action is actually executed after files are copied already.
One possible solution I can think of is to install all these files into the app dir, and then delete some unnesessary files in custom action. But these files are "secure" in some way, so I don't want to copy them to filesystem, even for a short period of time.
Any thoughts?

If your files shouldn't ever be on the filesystem, you have a problem in the requirements. The .msi storage itself is an open format and can be read by many tools, so if someone knows the file it's possible for them to find and extract it manually.
I agree that it's better to avoid deleting the files after they've been installed for two reasons. One: it avoids wasted work, and two: it won't cause repair scenarios due to missing files that Windows Installer thinks should be present. You should probably figure out how to determine whether these files should be present at an earlier stage of the installation, and set properties that cause this to happen (disable components by condition, or change feature states).

Most controls in MSI dialogs use installer properties. For example, a checkbox may use a property named MY_CHECKBOX which is set to a value or it's empty, based on whether the checkbox is checked or not.
These properties can be used to condition files:
select your setup project in Solution Explorer
click File System Editor button from Solution Explorer top pane
select the file you want to condition
in its Properties pane set Condition field to the condition you want, for example
MY_CHECKBOX = "value"

Related

Installshield problem setting file permissions

in InstallShield 2011, I cannot modify file permissions under Application Data -> Files and Folders. Whenever I right click on items, it shows grayed out menu buttons. I can't even delete existing entries.
In a bat script later in the installer, I can't copy over certain files because I don't have the right permissions so the installer fails when trying to reference files in BackupFiles. For some reason all the other files get copied over just fine; I can't modify those file's permissions either. I read online that you have to click the "Properties" button in that context menu to change permissions.
My version is InstallShield 2011 Premiere Edition Version 17.
I don't understand why this is grayed out. The source files do not have any restrictions on them so it must be the installer doing something related to permissions.
That boxy orange overlay on the folders and files indicates that these are coming from a Dynamic File Link. Because these files aren't actually added to your project, not all configuration options are available. You might have to edit the permissions on the source files (before build), or change your project to statically include all or some of these files. Given the size of that tree, changing it all to static could be a bit tedious. Changing parts of it (by editing the link exclusions) might be a good middle ground.
Or you could better determine what's going wrong and see if you can address it in the batch file. Assuming this is InstallScript (rather than InstallScript MSI), the entire setup along with any processes it launches should be elevated. So I'm having a hard time guessing what could go wrong. Perhaps a read-only flag? Perhaps use a tool like process monitor to get more information on that, and see if you can add a call to attrib -r, or cacls, or whatever.

Mark a large number of files as Build Action "None" in Visual Studio

I have a folder containing 12000 images. When I add them to my project they get marked as Resources, but I want to set their Build Action to None. If I select them all and go to the Properties tab and set None, VS starts working and engulfes itself.
Is there another way to do that? Or a way to set the default Build Action for newly added files to None?
Thank you!
Make a backup of your project file (e.g. by committing it to a branch in source control locally) before making manual changes to the file.
Right click the project node in Solution Explorer and click Unload Project.
Right click the project node in Solution Explorer and click Edit yourproject.csproj.
Replace all instances of
<Resource Include="Resources\
with
<None Include="Resources\
Save and close the project file.
Right click the project node in Solution Explorer and click Reload Project.
Optionally you could also remove all instances of these lines and use the following single line instead. You'll definitely want to mark your place in source control so you could undo the change if it doesn't work out like you expect.
<None Include="Resources\**\*.jpg"/>
12,000 files is a good two orders of magnitude beyond what you can reasonably expect to be performant during a build. Just checking if files need to copied can easily take 5 minutes on a spindle drive. Still uncomfortable on a solid-state drive.
You'll need a drastically different approach to solve this. Key approach is that you don't wait for it so cannot get annoyed at the delay. Like spinning this off into a separate project that builds a resource DLL, not included in the solution. Preferably done on another machine, build servers are good for that. Or a completely different approach to packing the files, like sticking them in a ZIP archive. A "wad" in gaming speak of old. Or taking your program to the files instead of the other way around, keeping them stored on disk and telling your code where to find them with a configuration setting.

MFC Menu won't propagate into application

I'm working on making slight changes to a legacy VS 2008 & MFC project, including changes to the WinAPI/MFC *.rc resource file. I have made those changes, e.g., changing a menu string (for IDR_MAINFRAME, if it matters) from "New Scan" to "New Organism" on one computer, commited to VCS, and tried rebuilding the project on another, practically identical configuration (not sure if relevant), which is when I ran into problems.
Currently, I have
changes to the menu from within the VS resource editor that do not propagate into the application (old values remain)
changes to the about dialog that do propagate into the application
an RC file that contains no mention of "New Scan"
no file, including binaries, containing "New Scan" (though, as mentioned, this might be due to encoding)
I have
cleaned and rebuilt
manually cleaned and rebuilt
deleted the *.res file and compiled just the *.rc file into a *.res just to make sure the paths there are alright
modified the configuration so that (Project -> Properties -> Resources -> Command Line) has an absolute path to the *.res file.
verified that the current module is indeed the exe being executed via GetModuleHandle
verified that all calls to FindResource and LoadResource pass NULL as the current module, meaning the resource should be loaded from the exe
verified using ResEdit that the resource within the exe contains "New Organism", even though it shows "New Scan" when run. I verified the #define for the resource is the same number as the number reported by ResEdit. Verified there's no other similar resources in the exe.
verified that I'm running the same exe I'm inspecting and tried running it from both the IDE and from Windows Explorer.
inspected all (two) non-system DLLs that get loaded (as reported by the output window and dependency walker) using ResEdit and both of them belong to a 3rd paty library and none of them contain any menu resources (they only contain manifests).
tried changing/removing the command that loads the menu (CFrameWndEx::LoadFrame) and verified it forces the application to fail.
verified that having an IDR_AppnameTYPE MENU with a second copy of the menu doesn't help (see thomiel's answer below)
Using google
To no avail. I am especially unsure where the original string, "New Scan", is coming from and how come changes to my about dialog propagate and changes to the menu don't. How do I make the changes to the menu propagate to the *.exe itself?
In case of a SDI or MDI: Not only change IDR_MAINFRAME but also IDR_??????TYPE, which is the menu displayed when you have an open document.
I have had the exact same problem. This is going to sound crazy, but if you create a SUB menu in the menu item, and then delete the APS AND RES files, and then SAVE ALL and to a REBUILD of the ENTIRE SOLUTION, you should be OK. Please contact me if you have any other questions. I'm happy to help.
It seems that MFC will cache the menu items in registry when you quit your application. To prove it you can copy your program to a new machine and runs it. If it displays the modified menu items normally, it means MFC uses cached menu items on your own machine.
You can clean the registry key to make your modifications take effects. The registry entry may locate at
HKEY_CURRENT_USER\Software\Local AppWizard-GeneratedApplications\MyMFCApplication1
-or-
HKEY_CURRENT_USER\Software\{your company}\{your project name}\Workspace
based on the MFC version.

Visual Studio Setup Project - conditionally install file

I have a VS 2008 Setup project. I only want to install an XML file if it does not already exist on the target system. The installer overwrite rules for non versioned files ensure that a file will never be overwritten if it has not been modified on the target system. But I want to never overwrite the file. There is a Condition property that can be set on a file in the Visual Studio installer properties for a file. What is the correct syntax for the Condition property to check for existence of file and only install if it is not there?
You will need to go to the Launch Conditions tab and search the target computer for the file you want to check for. The launch condition will let you specify the name of a property it will set to the path of the file if it exists, otherwise it will be empty. You can now use this property as the condition on your file.
I was able to use a launch condition to set a property, and use this for a conditional install of a file, so I will mark 'heavyd' as the correct answer. However, was not able to use the file search effectively, as was suggested (see comments on the answer). Instead, I used a Windows Installer Search (one of the three types of searches available in a VS 2008 Setup Project) with the MSI ComponentID, as follows (I found the technique here):
Product 1 is installed and has a file named MyFile.txt.
You use ORCA (from the Windows Installer SDK) to view the File table, and find the row that represents MyFile.txt.
You get the value of the Component_ column and then open the Component Table.
In the Component Table you find the row that has the Component_ value in the Component column, and get the ComponentID. Copy this value into clipboard. Close ORCA.
In your setup project, open the Launch Conditions Editor and add a Windows Installer Component Search. For the ComponentID property of the new search, paste the ComponentID.
Copy the Property property. It should be something like COMPONENTEXISTS1.
Open the File System Editor and select the Application Folder, then select the file you want to conditionally install.
Edit the Condition property to be COMPONENTEXISTS1 = FALSE.
Set the Transitive property to true if you want the condition to be evaluated each time the installer is run (not just the first time).
Now, MyFile.txt will only be installed if it is not already there.
There is one caveat with this technique: Doing a repair on the installation will cause the file to be deleted, even though the file is marked as Permanent! Not good. I worked around this by adding some custom actions (calling vbscript files) to backup and restore my file.
What a hassle to just achieve so simple a task: install a file once on initial install, then, never again overwrite it.
If anyone has a better solution, I am all ears.

How to check out all VB6 Project files from VSS?

I have a VB6 project in Visual Source Safe 6.0. When I open the project I want to Check Out (Get) all the files in the project so that I can edit them.
I have the VSS Options (within VB6) set to act on the Project recursively, but when I check out the project.vbp it only checks out the project file, not all the modules, etc. Those files all remain write protected until I individually check out each one.
SOLUTION: Select the Project.vbp and, from the Tool>SourceSafe menu choose Check Out, you get a dialog which lets you choose ALL files (you get a checkbox for each and a button for Select All).
Why I had problems
For some reason, if you right-click on the Project in the Project tree and choose Check Out it doesn't give you that dialog. It just checks out the Project file. (However, if you do the same thing and Check In, it gives you the dialog with the checkboxes for each file. I guess that that point it knows that you have more than one file to check in.
FWIW generally speaking you get more options when choosing 'Check out...' via the Tools menu as compared with choosing 'Check out' from the right click context menu. One of the more useful 'Advanced' options is to check out with out 'getting' (i.e. replacing) your local file.

Resources