Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从C#执行另一个程序时,是否需要解析;命令行“;我自己?_C#_Shellexecute - Fatal编程技术网

从C#执行另一个程序时,是否需要解析;命令行“;我自己?

从C#执行另一个程序时,是否需要解析;命令行“;我自己?,c#,shellexecute,C#,Shellexecute,从注册表中,对于给定的文件类型,我得到一个字符串,其中包含以下内容: "C:\Program Files\AppName\Executable.exe" /arg1 /arg2 /arg3 或者有时: "C:\Program Files\AppName\Executable.exe" /arg1 /arg2 /arg3 "%1" 为了让我执行这个程序,并将文件名作为参数传递(我知道它可以接受),我必须自己解析这个字符串,还是有一个运行时类可以为我解析这个字符串?请注意,我并不是要处理这两者之

从注册表中,对于给定的文件类型,我得到一个字符串,其中包含以下内容:

"C:\Program Files\AppName\Executable.exe" /arg1 /arg2 /arg3
或者有时:

"C:\Program Files\AppName\Executable.exe" /arg1 /arg2 /arg3 "%1"
为了让我执行这个程序,并将文件名作为参数传递(我知道它可以接受),我必须自己解析这个字符串,还是有一个运行时类可以为我解析这个字符串?请注意,我并不是要处理这两者之间是否有“%1”的差异,而是需要分离可执行文件的名称,分别获取其命令行参数

我试着在上面的字符串中添加/注入要传递的文件的完整路径和名称,并将整个shebang传递给Process.Start,但是它当然只希望文件名作为单个参数,所以这不起作用

基本上,上述操作必须手动完成:

Process proc = new Process();
proc.StartInfo.FileName = @"C:\Program Files\AppName\Executable.exe";
proc.StartInfo.Arguments = "/arg1 /arg2 /arg3 \"" + fileName + "\"";
proc.Start();
我试着用了,但没用。还有其他的指示吗

说清楚一点,我希望:

String commandPath = ReadFromRegistry();
String fullCommand = commandPath + " " + fileName; // assuming not %1
Process.Start(fullCommand); // <-- magic happens here
String commandPath=ReadFromRegistry();
String fullCommand=commandPath+“”+fileName;//假设不是%1
Process.Start(fullCommand);// 我相信(我做这件事已经有一段时间了)您可以使用:

System.Diagnostics.Process.Start(/*File to open*/);
如果有默认应用程序,它将使用默认应用程序打开该文件。您不需要知道它将要使用的应用程序


我明白你在看什么吗?还是我遗漏了什么?

生成cmd.exe/C“你的字符串”怎么样

比如

Process proc = new Process();
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = @"/C ""C:\Program Files\AppName\Executable.exe"" /arg1 /arg2 /arg3 """ + fileName + """";
proc.Start();

您面临的问题是,可执行文件名和一些参数已经在变量
commandPath
中(这不仅是路径,而且是一些参数)。如果第一部分仅由字符组成(没有空格),那么将可执行文件与参数分开并不难,但这是Windows,因此您可能有空格,因此您被卡住了。看来是这样

解决方案使用
过程处于状态。启动
,并使用
外壳执行
Process.Start
,无论您要求它使用
ShellExecute
还是
CreateProcess
,在这两种情况下,它都需要设置
FileName
参数/成员,并按原样传递给CreateProcess和ShellExecute

那又怎样?简单地说:自己使用
CreateProcess
。该API函数的一个鲜为人知的特性是,您可以向它传递完整的命令行,就像在WinKey+R(Windows运行)下一样。通过将第一个参数设置为
null
,将第二个参数设置为完整路径(包括所有参数),可以实现您所要求的“魔力”。如下所示,它将为您启动Windows照片库,同时将相同的字符串与参数一起使用
进程。启动
任何方式都会产生“未找到文件”错误:

请注意,我故意不在可执行路径周围加引号。但是,如果可执行路径周围有引号,就像上面的代码一样,它仍然可以工作,所有的魔力都在那里。结合您的代码片段,以下内容将以您想要的方式启动该过程:

/* with your code */
String commandPath = ReadFromRegistry();
String fullCommand = commandPath + " " + fileName; // assuming not %1
STARTUPINFO si = new STARTUPINFO();
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
CreateProcess(
    null,
    fullCommand, 
    IntPtr.Zero, 
    IntPtr.Zero, 
    false,
    0, 
    IntPtr.Zero, 
    null, 
    ref si, 
    out pi);
声明是您可以从中获得的,但是为了方便起见,这里有一部分应该粘贴在类部分中,以使上面的工作正常。关于这些功能的参考,如何检查结果(成功/失败)以及
STARTUPINFO
PROCESS\u INFORMATION
结构,请访问。为了方便起见,我建议将对
CreateProcess
的调用放在实用函数中

/* place the following at the class level */
[DllImport("kernel32.dll")]
static extern bool CreateProcess(
    string lpApplicationName, 
    string lpCommandLine, 
    IntPtr lpProcessAttributes, 
    IntPtr lpThreadAttributes,
    bool bInheritHandles, 
    uint dwCreationFlags, 
    IntPtr lpEnvironment,
    string lpCurrentDirectory, 
    ref STARTUPINFO lpStartupInfo,
    out PROCESS_INFORMATION lpProcessInformation);

public struct PROCESS_INFORMATION
{
    public IntPtr hProcess;
    public IntPtr hThread;
    public uint dwProcessId;
    public uint dwThreadId;
}



public struct STARTUPINFO
{
    public uint cb;
    public string lpReserved;
    public string lpDesktop;
    public string lpTitle;
    public uint dwX;
    public uint dwY;
    public uint dwXSize;
    public uint dwYSize;
    public uint dwXCountChars;
    public uint dwYCountChars;
    public uint dwFillAttribute;
    public uint dwFlags;
    public short wShowWindow;
    public short cbReserved2;
    public IntPtr lpReserved2;
    public IntPtr hStdInput;
    public IntPtr hStdOutput;
    public IntPtr hStdError;
}
希望我正确理解了你的问题。如果您在实现上述代码时遇到问题,请告诉我。

我也遇到类似问题(解析注册表中的ClickOnce卸载字符串以使用System.Diagnostics.Process执行)。我通过从卸载字符串的末尾删除标记,直到检测到有效的文件路径,解决了这个问题

    public static string GetExecutable(string command)
    {
        string executable = string.Empty;
        string[] tokens = command.Split(' ');

        for (int i = tokens.Length; i >= 0; i--)
        {
            executable = string.Join(" ", tokens, 0, i);
            if (File.Exists(executable))
                break;
        }
        return executable;
    }

也许我的问题没有说清楚,但我试过了,它抱怨找不到文件,因为它使用整个命令作为文件名,包括参数和选项。我想你必须手动执行。看看+1:好把戏!我还使用了
proc.StartInfo.WindowStyle=ProcessWindowStyle.Hidden隐藏控制台窗口
    public static string GetExecutable(string command)
    {
        string executable = string.Empty;
        string[] tokens = command.Split(' ');

        for (int i = tokens.Length; i >= 0; i--)
        {
            executable = string.Join(" ", tokens, 0, i);
            if (File.Exists(executable))
                break;
        }
        return executable;
    }