我正在用C#编写工具箱程序,其功能是模拟Windows“开始”菜单“运行”对话框,同时也允许用户在需要时提升权限。
为此,我有一个带有textBox的简单WinForm(用户输入的位置)和一个checkBox(如果选中,则添加“runas”动词)。当然还有3个按钮:OK,Cancel和Browse(打开文件对话框)。所以我的代码看起来像这样:
var psi = new ProcessStartInfo(textBox1.Text, "");
psi.CreateNoWindow = true;
psi.UseShellExecute = true;
if (checkBox1.Checked == true)
{
psi.Verb = "runas";
}
try
{
Process.Start(psi);
}
catch (System.ComponentModel.Win32Exception ex)
{
// do something
MessageBox.Show("Error : " + ex.Message);
}
如果用户键入“notepad”或“notepad.exe”或“c:\ whatever \ path \ notepad”,则可以使用。传递参数时会出现问题:“notepad test.txt”将无效。
我的第一个想法是在遇到空格时拆分textBox1.Text,然后将第一部分用于ProcessStartInfo.Filename,将第二部分用于Arguments。 “notepad test.txt”就可以了。但是,如果用户使用文件对话框选择路径和/或文件名包含空格(或键入空格)的文件,那么字符串将被拆分,一切都会出错。
不幸的是,ParseStartInfo需要文件名和参数(可以是空字符串),但文件名不能包含参数...使用引号(对于整个textBox1.Text作为文件名)也不起作用。
那么,有没有人有解决方案:
OR
编辑:添加了MessageBox.Show以显示错误消息
答案 0 :(得分:1)
虽然我通常不喜欢将更长的代码转储到SO上,但这次对你来说仍然有点帮助。
这是我自己多年来一直使用的功能:
/// <summary>
/// Splits the file name if it contains an executable AND an argument.
/// </summary>
public static void CheckSplitFileName( ref string fileName, ref string arguments )
{
if ( !string.IsNullOrEmpty( fileName ) )
{
if ( fileName.IndexOf( @"http://" ) == 0 ||
fileName.IndexOf( @"https://" ) == 0 ||
fileName.IndexOf( @"ftp://" ) == 0 ||
fileName.IndexOf( @"file://" ) == 0 )
{
// URLs not supported, skip.
return;
}
if ( File.Exists( fileName ) )
{
// Already a full path, do nothing.
return;
}
else if ( Directory.Exists( fileName ) )
{
// Already a full path, do nothing.
return;
}
else
{
// Remember.
string originalFileName = fileName;
if ( !string.IsNullOrEmpty( fileName ) )
{
fileName = fileName.Trim();
}
if ( !string.IsNullOrEmpty( arguments ) )
{
arguments = arguments.Trim();
}
// --
if ( string.IsNullOrEmpty( arguments ) &&
!string.IsNullOrEmpty( fileName ) && fileName.Length > 2 )
{
if ( fileName.StartsWith( @"""" ) )
{
int pos = fileName.IndexOf( @"""", 1 );
if ( pos > 0 && fileName.Length > pos + 1 )
{
arguments = fileName.Substring( pos + 1 ).Trim();
fileName = fileName.Substring( 0, pos + 1 ).Trim();
}
}
else
{
int pos = fileName.IndexOf( @" " );
if ( pos > 0 && fileName.Length > pos + 1 )
{
arguments = fileName.Substring( pos + 1 ).Trim();
fileName = fileName.Substring( 0, pos + 1 ).Trim();
}
}
}
// --
// Possibly revert back.
if ( !string.IsNullOrEmpty( fileName ) )
{
string s = fileName.Trim( '"' );
if ( !File.Exists( s ) && !Directory.Exists( s ) )
{
fileName = originalFileName;
}
}
}
}
}
我正在以下列方式使用它:
var fileName = textBox1.Text.Trim();
var arguments = string.Empty;
CheckSplitFileName( ref fileName, ref arguments );
然后,将其传递给ProcessStartupInfo
类:
var info = new ProcessStartInfo();
info.FileName = fileName;
info.Arguments = arguments;
答案 1 :(得分:0)
我会尝试将TextBox字符串拆分为:
string[] elements1 = textBox1.Text.Split(new string[] {"\\"}, StringSplitOptions.RemoveEmptyEntries);
您将获得路径元素string[] elements2 = elements1[elements1.length-1].Split(new string[] {" "}, StringSplitOptions.RemoveEmptyEntries);
所以elements2[0]
包含应用程序名称(例如记事本),其他元素包含文件名string filename = String.Concat(elements2[1], " ", elements2[2], " ", ...)
答案 2 :(得分:-1)
您仍然可以使用split方法,而不是使用“first string”(从split方法返回的数组的第一个元素)作为命令,然后重新连接其他字符串以组成文件的名称。