Process.Start() Emulator and command line - c#

I'm using the .Start process to run an emulator and a command line for the emulator to open the game, but when I run it, it opens the emulator but without the command line and the game that is selected in a listbox, would anyone have any ideas for this command line.
Command Line arguments:
-L "cores\genesis_plus_gx_libretro.dll"
private void StartGame()
{
string rom = #"ROMFILES\" + RomfilesList.Text.ToString() + ".zip".ToString();
string emulator = #"EMULATOR\retroarch.exe";
string commandline = #"-L cores\genesis_plus_gx_libretro.dll" + rom;
if (!File.Exists(emulator))
{
MessageBox.Show("Emulator is required to continue.", "ERROR", MessageBoxButtons.OK,MessageBoxIcon.Error);
}
if (File.Exists(emulator))
{
Process.Start(emulator, "\"" + commandline);
}
}

Related

Powershell Timeout From C#

I want to set a timeout on powershell scripts I have running in c#.
My code to run my scripts is
private void RunPowerShell(string scriptText)
{
string tempFile = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "PinScript.ps1");
var file = new StreamWriter(tempFile);
file.AutoFlush = true;
file.WriteLine(scriptText);
file.Dispose();
string output, errors = string.Empty;
//this is basically a helper method that runs an exe via the command prompt in c#
//I want to keep this as is and either add an argument to powershell.exe or alter the
//.psi scripts themselves
_cmd.Run(#"powershell.exe",
#"-NoProfile -ExecutionPolicy Bypass " + #"& '" + tempFile + "'",
out output,
out errors);
Console.WriteLine("Powershell Output: " + output);
Console.WriteLine("Powershell Errors: " + errors);
File.Delete(tempFile);
}
I see there is code that works to time out a script here but I cannot understand how to ingrate that concept into what I have above.

Get standard out from command line call in c#?

