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