Reputation: 460
I have a third party executable command which is being bundled into my winform application. The command is placed inside a directory called "tools" from the directory where the application is being executed.
For example, if my winform mytestapp.exe is placed in D:\apps\mytestapp directory, then the path to the third party command is D:\apps\mytestapp\tools\mycommand.exe. I'm using Application.StartupPath to identify the location of mytestapp.exe, so that it can be run from any location.
I'm executing this command by starting a process - System.Diagnostics.Process.Start and executing the same using command prompt. There are additional parameters to be passed to run the command.
The problem I'm facing is, if the path to my application and the command does not have any white spaces in it, it works fine
For example, if my app and command is placed like below, it works D:\apps\mytestapp\mytestapp.exe D:\apps\mytestapp\tools\mycommand.exe "parameter1" "parameter2" - this works
however if I have a white space in the path, it fails
C:\Documents and settings\mytestapp\tools\mycommand.exe "parameter1" "parameter2" - doesnt work C:\Documents and settings\mytestapp\tools\mycommand.exe "parameter1 parameter2" - doesnt work "C:\Documents and settings\mytestapp\tools\mycommand.exe" "parameter1 parameter2" - doesnt work "C:\Documents and settings\mytestapp\tools\mycommand.exe parameter1 parameter2" - doesnt work
I tried using double quotes for executing the command as shown above and it doesn't work. So, how do I execute my custom command. Any inputs or work around for this issue? Thanks in advance.
Here is the code for starting the process
try
{
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
proc.WaitForExit();
}
catch (Exception objException)
{
// Log the exception
}
Upvotes: 1
Views: 1463
Reputation: 71167
I think it could be because quotes are needed in args (and command) strings that refer to paths that contain whitespace; also they need to be escaped when defined non-verbatim (i.e. no @
preceding the string) in-code, so the command
string would be defined like this:
var command = "\"C:\\Documents and settings\\mytestapp\\tools\\mycommand.exe\"";
// ^ escaped quote ^ escaped quote
Specifically for starting processes I wrote this method not long ago, it could be a little bit too specialized for this specific case, but one could easily take it as is and/or write overloads with different parameters for different flavors of setting up a process:
private ProcessStartInfo CreateStartInfo(string command, string args, string workingDirectory, bool useShellExecute)
{
var defaultWorkingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty;
var result = new ProcessStartInfo
{
WorkingDirectory = string.IsNullOrEmpty(workingDirectory)
? defaultWorkingDirectory
: workingDirectory,
FileName = command,
Arguments = args,
UseShellExecute = useShellExecute,
CreateNoWindow = true,
ErrorDialog = false,
WindowStyle = ProcessWindowStyle.Hidden,
RedirectStandardOutput = !useShellExecute,
RedirectStandardError = !useShellExecute,
RedirectStandardInput = !useShellExecute
};
return result;
}
I'm using it like below; here the _process
object could be any Process
- having it as an instance variable might not be valid for your use case; also the OutputDataReceived
and ErrorDataReceived
event handlers (not shown) only log the output string - but you could parse it and base some course of action upon it:
public bool StartProcessAndWaitForExit(string command, string args,
string workingDirectory, bool useShellExecute)
{
var info = CreateStartInfo(command, args, workingDirectory, useShellExecute);
if (info.RedirectStandardOutput) _process.OutputDataReceived += _process_OutputDataReceived;
if (info.RedirectStandardError) _process.ErrorDataReceived += _process_ErrorDataReceived;
var logger = _logProvider.GetLogger(GetType().Name);
try
{
_process.Start(info, TimeoutSeconds);
}
catch (Exception exception)
{
logger.WarnException(log.LogProcessError, exception);
return false;
}
logger.Debug(log.LogProcessCompleted);
return _process.ExitCode == 0;
}
The args
string you pass is exactly how you would enter it at the command-line, so in your case that might look like:
CreateStartInfo("\"C:\\Documents and settings\\mytestapp\\tools\\mycommand.exe\"",
"-switch1 -param1:\"SomeString\" -param2:\"Some\\Path\\foo.bar\"",
string.Empty, true);
If you instead put the path/command strings in a settings file, you can store them without needing to escape quotes and backslashes.
Upvotes: 0
Reputation: 216253
Try to extract the Working directory from your command and set the WorkingDirectory property for the ProcessStartInfo object. Then in your command pass only the filename.
This example assumes that command contains only the full filename.
Need to be adjusted for your actual command text
string command = "C:\Documents and settings\mytestapp\tools\mycommand.exe";
string parameters = "parameter1 parameter2";
try
{
string workDir = Path.GetDirectoryName(command);
string fileCmd = Path.GetFileName(command);
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c " + fileCmd + " " + parameters);
procStartInfo.WorkingDirectory = workDir;
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
proc.WaitForExit();
}
catch (Exception objException)
{
// Log the exception
}
Upvotes: 1
Reputation: 1
I believe the following works: "C:\Documents and settings\mytestapp\tools\mycommand.exe" "parameter1" "parameter2"
You may have something else wrong. Try to debug and check whether quote is used twice, or if there are quotes in the middle.
Upvotes: 0