How to run a setup from another setup? - c#

I have a solution with 3 modules. Windows, Web, and Windows Service. I want to create one parent setup that runs three child setup packages regarding to the user choose.
I created a setup project as the following:
I created a library that contains InstallerHelper which is inherited from Installer class
I added the following code:
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
try
{
FileInfo fileInfo = new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location);
string sProgram = Path.Combine(fileInfo.DirectoryName, "Setup1.msi");
Process p = Process.Start(sProgram);
p.WaitForExit();
}
catch (Exception exc)
{
Context.LogMessage(exc.ToString());
throw;
}
}
The problem is that the windows installer refuses to run multiple instances of windows installer and throws the following error:
Another installation is in progress. You must complete that
installation before continuing this one.
Is my approach correct? Is ther another way to run another setup and the parent setup should wait all of them with one Finish click?.

You can use Wix Burn to create a setup package contained multiple application installers (msi/exe):
Wix Toolset: Building Installation Package Bundles
Neil Sleightholm's Blog: WiX Burn – tips/tricks

Related

Creating an auto updating Windows service [duplicate]

For the project I am working on, I am not allowed to use ClickOnce. My boss wants the program to look "real" (with an installer, etc).
I have installed Visual Studio 2012 Professional, and have been playing around with the InstallShield installer, and it definitely makes nice installers, but I can't figure out how to enable the application to "auto-update" (that is, when it starts up, checks to make sure that it is using the latest version).
I have been asked to make a tiny change to the code - switching an addition to a subtraction, and I don't really want people to have to uninstall the old version, and then have to reinstall the new version every time I make a small change like this.
How can I make the application check for updates, and install them? Or is this not possible (or not easy)?
There are a lot of questions already about this, so I will refer you to those.
One thing you want to make sure to prevent the need for uninstallation, is that you use the same upgrade code on every release, but change the product code. These values are located in the Installshield project properties.
Some references:
Auto update .NET applications
Auto-update library for .NET?
Auto update for WinForms application
Suggest a method for auto-updating my C# program
Automatic update a Windows application
I think you should check the following project at codeplex.com
http://autoupdater.codeplex.com/
This sample application is developed in C# as a library with the project name “AutoUpdater”. The DLL “AutoUpdater” can be used in a C# Windows application(WinForm and WPF).
There are certain features about the AutoUpdater:
Easy to implement and use.
Application automatic re-run after checking update.
Update process transparent to the user.
To avoid blocking the main thread using multi-threaded download.
Ability to upgrade the system and also the auto update program.
A code that doesn't need change when used by different systems and
could be compiled in a library.
Easy for user to download the update files.
How to use?
In the program that you want to be auto updateable, you just need to call the AutoUpdate function in the Main procedure. The AutoUpdate function will check the version with the one read from a file located in a Web Site/FTP. If the program version is lower than the one read the program downloads the auto update program and launches it and the function returns True, which means that an auto update will run and the current program should be closed. The auto update program receives several parameters from the program to be updated and performs the auto update necessary and after that launches the updated system.
#region check and download new version program
bool bSuccess = false;
IAutoUpdater autoUpdater = new AutoUpdater();
try
{
autoUpdater.Update();
bSuccess = true;
}
catch (WebException exp)
{
MessageBox.Show("Can not find the specified resource");
}
catch (XmlException exp)
{
MessageBox.Show("Download the upgrade file error");
}
catch (NotSupportedException exp)
{
MessageBox.Show("Upgrade address configuration error");
}
catch (ArgumentException exp)
{
MessageBox.Show("Download the upgrade file error");
}
catch (Exception exp)
{
MessageBox.Show("An error occurred during the upgrade process");
}
finally
{
if (bSuccess == false)
{
try
{
autoUpdater.RollBack();
}
catch (Exception)
{
//Log the message to your file or database
}
}
}
#endregion
The most common way would be to put a simple text file (XML/JSON would be better) on your webserver with the last build version. The application will then download this file, check the version and start the updater. A typical file would look like this:
Application Update File (A unique string that will let your application recognize the file type)
version: 1.0.0 (Latest Assembly Version)
download: http://yourserver.com/... (A link to the download version)
redirect: http://yournewserver.com/... (I used this field in case of a change in the server address.)
This would let the client know that they need to be looking at a new address.
You can also add other important details.
A Lay men's way is
on Main() rename the executing assembly file .exe to some thing else
check date and time of created.
and the updated file date time and copy to the application folder.
//Rename he executing file
System.IO.FileInfo file = new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location);
System.IO.File.Move(file.FullName, file.DirectoryName + "\\" + file.Name.Replace(file.Extension,"") + "-1" + file.Extension);
then do the logic check and copy the new file to executing folder
This is the code to update the file but not to install
This program is made through dos for copying files to the latest date and run your program automatically. may help you
open notepad and save file below with ext .bat
xcopy \\IP address\folder_share_name\*.* /s /y /d /q
start "label" /b "youraplicationname.exe"
These days you could use included in Windows 10 mechanism for app delivery called AppInstaller by packaging your app in MSIX bundle or package.
With it, you don't have to think about an installer (if your app doesn't use a lot of dependencies), background updating, and all of that. It's much better than ClickOnce, command-line usage works like a charm thanks to aliases, updates are non-obtrusive and could be used for background apps too.
The installation experience is much better too: a user just needs to click a button on HTML and Windows will install the app automatically.
It's not super-simple, I'd say more complicated than ClickOnce, but not as hard as Wix.
Official guide doesn't work with .NET Core or .NET 5 apps, so you can refer to this article, or to this great video, for example. This site also contains a lot of useful information.

