I am writing a InstallerClass using C# as a custom action for my installer, and I can successfully run an external exe (installation) using the InstallerClass, but when I try to use /quiet in the InstallerClass, it does not install the exe. But I can successfully install this in silent mode using /quiet in the command prompt.
Is there any reason for this or otherwise how to install in silent mode using C#?
Following is the code I use within the Commit method (overriden):
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = pathExternalInstaller;
p.StartInfo.Arguments = "/quiet";
p.Start();
Here is what I use to do a quiet Install and Uninstall:
public static bool RunInstallMSI(string sMSIPath)
{
try
{
Console.WriteLine("Starting to install application");
Process process = new Process();
process.StartInfo.FileName = "msiexec.exe";
process.StartInfo.Arguments = string.Format(" /qb /i \"{0}\" ALLUSERS=1", sMSIPath);
process.Start();
process.WaitForExit();
Console.WriteLine("Application installed successfully!");
return true; //Return True if process ended successfully
}
catch
{
Console.WriteLine("There was a problem installing the application!");
return false; //Return False if process ended unsuccessfully
}
}
public static bool RunUninstallMSI(string guid)
{
try
{
Console.WriteLine("Starting to uninstall application");
ProcessStartInfo startInfo = new ProcessStartInfo("cmd.exe", string.Format("/c start /MIN /wait msiexec.exe /x {0} /quiet", guid));
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process process = Process.Start(startInfo);
process.WaitForExit();
Console.WriteLine("Application uninstalled successfully!");
return true; //Return True if process ended successfully
}
catch
{
Console.WriteLine("There was a problem uninstalling the application!");
return false; //Return False if process ended unsuccessfully
}
}
This works for me.
Process process = new Process();
process.StartInfo.FileName = # "C:\PATH\Setup.exe";
process.StartInfo.Arguments = "/quiet";
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
process.WaitForExit();
Have you tried using the /Q or /QB parameter that is listed in the Installation parameters? It might look something like this:
p.StartInfo.Arguments = "/Q";
I got that out of this document: http://msdn.microsoft.com/en-us/library/ms144259(v=sql.100).aspx
Here is my logic to silent install an app for all users:
public void Install(string filePath)
{
try
{
Process process = new Process();
{
process.StartInfo.FileName = filePath;
process.StartInfo.Arguments = " /qb ALLUSERS=1";
process.EnableRaisingEvents = true;
process.Exited += process_Exited;
process.Start();
process.WaitForExit();
}
}
catch (InvalidOperationException iex)
{
Interaction.MsgBox(iex.Message, MsgBoxStyle.OkOnly, MethodBase.GetCurrentMethod().Name);
}
catch (Exception ex)
{
Interaction.MsgBox(ex.Message, MsgBoxStyle.OkOnly, MethodBase.GetCurrentMethod().Name);
}
}
private void process_Exited(object sender, EventArgs e)
{
var myProcess = (Process)sender;
if (myProcess.ExitCode == 0)
// do yours here...
}
string filePath = #"C:\Temp\Something.msi";
Process.Start(filePath, #"/quiet").WaitForExit();
It worked for me.
Related
I use System.Diagnostics.Process in C# to call the PostgreSQL backup database component pg_dump.exe. Here is my code:
string argbackup = #"--host localhost --port 5432 --username ""postgres"" --no-password --format custom --blobs --verbose --file dtname dtname";
Process backupProcess = new Process();
backupProcess.StartInfo.FileName = #"C:/Program Files/PostgreSQL/9.5/bin/pg_dump.exe";
backupProcess.StartInfo.Arguments = argbackup;
backupProcess.EnableRaisingEvents = true;
backupProcess.Exited += (object sender, EventArgs args) =>
{
//Execution after the process ends.
};
backupProcess.Start();
The code can run successfully in C#. But pg_dum.exe cannot be called when I publish the project in Visual Studio and deploy it on IIS. And the code that was run after the process ended successfully ran.
I modified the above code:
var pinfo = new ProcessStartInfo();
pinfo.Arguments = #"--host localhost --port 5432 --username ""postgres"" --no-password --format custom --blobs --verbose --file dtname dtname";
info.FileName = #"C:/Program Files/PostgreSQL/9.5/bin/pg_dump.exe";
pinfo.UseShellExecute = false;
using (var process = new Process())
{
process.EnableRaisingEvents = true;
process.StartInfo = pinfo;
process.Start();
while (!process.HasExited)
Thread.Sleep(10000);
process.WaitForExit();
if (process.ExitCode != 0)
throw new Exception("error");
process.Close();
}
It can also be used in C#, but it still won't work in IIS.
I modified the code again:
string argpostgre = #"c: && cd C:/Program Files/PostgreSQL/9.5/bin";
string argbackup = #"pg_dump.exe --host localhost --port 5432 --username ""postgres"" --no-password --format custom --blobs --verbose --file dtname dtname";
Process theProcess = new Process();
theProcess.StartInfo.FileName = #"cmd.exe";
theProcess.StartInfo.UseShellExecute = false;
theProcess.StartInfo.RedirectStandardInput = true;
theProcess.StartInfo.RedirectStandardOutput = true;
theProcess.StartInfo.RedirectStandardError = true;
theProcess.StartInfo.CreateNoWindow = false;
theProcess.EnableRaisingEvents = true;
theProcess.Exited += (object sender, EventArgs args) =>
{
//Execution after the process ends.
};
string strOutput = null;
try
{
theProcess.Start();
theProcess.StandardInput.WriteLine(argpostgre + " && " + argbackup + " & exit");
theProcess.WaitForExit();
}
catch (Exception ex)
{
strOutput = ex.Message;
}
It has been runnning in C# and will not exit. But the database can be backed up successfully after I forcefully close the C# program. And it will automatically stop process but the situation is the same as above when I deploy to IIS.
I am sure it is not the setup issue in IIS, because I have also used the Process component to access the WinRAR.exe (C:\Program Files\WinRAR\WinRAR.exe) compression program, which can run successfully.
I wonder if PostgreSQL has permissions so I can not access pg_dump.exe and other components such as pg_restore.exe.
I've a free trial launcher for the Final Fantasy XIV game. Now I want to launch it through process.start in a windows service in C#. the process starts successfully, as I can see it in the windows task manager, but it does not launch the setup file. Here is the code I've tried.
try {
var process = new Process();
var startInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Normal,
FileName = "cmd.exe",
Arguments = "/C " + setupFile + " /DIR=" + installLocation,
};
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
}
catch (Exception ex)
{
Logger.Log.Error("Error Installing game.", ex);
}
Where setupfile is the complete path for ffxivsetup_ft.exe.
Try this code :
ProcessStartInfo startInfo = new ProcessStartInfo(path);
Process.Start(startInfo);
I've got a WPF application that whilst processing a file needs to use a docker process. The docker container is built on the box, currently after processing a file with the WPF application the user has to start a command prompt and type in
docker run --it --rm -v folderdedirect process parameters_including_filePath
to do further processing.
I want to include that in the WPF application. I could presumably use system.diagnostics.process with cmd.exe? I looked at the Docker.dotnet but couldn't for the life of me work out how it's supposed to just run a local container.
Here's how I did it in the end but there may be a better way.
var processInfo = new ProcessStartInfo("docker", $"run -it --rm blahblahblah");
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardError = true;
int exitCode;
using (var process = new Process())
{
process.StartInfo = processInfo;
process.OutputDataReceived += new DataReceivedEventHandler(logOrWhatever());
process.ErrorDataReceived += new DataReceivedEventHandler(logOrWhatever());
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit(1200000);
if (!process.HasExited)
{
process.Kill();
}
exitCode = process.ExitCode;
process.Close();
}
Adapted the code above for my context. The hardest part is determining how you want to monitor if your process finished. You can try setting up event listeners as shown here. Having other conditions to verify (if client sends a kill signal), I decided to just continually monitor process.HasExited value.
private static void RunDockerImage(ContainerData containerData)
{
var processInfo = new ProcessStartInfo("docker", $"run "+containerData.ImageName);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardError = true;
int exitCode;
using (var process = new Process())
{
process.StartInfo = processInfo;
// indicate process is started
StartUpdateOrch(containerData);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
while(!process.HasExited)
{
// continually check if kill signal is set
if (getKillSignal())
{
process.Kill();
}
Thread.Sleep(2000);
}
exitCode = process.ExitCode;
containerData.exitCode = exitCode;
// indicate process is done
FinishUpdateOrch(containerData);
process.Close();
}
}
Well... everything is in the title, this is a C# console app and i'm trying to execute these commands... it dosen't seems to work but why ?
It just open a cmd, i don't see anything like a command
static void Main(string[] args)
{
string strCmdText = "mysqlcheck -r JAMFSOFTWARE -u root -p password";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
string strCmdText2 = "mysqlcheck -o JAMFSOFTWARE -u root -p password";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
string strCmdText3 = "mysqlcheck -c JAMFSOFTWARE -u root -p password";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
}
Edit : The thing is i don't want to put that password in a batch file where it would be easely accessible, so basically any solution would do as long as no one can see what's in the commande file
GOT CLOSER TO A SOLUTION :
static void Main(string[] args)
{
ProcessStartInfo startInfo = new ProcessStartInfo("mysqlcheck");
startInfo.Arguments = "-c JAMFSOFTWARE -u root -p !!fakepassword!!";
Process process = new Process();
process.StartInfo = startInfo;
process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
try
{
process.Start();
}
catch
{
}
}
static void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
StreamWriter sw = new StreamWriter("C:\\JAMFCHECK.txt");
sw.WriteLine( e.Data);
}
now i don't know why but it ask for a password...
based on your comment, I think you don't need CMD
you can start the 'mysqlcheck' directly using a different executable (see below)
to get all the results from the command-line can be a bit tricky.
I added a working sample at the end of the answer but I'd like to explain it a bit.
set up what you want to execute first
FileInfo executable = new FileInfo(#"C:\Temp\cmd.bat");
ProcessStartInfo startInfo = new ProcessStartInfo(executable.FullName);
startInfo.Arguments = "two arguments";
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = true;
make sure to redirect the output (also I don't want to see it)
Now you give your StartInfo to the process
Process process = new Process();
process.StartInfo = startInfo;
because we want to read the Output we need to
process.EnableRaisingEvents = true;
I assigned two events:
process.OutputDataReceived += new ...
process.Exited += new ...
start the process and start reading
process.Start();
process.BeginOutputReadLine();
The batchFile I used gave me the file and the arguments
#echo off
echo %~nx0
echo %1
echo %2
you can call any executable like this (except cmd.exe, it never finishes)
I attached the complete code and also added a Reset-Event to sync the execution. Here is the output from my debug-console:
Beginn
Starting external Application: C:\Temp\cmd.bat
cmd.bat
two
arguments
Finished executing external Application
End
listing:
// using System.Diagnostics;
// using System.Threading;
// using System.IO
private ManualResetEvent mre;
private void button_Click(object sender, EventArgs e)
{
mre = new ManualResetEvent(false);
Debug.WriteLine("Beginn");
FileInfo executable = new FileInfo(#"C:\Temp\cmd.bat");
ProcessStartInfo startInfo = new ProcessStartInfo(executable.FullName);
startInfo.Arguments = "two arguments";
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = true;
Process process = new Process();
process.EnableRaisingEvents = true;
process.StartInfo = startInfo;
process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
process.Exited += new EventHandler(process_Exited);
Debug.WriteLine(String.Format("Starting external Application: {0}", executable.FullName));
process.Start();
process.BeginOutputReadLine();
mre.WaitOne();
Debug.WriteLine("End");
}
void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Debug.WriteLine(e.Data);
}
void process_Exited(object sender, EventArgs e)
{
Debug.WriteLine("Finished executing external Application");
mre.Set();
}
hope it helps, best regards
You need to start strCmdText with /C:
static void Main(string[] args)
{
string strCmdText = "/C mysqlcheck -r JAMFSOFTWARE -u root -p password";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
string strCmdText2 = "/C mysqlcheck -o JAMFSOFTWARE -u root -p password";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
string strCmdText3 = "/C mysqlcheck -c JAMFSOFTWARE -u root -p password";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
}
I have several batch files that I need to execute using C#, the problem is at the end of the first batch file it is running a daemon process. This is causing the second batch file to never be executed because of the WaitForExit(). I can not take this out because I dont know how much time the first batch file need to run (until it hits running the daemon)
BatchFile1.bat ->
BatchFile2.bat ->
BatchFile3.bat ->
BatchFile4.bat
inside BatchFile1.bat, I have blah, blah, blah and at the end it is running a daemon process which of course will never exit
//not exit , even if there is error
public void Run_Process(string process_name, string s)
{
Process myProcess = new Process();
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.FileName = "cmd.exe";
myProcess.StartInfo.Arguments = "/C " + process_name + s;
myProcess.StartInfo.CreateNoWindow = true;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardError = true;
myProcess.Start();
string standard_output = myProcess.StandardOutput.ReadToEnd();
myProcess.WaitForExit();
Console.WriteLine(standard_output);
}
To Execute a cmd.exe this might work:
static void ExecuteCommand(string command)
{
int exitCode;
ProcessStartInfo processInfo;
Process process;
processInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
// *** Redirect the output ***
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
process = Process.Start(processInfo);
process.WaitForExit();
// *** Read the streams ***
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
exitCode = process.ExitCode;
Console.WriteLine("output>>" + (String.IsNullOrEmpty(output) ? "(none)" : output));
Console.WriteLine("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error));
Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand");
process.Close();
}
static void Main()
{
ExecuteCommand("echo testing");
}