Select custom components to uninstall on Inno Setup uninstaller - delphi

I made installer with Inno Setup. It consist of multiple executables all located in Program Files "APP" folder. But for every executable there's different subfolder in this "APP" folder.
Because every executable is different from purpose, I want to create uninstaller where I can choose, which component I want to uninstall (for example Change button in Add/Remove programs). At the moment uninstaller removes all the applications.
One option is to create different installer for every component and then create installer that contains other installers, but this is too weird.
Is it possible to create custom uninstaller with option to select which component I want to uninstall?

What seems that you need is a modify/repair setup option to your application's setup, right?
Take a look in this extension named UninsHs
Note: Searching in Google I've found another newer version in other site, but I am not sure if it is legit.

It is possible to do in the Inno uninstaller but it won't "fit in" with the wizard style, and will require showing your own forms, and cancelling the uninstall when you've removed the bits you want.
An alternative is to use the setup (which is slightly better suited for this) and handle components being ticked and unticked.
Both of these will require fairly extensive [Code] being written though.

Related

How to combine MSI files created with WiX in differnet languages to one file where yo can select the language?

I have a Windows Installer XML (WiX 3.5) project and five localization files for my installer. Therefore WiX creates five .msi files, for every language one. How can i put all in one .msi and let the user select the language when executing the installer?
I heard something about a bootstrapper, but then i would have a Setup.exe and i need a msi file. Is it not possible to adabt the localization strings after compiling with WiX?
This can be done using transforms. Please take a look at this article:
http://www.installsite.org/pages/en/msi/articles/embeddedlang/
There are 2 parts to making this happen,
localisation of the Installer UI, and/or
choice of installed files.
The method I chose will automatically select the local (or near local) language, and can also be forced to a specific transform using command line options. This doesn't prompt the user to choose which language to install in - so maybe it doesn't actually meet your needs.
The second 'installed files' doesn't seem to be documented as well and I was recently asking about it in Why would MST not include files with different content.
As a response provided there is now an ANT build script using Windows7 SDK & antdotnet

Need to create a compiled delphi app that can make a separate compiled app

I need to make an app that will let users select some options, click a button, and a separate compiled app is created. Is this possible? I am using delphi 7 and 2010.
Thanks for the replies. Here is a little more info.
It would have to be a graphical app and create a graphical app.
What I want is the user to fire up 'App A' (I originally made), be able to select some options (I apologize for the secrecy. I think this is a million dollar idea that probably 3 people may find useful :) then use the program to create 'App B.' 'App B' can then be distributed to end users and 'App B' is a single executable that includes a compiled app plus the configuration data. I don't care how, but I need 'App B' to be a single executable.
I wouldn't even need to use Delphi for the final compiled app. If there is some sort of "pseudo-compiler" that I can call from Delphi that would marry a precompiled exe and a separate config file into a single executable. That would work just fine as well.
Thank you for the replies and help.
Thank you.
I also faced a similar situation once. I had to produce an exe using my exe. I didn't want to go the compiling a source code because of complexity and license problems.
Lets call the parent app P and child app C. Also lets assume that whatever option C needs can be summed up in a config file (XML/INI etc). What I ended-up doing was:
Create P and C. Inserted C in resource data of P.
When user clicked the button after selecting options, P would extract C from its resource data.
Created an XML file containing the options selected by user and inserted it in C's resource data.
So whenever C will run, it will use the options given in the XML file stuffed in it. It looks like complicated and hacky but is reliable and simple. Do a google on "delphi embedding resource in exe" and you will find plenty of articles to do above.
It is possible. You will need a Delphi 7 (or compatible) compiler (command line at least) on the target machine. You will also need all the source code for the compiled application and that includes all the third party libraries if you use any.
When you have it all set just call the command line compiler (DCC32.EXE) with the proper parameters and paths.
You can use two approaches for this:
Call ShellExecute
Call CreateProcess
You will have more control over the execution with CreateProcess. Also you will have to watch out for legal issues and licences if you plan to use the compiler this way.
Given that the Delphi compiler can't be redistributed, one solution if the user has not a copy of Delphi may be to use a script engine (i.e. RemObjects PascalScript, but there are others), generate code for it, and embed that code (i.e. within a resource) in an executable that will execute it when launched.
Create a separate stub executable that implements all the logic you need, and that reads its configuration from its own local resources (look at the TResourceStream class to help you load a resource at runtime).
Include that stub executable as an RCDATA resource in your main app's resources when it is compiled.
At runtime, the main app can extract the stub executable from its resources when needed, save it to disk, and insert the necessary configuration data into the stub's resources using the Win32 API UpdateResource() function.
Without knowing more about why you think you need to do this, I assume you don't actually need to do this. Given the stated requirements, I'd simply have one app, written in Delphi, that looks for the existence of configuration data (.ini file, registry, etc..) In the absence of this, it presents a screen that "will let users select some options, click a button". Then the options are stored in a .ini file, and the rest of the program proceeds, making use of those options.
Alternately, I'd use some pascal scripting, such as provided by TMS.
If you are looking for a way to crank out custom-branded versions of an app, maybe use Inno Setup with a ResHacker step. i.e. gather requirements in Inno, spit out your .exe into a temp directory, use ResHacker to modify the .exe, copy it into the program folder.

