Running an installer from within C# - c#

I need to write code to download and run a program, e.g. notepad++ (npp.5.9.3.Installer.exe) this can be found on the web.
I run it with the ProcessStartInfo class. However when I normally execute the notepad++ installer, it will show me a few steps before actually installing, like choose language, path etc.
Is there any way to programatically skip these steps, and install the software? I hope my question is clear. If it helps, I also attach the method that so far only starts the installer
private int RunFile()
{
ProcessStartInfo psi = new ProcessStartInfo(GetFileFullPath());
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.CreateNoWindow = true;
using (Process process = Process.Start(psi))
{
process.WaitForExit();
if (process.HasExited)
return process.ExitCode;
}
}
Shall I pass some arguments for this to work?
Thank you in advance.
Regards,

Use npp.5.9.3.Installer.exe /S for unattended installation of notepad++, and %ProgramFiles%\Notepad++\uninstall.exe /S for uninstall.

There are some installers which supports -s or -silent switches which means that when you install a software by passing -s switch to installer and it will silently install with default options. Try to find out whether your installer supports that or not

you have to drive the installation emulating the user. It is possible send kind of command(message) to the other window from a C# application
have a look at the below
http://social.msdn.microsoft.com/forums/en-US/winforms/thread/345d85e8-cc5f-4508-b3f2-74ee43521169/
Interact with other desktop-applications in windows using C# winforms

A wellwritten installer have options for silent installs with no user interface. If the installer is an .msi file there are options that can be passed to msiexec to make a silent install.
For other install systems there are sometimes options to. Automating installations without user involvement is a common task for system administrators, so if you have questions on a specific installation package I would suggerst asking at ServerFault or AppDeploy. Unfortunately there are many bad installation programs out there that doesn't support silent install.

This will ONLY depend on the installer (npp.5.9.3.Installer.exe). You have to search if the installer provides options that can be used in command line, such as silentinstall.
EDIT: You can use the /S (capital S) option for Notepad++ to perform a silent install.

Related

Is there a way to accept the license agreement to a silent installation of a .msi file using C#?

