1

我有一个第三方可执行命令,它被捆绑到我的 winform 应用程序中。该命令放置在执行应用程序的目录中名为“tools”的目录中。

比如我的winform mytestapp.exe放在D:\apps\mytestapp目录下,那么第三方命令的路径就是D:\apps\mytestapp\tools\mycommand.exe。我正在使用 Application.StartupPath 来识别 mytestapp.exe 的位置,以便可以从任何位置运行它。

我通过启动一个进程 - System.Diagnostics.Process.Start 并使用命令提示符执行相同的命令来执行此命令。要传递其他参数来运行命令。

我面临的问题是,如果我的应用程序和命令的路径中没有任何空格,它可以正常工作

例如,如果我的应用程序和命令如下所示,它可以工作 D:\apps\mytestapp\mytestapp.exe D:\apps\mytestapp\tools\mycommand.exe "parameter1" "parameter2" - 这个工作

但是,如果我在路径中有空格,则会失败

C:\Documents and settings\mytestapp\tools\mycommand.exe "parameter1" "parameter2" - 不工作 C:\Documents and settings\mytestapp\tools\mycommand.exe "parameter1 parameter2" - 不工作 "C:\Documents and settings\mytestapp\tools\mycommand.exe" "parameter1 parameter2" - 不起作用 "C:\Documents and settings\mytestapp\tools\mycommand.exe parameter1 parameter2" - 不起作用

我尝试使用双引号来执行如上所示的命令,但它不起作用。那么,如何执行我的自定义命令。对此问题的任何输入或解决方法?提前致谢。

这是启动该过程的代码

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
        }
4

3 回答 3

1

尝试从您的命令中提取工作目录并为 ProcessStartInfo 对象设置 WorkingDirectory 属性。然后在您的命令中仅传递文件名。

此示例假定命令仅包含完整文件名。
需要根据您的实际命令文本进行调整

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
}
于 2013-07-05T19:06:10.207 回答
0

我相信以下工作:“C:\Documents and settings\mytestapp\tools\mycommand.exe”“parameter1”“parameter2”

您可能还有其他问题。尝试调试并检查引号是否使用了两次,或者中间是否有引号。

于 2013-07-05T19:26:46.197 回答
0

我认为这可能是因为在引用包含空格的路径的 args(和命令)字符串中需要引号;当在代码中定义非逐字(即没有在字符串之前)时,它们也需要被转义@,因此command字符串将被定义如下:

var command = "\"C:\\Documents and settings\\mytestapp\\tools\\mycommand.exe\"";
             // ^ escaped quote                                              ^ escaped quote

专门针对启动进程,我不久前编写了此方法,对于这种特定情况,它可能有点过于专业化,但可以很容易地按原样和/或编写具有不同参数的重载,以用于不同风格的设置进程:

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;
}

我正在使用它,如下所示;这里的_process对象可以是任何对象Process- 将其作为实例变量可能对您的用例无效;OutputDataReceived和事件处理程序(未显示)也ErrorDataReceived只记录输出字符串 - 但您可以解析它并基于它采取一些行动:

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;
}

您传递的args字符串正是您在命令行中输入它的方式,因此在您的情况下可能如下所示:

CreateStartInfo("\"C:\\Documents and settings\\mytestapp\\tools\\mycommand.exe\"", 
                "-switch1 -param1:\"SomeString\" -param2:\"Some\\Path\\foo.bar\"",
                string.Empty, true);

如果您将路径/命令字符串放在设置文件中,则可以存储它们而无需转义引号和反斜杠。

于 2013-07-06T01:13:12.907 回答