How do I run all projects in a project group?

I have a project group containing two projects that share one source folder,but do different things.What I find strange is the use of 'project group',but I don't want to turn this a subjective question,thereby I directly ask you:
How do I run all the projects in a project group - is there a short way?
Thank you in advance!
Actually, all of you are wrong. You can debug multiple programs at the same time.
I don't know when this was first implemented, most probably when the project groups were added to the Delphi, but I'm using this since "forewer" and I'm sure that at least Delphi 2005 was capable of doing it.
In short:
Create a project group with two programs.
Build them all! You won't be able to use the compiler after you start the debugger.
Activate the first program (double-click on its name in the Program Manager) and press F9 (run).
Activate the second program in the Program Manager (you cannot use the drop-down next to the "Run" toolbar button for that as it will become disabled in the previous step) and press F9.
Voila! You have two programs running under the debugger. You can set breakpoints in any of them and they will work just file.
This approach works with any number of programs. (There may be some hardcoded limitations but I've never run into them.)
The debugger can debug only one application (actually: Process) at the time, and if you run from the IDE it is in the debugger.
So I think the answer is : you can't.
Well, I guess unless you count dlls that are launched in the same process, but are individual projects. (seeing the other post), but I never tried that.
To run all the projects at once, add a new batch file to your project group. Make the batch file run each program, and when you want to run them all later, simply choose the batch file in the project group and run it. This isn't the same as debugging all the projects, just running them. It's simply a way to automate the procedure given in Bruce's answer.
You can only debug one project at a time, but you can run as many as you like from the IDE without debugging.
Shift + Ctrl+ F9
Update: I stand corrected. You can debug multiple projects at the same time. Excellent for debugging a client and a server at the same time.
The projectgroup is a tool to build multiple projects.
You can select build all from here to build them all.
You can run several from within the debugger if one is a program and the others are dlls that are used by the program.
Multiple programs's can't be run/debugged at the same time.
Although you can use a program as a DLL but I'm not sure if the IDE can handle that use. In that case you can use a main procedure which is the only thing called from the main program. Then you should export this main proc. Create an additional exe project that calls all of them from different threads. I have not tested this. And it is a hack, but it could probably work.
But why do you want to run/debug several apps at the same time?
As a side note: Check all dependent projects (right click on project -> Dependencies) to have them build automatically before debugging.

In Delphi, should I add shared units to my projects, to a shared package, or neither?

This question is similar to this one, but not a duplicate because I'm asking about issues not discussed in that question.
I have a client-server project in Delphi 7 with the following directory structure:
\MyApp
\MyClientApp
\MyServerApp
\lib
There are 2 actual Delphi projects (.dpr), one each in the MyClientApp and MyServerApp folders.
The lib folder has .pas units that have common code to the client and server apps. What I'm wondering is if I should include those .pas files in the client and server projects? Or should I create a package in the lib folder which includes those units? Or should I just leave the .pas files sitting in the lib folder and not add them to any app/package?
What are the pros/cons of each approach? Which way is "best"? Is there any issue with having those units from the lib folder be included in more than one project?
Right now the units in the lib folder are not a part of any app/package. One disadvantage of this is that when I have my client app open in Delphi, for example, and I want to search in all files in the project for something, it doesn't also search in the units in the lib folder. I get around this by opening those units and doing a find in all open files, or using grep search (but I'd prefer a better solution).
I would also greatly prefer a solution where I will not have to go and open some separate package and recompile it when I make changes to those files in the lib folder (is this where I should use a project group?).
Sharing units between applications always carries the risk of incompatible changes done in one application that breaks the other. On the other hand, making copies of these units is even worse, so your approcach of moving them to their own subdirectory at least adds a psychological barrier to changing them without considering other programs.
As for adding them to the project files: I usually add some units which I frequently access (either for expanding or for reference) from the IDE to the project, and leave others out for the compiler to pick using the search path. I do that on per project basis, that means, some units may be part of several projects, why not?
Putting them into a package only makes sense, if you actually want to create a package based application, otherwise, why bother?
For more info on how I organize my projects and libraries, see http://www.dummzeuch.de/delphi/subversion/english.html
I dislike having files shared by projects. All too often, you'll be tempted to edit one of the shared files, and you'll either break something in the other project, or you'll forget that you have to rebuild the other project at all.
When the shared files are instead separated into their own library (package), then there's a little extra barrier to editing them. I consider that a good thing. It will be a light reminder that you're switching from project-specific code to shared code. You can use project groups to let you keep every together in a single IDE instance. arrange the library projects ahead of the executable projects. The "build all" command will build everything in order, starting with the first project.
Keep your DCU files separate from your PAS files. You can do this easily by setting the "DCU output directory" project option to send your package's units to some other location. Then put that destination directory on your other projects' "search path." They'll find the DCU, but they won't find the PAS file, and so no other project will accidentally recompile a unit that isn't really a member.
Having a separate package also discourages use of project-specific conditional defines. Those cause all sorts of trouble when you're sharing units between projects. Find a way to instead keep all project-specific options within the respective projects. A shared library shouldn't require project-specific modifications. If a library needs to act differently based on who's using it, then employ techniques like callback functions that the library user can set to modify the library's behavior.
I would need to have a very good reason to add shared code to a package. If you just have a few shared files stick them all in a directory called Shared. This should make it obvious the files are shared between projects.
Also use a good build tool to do automated builds so you will find out soon enough if you break something.
.bpl files are fine for components, but bring in serious added complexity for things like this, unless you have a huge amount of shared files.
I usually create a package with all shared unit, and just use the units.
If you do not explicitly mark "Build with run time packages" the package content (all used dcu's) will be linked to your project as any other unit.
I would only use runtime packages if you actually had two binaries that were supposed to run on the same physical machine and that shared some code. Keep in mind that runtime packages are mostly an all-or-nothing approach. Once you decide to use them you will also no longer be able to link the RTL and VCL units straight into your projects and will instead have to deploy those separately as well.
However, packages might still be a good solution to your problem when combined with project groups which is exactly what I'm doing. I hate having shared units included in multiple projects. Including the shared units in a package (but not compiling your actual projects with runtime packages) allows you to add that package to your project group so you (and the IDE!) will always have them easily accessible yet nicely separated from the project-specific code. Strictly speaking you don't even ever have to compile those packages. They can merely serve as an organisational unit in the project manager.
Note that for the Find in Files, you can also specify "in all files in project group"

Organizing the search path

We create via "Tools | Options | Environment Variables" Variables like that:
$(Sources) = D:\Sources\Delphi
$(OurLib) = $(Sources)\OurLib\Src
$(OurApp1) = $(Sources)\Applications\App1\3.x
$(ThirdParty) = $(Sources)\ThirdPartyComponents
We use these Variables in the project search path like that:
($OurApp1)\Src\Core;($OurApp1)\Src\GUI;($OurApp1)\Src\Plugins;$(ThirdParty)\JVCL
But this is broken (meanwhile fixed) since Delphi 2009 as these variables are not evaluated completely anymore (see QC #73276). So the files in the directories are not found by the compiler. A workaround: Use only complete directories in the environment variables.
We use this approach because on all developer machines and the build servers the files can be found and we only have to point $(Sources) to the right place.
We don't have anything in our global library path (except the Delphi defaults), because that wouldn't be in the version control and isn't reflected on other developers or build machines.
One problem is: If one unit in $(OurLib) decides to include another new unit maybe in a new path, all projects break because they don't find this new unit. Then we have to go through all projects and add the search path. (BTW: I really hate the search path editor...wouldn't be a simple memo field much better to edit than this replace/add/delete logic?)
Another thing we do is not adding many units to our project. Especially everything from $(OurLib), but we often have units like plugins which add functionality only by including them. For different editions of our products, we want to include different units. As Delphi always messes up $IFDEFs in the uses clause in the .dpr we help us by including units named like "IncludePlugins" which then include the units depending on IFDEFs.
But not including units in the project makes navigating to a pain. The units don't appear in the project, they are not found by Ctrl+12 (Show Units), they are not shown in code completion etc.
Has anybody a better way to cope with these problems?
We use only relative paths, any libraries are always below the libs subdirectory while the project source code resides in the src subdir. So our search paths always look like:
..\libs\library1;..\libs\library2\common;
etc.
All libraries are added as svn:external to each project, so checking out the project will automatically check out the libraries as well and the search path will always point to the correct version of the library for that project.
Not perfect, but it works most of the time.
I have to agree about the search path editor, it is even worse for relative paths because you must not use the "..." buttons otherwise Delphi will insert an absolute path.
We use standard drive mappings.
Our current project is always on W: regardless if it is a network drive or a substitute.
This works great.
When you need to work on a different project, swap the W: and you can continue.
You can copy the search path out to an editor, modify it and then copy it back.
Your search path is much too big. It should contain only the things you want Delphi to recompile with your project. You don't really want to recompile the Jedi VCL every day, do you?
I create a single directory where all compiled units go. Say, C:\dcu. Specify that as the "unit output directory" in all packages. My "search path," then, is always just this:
$(Delphi)\Lib;C:\dcu
The compiler finds everything it needs, and it never finds any source code. The only source code it ever sees is in the files that directly belong to whatever project I'm compiling. The project's own source directories don't need to be on the search path because all of those files are already direct members of the project. The compiler knows exactly where they are.
For me, all a project's source files go in a single directory. If you want separate directories for different parts, like Core and GUI, then I would put those in separate packages so I could work on them and compile them separately. Even if the final program doesn't use the resultant BPLs, packages are still a good way of segmenting your project and defining dependencies.
When compiling units for one project doesn't automatically compile units for all the other projects, you're forced to change active projects. It takes a moment of your time, but it also serves as a mental reminder that you're "changing hats," too.
Although you're producing just one product, that doesn't mean you should have just one project in Delphi. You should have at least one project for each executable module (EXE, DLL, BPL) in your product. Use project groups to manage multiple projects in a single IDE session. No unit should be a member of more than one project.
I don't understand your part about plug-ins and different editions of your project. When you say "plug-in," I assume you're talking about separate executable modules, like DLLs or packages, that the customer can choose to include or not. Couldn't you turn your different editions' features into plug-in modules that simply don't include in the lesser editions? Then you don't have to worry about conditional compilation of your project; just have several different installer packagers that grab different sets of plug-ins.
I have always found it odd that this has never been addressed adequately. I suggested recently to David I that Delphi should allow the user to set up some sort of preferred development structure and that third party library publishers could be made aware of this so that they could automatically adjust their installers to install correctly in the preferred development framework. If the preferred development structure was stored in an XML file or similar, then, it could be copied from one computer to another on a development team.
As an alternative, it could make an interesting project to create a Delphi application that would allow a user to "refactor" their library installation in a high level way. You specify which folders on your system contain source or compiled components or whatever and where you want to keep source files or compiled units, hit Go and your system gets rearranged for you, while updating your Delphi environment so that when you start Delphi, it finds everything it should.
I've just recently discovered a way to have project specific environment variables in delphi builds using XE6, it's not quite as good as a full blown #define like in C but at least I can now have consistent search paths across multiple projects and create some shared option sets.
What I've done is setup environment variables in the same manner as the original poster and then override them in the dproj or optionset.
The BuildPaths.optset added to the project looks like
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SVN_Root>..\..\..</SVN_Root>
<SVN_Riemann>$(SVN_Root)\Riemann</SVN_Riemann>
<SVN_Library>$(SVN_Root)\Library</SVN_Library>
<SVN_ThirdParty>$(SVN_Library)\Third Party</SVN_ThirdParty>
</PropertyGroup>
<ProjectExtensions>
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
<Borland.ProjectType>OptionSet</Borland.ProjectType>
<BorlandProject>
<Delphi.Personality/>
</BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion>
</ProjectExtensions>
</Project>

Resources