I'm trying to quietly install a .msi file using C# without the need for any user input. I'm having trouble trying to get past the license agreement so that the installation can continue. Is there a way to pass an argument so that the agreement is accepted without any user imput?
Caution: I would avoid triggering software installation from within an application binary - unless you are making an actual setup launcher application. It can work, but it may trigger serious problems with anti-virus and malware scanners. I have seen that before. I would assume you would also need to run elevated - with admin rights - to kick off your installs (per-machine installations).
Some digressions and suggestions first: MSI can be installed via msiexec.exe commands, Powershell, DTF C# (see below), WMI, MSI API (COM, Win32).
Batch: With that said, why don't you just install using a regular batch file? The /QN switch will bypass the entire setup GUI-sequence and then there should be no need to accept any license agreements. MSI logging information (short version: open log and search for "value 3" to find errors).
This command must be run from an elevated command prompt (admin rights):
msiexec.exe /I "Installer.msi" /QN /L* "C:\msilog.log" ALLUSERS=1
Setup.exe: You can also make a WiX Burn bundle (see link for code mockup) or use some sort of other tool to make a setup.exe that will install your original application and then other components in sequence - so there is nothing to trigger to install from the application.
Interactive Install: If you want to install with some user interaction you can locate the property controlling the accept status of the license agreement and set that to the appropriate value - usually 1 - to indicate accepted license.
DTF: Now the code answer. There is a component installed with the WiX toolkit called DTF - Desktop Tools Foundation It has a number of C# classes designed to deal with MSI files via managed code. This answer explains what file to add as a reference in Visual Studio and describes the different files / assemblies of DTF briefly. Another DTF sample.
The relevant file for your described purpose is: "Microsoft.Deployment.WindowsInstaller.dll".
NOTE!
You must launch Visual Studio with admin rights to install per machine.
Add project reference to "%ProgramFiles(x86)%\WiX Toolset v3.11\bin\Microsoft.Deployment.WindowsInstaller.dll".
The below code tested in VS2017 (a more elaborate version with admin check here - zipped):
using System;
using Microsoft.Deployment.WindowsInstaller;
// RUN WITH ADMIN RIGHTS
namespace DTFTest
{
class Program
{
static void Main(string[] args)
{
try
{
Installer.SetInternalUI(InstallUIOptions.Silent);
Installer.EnableLog(InstallLogModes.Verbose, #"E:\Install.log");
Installer.InstallProduct(#"E:\Install.msi", "");
}
catch (Exception ex)
{
Console.WriteLine("Exception:\n\n " + ex.Message);
}
}
}
}
Link:
On reboot initiated issues
Install via VBScript COM, DTF, Win32
Generally you just run the msi silently like
msiexec /i foo.msi /qn
If the MSI has implemented an additional consent you might have to pass a property like
msiexec /i foo.msi /qn ACCEPTEULA=1
The exact name of this property would depend on the MSI so you'd need to consult vendor documentation or examine the MSI using a tool such as ORCA.

C# cmd prompt cannot see telnet.exe

I used C# with a console program to create a new cmd process, did not redirect stdin or stdout, so I could type into the command line from here.
(I was having trouble using telnet from there, so this step was just an investigation.)
Able to type into the window and receive output.
When I switched to c:Windows\system32, typing dir te*.exe shows nothing.
In another command prompt I created directly, I see the file (telnet.exe).
Any suggestions about what is wrong?
{
ProcessStartInfo startInfo = new ProcessStartInfo(#"cmd.exe");
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.WindowStyle = ProcessWindowStyle.Normal;
startInfo.CreateNoWindow = false;
startInfo.Arguments = host;
using (Process p = new Process())
{
p.StartInfo = startInfo;
p.Start();
}
}
Since Windows 7, I believe, you have to install Telnet as a Windows Feature.
Here you have a guide to enable Telnet on Win 7, but it's applicable to Win 8.1 as well as Windows 10.
Just in case you can't read the site, the steps are:
Go to Control Panel -> Programs -> Turn Windows Features on or off -> Scroll down until you find the Telnet Client option
Based on the above article, looked at project build properties.
Platform target was set to x86.
Changing to "Any CPU" at least allows me to see the program!
BTW I have looked for the answer for several days before posting this, but in the margin in related - "C# New process created cannot access certain files" gave me the info - after I created this question
Thanks, heuristics!
This is a really devious one. When you are using windows explorer or opening a command prompt directly, you are starting a 64-bit process. When you are starting the "cmd.exe" with Process.Start(), you will get the same version as the process that's starting it. In your case, you are creating a 32-bit process, so you get the 32-bit version of the command prompt. If you change your project to create target x64, you will see the files!
Why is this so? Because, depending on whether you are accessing System32 through a 32-bit or 64-bit app, you will actually be accessing different System32 folders! For more on this, follow this link:
https://superuser.com/questions/330941/some-files-in-system32-not-accessible-outside-explorer-on-windows-7

How to silent install an external NSIS exe in WPF C#

Like the title says, i'm trying to install an .exe silently (say, for example, inkscape) through my application written in WPF C#. The problem is, the install process i use always return an exception and fails.
Here is the code that i use :
public static bool StartInstall(string pathtofile)
{
try
{
Process process = new Process();
process.StartInfo.FileName = "Temp.exe";
process.StartInfo.Arguments = string.Format(" /S", pathtofile);
process.Start();
process.WaitForExit();
Console.WriteLine("Silent Install was successful.");
return true;
}
catch
{
MessageBox.Show("Error!");
return false;
}
}
According to this website, the switch for a silent install for NSIS packaged exes is /S. I'm not sure whether or not i'm doing something wrong in the syntax, though.
The code i'm using come from this stackoverflow post. It does work for a .msi package. Maybe it does not work for NSIS exes?
I'm relatively clueless as to why it does not work. The code above will crash at the "process.Start()" line, most probably because of a unknown command or something.
I'd be thankful if anybody could shred a bit of light as to how to launch that process for a NSIS installer.
I have solved the problem with the help of csharpfolk.
My problem was a combination of two different cause :
First, Admin privileges were indeed required to run the application.
Second, the line "process.StartInfo.Filename" requires the full path to the file. As soon as i changed it to "C:\Downloads\Temp.exe", it worked.

Process.Start("IIS Manager.lnk") fails with "The system cannot find the file specified"

I'm launching the path C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk via Process.Start, but it fails with The system cannot find the file specified.
The link shows up on a dir, so it exists.
Can it be permissions?
Notes:
The path is auto-discovered by iterating over the Start Menu directory.
I can launch it via explorer and command line.
Clarifications:
Code is as follows:
public void Execute() { Process.Start(_shortcut.FullName);}
_shortcut is of type FileInfo
_shortcut.Exists is true, so the file can be found
replacing _shortcut.FullName with the explicit path #"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk" has the same effect.
This is a WPF app using Caliburn and MEF.
Running as Administrator has the same effect.
This here on the other hand seems to work:
[Fact]
public void TestIisManager()
{
var path = new FileInfo(#"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk");
Process.Start(path.FullName);
}
It does seem to be a bit "environment" based.
Second clarification:
It seems to work in a Windows 7 x86 but not in a Windows 7 x64.
I ran into this recently. Windows Forms based solution, VS2013, x64 machine. Process.Start() could not launch applications via .lnk file. Using process explorer, it seemed that the target specified in the .lnk file was resolving incorrectly to c:\program files (x86)... instead of c:\program files... I followed Bruno's excellent advice, but then again my Target was already marked as "AnyCPU".
After some head scratching, it turned out there's a new compiler flag in VS11+ called "Prefer 32-bit" that was checked by default. This was forcing the EXE output to be 32-bit even though my OS was 64-bit and platform was set to AnyCPU. After I unchecked and recompiled, the problem was fixed.
More reading at: http://blogs.microsoft.co.il/sasha/2012/04/04/what-anycpu-really-means-as-of-net-45-and-visual-studio-11/
Found the issue.
The WPF application was compiled as x86 (all other dlls were compiled as AnyCPU), and when launching some executables or links in a 64 bit machine it failed.
Changing the "Platform Target" to AnyCPU fixes this.
This may not actually relate to your situation, but you can launch the IIS Manager by using
Process.Start("inetmgr.exe")
If you want to continue to use the shortcut, it will probably work if you start the process using a ProcessStartInfo and set ProcessStartInfo.UseShellExecute to true
Can you make sure that you are trying this from an STA thread? You can see whether the apartment state is a problem if the following sample succeeds:
using System;
using System.Diagnostics;
public class Program
{
// make sure to call Process.Start from an STA thread
[STAThread]
static void Main(string[] args)
{
Process.Start(#"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk");
}
}
Process.Start calls ShellExecute under the hood to run the file passed. As described by Raymond Chen, shell functions require an STA thread:
One possible reason why ShellExecute returns SE_ERR_ACCESSDENIED and ShellExecuteEx returns ERROR_ACCESS_DENIED
As stated already, you will see the "The system cannot find the file specified" error because Windows is looking for inetmgr.exe in ...\SysWOW64\intsrv\ (caused by file system redirection), but it only exists in ...\System32\intsrv\.
This is caused by your 32-bit executable attempting to launch a 64-bit executable. As suggested, not using a 32-bit executable will solve this, but for anyone who must build for 32-bit (a WiX installer bundle in my case), try the following.
Using the start menu LNK/shortcut to inetmgr.exe instead of the executable is a good start, but an extra level of distance is required. This can be provided by using explorer.exe, which can be launched from a 32-bit executable:
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "explorer.exe";
startInfo.Arguments = "/seperate /root,\"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Administrative Tools\\IIS Manager.lnk\"";
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo = startInfo;
process.Start();
It's a bit of a hack, but try launching it like this:
string path = #"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk";
Process.Start("cmd.exe", String.Format("/k \"\"{0}\"\"",path));
Note the double quotes needed to save the spaces in the path.
That way, you might see a more precise error message and/or walk around in the command environment afterwards to see what is wrong with the path.

Uninstall Command Fails Only in Release Mode

I'm able to successfully uninstall a third-party application via the command line and via a custom Inno Setup installer.
Command line Execution:
MSIEXEC.exe /x {14D74337-01C2-4F8F-B44B-67FC613E5B1F} /qn
Inno Setup Command:
[Run]
Filename: msiexec.exe; Flags: runhidden waituntilterminated;
Parameters: "/x {{14D74337-01C2-4F8F-B44B-67FC613E5B1F} /qn";
StatusMsg: "Uninstalling Service...";
I am also able to uninstall the application programmatically when executing the following C# code in debug mode.
C# Code:
string fileName = "MSIEXEC.exe";
string arguments = "/x {14D74337-01C2-4F8F-B44B-67FC613E5B1F} /qn";
ProcessStartInfo psi = new ProcessStartInfo(fileName, arguments)
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true
};
Process process = Process.Start(psi);
string errorMsg = process.StandardOutput.ReadToEnd();
process.WaitForExit();
The same C# code, however, produces the following failure output when run as a compiled, deployed Windows Service:
"This action is only valid for products that are currently installed."
Additional Comments:
The Windows Service which is issuing
the uninstall command is running on
the same machine as the code being
tested in Debug Mode. The Windows
Service is running/logged on as the
Local system account.
I have consulted my application logs
and I have validated that the
executed command arguments are thhe
same in both debug and release mode.
I have consulted the Event Viewer
but it doesn't offer any clues.
Thoughts? Any help would be greatly appreciated. Thanks.
Step 1: Check the MSI error log files
I'm suspicious that your problem is due to running as LocalSystem.
The Local System account is not the same as a normal user account which happens to have admin rights. It has no access to the network, and its interaction with the registry and file system is quite different.
From memory any requests to read/write to your 'home directory' or HKCU under the registry actually go into either the default user profile, or in the case of temp dirs, c:\windows\temp
I've come across similar problems in the past with installation, a customer was using the SYSTEM account to install and this was causing all sorts of permission problems for non-administrative users.
MSI log files aren't really going to help if the application doesn't appear "installed", I'd suggest starting with capturing the output of MSIINV.EXE under the system account, that will get you an "Inventory" of the currently installed programs (or what that user sees installed) http://blogs.msdn.com/brada/archive/2005/06/24/432209.aspx
I think you probably need to go back to the drawing board and see if you really need the windows service to do the uninstall. You'll probably come across all sorts of Vista UAC issues if you haven't already...
Thanks to those offering help. This appears to be a permissions issue. I have updated my service to run under an Administrator account and it was able to successfully uninstall the third-party application. To Orion's point, though the Local System account is a powerful account that has full access to the system -- http://technet.microsoft.com/en-us/library/cc782435.aspx -- it doesn't seem to have the necessary rights to perform the uninstall.
[See additional comments for full story regarding the LocalSystem being able to uninstall application for which it installed.]
This is bizarre. LocalSystem definitely has the privileges to install applications (that's how Windows Update and software deployment in Active Directory work), so it should be able to uninstall as well.
Perhaps the application is initially installed per-user instead of per-machine?
#Paul Lalonde
The app's installer is wrapped within a custom InnoSetup Installer. The InnoSetup installer, in turn, is manually executed by the logged in user. That said, the uninstall is trigged by a service running under the Local System account.
Apparently, you were on to something. I put together a quick test which had the service running under the LocalSystem account install as well as uninstall the application and everything worked flawlessly. You were correct. The LocalSystem account has required uninstall permissions for applications in which it installs. You saved the day. Thanks for the feedback!

Categories

Resources