I tried to port a .net console application to a docker container. The application tries to call ffmpeg.exe, I get an error? Is it possible that I can't run an exe in this container?
static void encoder(string inputFile, string outputFolder, string outputFileName)
{
if (!Directory.Exists(outputFolder))
{
Directory.CreateDirectory(outputFolder);
}
var GetDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
// Part 1: use ProcessStartInfo class.
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardInput = true;
startInfo.FileName = GetDirectory + #"/ffmpeg.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
// Part 2: set arguments.
startInfo.Arguments = "-i " + inputFile + " -q:a 8 -filter:a loudnorm " + outputFolder + outputFileName;
// Part 3: start with the info we specified.
// ... Call WaitForExit.
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.StandardInput.WriteLine("y");
exeProcess.WaitForExit();
}
}
Error
OPUS-Encoder System.ComponentModel.Win32Exception (8): An error occurred trying to start process '/App/ffmpeg.exe' with working directory '/App'. Exec format error
at System.Diagnostics.Process.ForkAndExecProcess(ProcessStartInfo startInfo, String resolvedFilename, String[] argv, String[] envp, String cwd, Boolean setCredentials, UInt32 userId, UInt32 groupId, UInt32[] groups, Int32& stdinFd, Int32& stdoutFd, Int32& stderrFd, Boolean usesTerminal, Boolean throwOnNoExec)
at System.Diagnostics.Process.StartCore(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start()
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
at Program.<<Main>$>g__encoder|0_0(String inputFile, String outputFolder, String outputFileName) in /App/Program.cs:line 77
at Program.<Main>$(String[] args) in /App/Program.cs:line 34
thx
Looks like your docker container running Linux, but executable is Windows PE.
If your container is running Linux you need Linux binary not Windows
".exe".
You can get one here
API for call will be same.
If you want to support Linux and Windows you will need to change path parameter according to current OS.
Here is the question about how to do it on runtime.
Related
I am trying the following:
1) Running a c# executable from another executable.
I am using .net core 3.1
Problem
I get the following error when I run the app in linux.
Error =>No such file or directory
Exception encountered => System.ComponentModel.Win32Exception (2): No such file or directory
at System.Diagnostics.Process.ForkAndExecProcess(String filename, String[] argv, String[] envp, String cwd, Boolean
redirectStdin, Boolean redirectStdout, Boolean redirectStderr, Boolean
setCredentials, UInt32 userId, UInt32 groupId, UInt32[] groups, Int32&
stdinFd, Int32& stdoutFd, Int32& stderrFd, Boolean usesTerminal,
Boolean throwOnNoExec)
at System.Diagnostics.Process.StartCore(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start()
at ConsoleMQTT_Sender.ProcessClass.LaunchProcess(....) in ...
The app is generated through jenkins running in a linux environment.
The file is present but getting the above error.
Is this a cross-platform issue?
or a permission issue?
Flag when running the first executable
dotnet firstexecutable.dll --secondexecutablepath "/opt/publish/xyz.dll"
dotnet firstexecutable.dll --secondexecutablepath "dotnet /opt/publish/xyz.dll"
both giving the same exception
How I am triggering the executable inside c# console app :
process.EnableRaisingEvents = true;
process.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_OutputDataReceived);
process.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_ErrorDataReceived);
process.StartInfo.FileName = firstexecutablepath;
process.StartInfo.Arguments = "--secondexecutablepath \"" + executablepath + "\"";
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
process.WaitForExit();
I am creating an app in asp.net core that is run in a linux docker container using visual studio on windows. This app launches a different process depending on what platform it is on with Process.Start(). Currently, the process is launched correctly when run on my local windows machine, but when I switch to linux container I get this error (even tho both files I am attempting to launch are stored in the same directory). I did a check with File.Exists(processPath) and it shows that the file does in fact exist, but when the process is launched the Interop.Sys.ForkAndExecProcess() method seems to throw "No such file or directory" when it actually tries to launch the binary.
Unhandled Exception: System.ComponentModel.Win32Exception: No such file or directory
at Interop.Sys.ForkAndExecProcess(String filename, String[] argv, String[] envp, String cwd, Boolean redirectStdin, Boolean redirectStdout, Boolean redirectStderr, Boolean setUser, UInt32 userId, UInt32 groupId, Int32& lpChildPid, Int32& stdinFd, Int32& stdoutFd, Int32& stderrFd, Boolean shouldThrow)
at System.Diagnostics.Process.StartCore(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start()
Here is the code
var assemblyFileInfo = new FileInfo(typeof(TemplateClass).Assembly.Location);
var rootDirectory = Path.Combine(assemblyFileInfo.DirectoryName, "HelmExecutables/Data/");
var processPath = "";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
processPath = Path.Combine(rootDirectory + "helm_windows.exe");
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
processPath = Path.Combine(rootDirectory + "helm_linux.out");
}
var process = new Process();
var startInfo = new ProcessStartInfo();
startInfo.FileName = processPath;
process.StartInfo = startInfo;
process.Start();
One thing that came into my mind looking your code is processPath can be just an empty string if both RuntimeInformation.IsOSPlatform(OSPlatform.Windows) and RuntimeInformation.IsOSPlatform(OSPlatform.Linux) are false.
What I would do is check if RuntimeInformation.IsOSPlatform(OSPlatform.Linux) is true when the code runs in the docker image.
After that, I would Console.WriteLine(processPath) (or get the value of processPath in any other way) and try to start that executable from the command-line manually and see what happens.
I need to print a pdf-file with ProcessStartInfo.
string docInvoicePath = #"[Path]";
string printername = "\"PRN-OFFICE\"";
string driver = "\"Xerox Global Print Driver PS\"";
string port = "\"[IP]\"";
ProcessStartInfo psInfo = new ProcessStartInfo
{
FileName = #"""C:\Program Files (x86)\Adobe\Reader 9.0\Reader\AcroRd32""",
Arguments = String.Format("/s /o /h /t " + docInvoicePath + " " + printername + " " + driver + " " + port),
Verb = "print",
WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true,
UseShellExecute = false
};
Process process = Process.Start(psInfo);
process.WaitForExit(6000);
if (process.HasExited == false)
{
process.Kill();
}
process.Close();
The filename and arguments are correct they work when pasted in cmd.
The code works properly but after Process.Start when it comes to WaitForExit the programm doesn`t finish. I get the timeout error:
System.Threading.ThreadAbortException: Thread was being aborted.
at System.Threading.WaitHandle.WaitOneNative(SafeHandle waitableSafeHandle, UInt32 millisecondsTimeout, Boolean
hasThreadAffinity, Boolean exitContext)
at System.Threading.WaitHandle.InternalWaitOne(SafeHandle waitableSafeHandle, Int64 millisecondsTimeout, Boolean
hasThreadAffinity, Boolean exitContext)
at System.Diagnostics.Process.WaitForExit(Int32 milliseconds)...
I searched and try a few things like setting <httpRuntime executionTimeout="300"/> and run into a 500 or like in the code with process.WaitForExit(6000); and higher ther where no exeption but nothing got printed.
Is there an error or am i missing something?
EDIT:
I changed my codeblock above. Now the code works in debug mode but it still won´t print my document when published. I also tried to use a different User.
In debug mode the code prints the document but runs in the kill query.
The ProcessStartInfo.Verbs returns a Argument Exception but i don´t know why.
After a lot of trying, testing and searching i am sure my code works.
So i still don´t really know why my code stoped working.
But changing from Adobe Reader 9.0 on the server to 7.0 it now works.
When i was debuging locally with Adobe Reader 9.0 it also worked, so i think maybe there was an update on the webserver. I diden`t verifyed that yet.
TekRadius is a Radius server that I want to access through my ASP.NET application. I first tried to execute TekRadius CLI directly using C#. But it didn't worked. Now I am trying to execute it through CMD by calling it in C# code like this:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.CreateNoWindow = true;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C \"c:\Program Files (x86)\TekRADIUS LT\trclilt.exe\" -u " + username + " " + password;
process.StartInfo = startInfo;
process.Start();
string line = "";
while (!process.StandardError.EndOfStream)
{
line = line + "\n" + process.StandardError.ReadLine();
}
File.WriteAllText(HttpContext.Current.Server.MapPath("~\\error.txt"), line);
TekRadius is working fine when executed directly through CLI or GUI or through Visual Studio's Internal Server. But on main server my custom error log error.txt is showing this error:
Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.UnauthorizedAccessException: Access to the path 'C:\Windows\TEMP\System.Data.SQLite.dll' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.File.InternalReadAllBytes(String path, Boolean checkHost)
at ????????????????????????????????????????.????????????????????????????????????????(String , String )
at ????????????????????????????????????????.????????????????????????????????????????()
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at ????????????????????????????????????????(String[] )
TekRadius CLI uses SQLLite for storing its username and password. And I know its the TekRadius that is unable to access 'C:\Windows\TEMP\System.Data.SQLite.dll', not my application because I am using SQL Server and my above C# code is not making any attempts to access database. I am using Windows Server 2012 R2 and I am also unable to set new permissions on Windows folder. Please tell me what can I do to give access to this location to TekRadius CLI?
Finally after 12 hours I was able to solve it by myself. Solution was to give full control to ISS_IUSRS for System.Data.SQLite.dll in C:\Windows\Temp folder. Also, do the same for c:\Program Files (x86)\TekRADIUS LT\trclilt.exe.
In an application I need to execute other programs with another user's credentials. Currently I use System.Diagnostics.Process.Start to execute the program:
public static Process Start(
string fileName,
string arguments,
string userName,
SecureString password,
string domain
)
However this function does not load the roaming profile from the net - which is required.
I could use "runas /profile ..." to load the profile and execute the command, but that would ask for a password. There must be an more elegant way...
But where?
My solution (based on leppie's hint):
Process p = new Process();
p.StartInfo.FileName = textFilename.Text;
p.StartInfo.Arguments = textArgument.Text;
p.StartInfo.UserName = textUsername.Text;
p.StartInfo.Domain = textDomain.Text;
p.StartInfo.Password = securePassword.SecureText;
p.StartInfo.LoadUserProfile = true;
p.StartInfo.UseShellExecute = false;
try {
p.Start();
} catch (Win32Exception ex) {
MessageBox.Show("Error:\r\n" + ex.Message);
}
System.Diagnostics.ProcessStartInfo.LoadUserProfile