Username/Pass request during WinService installation

I have done a test Win service to make sure I have the Installer project (which is the part of that project and is set to InstallShield Limited by default) works fine.
I've searched for the correct manual and did the same as it was suggested:
Pls, see the WinService Installation class definition:
Then I tried both ways
1)
2)
Then I successfully build the Installation project and get the setup package..
As you can see everything is set to be installed under the Local user..
But each time I run the installation pask it asks for credentials..
My question is: how to avoid that dialog during installation?
Actually, I found the solution by myself.
The start point should be: To make yourself sure that the service is installable manually using InstallUtil.
In my case I mistakenly named ServiceName in AfterInstall event, when engaged Service Controller.. missed letter "1"
private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
{
using (ServiceController sc = new ServiceController(serviceInstaller1.ServiceName))
{
sc.Start();
}
}
After that I changed the settings in InstallShield Project..
1) I dropped the added service at screen Way#1
2) Add InstallClass as it shown on Way#2
The request of the credential was because inside the service itself, I missed setting LocalSystem for Property Account of Service Process Installer in the Design Mode.
So, now it works..

Start windows service on install without setup project

I have developed a windows service, but need it to start automatically on install. Problem is that every tutorial I found is showing me through the Setup Project. There is a fantastic 3 part tutorial HERE that I used to convert my app to a service, but I don't have the Setup Project in my other project types. Can I do this programatically or is there a way I can get the Setup Project project type?
In your Installer class, add a handler for the AfterInstall event. You can then call the ServiceController in the event handler to start the service.
public ServiceInstaller()
{
//... Installer code here
this.AfterInstall += new InstallEventHandler(ServiceInstaller_AfterInstall);
}
void ServiceInstaller_AfterInstall(object sender, InstallEventArgs e)
{
using (ServiceController sc = new ServiceController(serviceInstaller.ServiceName))
{
sc.Start();
}
}
Now when you run InstallUtil on your installer it will install and then start up the service.
MSDN link for more details
I believe Topshelf project has built-in service Installer/Uninstaller. when integrated in the application, it can be installed as a service through simple command from application itself, for example we can easily install and start myService.exe with myService.exe install start command.
we can simply create a self installing service, here is an Example:
public class ServiceClass
{
public ServiceClass()
{
}
public void Start() { }
public void Stop() { }
}
public class Program
{
public static void Main(string[] args)
{
//we can simply install our service by setting specific commands for same or install it directly from command line or from another process
if (args.Length == 0)
{
var processName = Process.GetCurrentProcess().ProcessName + ".exe";
var install = Process.Start(processName, "install start");
install.WaitForExit();
return;
}
HostFactory.Run(x =>
{
x.Service<ServiceClass>(s =>
{
s.ConstructUsing(name => new ServiceClass());
s.WhenStarted(tc => tc.Start());
s.WhenStopped(tc => tc.Stop());
});
x.RunAsLocalSystem();
x.SetDescription("Topshelf Host");
x.SetDisplayName("TopShelf");
x.SetServiceName("TopShelf");
});
}
}
you can get Topshelf through PM> Install-Package Topshelf Nuget command.
Best thing to do is to add on the Installer Projects Extension!
The Setup project type was deprecated after VS 2010, but following feedback Microsoft have brought back a new version for VS 2013.
Install the new Installer Projects Extension from Microsoft: https://visualstudiogallery.msdn.microsoft.com/9abe329c-9bba-44a1-be59-0fbf6151054d
This should work for any non-express version of Visual Studio 2013 (including the new free Community Edition SDK)
Then you can just follow the same instructions as for the VS 2010 setup projects :)
There isn't an easy option for VS2012 (you could try an installer with WiX I guess, but thats a lot to learn!)
I'm not sure if InstallShield LE (free version for VS2012) would work for this situation, but you could give it a try.
You can always change the startup type of a service after installation remember. (Control Panel -> Administrative Tools -> Services -> right click service -> Properties -> change "Startup Type" to "Automatic" )
If you are targeting Windows 7 and up, Powershell is installed by default. One option is to run a simple powershell script which installs the service, starts it, and sets the service to start automatically if the machine is rebooted:
InstallUtil yourService.exe
Start-Service yourService
Set-Service yourService -startuptype "Automatic"

