Create allways install/uninstall Component

Aug 2, 2010 at 4:43 PM
Edited Aug 2, 2010 at 4:49 PM
I searched the discussion and found no hint on this so I start a new topic. In our company we have the use case where we need to run a msi installation that is shared between our product during every install and uninstall scenario since it has a custom actions that needs to be executed in any case and it has an own reference counting. (I know it is bad but this came from an old setup technology and the modules the msi installes are installed only one time on the system in a "CommonFiles" folder and are used from there). Since I am starting to migrate to dotNetInstaller the question is if this scneario can be done in dotnetinstaller somehow. This would mean that there must exist an installedCheck that is true if the msi file is installed and that there must be another installed check that is allways false, so the installation gets triggered everytime. I do not know how to do it in dotnetinstaller may be you have any hints of where to start. I am just starting to use dotnetinstaller so please forgive me the (possibly stupid) questions. UPDATE: I tryed with the conditions installedcheck but this so far does not work. I tried with the and and or check and combined a check for productcode and one that is always false... (checking a file version that does never exist on a non existing file)
Aug 3, 2010 at 12:20 PM

I don't understand. If you want a component to install every time - just don't have any install conditions?

If you have a shared set of DLLs that go in some Common Files - create an MSI (preferred) or a merge module that's included in all MSIs for that. Then you don't need any reference counting.

Aug 3, 2010 at 12:52 PM
Edited Aug 3, 2010 at 12:53 PM

If you have an MSI (that's needed for indiviual servicing, so merge module is not an option) and install it multiple times, I have not heard it does any reference counting on that ...

Nevertheless my scenario is that the dlls where installed with a non MSI technology before and that these installations must be taken into account as well.
And as far as I understood it is not possible to have no installed checks in dni and use the uninstall.

Let's try an example: I have product A that consists of DNI components A1 and common1(MSI component) and I have Product B that consists of DNI components B1 and common1.
I now install Product A, which installs component A1 and common1(=>executes custom action customised with parameters for component A1).
After that I install Product B, which must install component B1 and common1(=>executes custom action customised with parameters for component B1)
When I now uninstall Product A with DNI, it must uninstall component A1 and start uninstallation of component common1(executes custom Action => "detects" that there is still product B and "cancles" uninstallation).
At last I uninstall Product B with DNI, it must uninstall componentB1 and start uninstallation of component common1 (executes custom Action => "detects" that there is no furhter products => component common1 uninstall correctly).

So after writing that example I would just need a DNI MSI-Component that installs regardless it is installed or not, since the uninstall should work when the first try leaves the component installs.

It still may sound crazy and I think it should be simplified, but as in most times I am not in the position to decide that.

I hope you understand the situation.

Aug 3, 2010 at 7:21 PM
quirrel wrote:

And as far as I understood it is not possible to have no installed checks in dni and use the uninstall.

That's not true. It's not possible to have automatic uninstall kick-in when all components are installed. But you can run the bootstrapper with /x to make the decision for it that this is uninstall. That's what we do for the uinstall shortcut in my tutorial. Doesn't that solve all the issues you're describing?

Aug 4, 2010 at 7:16 AM

ok, so it seem I did not understand it well. I think my issues are not solved completely. My experience is that if I Installed an MSI component and had no installed check, even launching the bootstrapper with /x brings up the "uninstall sequence". I had to add an installed_check, but then a "reinstall" does not work since the bootstrapper detects that the MSI component is allready installed.....

That is what apears in the log when I run the /x command on a bootstrapper with one MSI component without installed checks:

2010-08-04 08:13:59	-------------------------------------------------------------------
2010-08-04 08:13:59	dotNetInstaller (DNI), version 1.10.1525.0
2010-08-04 08:13:59	Copyright (c) DevAge, Vestris Inc. & Contributors
2010-08-04 08:13:59	Operating system: Windows XP Sp3
2010-08-04 08:13:59	-------------------------------------------------------------------
2010-08-04 08:13:59	Sequence: uninstall
2010-08-04 08:13:59	UI level: full
2010-08-04 08:13:59	-- Loading supported components (lcid=1033)
2010-08-04 08:13:59	-- mysetup.msi (display_name='mysetup.msi', os_filter_lcid=, os_filter=, os_filter_min=, os_filter_max=, processor_architecture_filter=): LOADED
2010-08-04 08:13:59	--- Loaded 1 supported component(s)
2010-08-04 08:13:59	-- mysetup.msi (mysetup.msi): NOT INSTALLED
2010-08-04 08:13:59	dotNetInstaller finished, return code=0
I'll keep up looking for this.

Aug 4, 2010 at 12:57 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Aug 4, 2010 at 1:00 PM

Ok. I get it now. This is bad behavior of the bootstrapper. When a component doesn't have any installed checks, and it supports uninstall, it should just be defaulted to uninstall during the uninstall sequence. I filed a bug. If you want it quickly, you can do it yourself - write a unit test first.

Aug 4, 2010 at 1:13 PM

May be it really is my first fix, but where should I fix it? Is there a branch for 1.10? I think I have to get it to compile first... Is this behaviour still in the htmlinstaller?

Aug 4, 2010 at 1:42 PM

I think Component::IsInstalled should be made aware of the sequence currently run. You can get it from InstallerSession::Instance->sequence. Currently it says:

	if (installedchecks.size() == 0)
		return false;


Unit tests for components are written in C++ (dotNetInstallerLibUnitTests) and for the whole thing are written in C# (dotNetInstallerUnitTests). You need those at all levels.

You can try to fix it on the 1.10 stable branch ( or on trunk, either way. Both dotNetInstaller and htmlInstaller share all the same execution engine.

Looking forward to patches. 

Aug 4, 2010 at 3:55 PM
Edited Aug 4, 2010 at 4:09 PM

so, I managed to get the source code, the msbuild community task, sandcastle, the sancastle style patch (both in 2.6., hope this does not matter), svn cmdline client. I only left out VS2005 since this seemed to be a little overkill since I have 2008 and 2010 Version installed.

So a first try ended shortly, so had a look at build.cmd file and changed path to vcvarsall.bat to take it from VC2008(9.0). And then opened the solution in VS2008 which converted some proj files. This made it a bit better but I am again stuck.
The Build Log when call "build all"  says


               Target GetFrameworkPaths:
                    Could not locate the .NET Framework SDK.  The task is looking for the path to the .NET Framework SDK at the location specified in the SDKInstallRootv2.0 value of the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework.  You may be able to solve the problem by doing one of the following:  1.) Install the .NET Framework SDK.  2.) Manually set the above registry key to the correct location.