Right now I am trying to get the standard out when I pass in the command to a batch shell (.bat file) through C#. I am able to get the initial standard out when the cmd prompt starts up (says something like "Hello World" when opened), however if I give it an argument like "ping 127.0.0.1", I am unable to get the output. I have tried two ways of capturing the output so far. The starting of the process stays the same.
private void testShell(string command)
{
ProcessStartInfo pi = ProcessStartInfo(*batch shell path*, command);
pi.CreateNoWindow = true;
pi.UseShellExecute = false;
pi.RedirectStandardOutput = true;
pi.RedirectStandardInput = true;
Process pr = Process.Start(pi);
//option 1
while(!pr.StandardOutput.EndOfStream)
{
//do something with the line
}
//option 2
string str = "";
using (System.IO.StreamReader output = pr.StandardOutput)
{
str = output.ReadToEnd();
}
//option 3
string output = pr.StandardOutput.ReadToEnd();
//do something with the output
}
Is it possible to pass in a argument to a batch file (this seems to be the actual problem)?
You can't directly pass a command as an argument.
CMD [/A | /U] [/Q] [/D] [/E:ON | /E:OFF] [/F:ON | /F:OFF] [/V:ON | /V:OFF]
[[/S] [/C | /K] string]
/C Carries out the command specified by string and then terminates
/K Carries out the command specified by string but remains
You need to write the start argument as /c ping 127.0.0.1 or :
ProcessStartInfo pi = ProcessStartInfo(*batch shell path *, "/c " + command);
note: this will break, if the start process file is a batch file (*.bat) instead of a shell console ("cmd")
Alternatively, you can write the command to the standard input :
pr.StandardInput.WriteLine(command);
// do stuffs with pr.StandardOutput
Attach a method to the outputdatareceived event.
pi.OutputDataReceived += (objectsender,DataReceivedEventArgs e) => datareceivedtwritetolog(sender, e);
Then create a method to do something with the output:
public static void datareceivedtwritetolog(object sender, DataReceivedEventArgs e)
{
string logpath = #"c:\log-" + DateTime.Now.ToString("MMddyy") + ".txt";
File.AppendAllText(logpath, e.Data + Environment.NewLine);
}
The code you're showing won't compile (it's missing a new directive). At any rate, something specific about the batch file you're not showing is probably failing. The following will work:
Create a file called Example.cs with the following contents:
using System;
using System.Diagnostics;
namespace Example
{
class ExampleClass
{
static void Main()
{
ProcessStartInfo pi = new ProcessStartInfo("ExampleBatch.cmd", "a b c d");
pi.CreateNoWindow = true;
pi.UseShellExecute = false;
pi.RedirectStandardOutput = true;
pi.RedirectStandardInput = true;
Process pr = Process.Start(pi);
string output = pr.StandardOutput.ReadToEnd();
Console.WriteLine("--------------------");
Console.WriteLine("[" + output.ToUpper() + "]");
Console.WriteLine("--------------------");
}
}
}
Then create a file called ExampleBatch.cmd with the following contents:
#echo off
echo This is from the example.
echo Param 1: [%1]
echo Param 2: [%2]
echo Param 3: [%3]
echo Param 4: [%4]
echo Param 5: [%5]
Then compile the .cs file with csc Example.cs. And finally, running Example.exe will show the following output:
--------------------
[THIS IS FROM THE EXAMPLE.
PARAM 1: [A]
PARAM 2: [B]
PARAM 3: [C]
PARAM 4: [D]
PARAM 5: []
]
--------------------
This shows that the batch file was able to capture the command line arguments, and the C# program was able to capture the output and process it.

Process.Start not executing command

I am using ImageMagick C# tool to convert PDF to JPG by calling the executable from C#. I believe I set up the command correctly but it does not execute; it just passes through Process.Start(startInfo) without executing it. I do see the command prompt popping up but nothing happens.
string PNGPath = Path.ChangeExtension(Loan_list[f], ".png");
string PDFfile = '"' + Loan_list[f] + '"';
string PNGfile = '"' + PNGPath + '"';
string arguments = string.Format("{0} {1}", PDFfile, PNGfile);
ProcessStartInfo startInfo = new ProcessStartInfo(#"C:\Program Files\ImageMagick-6.9.2-Q16\convert.exe");
startInfo.Arguments = arguments;
Process.Start(startInfo);
I wasn't sure if it was because of the double quotes I added to each argument before hand but after commenting it out and running it again, it still skipped over. Any thoughts?
Edit: To add some clarity, I am expecting a JPG files from a PDF but I see no output file from this part of code. I ran the following in my command prompt to convert PDF to JPG
"C:\Program Files\ImageMagick-6.9.2-Q16\convert.exe" "C:\Users\rwong\Desktop\RoundPoint\1000965275\1000965275_157_Credit File_10.PDF" "C:\Users\rwong\Desktop\RoundPoint\1000965275\1000965275_157_Credit File_10.png"
I explicitly called the convert.exe for clarity sake in my code. The command works fine in command prompt but when coping the structure over to C# it doesn't do anything. I see the code step into it but it continues without an error.
Edit2: Upon request below is the code and output for a Process Exit code
string PNGPath = Path.ChangeExtension(Loan_list[f], ".png");
string PDFfile = '"' + Loan_list[f] + '"';
string PNGfile = '"' + PNGPath + '"';
try
{
Process myprocess = null;
string[] arguments = { PDFfile, PNGfile };
myprocess=Process.Start(#"C:\ProgramFiles\ImageMagick6.9.2Q16\convert.exe", String.Join(" ", arguments));
Console.WriteLine("Process exit code: {0}", myprocess.ExitCode);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Process exit code: 1
Assuming that you are right and there was a problem (rather than the process just executed very quickly and exited), you can check the return code as follows:
if (Process.Start(startInfo) == null)
{
int lastError = Marshal.GetLastWin32Error();
}
You then go here to look up the error code:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
Hopefully, that vendor actually sets an error code on failure (they may or may not).

Install SQL Server 2012 Express Programmatically

I work on Setup application to install all requirement for my WPF product, one of the requirement is SQL Server 2012 Express, the code below is to install it after I generate the configuration file for silent installation :
private void SetupSQLServer()
{
string result = "";
string commandLine = "";
if (os64)
commandLine = string.Format(#"{0}\SQLServer\sql64\setup.exe PCUSOURCE={0}\SQLServer\sql64 /SAPWD=""p#ssw0rd"" /CONFIGURATIONFILE={0}\SQLServer\ConfigurationFile64.ini /HIDECONSOLE", setupFolder);
else
commandLine = string.Format(#"{0}\SQLServer\sql86\setup.exe PCUSOURCE={0}\SQLServer\sql86 /SAPWD=""p#ssw0rd"" /CONFIGURATIONFILE={0}\SQLServer\ConfigurationFile32.ini /HIDECONSOLE", setupFolder);
startInfo.WorkingDirectory = setupFolder;
startInfo.Arguments = "/c " + commandLine;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
process.StartInfo = startInfo;
try
{
process.Start();
}
catch (Exception e)
{
result = e.Message;
}
result = result + "\n" + process.StandardOutput.ReadToEnd();
UpdateStepResult(result);
}
There's no error in the code but it does not work .. when I run the code the command window appear and disappear and nothing happen.
UPDATE:
When I used:
fileName = string.Format(#"{0}\SQLServer\sql64\setup.exe", setupFolder);
The installation is run but without configuration file, when I used:
fileName = string.Format(#"{0}\SQLServer\sql64\setup.exe /CONFIGURATIONFILE={0}\SQLServer\sql64\ConfigurationFile64.ini", setupFolder);
It gives me this error "The system cannot find the file specified" !!!
The file is exist in the same folder !!
Please can you help me to discover the mistake.
Thanks in advance.
The ProcessStartInfo requires the FileName property to be valid. Your code above doesn't set it but pass everything as Arguments.
Probably you need to separate the command line in two parts. The Executable to run and the arguments to pass
if (os64)
{
fileName = string.Format("{0}\SQLServer\sql64\setup.exe", setupFolder);
commandLine = string.Format(#"PCUSOURCE={0}\SQLServer\sql64 /SAPWD=""p#ssw0rd"" /CONFIGURATIONFILE={0}\SQLServer\ConfigurationFile64.ini /HIDECONSOLE", setupFolder);
}
else
{
// Same for 32 bit
.....
}
....
startInfo.FileName = fileName;
....

Getting output from DxDiag in C#

So I am trying to automate the output from DxDiag in C# and I have run into a problem. The program runs but doesn't produce any output file. It might be that I am not passing parameters correctly or that I am misunderstanding something.
When running DxDiag in the normal command line I do this and it works as expected:
dxdiag -64bit -x C:\dxFromCode.xml
And this is how I am trying to do it in code:
//Create process
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
pProcess.StartInfo.FileName = "dxdiag";
pProcess.StartInfo.Arguments = #"64bit x C:\dxFromCode.xml";
pProcess.StartInfo.UseShellExecute = false;
//Set output of program to be written to process output stream
pProcess.StartInfo.RedirectStandardOutput = false;
//Start the process
pProcess.Start();
//Wait for process to finish
pProcess.WaitForExit();
EDIT:
Ok, so I changed my code to build for x64. This makes dxdiag automatically start the as the 64-bit version. Then I could just take away the 64bit switch and suddenly everything works as I would expect.
DxDiag is quite cranky on a 64-bit OS. The 32-bit version and the 64-bit version accept different command line switches and it doesn't give a peep when you use the wrong one. The /x option simply does not work when you try to use the /64bit option on the 32-bit version. And the 64-bit version does not accept /64bit. You'll have to start the 64-bit version explicitly when you run on a 64-bit OS and your program runs in 32-bit mode.
This worked well on my Win81 x64 machine:
private string RunDxDiag() {
var psi = new ProcessStartInfo();
if (IntPtr.Size == 4 && Environment.Is64BitOperatingSystem) {
// Need to run the 64-bit version
psi.FileName = System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Windows),
"sysnative\\dxdiag.exe");
}
else {
// Okay with the native version
psi.FileName = System.IO.Path.Combine(
Environment.SystemDirectory,
"dxdiag.exe");
}
string path = System.IO.Path.GetTempFileName();
try {
psi.Arguments = "/x " + path;
using (var prc = Process.Start(psi)) {
prc.WaitForExit();
if (prc.ExitCode != 0) {
throw new Exception("DXDIAG failed with exit code " + prc.ExitCode.ToString());
}
}
return System.IO.File.ReadAllText(path);
}
finally {
System.IO.File.Delete(path);
}
}
Try adding /user:Administrator cmd /K to the arguments statement. Like this:
Arguments = "/user:Administrator \"cmd /K " + command + "\""
Command being 64bit x C:\dxFromCode.xml. I think your problem might be that you need to run cmd as Administrator.
Weirdly, Hans's code didn't work for me. I found that the WaitForExit() call would return before the file could be read. As a workaround, I added this:
int nTries = 0;
do
{
string szText = System.IO.File.ReadAllText(path);
if (szText.Length != 0)
{
return szText;
}
else
{
System.Threading.Thread.Sleep(1000);
}
} while (nTries++ < 10);
return "";

Categories