从用户字符串中拆分文件名和参数
Split filename and arguments from user string
我正在用 C# 编写一个工具箱程序,它的一个功能是模拟 Windows 开始菜单 "Run" 对话框,还允许用户在需要时提升权限。
为此,我有一个简单的 WinForm,带有一个文本框(用户在其中键入内容)和一个复选框(如果选中,请添加 "runas" 动词)。当然还有 3 个按钮:确定、取消和浏览(打开文件对话框)。所以我的代码看起来像这样:
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" 不起作用。
我的第一个想法是在遇到 space 时拆分 textBox1.Text,然后将第一部分用于 ProcessStartInfo.Filename,将第二部分用于参数。 "notepad test.txt" 就可以了。但是,如果用户使用文件对话框 select 路径 and/or 文件名包含 space (或键入它)的文件,当然字符串将被拆分并且一切都会出错.
不幸的是,ParseStartInfo 需要文件名和参数(可以是空字符串),但文件名不能包含参数...使用引号(对于整个 textBox1.Text 作为文件名)不起作用要么。
所以,有没有人有解决方案:
- 要么正确拆分 textBox1.Text 到有效的文件名 + 参数,
正如 Windows 开始 - 运行 对话框那样
或
- 也许可以使用 Shell32.FileRun() 但在这种情况下,如何请求
随意提升(UAC 提示)?
编辑:添加了 MessageBox.Show 以显示错误消息
你仍然可以使用 split 方法,而不是使用 "first string"(从 split 方法返回的数组的第一个元素)作为命令,然后重新连接其他字符串以组成名称文件。
虽然我通常不喜欢将较长的代码转储到 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
class:
var info = new ProcessStartInfo();
info.FileName = fileName;
info.Arguments = arguments;
我会尝试像这样拆分 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], " ", ...)
我正在用 C# 编写一个工具箱程序,它的一个功能是模拟 Windows 开始菜单 "Run" 对话框,还允许用户在需要时提升权限。
为此,我有一个简单的 WinForm,带有一个文本框(用户在其中键入内容)和一个复选框(如果选中,请添加 "runas" 动词)。当然还有 3 个按钮:确定、取消和浏览(打开文件对话框)。所以我的代码看起来像这样:
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" 不起作用。
我的第一个想法是在遇到 space 时拆分 textBox1.Text,然后将第一部分用于 ProcessStartInfo.Filename,将第二部分用于参数。 "notepad test.txt" 就可以了。但是,如果用户使用文件对话框 select 路径 and/or 文件名包含 space (或键入它)的文件,当然字符串将被拆分并且一切都会出错.
不幸的是,ParseStartInfo 需要文件名和参数(可以是空字符串),但文件名不能包含参数...使用引号(对于整个 textBox1.Text 作为文件名)不起作用要么。
所以,有没有人有解决方案:
- 要么正确拆分 textBox1.Text 到有效的文件名 + 参数, 正如 Windows 开始 - 运行 对话框那样
或
- 也许可以使用 Shell32.FileRun() 但在这种情况下,如何请求 随意提升(UAC 提示)?
编辑:添加了 MessageBox.Show 以显示错误消息
你仍然可以使用 split 方法,而不是使用 "first string"(从 split 方法返回的数组的第一个元素)作为命令,然后重新连接其他字符串以组成名称文件。
虽然我通常不喜欢将较长的代码转储到 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
class:
var info = new ProcessStartInfo();
info.FileName = fileName;
info.Arguments = arguments;
我会尝试像这样拆分 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], " ", ...)