Problem launching FFmpeg inside C# - c#

I'm calling FFmpeg via ProcessStartInfo inside my C# application however, I can't keep getting the error;
File for preset 'lossless_slow' not
found
Here's my C# code;
var processinfo = new ProcessStartInfo();
processinfo.FileName = "FFmpeg\\bin\\ffmpeg.exe";
processinfo.Arguments = "-i C:\Temp\input.mp4 -y -acodec aac -strict experimental -ab 96k -vcodec libx264 -vpre lossless_slow -crf 22 -threads 0 C:\Temp\output.mp4"
processinfo.RedirectStandardOutput = true;
processinfo.RedirectStandardError = true;
processinfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
processinfo.UseShellExecute = false;
processinfo.LoadUserProfile = true;
processinfo.EnvironmentVariables.Add("HOME", #"C:\Users\wonea\.ffmpeg");
var reg = System.Diagnostics.Process.Start(processinfo);
string output = string.Empty;
string error = string.Empty;
using (System.IO.StreamReader myOutput = reg.StandardOutput)
{
output = myOutput.ReadToEnd();
}
using (System.IO.StreamReader myError = reg.StandardError)
{
error = myError.ReadToEnd();
}
Now I've put my presets in the folder
C:\Users\wonea\ .ffmpeg
and included this in the Windows path user variable HOME. This works fine when running FFmpeg from the command line, however fails when the commands are issued inside my C# application, why!? Thanks for any help...!
Also of note, I'm running the service as "Network Service".

In situations like this I always start up the procmon tool which can show you all the file operations of your application. You can set up a filter based on the name of the preset file and see where ffmpeg is trying to locate it.

Setting the HOME variable looks good here.
The only thing I see is that in the code you set HOME to be #"C:\Users\wonea.ffmpeg" and in the text you mention the file is at : C:\Users\wonea.ffmpeg
Is one of these a typo?

Related

How to import a Windows Power Plan with C#

I'm working on a small C# app that will import a power plan to the user's PC and set it as active.
It working perfectly with a .bat file when the .pow file is in the same folder and I'm running commands:
powercfg -import "%~dp0\Optimized.pow"
powercfg /setactive 62ffd265-db94-4d48-bb7a-183c87641f85
Now, in C# I tried this:
Process cmd = new Process();
cmd.StartInfo.FileName = "powercfg";
cmd.StartInfo.Arguments = "-import \"%~dp0\\Optimized\"";
cmd.StartInfo.Arguments = "powercfg /setactive 62ffd265-db94-4d48-bb7a-183c87641f85";
cmd.Start();
//and this:
private void button1_Click(object sender, EventArgs e)
{
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();
cmd.StandardInput.WriteLine("powercfg -import \"%~dp0\\Optimized\"");
cmd.StandardInput.WriteLine("powercfg /setactive 6aa8c469-317b-45d9-a69c-f24d53e3aff5");
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
cmd.WaitForExit();
Console.WriteLine(cmd.StandardOutput.ReadToEnd());
}
But the program doesn't see the .pow file in the project folder (I actually tried to put it in each and every folder in the project).
How it can be implemented to let the powercfg see the file?
Any help is much appreciated!
Thanks!
You could try something like this:
var cmd = new Process {StartInfo = {FileName = "powercfg"}};
using (cmd) //This is here because Process implements IDisposable
{
var inputPath = Path.Combine(Environment.CurrentDirectory, "Optimized.pow");
//This hides the resulting popup window
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
//Prepare a guid for this new import
var guidString = Guid.NewGuid().ToString("D"); //Guid without braces
//Import the new power plan
cmd.StartInfo.Arguments = $"-import \"{inputPath}\" {guidString}";
cmd.Start();
//Set the new power plan as active
cmd.StartInfo.Arguments = $"/setactive {guidString}";
cmd.Start();
}
This fixes the Arguments parameter that is being overwritten/used twice, as well as correctly disposes of the cmd variable. Additional lines added to hide the resulting pop-up window, and for generating the Guid upfront and specifying it as part of the command line.
Your first snippet does not work because you're reassigning cmd.StartInfo.Arguments before executing the process. The first assignment is lost when you throw it out in favor of the second assignment.
The first snippet most likely doesn't work because when you set cmd.startInfo.FileName to just a filename with no path, it will search only the directory of your C# app's .exe (likely in project/bin/Debug/). Since the FileName is cmd.exe and there is probably no cmd.exe in your project folder, it can't find anything.
You may also consider setting cmd.StartInfo.WorkingDirectory to an appropriate directory with your .pow file so that your relative paths will resolve correctly.

Executing Batch File At This Directory

I have this code piece that used in my c# form project. I also have exp.bat file contains shell commands as below.
But whatever I do, it does not create .txt file at working directory.
#echo off
echo "hello" > test.txt
path = #"‪C:\Users\abc\Desktop\exp.bat";
startingPath = #"C:\Users\abc\Desktop\";
bool success = false;
try
{
System.Diagnostics.ProcessStartInfo ProcStartInfo = new
System.Diagnostics.ProcessStartInfo("cmd");
ProcStartInfo.RedirectStandardOutput = true;
ProcStartInfo.UseShellExecute = false;
ProcStartInfo.CreateNoWindow = false;
ProcStartInfo.RedirectStandardError = true;
System.Diagnostics.Process MyProcess = new System.Diagnostics.Process();
ProcStartInfo.Arguments = "/c start /wait"+path;
ProcStartInfo.WorkingDirectory = startingPath;
MyProcess.StartInfo = ProcStartInfo;
success = MyProcess.Start();
MyProcess.WaitForExit();
}
catch (Exception ex) { string s = ex.StackTrace.ToString();}
Originally posted by use Mofi in comments.
posting the same answer as is so this question is not counted in unanswered, question author also confirms in comments that the answer by Mofi was correct and it helped.
I think enough background, here is the comment as the answer.
In C# code use the method Environment.GetEnvironmentVariable to get the string value of predefined Windows environment variable USERPROFILE to build the paths for exp.bat and starting directory dynamically already within C# application. Or even better get current user desktop folder directly, see How to get a path to the desktop for the current user in C#? – Mofi Feb 22 at 12:25
You can easily achieve that by adding the following commands to the beginning of your bat file.
%~d0
cd %~dp0

Unable to run python script in c# which runs scrapy spider

I followed this_link and I was able to run a dummy python file from my c# code like this...
public JsonResult FetchscrapyDataUrl(String website)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = #"C:\ProgramData\Anaconda3\python.exe";
start.Arguments = #"C:\Users\PycharmProjects\scraping_web\scrape_info\main.py";
//this is path to .py file from scrapy project
start.CreateNoWindow = false; // We don't need new window
start.UseShellExecute = false; // Do not use OS shell
//start.RedirectStandardOutput = true;// Any output, generated by application will be redirected back
start.RedirectStandardError = true; // Any error in standard output will be redirected back (for example exceptions)
Console.WriteLine("Python Starting");
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string stderr = process.StandardError.ReadToEnd(); // Here are the exceptions from our Python script
string result = reader.ReadToEnd(); // Here is the result of StdOut(for example: print "test")
Console.Write(result);
}
}
}
Now I know that I can run scrapy spider from a single file main.py like this...
from scrapy import cmdline
cmdline.execute("scrapy crawl text".split())
When I run main.py file from cmd in windows it works fine but it does not work when I run it from C# code .Net framework. The error is ...
"Scrapy 1.4.0 - no active project\r\n\r\nUnknown command: crawl\r\n\r\nUse \"scrapy\" to see available commands\r\n"
Any Idea how to run this...Or am i missing some path setting in windows ??
Or should I run my spider from C# in some other way??
You need to set the WorkingDirectory property
start.WorkingDirectory = #"C:\Users\PycharmProjects\scraping_web\scrape_info\"
Or you need to cd to that directory to make it work

