I am making software setup package, and previously I am using Inno Setup, and it works very good.
The current issue I met with Inno setup is, it does not support all languages for the setup UI, for example Simplified Chinese.
The setup project of VSTS 2008 supports almost all languages, but it does not support invoke another installer from the current installer to let end user install dependent software packages.
My program to publish is for Windows platform (Vista and XP), written in C# + VSTS 2008 + .Net 2.0.
Any advice for my problem?
thanks in advance,
George
As one of the comments to your question suggests, you may want to simply integrate the required language into your Inno Setup. You do that by adding the Languages section:
[Languages]
Name: "en"; MessagesFile: "compiler:Default.isl"
Name: "nl"; MessagesFile: "compiler:Languages\Dutch.isl"
This allows the UI to be displayed both in Englisch and Dutch. Other translations can be added accordingly.
The fact that Windows Installer does not allow "nested installations" (running an MSI from an MSI) can be annoying. You might, however, consider packaging the MSI installers into an UI-less (= silent) Inno Setup and have Inno Setup run the MSIs one by one.
EDIT
This shows you how you may run the EXE files to install your dependencies. Please note that they might be installed after your software. If it is required that they are installed before your software, you may need to code a little Pascal Script - this is explained in the help files.
[Files]
DestDir: {tmp}; Source: .\Files\sample.exe; Flags: deleteafterinstall;
[Run]
Filename: {tmp}\sample.exe; StatusMsg: Installing prerequisite
This includes file .\Files\sample.exe into the setup, copies it to the TEMP folder upon installation and removes it after the setup is done. Then, after copying your files, it runs TEMP\sample.exe and waits for it to finish.
EDIT 2
Regarding the OP's comment on the order of the items in the [Run] section:
There are two possible cases:
You're using Inno Setup to perform the actual installation of your software (copying files, registry entries, etc.) and additionally need to run the installers for the prerequisites.
You've got a separate installer for your software as well, and just need Inno Setup to run the installers for the prerequisites AND your software.
For case 1:
You do not need to put the your EXE file into the [Run] section at all, except you'd like to allow the user to start your application after setup as seen in many setups using a checkbox ("Run XYZ now?"). In that case, use the following line for your EXE:
Filename: {app}\yourprogram.exe; StatusMsg: Run the application; Flags: postinstall skipifsilent unchecked; Description: Run the application now
For case 2:
I'd order the entries in the [Run] section according to their dependencies. That is: first entry is the one that some others depend upon, last entry is your application setup. But I'm not sure about the order in which the entries are handled.
This might be answered in the docs for the [Run] section. When in doubt, try asking Jordan Russel (Inno Setup's author) for advice - he's a nice guy and when I last mailed him he was pretty quick replying.
Related
I'm looking for a way to add new pages to installer with its own interface. Ultimately, I would like my installer to do many things in turn, enabling the user to go to the next pages and check or set subsequent configurations.
But at the moment I'm looking for how to add an additional page that would run before installation and check if the computer has the required programs to install the application. I would like to attach my ready code to c # to check if these programs are installed on the given computer.
By using this tutorial:
https://www.youtube.com/watch?v=6Yf-eDsRrnM&t=7195s
I created the basic version of the installer. In the tutorial we create installer by using WixUI_Minimal.
I have looked through the documentation and it is written that you can create your own pages, but I can't find anywhere. For example there
https://wixtoolset.org/documentation/manual/v3/wixui/
is Customizing Built-in WixUI Dialog Sets but they dont show how do that.
Update 21th April 2020
I have created a public GitHub Gist, which explains the steps and even include a customized Dialog PrerequisitesDlg.wxs with up to 5 Prerequisites, which can be configured as WiX Properties (text and condition). The whole sequence is wrapped in WixUI_KargWareFeatureTree.wxs.
Text before 20th April 2020
The element you need is UIRef Element, Wix Toolset v3 Documentation.
Wix Toolset is an open source project, so you can review it on GitHub, Wix Toolset v3.
The dialoges which are embed in Wix Toolset are listed here, Source Code of the Default UI-Dialoges of Wix ToolSet. I would use the WixUI_Advanced one, but you can pick all others or start even from scratch.
Download the WixUI_Advanced.wxs from GitHub
Copy the wxs file to the root of your msi-project (where the *.wixproj os placed) and name it to e.g. MyWixToolsetPages.wxs
Edit the name of the UI xml element inside MyWixToolsetPages.wxs (near to line 50)
Add the MyWixToolsetPages.wxs to your wixproject
Replace or add the UIRef reference element in the product.wxs to <UIRef Id="WixUI_MyWixToolsetPages"/>
Add your new dialog as <DialogRef Id="myNewPage" />
Customize the order of the pages with Control Next / Back and Event NewDialog
Be aware to test your sequence in both directions (next, next, next, end) and (end, back, back, back)
Change <UI Id="WixUI_Advanced"> to <UI Id="WixUI_MyWixToolsetPages"> inside your MyWixToolsetPages.wxs (copied from the original WixUI_Advanced.wxs)
...
<UI Id="WixUI_MyWixToolsetPages">
...
Replace the UIRef inside the product.wxs
...
<UIRef Id="WixUI_MyWixToolsetPages"/>
...
I maintain an open source wix authoring tool that enables you to do this by uncommenting one line of XML. The trick is to insert additional rows into the ControlEvent table causing existing paths to be overridden.
https://github.com/iswix-llc/iswix/blob/master/Application/IsWiXNewAddIn/MSISolutionTemplate/SetupProjectTemplate/UI.wxs
https://github.com/iswix-llc/iswix/blob/master/Application/IsWiXNewAddIn/MSISolutionTemplate/SetupProjectTemplate/UI-CustomDialog.wxs
Overall Advice: It is generally an anti-pattern - as of this IT-epoch - to do too much with your setup GUI. In particular it is
better to do per-user configuration as part of the application launch.
Rule of Thumb: You should limit setup-GUI to genuinely shared settings that need to be written with admin or elevated rights to
per-machine locations (inaccessible for normal users). Set everything else from application launch. This can also help QA personnel with their testing.
Burn: Burn is the WiX toolkit's setup.exe creator. It is a bootstrapper, chainer, downloader, installer, etc... construct. Hello-Burn sampler here. And about replacing Burn's default GUI.
WiX MSI GUI: I have a minimalistic sample here for how to change your MSI installer GUI: https://github.com/glytzhkof/WiXCustomDialog. This is the GUI embedded inside your actual MSI. There are other possibilities with GUI.
GUI: You can replace the GUI inside each MSI with a GUI from a Burn setup.exe. There are some details here. This GUI you can implement as a normal executable with all the bells and whistles that allows. The MSI GUI is rudimentary and old. There is another answer here on how to change installer GUI.
The problem is following: I have my custom uninstaller called before MSI uninstall. After shutting down my application properly it calls msiexec to use Windows Installer to uninstall MSI.
It's done by executing something like "msiexec /x{PRODUCT_CODE} /promptrestart".
And here is important thing - if the system is not restarted after uninstallation, and then the user installs the app again, some of its files will be deleted after next restart, so it's not acceptable. The restart is required, however, I need prompt, automatic and unconditional restart is evil and should never ever be used.
So, the invocation above displays STUPID "uninstall / repair" dialog. I do not want it. When I use "msiexec /x{PRODUCT_CODE} /qr /promptrestart" - then it uninstalls nicely, however it refuses propt for restart afterwards.
I have read about setting ARPNOREPAIR property.
But the idiots who gave that answer wouldn't care to say WHERE and HOW that property could be set. Even... Where the property belongs, it's the property of what? MSI file?
Then, maybe is it another way to achieve this, like invoke the prompt for restart from my code, but... how? The uninstaller should remove all my files until that moment. Maybe it's possible to execute a kind of script after the uninstallation process is complete?
(One more problem, the Windows Installer doesn't delete ALL files and directories created by my app. It would be nice if I could execute some code to clean up better.)
UPDATE
I see 2 paths ahead: make a script to be run once the uninstallation ends (like using Registry or Task Scheduler or IDK), use Win32 API to modify MSI file, because AFAIK it's possible to change its properties that way.
Questions: Some questions first.
Restart Manager: Are you familiar with the Restart Manager feature of MSI? Intended to help shut down and restart
applications without the need for reboots. I would give it a quick
skim? I think this is your real solution?
Alternative MSI Tools: There are many tools available for creating MSI setups. This link also contains further links to a summary of the shortcomings of Visual Studio Installer Projects.
Using the free, open-source WiX toolset - for example - you can change MSI dialogs. Github sample. SO question 1. SO question 2. And here is the official WiX toolset site.
Adding my own answer from SO: Changing text color to Wix dialogs (please do skim)
I am not familiar with how to change dialogs in Visual Studio Installer Projects. Commercial products Advanced Installer and Installshield can certainly change dialogs.
Services: What is the nature of the product you are installing? Does it has a lot of services for example? Services can be shut down and restarted via MSI tables if you use a proper tool to build the MSI.
REINSTALLMODE: Do you use a custom REINSTALLMODE for your setup? (some settings can cause more reboot prompts).
Custom Uninstaller: How do you invoke that custom uninstaller of yours? Manually or do you register an uninstall command line with Add / Remove Programs? (this latter approach is not recommended).
ARP Applet vs MSI Dialogs: The ARPNOREPAIR property is set in the MSI itself - in the property table. It affects only what is seen in Windows' Add / Remove Programs applet (ARP = Add / Remove Programs), and not what you see when your MSI is invoked via command line. Then you see the dialogs defined in that MSI itself (which can be changed - not entirely trivial to do).
ARP / Add Remove Programs Applet: A quick review of this applet below:
Hold Windows Key and Tap R. Type: appwiz.cpl and press Enter. This opens the Add /Remove Programs Applet.
Select the different package entries in the list to see different settings for ARPNOREPAIR, ARPNOMODIFY, etc...
If ARPNOREPAIR is set in the MSI's property table then the Repair entry is missing.
If ARPNOMODIFY is set in the MSI's property table then the Change entry is missing.
If ARPNOREMOVE is set in the MSI's property table then the Remove entry is missing.
If the special ARPSYSTEMCOMPONENT property is set, then the MSI will be missing from ARP altogether.
Links:
In-use files not updated by MSI-installer (Visual Studio Installer project)
So, there is an "ugly hack" which solves the exact problem:
First - we need an executable, that isn't affected by the installer. This one is easy, we just copy that one installed exe to a TEMP directory and run it from there.
The next step is to that file must wait unit the uninstall phase is done. There are a couple of ways of doing so. You can observe the installer process, you can observe the file system if main program file is deleted. Considering the pace of common installer operations, polling once a second is a good enough option.
The next step is optional - you remove remaining files created by application, empty directories and such.
The next step is reboot itself, MessageBox.Show() from PresentationFramework is fine to ask user, when user answer OK or YES, then reboot itself can be performed in many ways, I use ExitWindowsEx() from user32.dll since it's probably what msiexec calls internally.
Here's example code:
if (MessageBox.Show(RestartPromptMsg, "", MessageBoxButton.OKCancel, MessageBoxImage.Exclamation) == MessageBoxResult.OK) {
NativeMethods.ExitWindowsEx(
NativeMethods.Flags.Reboot,
NativeMethods.Reason.MajorApplication | NativeMethods.Reason.MinorInstallation | NativeMethods.Reason.FlagPlanned
);
}
Of course some parameters could be passed to our special clean up executable, so it could do some extra things, like skip the restart prompt if it's not really required.
The last step is to delete our executable itself. It's easy, but it's tricky. Again I hope my example code would help:
var cleanUpTempPath = Path.Combine(Path.GetTempPath(), CleanUpExe);
File.Copy(CleanUpPath, cleanUpTempPath, overwrite: true);
Process.Start(new ProcessStartInfo {
FileName = "cmd",
Arguments = $"/c (\"{cleanUpTempPath}\" -purge \"{InstallerDir}\") & (del \"{cleanUpTempPath}\")",
UseShellExecute = false,
CreateNoWindow = true
});
We use cmd.exe special feature, the power of & and (). Commands separated with & gets executed when previous command exits. So when our clen up exe completes, it's gets deleted by the same cmd instance which called it. Remember to quote all paths, they can contain spaces. Remember to enclose a command with arguments in parentheses, because otherwise the & operator would be seen as a parameter to the previous command, not the cmd.exe.
I tested it in my big production application and it works as charm. The code examples don't work when just pasted, if you're looking for complete code, just google for it, there are plenty of working examples on pinvoke.net and StackOverflow.
I'm writing a .NET 4.0 based ActiveX control for IE7+. I have to manage an interface with a key-reader device. I followed some great tutorials and articles about "how to do" it, and currently is working well.
My problems started when I wanted to deploy an other version of my control.
I'm using VS2010 with setup deployment project and cabarc for the .CAB. The 1.0.0.0 version went well. Currently I would like to get the 1.0.2.0 version working, and it is doing its job well, but IE always prompting for an install. Again and again.
What I did:
1: Changed the AssemblyInfoVersion.cs to version 1.0.2.0
2: Changed the .inf file according version to 1.0.2.0
3: Changed the .msi version to 1.0.2
And I changed the OBJECT tag in the HTML page to #version=1,0,2,0
So far so fine. It is installed! I can see it under the "Uninstall Programs", the version of the control is 1,0,2 ! Great, but the IE still wants me to donwload and install it every time when I open the page.
I saw a thread connected with Excel: How to get COM Server for Excel written in VB.NET installed and registered in Automation Servers list?
And I got usefull information about I should change something in the registry. I did some search there, and I fould my classId under :
HKLM\SOFTWARE\Wow6432Node\Classes\CLSID{GUID}
I have here the following subkeys:
InstalledVersion
Implemented Categories
InprocServer32
ProgId
I was happy, because I saw, that in the InstalledVersion part the version still 1,0,1,0. I changed it to 1,0,2,0 and... it did not worked. I serched through the registry, now everywhere the InstalledVersion is 1,0,2,0. The .dll version is 1,0,2,0. The installed control's version is 1,0,2. Under the InprocServer32 I have all three 1,0,0,0 ; 1,0,1,0; 1,0,2,0 versions. And of course in the HTML code the version is also 1,0,2,0.
(My machine is 64 bit Win7, IE9)
Could anybody help in this, what I missed?
Other problem with this whole scenario: After the version increase by the first install my dev machine is rebooting without any question. Do you have any idea what kind of settings can make this behavior?
UPDATE:
The problem solved. I'm kind of blind or just a bit tired because of this.
But the problem is may important for the future:
First a summary about the issue:
After a new version was deployed (installed well on client) the IE was always propting for install the version.
The problem source is in the registry. You should have the rigth version number in the InstalledVersion(Default) registry key.
I had a very special case here (and I don't know the cause yet), but I had two entries with (Default) under the SubKey InstalledVersion. The firs one was empty, the second one contained the rigth value. I could not delete the first one, but the second one only. After I changed the first (Default) everything worked find!
The second problem with the automatic restart solved too.
This thread helped: MSI installer with Silent or Passive mode will automatically restart computer without prompt for user sometimes
Have to add the /qn /norestart or /promptrestart to end of an msiexec call, because without this flag the windows automatic restarts itself without questioning.
If somebody has a similiar issue, then here is the solution in my case:
[RunSetup]
run="""msiexec.exe""" /i """%EXTRACT_DIR%\KeyReaderEngineInstaller.msi""" /qn /promptrestart
According to Microsoft Documentatation:
/promptrestart
Prompt before restarting option. Displays a message that a restart is required to complete the installation and asks the user whether to restart the system now. This option cannot be used together with the /quiet option.
You can either use /qn /norestart or just /promptrestart. In my case, just the IE had to be restarted, instead of the whole operational system. Therefore, I use /qn /norestart
I am desperately trying to deploy an ActiveX for IE developed in C# as a CAB archive. I have read many resources (some of them from StackOverflow) and it appears a lot of people are having the same problems. I have tried 3 solutions: a) creating a CAB VS project, b) manually creating a CAB using CABARC with a COM registration in INF and c) manually creating a CAB with launching msiexec. None of them worked. I even tried d) creating a bootstrapper which launches msiexec to no avail (because some people suggested simply launching msiexec on Vista can't work).
I am running Windows Vista but my project fails to run even on IE6 on XP.
When I install ActiveX using MSI, all is fine on ALL Windows. Apparently CAB thing is not working and I could not find a proper way to debug this whole process yet.
Any help is appreciated.
Update: Note that this old but excellent answer is still a very good outline for how to approach solving this problem, at least as along the evolutionary scale as Win7 and IE11. I just succeeded making it all work using the Answerer's Firebreath.org toolset as a jumping off point. It's not simple but it can be done. I've added a reference to that project to the reference list below since it may make a more logical jumping off point for current developers than this overview is.
Hooray - I have just finished an identical project, so you'll be pleased to know that it's actually possible. I have only tested this on XP - I understand there may be issues where Vista/7 don't allow msiexec to be called.
Given that you have an assembly correctly exposing a COM interface, I did the following:
Strong-named the assembly.
Created an INF file
Created an MSI using the Visual Studio 2008 "Setup Project" template.
Created a CAB file using "iexpress.exe" bundled with Windows XP.
Create INF file
The *.inf file I used looks like:
[version]
signature="$CHICAGO$"
AdvancedINF=2.0
[Setup Hooks]
install=install
[install]
run=msiexec.exe /package """%EXTRACT_DIR%\SampInst.msi""" /qn
The only bit you should need to change is the SampInst.msi. Note I would use an 8.3 filename, as long filenames can cause issues. While testing, I would not use the qn switch either, as that is a silent install.
Create the Installer
The installer has to do only one thing, and that is register the assembly by calling RegAsm on it. Most installers will provide some method to easily do this. For example, an installer created through VS 2008 will simply need to have the “Register” property of the assembly set to “vsdrpCOM”. Note that vsdrpCOM should be chosen as it generates the appropriate registry entries at build-time. The vsdrpCOMSelfRegistration setting is likely to fail as it calls RegAsm at run-time, and will thus not work for non-administrators.
Package the installer into a CAB file
This can be done by any cab archiver. Windows XP contains iexpress.exe, a wizard driven archiver, while Microsoft’s CAB SDK contains cabarc.exe. Other 3rd-party tools are also available.
Note that you will need to reserve space in the CAB file for code-signing if you are going to sign the CAB.
You will need to CAB the INF file, and the MSI file. You will not need to CAB the Setup.Exe file.
Handy hint: The VS2008 Setup Project project type allows you to set a post-build step in the properties, so you can build and CAB in a single step. My post-build step looks like:
cd "$(ProjectDir)"
"%WINDIR%\System32\Makecab.exe" /f "VboCslib.ddf"
The DDF file format is documented.
Sample HTML page
The object tag is used to point to the cab file containing the installer. A very simple HTML page which would deploy an ActiveXControl would be:
<html>
<head></head>
<body>
<!--
ID : The id of the ActiveX control to be used in JavaScript.
CLASSID : The GUID associated with the ActiveX control.
CODEBASE: The location containing the CAB installer for the ActiveX
control. This could be a URL, or a relative path.
-->
<OBJECT ID="MyActiveXControl"
CLASSID="CLSID:FC36FAE1-48E0-4f6b-B469-E1B5A8C6D1AC"
CODEBASE="cabfiles\SampleCabFile.CAB#version=1,0,0,0">
</OBJECT>
<script>
MyActiveXControl.SomeMethod();
</script>
</body>
</html>
Handy hints
Ensure your installer installs on a "per-user" basis, not a "per-machine" basis. This will make it more likely to install if the user does not have admin privileges.
Trouble-shooting
Internet Explorer 6 actually provides a really useful diagnostic aid. Clear your Temporary Internet Files, then navigate to the web-page. If the installation does not work, go to your temporary internet files and you will see a couple of files in there. One of these will be an error log starting ?CodeDownloadErrorLog. Drag it to your desktop and open it in notepad, and it will give details on what it was trying to do when it failed.
References
Microsoft KB247257 – Steps for signing a .cab file
MSDN – About INF File Architecture
SN.EXE - Code Strong Programs with Strong Names
Nikolkos Craft – How To: Deploy .NET ActiveX Control
CodeProject – Create ActiveX .NET Step by Step
CodeProject – Downloading C# ActiveX Components through CAB file
MSDN - ALLUSERS Property (Windows)
MSDN – Non-Admin ActiveX Controls
MSDN – Microsoft Cabinet Format
Update: Firebreath.org has a toolset for generating browser plugins for many platforms. The IE/ActiveX code to solve the problem posed here is just a subset. But as of 6 Nov 2014, I found it easier to start with Firebreath and its instructions than to try to build up my dev environment and roll all my own solutions from scratch.
I have a Deployment Project for my VS2008 C# application. When installing a new version of my application I want to make sure that files are updated with the files contained in the installer.
I want my installer to automatically remove any old version of the installed application. To do that I follow this procedure (also described here):
Set RemovePreviousVersions to True
Set DetectNewerInstalledVersion to
True
Increment the Version of the
installer
Choose Yes to change the ProductCode
For the assemblies I make sure the AssemblyVersion is set to a higher version:
[assembly: AssemblyVersion("1.0.*")]
Everything is working as intended except for my configuration files (xml files). Since I cannot find a way to "version" these files I cannot make sure that the files are updated if they have been modified on the target machine.
Is there any way to do this and how?
UPDATE: I have tried the approach/solution/workaround found here
Include the file directly in a
project with the following
properties: "Build Action -> Content
file" and "Copy to Output Directory
-> Copy always"
Then add it to the deployment
project via Project
Output->Database->Content Files
Unfortunately it did not make any difference. The behavior is exactly the same.
Add the following property to the Property table of the MSI:
Property REINSTALLMODE with Value amus
Note: This will cause all the files in the MSI (versioned and nonversioned) to overwrite the files that are on the system.
If you're willing to use Orca (there may be another way to do this method, but it's the only one I know of) you may be able to set up RemoveFile directives.
See here for a typically light-weight MSDN document -- could be a starting point.
http://msdn.microsoft.com/en-us/library/aa371201.aspx
Alternatively you could always create a very simple bootstrapper executable that simply calls "msiexec /i REINSTALLMODE=oums" (or whichever command-line switches are needed). Call it setup.exe if you like...
Better option long-term may be to switch to InstallShield or similar -- VS2010 includes a light version of IS and I believe they're moving away from vdproj projects.
Have you tried the approach/solution/workaround found here?
Include the file directly in a
project with the following
properties: "Build Action -> Content
file" and "Copy to Output Directory
-> Copy always"
Then add it to the deployment
project via Project
Output->Database->Content Files
I may be incorrect here, and therefore I am exposing myself to down votes, but here goes anyway!
I believe it is on purpose that config files do not automatically get overwritten; the principle there being that you would not normally want your application's configuration overwritten when you install the new version of the program... at least not without numerous warnings and/or chances to merge configuration first.
Having your application configuration get overwritten by an updated version of a program could make for a very upset end user (in this case, web site admin).
Further, I know that sometimes, the developer may be the person doing the deployment. In such a case, this behavior might not seem so logical when deploying a single site to a single server; but when roles are split and/or you have multiple servers with different configurations, this can be a life saver.
You need to include the new version of your files in your custom installer and manually install these file during Custom Install routine is called
This must be applied to any file that does not have version that can be tracked by the installer.