How to get the installed application location in c#?

I have created a WPF application in my application i'm specifying the default path for the installation location suppose, XYZ is my application, "C:\MyApplication\XYZ\" this is my specified default location where my application gets installed, my application creates a folder dynamically which will be created during the installation of the application in the installed directory, i want when user uninstalls the application then my entire folder(XYZ) has to be deleted i tried many ways but i'm not getting it Please any one give suggestion it will helps me a lot.
Here is what i have tried :-
string filepath = String.Format(#"data\local", Environment.CurrentDirectory);
public override void Uninstall(IDictionary savedState)
{
try
{
base.Uninstall(savedState);
// If i Hard code this i.e if i give direct path(C:\MyApplication\XYZ\)
// then it's getting deleted but if user installs application in other
// location it gets fail.
Microsoft.VisualBasic.FileIO.FileSystem.DeleteDirectory(
filepath,
Microsoft.VisualBasic.FileIO.DeleteDirectoryOption.DeleteAllContents);
}
catch(Exception e)
{
MessageBox.Show(e);
}
}
Application installation is not something that we need to manage manually in the .NET Framework. It provides multiple installation options, so you do not have to manually install or uninstall your applications. The two main installation options the Framework are:
ClickOnce Deployment
Setup Projects
As there is far to much to discuss here, please follow the links to find out more.

How to run a batch script after installation is finished?

I'm working for a custom installer developed in Visual Studio 2008 (Setup & Deployment > Setup project) for a C# project. I'd like to run a batch file (*.bat) after installation is finished. How can I do that?
You will have to extend the Installer class and override the Committed event.
Here is an example. Hope you will be able to find how to run a .bat file in C#.
[RunInstaller(true)]
public class ServiceInstaller : Installer
{
string strServiceName = "MyServiceName";
public ServiceInstaller()
{
// .............
this.Committed += new InstallEventHandler(ServiceInstaller_Committed);
}
void ServiceInstaller_Committed(object sender, InstallEventArgs e)
{
// Run your batch file
}
}
Custom Install Action is another option. Here is a similar thread for that.
You can run a batch file using cmd.exe, anyway it is what executes batch files.
Start it this way: cmd.exe /c <path-to-batch>\batchfile.bat.

Categories