从用户字符串中拆分文件名和参数

时间:2018-01-09 10:19:01

标签: c# winforms uac processstartinfo

我正在用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作为文件名)也不起作用。

那么,有没有人有解决方案:

  1. 将textBox1.Text正确拆分为有效的文件名+参数, 就像Windows开始 - 运行对话框一样
  2. OR

    1. 也许使用Shell32.FileRun()但在这种情况下,如何要求 提升(UAC提示)随意?
    2. 编辑:添加了MessageBox.Show以显示错误消息

3 个答案:

答案 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字符串拆分为:

  1. string[] elements1 = textBox1.Text.Split(new string[] {"\\"}, StringSplitOptions.RemoveEmptyEntries);您将获得路径元素
  2. string[] elements2 = elements1[elements1.length-1].Split(new string[] {" "}, StringSplitOptions.RemoveEmptyEntries);所以elements2[0]包含应用程序名称(例如记事本),其他元素包含文件名
  3. string filename = String.Concat(elements2[1], " ", elements2[2], " ", ...)

答案 2 :(得分:-1)

您仍然可以使用split方法,而不是使用“first string”(从split方法返回的数组的第一个元素)作为命令,然后重新连接其他字符串以组成文件的名称。