and then there are many lines like

"dotNetInstallerDlg.obj : error LNK2001: unresolved external symbol "public: class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> > __thiscall Component::GetDisplayName(void)const " (?GetDisplayName@Component@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@XZ)"

So do I need the .Net Framework SDK???I am downloading it (2.0 Framework), so this should be resolved then. So the issue may be to the VS2005? Is there a way to avoid a installation?

=>Update: installing the .NEt 2.0 SDK did not change anything, still 681 Errors...

Aug 4, 2010 at 4:12 PM

You should be fine converting the project to VS 2008. The reason VS2005 is still used is because VS2008 produces binaries that don't work on Windows 95. Yeah, it's still supported :) You could probably change .NET Framework to 3.5 for your purposes too, otherwise do install 2.0. The other error is probably because dotNetInstallerLib didn't build. You need to look at the first error first.



Aug 5, 2010 at 9:46 AM
Edited Aug 5, 2010 at 12:23 PM

ah, ok, so your support time is even longer than the official (long) MS support times ;)

So anyway, I converted the Project but left .Net 2.0 since it is installed on my machine. If I try to build with the "build all" I still get 681 errors. So I thought "why not build in VS?" => this led to a quite clean build. The only error left is:


Error	4	'dotNetUnitTestsRunner.dotNetInstallerExeUtils' does not contain a definition for 'Location'	D:\Source\DotNetInstallerTrunk\UnitTests\InstallerLibUnitTests\InstallerLinkerUnitTests.cs	337	68	InstallerLibUnitTests


Is this a "bug" in the code? Since all other projects build without errors this seems unclear to me.

edit: is there a easy way to copy the build binaries together? there all reside in the "project\flavour\bin" directories and it is quite time taking collecting all together.... (ok, I could change the output path, but I do not want to change to much...)

Aug 5, 2010 at 2:07 PM

db thanks for the hint of where/how to fix the problem in code.
It seems like I found a way to get it working. I only need to add and run unit tests for this case. So how do I execute them? I think the error above gives me some limitations on execution I think...

What/how should I contribute the patch if done? send a whole sourcecode zip or just the changed files?

Thanks for your help so far, hope I can give something back now.


Aug 5, 2010 at 2:32 PM

I fixed the build break, my fault. If you build the project from command-line (build all), you will get identical output that gets uploaded to the website, including the zip. You can also just run build release which collects everything.

Aug 5, 2010 at 2:33 PM

For patches, there's an upload patch in Source Code. If you have a patch for an existing workitem, attach it to the workitem in the issues tracker.

Aug 5, 2010 at 2:34 PM

For unit tests, you need NUnit. You can open any test DLL with NUnit and run the tests manually. All tests run part of the build as well - currently custom control tests in dotNetInstallerUnitTests are broken, everything else works.

Sep 30, 2010 at 8:52 AM
Edited Sep 30, 2010 at 8:52 AM

so I com back to the "uninstall problem" I have read the tutorial and implemented it the same way. This works well. The only thing that is left is that the user can still use "add/remove" programs to uninstall a MSI Component, which then does not use the bootstrapper.
I know I could disavle the enty, but is there a better way than that? Is it possible to create an own ARP entry for the dotnetinstaller?
any pointers in the right direction are welcome

Sep 30, 2010 at 1:27 PM

We solved this problem by adding a "setup support files" to our bootstrapper (this could be part of your installer, but we have 12 of them bootstrapped). It's a trivial installer that brings a bootstrapper without embedded files and creates an uninstall shortcut to it (setup.exe /x). It could naturally create an ARP entry for control panel's add/remove programs if that mattered. This allows us to remove all the installers from add/remove programs (it wasn't important, we didn't actually do it).

dotNetInstaller could probably make this "trivial" part somewhat completely trivial without requiring an installer. I created a feature request to capture some of this.

Sep 30, 2010 at 1:45 PM

I allready created a "empty" bootstrapper that is installed to the product installation folder and create an shortcut (with cmdline -x) to it, but I thought to have an additional correct ARP entry would not be bad. If I search to uninstall something I also look there....
It would also be helpfull when it comes to maintenance/repair, but thats another story.
I hope the feature gets implemented.

Nov 19, 2010 at 1:31 PM

I would like to have this fix so when you run with /x and no installed checks it actually uninstalls. How can I get it without having to go through all what quirrel did?

Nov 19, 2010 at 1:38 PM

As of today, you would have to write the code ;)

Nov 19, 2010 at 1:55 PM

It appears it's been done in the beta 2.0 release according to this page

Is that true?

Nov 19, 2010 at 3:37 PM

I was confused, I thought you wanted the ARP part. Yes, the issue is fixed, give it a try. Start a new thread if you're having problems.