I've created a GUI app that basically loads a video file, launches 3 processes with arguments in sequential order, (ffmpeg, x264, mp4box) and has the ability to abort if needed.
I'm trying to figure out a way to launch these processes without them stealing focus from whatever program is opened. Not necessarily the original form itself...it could be IE, MS WORD, etc...I know about ProcessWindowStyle, however, all options still take focus away. I do not want to start these processes hidden either.
This is an example of my code for starting a process
Process ffmpegProcess = new Process();
ffmpegProcess.StartInfo.FileName = Settings.Default.ffmpeg;
ffmpegProcess.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
string outputaud = text2 + "_audio.aac";
string AudioBitrate = this.cBAudiobitrate.GetItemText(this.cBAudiobitrate.SelectedItem);
string ffargs = "-i " + quote + SourceFile + quote + " -filter_complex " + quote + "[0:2][0:3]amerge=inputs=2,pan=stereo|c0=c0+c1|c1=c0+c1[aout]" + quote + " -map " + quote + "[aout]" + quote + " -strict experimental -acodec aac -b:a " + AudioBitrate + "k " + quote + outputaud + quote;
ffmpegProcess.StartInfo.Arguments = ffargs;
ffmpegProcess.Start();
while (!ffmpegProcess.HasExited)
{
if (this.bw404p_withaudio.CancellationPending)
{
ffmpegProcess.Kill();
e.Cancel = true;
return;
}
Thread.Sleep(1000);
}
I know about using the Microsoft.VisualBasic Reference and Shell command with AppWinStyle as it has options for launching with no focus, I just can't seem to figure out how to modify my code to make it work with that.
Any ideas?
Thanks
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
Is that would you're looking for? More info below
How to start Process hidden?
http://www.dotnetperls.com/process-start
ProcessWindowStyle Enumeration
Related
I have been trying to run a Windows command, utilising Atmel Studios atprogram utility, which is not exactly relevant but helps for context.
The following is my code, and the idea is that the output from the command is pushed into a rich text box. This is completed within the "AddTestJigString(output)" section.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string command = cmd();
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.FileName = "CMD.exe";
startInfo.Arguments = "/c cd " + ((char)34) + Path.GetDirectoryName(Properties.Settings.Default.Preferredatprogram) + ((char)34) + " && atprogram.exe - t avrispmk2 - i isp - d ATtiny26 - v chiperase program -f 30 - 5004_U21_V0.7.hex write - fs--values 61F6";
process.StartInfo = startInfo;
process.Start();
string output = process.StandardOutput.ReadToEnd();
AddTestJigString(output);
process.WaitForExit();
}
Key line being;
startInfo.Arguments = "/c cd " + ((char)34) + Path.GetDirectoryName(Properties.Settings.Default.Preferredatprogram) + ((char)34) + " && atprogram.exe - t avrispmk2 - i isp - d ATtiny26 - v chiperase program -f 30 - 5004_U21_V0.7.hex write - fs--values 61F6";
If i change this to just;
startInfo.Arguments = "/c cd " + ((char)34) + Path.GetDirectoryName(Properties.Settings.Default.Preferredatprogram) + ((char)34) + " && atprogram.exe";
I get the output of the help / list of available commands within my rich text box from atprogram.exe, so i am doing something right. However as soon as any parmeters are added, the output is totally blank.
Thanks for the above responses.
In response, the arguments for this command are defintitly correct, as it is in use in a production environment as a batch script.
The issue is actually down to outputting the command to a rich text box or more basically redirecting the command output.
The following solution I managed to get working:
{
string comhex = Path.GetFullPath(Properties.Settings.Default.PreferredComHex);
return "/c atprogram -t avrispmk2 -i isp -d ATtiny26 -v chiperase program -f " + ((char)34) + comhex + ((char)34) + " write -fs --values 61F6 2>&1";
}
The key part being the "2>&1" that I have added to the end of the command string. This effectively tells the command to redirect both Standard Output (stdout) and Standard Error (stderr). With 2 being stderr and 1 being stdout.
For further reading / reference:
In the shell, what does " 2>&1 " mean?
https://support.microsoft.com/en-gb/help/110930/redirecting-error-messages-from-command-prompt-stderr-stdout
i have just made an updater whihch also controls if app running.
Process[] processOfApp = Process.GetProcessesByName(setting.ExeName);
if (processOfApp.Length == 0)
{
Program = StartProcess(realPath + "\\" + setting.ExeName + ".exe");
AppDir = realPath + "\\" + setting.ExeName + ".exe";
ProcessExtensions.StartProcessAsCurrentUser(AppDir);
}
If no app process then start process. But these code start multiple instances.
What i did wrong?
Edit: these code block is in while(true) and this is the only start process in the code.
You may have copied this from somewhere without knowing what it does? I am guessing StartProcess function starts a process. And I assume, so does ProcessExtensions.StartProcessAsCurrentUser. So yes, it would start multiple (two) processes instead of one. If the updater should run a program for the current user from a windows service, delete the Program = ... line and retrive that information later on (using Process.GetProcessesByName, for example), if it is needed for something. That way the updater will be run as Current User, which is probably what you want.
// This line starts an instance
Program = StartProcess(realPath + "\\" + setting.ExeName + ".exe");
AppDir = realPath + "\\" + setting.ExeName + ".exe";
// This line also starts an instance
ProcessExtensions.StartProcessAsCurrentUser(AppDir);
I am developing an ASP.NET Web Api in which I need to concatenate some video clips and rotate them. I could achieve the same when I tried in my local system. When I deployed the same project to an Azure Virtual Machine I am not getting response. I am pretty sure that there isn't any issue till video concatenation because I could see the concatenated video in the expected folder. Here is the code snippet.
var ffMpeg = new NReco.VideoConverter.FFMpegConverter();
NReco.VideoConverter.ConcatSettings set = new NReco.VideoConverter.ConcatSettings();
ffMpeg.GetVideoThumbnail(_fileNames[0], imageRootPath + tobename + ".jpg");
if (_fileNames.Count() > 1)
{
ffMpeg.ConcatMedia(_fileNames, videoRootPath + tobename + "_r.mp4", NReco.VideoConverter.Format.mp4, set);
string path = HttpContext.Current.Server.MapPath("~\\bin\\");
System.Diagnostics.Process ffmpeg = new System.Diagnostics.Process();
ffmpeg.StartInfo.FileName = path + "\\" + "ffmpeg.exe";
ffmpeg.StartInfo.Arguments = "-i " + videoRootPath + tobename + "_r.mp4" + " -c copy -metadata:s:v:0 rotate=90 " + videoRootPath + tobename + ".mp4";
ffmpeg.Start();
ffmpeg.WaitForExit();
}
ffmpeg.ConcateMedia is working fine. I can't figure out why the External process that I have invoked does not complete. The same piece is working fine in my local Visual Studio.
Thank you in advance
It seems you are using Nreco VideoConvertor for joinging videos and external process to rotate the video.
You can always use Invoke method to write the custom commandline. something like this
ffMpeg.Invoke("-i " + videoRootPath + tobename + "_r.mp4" + " -c copy -metadata:s:v:0 rotate=90 " + videoRootPath + tobename + ".mp4");
Hope this Helps...
Your path ends with a slash, and when adding the paths together you also add a slash.
Use Path.Combine:
string path = HttpContext.Current.Server.MapPath("~\\bin");
ffmpeg.StartInfo.FileName = System.IO.Path.Combine(path, "ffmpeg.exe");
Env: .NET 3.5 Visual Studio 2008 SP1, on Win XP SP3, Python 2.7. Corporate image, no admin rights.
In C# 3.5, I want to pass a parameter to a command-line program, and this parameter contains newlines. It works in Python 2.7 but not in C#.
When body contains newline, c# truncates the result, but python passes it correctly.
Python code
cmd = self.app_path + ' email -Subject "' + subject + '" -From "' + address_from + '" -To "' + address_to +'" -Body "' + body +'"'
cmd_result = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()
C# code:
string Command = "<path to executable>";
string arguments = " email -From " + FromAddress + " -To " + ToAddress + " -Subject \"" + SubjectLine + "\" -Body \"" + emailBody + "\" ";
System.Diagnostics.ProcessStartInfo start = new System.Diagnostics.ProcessStartInfo(Command, arguments);
start.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
start.CreateNoWindow = false;
start.UseShellExecute = true;
System.Diagnostics.Process process = System.Diagnostics.Process.Start(start);
Any idea?
Update: body in the python example and emailBody in the c# example contain the same string, as strings are represented in each language.
Update: noticed the command wasn't terminated correctly in the python code. I added + '"' at the end of line 2. The code ran as before.
Also, as you can tell, the app called sends the body (emailBody) parameter content as an email body.
Sorry but I think it is the process you call that does not take the arguments correctly; it is not the C# that is involved, and as a proof of that:
Create a new windows form application
Make sure that the Main signature looks like this:
static void Main(string[] args)
Make sure that the call of your Main Form (named Form1) looks like this:
if (args==null)
{
Application.Run(new Form1());
}
else
{
Application.Run(new Form1(args));
}
Add a textbox to your form, with the multiline property set to true
Add a button to your form
Run the application once
Then Put this in the code of your button1_Click function (replace TheNameOfTheCurrentApp):
string Command = "TheNameOfTheCurrentApp";
string arguments = textBox1.Text;
System.Diagnostics.ProcessStartInfo start = new System.Diagnostics.ProcessStartInfo(Command, arguments);
start.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized;
start.CreateNoWindow = true;
start.UseShellExecute = true;
System.Diagnostics.Process process = System.Diagnostics.Process.Start(start);
Add this constructor to your form:
public Form1(string[] args)
{
InitializeComponent();
textBox1.Text = string.Join(" ", args);
}
Then run your app, insert muliple lines in your textbox and click the button. The same app will appear with the textbox correctly filled with the line breaks
I'm trying to hide a folder with C# using the MSDOS "attrib" command.
For now i'm able to do that by writing the "attrib" command + arguments in a batch file, running that file using Process.Start(), and then deleting it. I was wondering, can I do that directly from C#?
Here is what i've tryed so far... (the code below doesen't work)
public static void hideFolder(bool hide, string path)
{
string hideOrShow = (hide) ? "+" : "-";
Process.Start("attrib " + hideOrShow + "h " + hideOrShow + "s \"" + path + "\" /S /D");
}
Any help would be appriciated!
Thanx!
What you asked for:
string hideOrShow = (hide) ? "+" : "-";
Process.Start("cmd /c attrib " + hideOrShow + "h " + hideOrShow + "s \"" + path + "\" /S /D");
What you should do instead:
File.SetAttributes(path, FileAttributes.Hidden);
The first parameter to Process.Start() needs to be the name of an executable file or document. You'll need to pass in two parameters, like this:
Process.Start("attrib.exe", hideOrShow + "h " + hideOrShow + "s \"" + path + "\" /S /D");
Also, while attrib.exe will work when called directly, most people will pass this kind of DOS-style command to the command interpreter (which will also work for built-in commands, etc.)
Process.Start("cmd.exe", "/c attrib " + restOfTheArguments);
C# makes this really easy - the idea is you get the files current attributes (File.GetAttributes()), then you add in the Hidden attribute before calling File.SetAttributes()
check the below out, it'll make c:\blah hidden
static void Main(string[] args)
{
FileAttributes oldAttributes = File.GetAttributes(#"c:\blah");
File.SetAttributes(#"c:\blah", oldAttributes | FileAttributes.Hidden);
}
to remove the hidden attribute you need to remove the hidden attribute
static void Main(string[] args)
{
FileAttributes newAttributes = File.GetAttributes(#"c:\blah");
newAttributes = newAttributes & (~FileAttributes.Hidden);
File.SetAttributes(#"c:\blah", newAttributes);
}
What's the error? Why not use http://msdn.microsoft.com/en-us/library/system.io.filesysteminfo.attributes.aspx ?