I have a problem to execute uninstallString using process, it won't work in all cases.
I need a generic procedure that will run in any case.
one of my ideas was to parse uninstall string
Code:
int indexOfExe = uninstallString.ToLower().IndexOf(".exe") + 4;
string exeFile = uninstallString.Substring(0, indexOfExe).Trim();
string args = uninstallString.Substring(indexOfExe, uninstallString.Length - indexOfExe).Trim();
if (args.Length > 0)
{
procStartInfo.FileName = exeFile;
procStartInfo.Arguments = args;
}
else
{
procStartInfo.FileName = exeFile;
procStartInfo.Arguments = "";
}
procStartInfo.Verb = "runas";
procStartInfo.CreateNoWindow = true;
procStartInfo.UseShellExecute = false ;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
proc.WaitForExit();
my second idea was:
Code:
if (uninstallString.Contains("msiexec"))
{
uninstallString = uninstallString.Replace("\"", "");
uninstallString = RegistryHandler.getCommandInCommaAndArgumentsOutside(uninstallString);
}
else
{
procStartInfo.FileName = "cmd";
string[] words = uninstallString.Split("/".ToCharArray());
if (uninstallString.StartsWith(#"""") && words.Count() == 1)
{
procStartInfo.FileName = uninstallString;
procStartInfo.Arguments = "";
}
else
{
//procStartInfo.Arguments = "/c " + "\"" + uninstallString + "\"";
if ((uninstallString.StartsWith(#"""") && words.Count() > 1))
{
procStartInfo.Arguments = "/c " + uninstallString;
}
else
{
procStartInfo.Arguments = "/c " + RegistryHandler.getCommandInCommaAndArgumentsOutsideByExe(uninstallString);
}
}
}
but still it won't cover all cases.
What is the generic solution for all cases?
Your second idea should, technically, work (for all programs using Windows Installer). However, you need to get the proper uninstall string. I suspect the problem is your Uninstall String is incorrect.
You should be able to query the registry for the Uninstall String by looking at:
HKLM\Software\Microsoft\Windows\Currentversion\Uninstall\{NameOfApplication}\UninstallString
The section above marked {NameOfApplication} should have an entry for all programs which can be uninstalled. For details, see the Uninstall Registry Key.
//i wrote this code, which is working in most of the cases :
//----------------------------------------------------------------------------------------------
if (uninstallString.Contains("msiexec"))
{
uninstallString = uninstallString.Replace("\"", "");
uninstallString = RegistryHandler.getCommandInCommaAndArgumentsOutside(uninstallString);
}
else
{
if (uninstallString.StartsWith(#""""))
{
int indexOfLastComma = uninstallString.IndexOf("\"", 1) + 1;
procStartInfo.FileName = uninstallString.Substring(0, indexOfLastComma);
procStartInfo.Arguments = uninstallString.Substrin(indexOfLastComma,uninstallString.Length - indexOfLastComma));
}
else
{
procStartInfo.FileName = "cmd.exe";
procStartInfo.Arguments = "/c " + RegistryHandler.getCommandInCommaAndArgumentsOutsideByExe(uninstallString);
}
}
//----------------------------------------------------------------------------------------------
public static string getCommandInCommaAndArgumentsOutsideByExe(string command)
{
int ind = 0;
string[] prms = command.Split(' ');
ind = prms[0].Length; //command.IndexOf(".exe") + 4;
int exeLocationIndex = command.IndexOf(".exe") + 4;
string cmd = command.Substring(0, exeLocationIndex);
string arguments = command.Substring(command.IndexOf(".exe") + 4, command.Length - exeLocationIndex);
return "\"" + cmd + "\"" + arguments;
}
Here is my code, using the same way as Roy did,perhaps a litter simpler:
private string SwitchCondition(string uninstallstring)
{
if (uninstallstring.Substring(0, 1).Equals("\"") |
uninstallstring.ToLower().Contains("msiexec") |
uninstallstring.Contains("~"))
{
Debug.WriteLine(uninstallstring);
}
else if (uninstallstring.ToLower().IndexOf(".exe") > 0)
{
uninstallstring = "\"" + uninstallstring.Insert(uninstallstring.ToLower().IndexOf(".exe") + 4, "\"");
Debug.WriteLine("Contains .exe" + uninstallstring);
}
else
{
uninstallstring = "\"" + uninstallstring + "\"";
Debug.WriteLine("Case end " + uninstallstring);
}
return uninstallstring;
}
Related
public class CmdHelper
{
public static string StartCmd(string commandLine)
{
commandLine = commandLine.Trim().TrimStart('&') + "&exit";
string outputMsg = "";
Process pro = new Process();
pro.StartInfo.FileName = "cmd.exe";
pro.StartInfo.UseShellExecute = false;
pro.StartInfo.RedirectStandardError = true;
pro.StartInfo.RedirectStandardInput = true;
pro.StartInfo.RedirectStandardOutput = true;
pro.StartInfo.CreateNoWindow = false;
pro.Start();
pro.StandardInput.WriteLine(commandLine);
pro.StandardInput.AutoFlush = true;
pro.StartInfo.StandardErrorEncoding = Encoding.UTF8;
pro.StartInfo.StandardOutputEncoding = Encoding.UTF8;
outputMsg += pro.StandardOutput.ReadToEnd();
pro.WaitForExit();
pro.Close();
return outputMsg;
}
public static void CommitBundleToSvn()
{
string folderPath = EditorConst.BundlesPath + VEngine.Editor.Builds.Settings.GetPlatformName();
string command = "svn status " + folderPath;
string regaxPattern = ".*&exit";
string output = "";
string[] regexRes = {};
command = "svn st " + folderPath+ " | awk \"{if ($1 == \\\"?\\\") {print $2} }\"";
output = CmdHelper.StartCmd(command);
UnityEngine.Debug.LogError(command);
UnityEngine.Debug.LogError(output);
}
Execute command:
("svn st " + folderPath+ " | awk \"{if ($1 == \\\"?\\\") {print $2} }\"")
In windows cmd, cmd could get return message.
Now I call the CommitBundleToSvn(). but the cmd will not exit.
If the command is "svn status " + folderPath, it is expected.
Another option is to not use awk in this case, and do:
command = "svn st " + folderPath+ ";
output = CmdHelper.StartCmd(command);
output = string.Join("\r\n", output.Split("\r\n",StringSplitOptions.RemoveEmptyEntries)
.Where(x => x.Split(' ',StringSplitOptions.RemoveEmptyEntries)[0]
.Contains("?"))
.Select(s => s.Split(' ',StringSplitOptions.RemoveEmptyEntries)[1])
.ToList());
My c# code
public static string RunRScript(string filePath, string rScriptExecutablePath, string args, int totalFiles,
int RowsInChunk, int TotalRows, string identity)
{
string rCodeFilePath = filePath; //RScriptPath.GetFilePath();
//string file = rCodeFilePath;
string result = string.Empty;
// IEnumerable<string> connections = _connections.GetConnections(identity)
try
{
var info = new ProcessStartInfo();
info.FileName = rScriptExecutablePath;
info.WorkingDirectory = Path.GetDirectoryName(rScriptExecutablePath);
info.Arguments = "\"" + rCodeFilePath + "\"" + " " + args;
info.RedirectStandardInput = false;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
info.CreateNoWindow = true;
string fileName = string.Empty;
DateTime startTime = DateTime.Now;
List<ProgressTracker> lstProgress = new List<ProgressTracker>();
ProgressTracker p;
using (var proc = new Process())
{
//proc.StartInfo.Verb = "runas";
for (int i = 1; i <= totalFiles; i++)
{
p = new ProgressTracker();
p.DT = DateTime.Now;
p.Progress = i;
lstProgress.Add(p);
info.Arguments = "\"" + rCodeFilePath + "\"" + " " + args + " " + i.ToString();
proc.StartInfo = info;
proc.Start();
proc.WaitForExit();
result = proc.StandardOutput.ReadToEnd();
p.TimeTaken = (DateTime.Now - p.DT).TotalSeconds;
Functions.SendProgress("Process in progress...", i, totalFiles, RowsInChunk, TotalRows, lstProgress, identity);
}
}
return FormatOutput(result);
}
catch (Exception ex)
{
throw new Exception("R Script failed: " + result, ex);
}
}
Now objects have values like
info.FileName = C:\Program Files\R\R-3.4.3\bin\Rscript.exe
info.WorkingDirectory = C:\Program Files\R\R-3.4.3\bin
info.Arguments = "C:\MANOJ R\Topic modelling v2\TM_Webapi\Honeywell.UOP.TopicModel.Api\Uploads\h481821\TopicSearch.R" h481821 1
But process is not creating and its not calling R script and even it doesn't throwing any exception
Even I tried running VS as admin but no luck!
I have changed the .exe file path from
C:\Program Files\R\R-3.4.3\bin\Rscript.exe
to
C:\Program Files\R\R-3.4.3\bin\x64\Rscript.exe
Since I am using 64 bit machine
Now the process is working
My program allow user to insert bunch of images and one audio file, then can generate them into a video file. My program also allow user to provide duration for each images.
I am able to adding audio background into video output, but when video length is more longer than audio length, audio is not looping.
Also when audio length is more longer than video length, the video output will show blank till the end of audio.
Create Video
public bool CreateVideo(string name, List<string> imgs)
{
Bitmap bitmap = (Bitmap)null;
try
{
if (!Directory.Exists(this.outputFolder + "\\temp"))
Directory.CreateDirectory(this.outputFolder + "\\temp");
int num = this.rand.Next(this.delayMin, this.delayMax + 1);
List<string> stringList = new List<string>((IEnumerable<string>)imgs);
if (this.randomizeImages)
this.Shuffle((IList)stringList);
if (!string.IsNullOrEmpty(this.waterImage) && File.Exists(this.waterImage))
bitmap = (Bitmap)Image.FromFile(this.waterImage, true);
if (!string.IsNullOrEmpty(this.introImage))
{
int index = stringList.IndexOf(this.introImage);
if (index > 0)
{
string str = stringList[index];
stringList[index] = stringList[0];
stringList[0] = str;
}
}
for (int position = 0; position < stringList.Count; ++position)
this.ApplyWatermarkImage(stringList[position], position, (Image)bitmap);
if (bitmap != null)
bitmap.Dispose();
string str1 = "";
if (!string.IsNullOrEmpty(this.audioFile))
{
str1 = " -i \"" + this.audioFile + "\" -ar 22050 -ab 64k ";
if (this.GetAudioLength(this.audioFile) > num * stringList.Count)
str1 += "-shortest ";
}
string str2 = this.outputFolder + "\\" + name + ".avi";
ProcessStartInfo processStartInfo = new ProcessStartInfo(Environment.CurrentDirectory + "\\sm\\ffmpeg.exe", str1 + "-fflags +genpts -r 1/" + (object)num + " -b 32K -f image2 -i \"" + this.outputFolder + "\\temp\\%3d.jpg\" -vcodec mjpeg -s " + this.width.ToString() + "x" + this.height.ToString() + " -y -r 30 \"" + str2 + "\"");
Process process = new Process();
processStartInfo.WorkingDirectory = Directory.GetCurrentDirectory();
processStartInfo.CreateNoWindow = true;
processStartInfo.UseShellExecute = false;
processStartInfo.RedirectStandardError = true;
process.StartInfo = processStartInfo;
process.Start();
StreamReader standardError = process.StandardError;
Trace.WriteLine(standardError.ReadToEnd());
standardError.Close();
process.WaitForExit();
return process.ExitCode != 1 && process.ExitCode != -1;
}
catch (Exception ex)
{
Trace.WriteLine("CreateVideo: " + ex.Message);
return false;
}
finally
{
if (bitmap != null)
bitmap.Dispose();
try
{
if (Directory.Exists(this.outputFolder + "\\temp"))
Directory.Delete(this.outputFolder + "\\temp", true);
}
catch
{
}
}
}
Get Audio Length
public int GetAudioLength(string path)
{
string output = this.GetOutput(path);
int num = 0;
if (output == "" || output.Contains("Invalid data found when processing input") || output.Contains("could not find codec parameters"))
return num;
string str;
try
{
str = Regex.Match(output, "(?:Duration\\:)(.*?)(?:,)", RegexOptions.Singleline).Groups[1].Value.Trim();
}
catch (Exception ex)
{
str = "";
}
if (str != "")
{
try
{
num = int.Parse(str.Split(':')[0]) * 3600;
num += int.Parse(str.Split(':')[1]) * 60;
num += (int)double.Parse(str.Split(':')[2]);
}
catch (Exception ex)
{
}
}
return num;
}
Get Output
private string GetOutput(string video_file)
{
try
{
return Process.Start(new ProcessStartInfo()
{
FileName = Environment.CurrentDirectory + "\\sm\\ffmpeg.exe",
Arguments = "-i \"" + video_file + "\"",
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
}).StandardError.ReadToEnd();
}
catch (Exception ex)
{
return "";
}
}
I've looked around but couldn't find a solution. Any help will be greatly appreciated.
Is there any way to install JMF in silent mode using C#?
I have jmf.iss and JMF setup.exe and I'm having problems setting the silent parameter:
string[] programArray = {"SETUP.exe","Java-jre-7u45-windows-i586"};
foreach (string path in programArray)
{
using (Process p = new Process())
{
string arg = "passive";
if (path.Contains("SETUP"))
{
arg = "s /f1" + AppDomain.CurrentDomain.BaseDirectory + #"jmf.iss";
}
else if (path.Contains("Java"))
{
arg = "s";
}
p.StartInfo = new ProcessStartInfo(Application.StartupPath + "\\" + path);
p.StartInfo.Arguments = string.Format("/" + arg, path);
p.Start();
//p.WaitForExit();
while (!p.HasExited)
{
Application.DoEvents();
}
}
I have been trying to export and save registry files to an arbitrary location, the code is running. However, on specifying the path and saving, the function does not work and no registry is exported. There is no error shown either.
private static void Export(string exportPath, string registryPath)
{
string path = "\""+ exportPath + "\"";
string key = "\""+ registryPath + "\"";
// string arguments = "/e" + path + " " + key + "";
Process proc = new Process();
try
{
proc.StartInfo.FileName = "regedit.exe";
proc.StartInfo.UseShellExecute = false;
//proc.StartInfo.Arguments = string.Format("/e", path, key);
proc = Process.Start("regedit.exe", "/e" + path + " "+ key + "");
proc.WaitForExit();
}
catch (Exception)
{
proc.Dispose();
}
}
You need to add a space after the /e parameters so your code will be :
private static void Export(string exportPath, string registryPath)
{
string path = "\""+ exportPath + "\"";
string key = "\""+ registryPath + "\"";
using (Process proc = new Process())
{
try
{
proc.StartInfo.FileName = "regedit.exe";
proc.StartInfo.UseShellExecute = false;
proc = Process.Start("regedit.exe", "/e " + path + " "+ key);
proc.WaitForExit();
}
catch (Exception)
{
// handle exceptions
}
}
}
regedit.exe requires elevated privileges. reg.exe is better choice. It does not require any elevation.
Here's what we do.
void exportRegistry(string strKey, string filepath)
{
try
{
using (Process proc = new Process())
{
proc.StartInfo.FileName = "reg.exe";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.Arguments = "export \"" + strKey + "\" \"" + filepath + "\" /y";
proc.Start();
string stdout = proc.StandardOutput.ReadToEnd();
string stderr = proc.StandardError.ReadToEnd();
proc.WaitForExit();
}
}
catch (Exception ex)
{
// handle exception
}
}