At work I have to uninstall the same application several times per day (and reinstall new versions). I'm trying to make a C# program that I can run that will do this all for me. Right now, I'm stuck on the uninstall process.
The code I have runs and attempts to uninstall the application, but Windows gives me an error during this.
Here's what I have right now:
static void Main(string[] args)
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
const string prodName = "myApp";
Console.WriteLine("searching...");
foreach (ManagementObject wmi in searcher.Get())
{
if (wmi["Name"].ToString() == prodName)
{
Console.WriteLine("found");
string productCode = "/x {" + wmi.Properties["IdentifyingNumber"].Value.ToString() + "}";
Process p = new Process();
p.StartInfo.FileName = "msiexec.exe";
p.StartInfo.Arguments = productCode;
p.Start();
Console.WriteLine("Uninstalled");
break;
}
}
Console.ReadLine();
}
This is the error I get when it tries to do the uninstall:
"This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package"
Uninstall Reference: This old answer might have what you need: Uninstalling an MSI file from the command line without using msiexec. It shows various ways to uninstall an MSI.
DTF: The DTF (Desktop Tools Foundation) included with the WiX toolset can be used to uninstall. Here is some sample C# code:
Uninstalling program
- run elevated, quick link to sample.
VBScript / COM: Here are some links to VBScript samples and various ways to uninstall (uninstall by product name, uninstall by upgrade code, etc...): WIX (remove all previous versions) - the uninstall by upgrade code (sample code towards bottom) is interesting because it generally works for all versions and incarnations of your installer (upgrade code tends to remain stable across releases).
CMD.EXE: Personally I might just use an install and an uninstall batch file. More of these samples in section 3 here. Just create two different files:
Install: msiexec.exe /i "c:\Setup.msi" /QN /L*V "C:\msi.log" REBOOT=ReallySuppress
Uninstall: msiexec.exe /x "c:\Setup.msi" /QN /L*V "C:\msi.log" REBOOT=ReallySuppress
Related
My application call msiexec to run uninstall.
logger->LogDebug("Actions: MsiUninstallExec()!");
System::Diagnostics::Process ^p = gcnew System::Diagnostics::Process();
p->StartInfo->FileName = "msiexec";
p->StartInfo->Arguments = "/x " + AppSetting::ProductCode;
p->Start();
/// -->>> Uninstall
/// -->> Choose restart or not.
/// -->>> Application Exit
When uninstallation is done, users have to choose restart or not to complete this process.
But my customer request : "The progress bar of msiexec must move to the last (right end)."
How to edit it ? Do you have any idea for me?
Suggestion: You can try something like this (find product GUID):
msiexec.exe /X {PRODUCT-GUID} /QN REBOOT=ReallySuppress /L*V "C:\Temp\msilog.log"
Quick command line explanation:
/X {PRODUCT-GUID} = run uninstall sequence for specified product
/QN = run completely silently
/REBOOT=ReallySuppress = suppress reboot prompts
/L*V "C:\Temp\msilog.log" = verbose logging at specified path
Alternatives: There are many ways to invoke MSI uninstall: Uninstalling an MSI file from the command line without using msiexec. You can uninstall via: msiexec, ARP, WMI, PowerShell, deployment Systems such as SCCM, VBScript / COM Automation, DTF, or via hidden Windows cache folders, and a few other options.
msiexec.exe: There are two flavors of the msiexec.exe command line. An original one and a later one that added the "full word" switches such as /quiet and /noreboot and the likes. The original command line used /qn as the switch for silent mode. Here are links to both flavors: MSIEXEC what is the difference between qn and quiet.
Some Links:
Silent installation of a MSI package
How can I find the product GUID of an installed MSI setup?
How to report msi installation status on quiet install
msiexec /passive /x ProductCode
This should give you just the ProgressBar UI. You can also ask the user whether they want to skip restart or always force restart when the Uninstall completes. Then can add the /norestart or /forcerestart option appropriately.
Initially I created an application that I completely rewrite in a second version. It is a complete different Visual studio solution.
Now I would like that its Setup installer uninstall the previous version but because it was not created using the same solution, the automatic uninstallation of previous version does not work.
Is there any way to force the installer to uninstall certain application based on product name or product code?
I found a WMIC command that works when run from command line
wmic product where name="XXXX" call uninstall /nointeractive
So I created a VBS script which execute a bat file containing the WMIC code and I added it to the Setup project
dim shell
set shell=createobject("wscript.shell")
shell.run "uninstallAll.bat",0,true
set shell=nothing
but when I run the result MSI, it fires an error 1001, meaning that a service already exists. , in other words the uninstallation didn't work.
The old program is still present and they create a service with the same name. :/
any suggestion?
There are 2 options:
You can increase the version of MSI project so it will treat as upgrade and it will not throw any error while installing.
another way out is the write some in the installer project as follows:
protected override void OnBeforeInstall(IDictionary savedState)
{
//Write uninstall powershell script
//installutil /u <yourproject>.exe
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript("");
PowerShellInstance.AddParameter("");
}
PowerShellInstance.Invoke();
}
Note: This InstallUtil is available with the .NET Framework, and its path is %WINDIR%\Microsoft.NET\Framework[64]\<framework_version>.
For example, for the 32-bit version of the .NET Framework 4 or 4.5.*, if your Windows installation directory is C:\Windows, the path is C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe.
For the 64-bit version of the .NET Framework 4 or 4.5.*, the default path is C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe
I decided to go for the option of introducing c# code in the project installer. Firstly I added the reference for System.Management.Automation via nuget
https://www.nuget.org/packages/System.Management.Automation
After this, I just created a string variable containing the PS code I need to uninstall several programs with a similar name.
string unInstallKiosk = #"$app = get-WMIObject win32_Product -Filter ""name like 'KIOSK'""
foreach ($program in $app){
$app2 = Get-WmiObject -Class Win32_Product | Where -Object { $_.IdentifyingNumber -match ""$($program.identifyingNumber)""
}
$app2.Uninstall()}";
and passed this variable to the method PowerShellInstance.AddScript()
PowerShellInstance.AddScript(unInstallKiosk);
The installation ends but the uninstallation simply dont happens.
anyone has an idea how to solve this?
I finished my software and I'm not able to find a correct way to create its setup.
I searched the web and here but I found only old post referring old visual studio versions.
As I know in VS 2013 community edition I have a limited Installshield plugin and I was able to download the Visual Studio Installer plugin too. To create a simple setup is relatively easy but I need to silent install a small software during my setup. The software is Double Agent (an updated version of the Microsoft Agent) and the developer recommend to launch the setup in this way:
Simply run:
msiexec /i DoubleAgent_x86.msi /qb-!
during your setup (i think the best place should be the Commit event).
By the way it's not possible to launch .msi installer with an action and I really don't understand the best practice to create a custom action.
I read something about to create a class but most articles refer to Visual Studio 2008 or to Wix plugin. I'm searching a way to use Msiexec with Visual Studio Installer or installshield.
Edit: I found this solution and it works so good: https://msdn.microsoft.com/it-it/library/vstudio/d9k65z2d%28v=vs.100%29.aspx
It's in Italian but it's easy to translate to the original language (English) with the top right radio button. It's working perfectly with Visual Studio Setup plugin and VS Community edition 2013.
I have no code to post at this time because I built only their sample but I will post it asap with the usage of msiexec for the hidden installation.
I created a test winform project, I added the installer class with this code:
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
public override void Commit(IDictionary savedState)
{
base.Commit(savedState);
// Use ProcessStartInfo class
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "msiexec.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = "/i DoubleAgent.msi /qb-!";
try
{
// Start the process with the info we specified.
// Call WaitForExit and then the using statement will close.
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
}
}
catch
{
// Log error.
}
}
And I created the setup with Visual Studio installer. At the end of the main setup something start saying there is another installation but the double agent does not install.
Edit again: I have not Admin right to execute msiexec silently. I think because the Double Agent setup need admin rights. I don't want to use manifest to elevate privileges then I think the only solution is to show the DoubleAgent installer (also if in minimal output).
By the way I have this code working in form 1 Button:
private void button1_Click(object sender, EventArgs e)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.FileName = "msiexec.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = "/i DoubleAgent.msi /qn";
try
{
// Start the process with the info we specified.
// Call WaitForExit and then the using statement will close.
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
MessageBox.Show("Finish");
}
}
catch
{
// Log error.
}
}
But the same code does not work during the installation process.
This isn't going to work! One MSI setup cannot launch another MSI setup. When it says "another install is in progress" it is referring to your one that is already running. It's not about admin privilege - you cannot install another MSI from an installer custom action, no matter what that developer says.
In general this is what bootstrappers are for, to install prerequisites before installing the main MSI. That's why even VS setups let you generate a setup.exe to install prerequisites (many of which are MSI-based) before installing your MSI.
So you'll need to figure out a bootstrapper (don't know if InstallShield LE has one) that will install that MSI. There used to be a tool called Bootstrap Manifest Generator that you could use to tailor the setup.exe to install custom prerequisiyes like yours. Or you could use the bootstrapper from WiX to install that MSI then your MSI. Or you could just copy that MSI to the system and have your app install it the first time it is used.
Or maybe that agent software is available as merge modules, in which case you just add the merge modules to your MSI build.
I am using a C# code to install a program using a process which runs the msiexec, giving it the path to the MSI file.
This is the code I use:
string pathtoMsiFile = "\"" + msiPath + msiName + "\"";
Process p = new Process();
p.StartInfo.FileName = "msiexec.exe";
p.StartInfo.Arguments = "/i " + pathtoMsiFile + " /quiet";
p.Start();
p.WaitForExit();
The strange thing is that when I try to install the program, for a certain version it installs it to the correct location I would expect to on C:\path but a different version it installs to D:\path for some reason. If I open the MSI itself manually, the default location there is C:\path. Any idea why?
Eventually it appears the problem is with the program the msiexec tried to install.
I am not that program's developer so I couldn't know the problem in advanced on my own.
The program had a custom action in its installation that set a variable representing the drive to install on as the one where the OS is installed. The problem is, that this action was invoked only through the installation's UI (when double clicking the MSI), but not when using a quiet CLI command to install it.
I have a Custom Action that should execute during the Install portion of an .msi setup. I have a previous version that was installed using InstallShield (which was overkill) and wanted to move to the simpler VS Setup Proj because I do not require all the control that an .isproj provides. However, doing a straight install with my new .msi seems to install side by side with the previous version. Here's what I have found out so far:
I have my product ID
I have written code that will uninstall the previous version through creating a process that uses MsiExec.exe (code will follow)
Tried implementing the custom action to uninstall during setup but it seems you can only have one instance of MsiExec.exe running at a time.
Have been to this post (http://stackoverflow.com/questions/197365/vs-setup-project-uninstall-other-component-on-install), which didnt help.
Custom Action code:
//Exe used to uninstall
string fileName = "MsiExec.exe";
//Product ID of versions installed using InstallShield
string productID = "{DC625BCF-5E7B-4FEF-96DD-3CDBA7FC02C1}";
//Use /x for uninstall and use /qn to supress interface
ProcessStartInfo startInfo = new ProcessStartInfo(fileName, string.Format("/x{0}", productID));
startInfo.WindowStyle = ProcessWindowStyle.Normal;
startInfo.UseShellExecute = false;
//Start process
Process uninstallProcess = Process.Start(startInfo);
//Wait until uninstall is complete
uninstallProcess.WaitForExit();
My hope is to eventually deploy my .msi via ClickOnce, so I am hoping for an option that will fit into deployment option. Currently everything is written in .NET 2.0 and VS 2005, but I do have .NET 4.0 and VS 2010 available to me if there is a new option that works.
Any help is appreciated.
I was able to install over the top of the previous install by making the product code of my setup the same as the code of the older version. Didn't dawn on me to try that because when you create a new version of the setup package, VS always prompts you to change your product code.