How to catch %ERRORLEVEL% when running Psexec.exe in C#, save to log file

I am using psexec.exe to install some software on a large amount of computers. I would like to be able to catch the %ERRORLEVEL% (or its c# equivalent) and write them to a TXT file. ( cmd.exe exited on 6440-nbpb00f51w with error code 0.)
After extensive research, I am finding several possibilities. My end-goal will be to have a .CSV file. Each row would have the computer name and the output of the psexec command. Using this data I will be able to determine which computers the update was successful on.
string[] pcnamearray = new string[] {"COMPUTERNAME1", "COMPUTERNAME2"};
foreach (string i in pcnamearray)
{
Process p = new Process();
string psexeclaunch = "psexec.exe";
p.StartInfo.FileName = psexeclaunch;
p.StartInfo.RedirectStandardOutput = false;
p.StartInfo.UseShellExecute = true;
p.StartInfo.CreateNoWindow = false;
string arg = "/silent";
p.StartInfo.Arguments = #" -i \\" + i + #" -u mydomain\admin -p mypassword -h -e cmd.exe /c start \\networkserver\sw\myfile.exe" + arg;
p.Start();
}
I am not here looking for someone to write the code for me. I am here to ask people for their advice, or past experiences with this. I know there are several different methods available. Ideally, I would prefer to have a short sweet line for each result, but if i have to take the entire output and use macros to shave them down to a more readable form, that is fine too.
So far, I have tried:
Console.WriteLine(p.StandardOutput.ReadToEnd());
And...
System.IO.File.WriteAllLines(#"C:\Users\areu2447\Desktop\UpdateDAT\Final\out.txt", lines);
And...
FileStream filestream = new FileStream(#"C:\Users\areu2447\Desktop\UpdateDAT\Final\out.txt", FileMode.Append);
var streamwriter = new StreamWriter(filestream);
streamwriter.AutoFlush = true;
Console.SetOut(streamwriter);
Console.SetError(streamwriter);
The last one seems to me like the best one but cannot seem to get it to work. I have tried including it in my foreach loop, but file is in use by another process, so after looking into it i found that it needed to be on its own. Even with it alone, i still cannot get it to work.
Please help/advise!
I was able to get it to actaully modify my TXT file, even though there was nothing added to it, by using the following:
System.IO.StreamReader reader = p.StandardOutput;
String sRes = reader.ReadToEnd();
StreamWriter SW;
SW = File.CreateText(#"C:\Users\areu2447\Desktop\UpdateDAT\Final\out.txt");
SW.WriteLine(sRes);
SW.Close();
Console.WriteLine("File Created Successfully");
reader.Close();
I would recommend using System.Management.Automation to create a PowerShell pipeline and run the script in process.
Executing PowerShell scripts from C#

Running Phantomjs using C# to grab snapshot of webpage

I'm trying to grab snapshots of my own website using phantomjs - basically, this is to create a "preview image" of user-submitted content.
I've installed phantomjs on the server and have confirmed that running it from the command line against the appropriate pages works fine. However, when I try running it from the website, it does not appear to do anything. I have confirmed that the code is being called, that phantom is actually running (I've monitored the processes, and can see it appear in the process list when I call it) - however, no image is being generated.
I'm not sure where I should be looking to figure out why it won't create the images - any suggestions? The relevant code block is below:
string arguments = "/c rasterize.js http://www.mysite.com/viewcontent.aspx?id=123";
string imagefilename = #"C:\inetpub\vhosts\mysite.com\httpdocs\Uploads\img123.png";
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.CreateNoWindow = false;
p.StartInfo.FileName = #"C:\phantomjs.exe";
p.StartInfo.Arguments = arguments + " " + imagefilename;
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
I check the errors that phantomjs throws during its process.
You can read them from Process.StandardError.
var startInfo = new ProcessStartInfo();
//some other parameters here
...
startInfo.RedirectStandardError = true;
var p = new Process();
p.StartInfo = startInfo;
p.Start();
p.WaitForExit(timeToExit);
//Read the Error:
string error = p.StandardError.ReadToEnd();
It will give you an idea of what happened
The easiest way for executing phantomjs from C# code is using wrapper like NReco.PhantomJS. The following example illustrates how to use it for rasterize.js:
var phantomJS = new PhantomJS();
phantomJS.Run( "rasterize.js", new[] { "https://www.google.com", outFile} );
Wrapper API has events for stdout and stderr; also it can provide input from C# Stream and read stdout result into C# stream.

Categories