代码之家  ›  专栏  ›  技术社区  ›  Dédé Lateur

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

  •  1
  • Dédé Lateur  · 技术社区  · 7 年前

    我正在用C语言编写一个工具箱程序,其功能之一是模拟Windows开始菜单的“运行”对话框,还允许用户在需要时提升权限。

    为此,我有一个简单的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:\which\path\notepad”,则可以使用。传递参数时会出现问题:“notepad test.txt”无法工作。

    我的第一个想法是拆分文本框1。遇到空格时,请使用ProcessStartInfo的第一部分。文件名,以及参数的第二部分。“notepad test.txt”就可以了。但是,如果用户使用文件对话框选择路径和/或文件名包含空格的文件(或键入空格),那么字符串当然会被拆分,所有内容都会出错。

    不幸的是,ParseStartInfo需要文件名和参数(可以是空字符串),但文件名不能包含参数。。。使用引号(对于整个textBox1.Text作为文件名)也不起作用。

    那么,是否有人能解决以下问题:

    1. 正确拆分文本框1。文本转换为有效的文件名+参数, 就像Windows的“开始-运行”对话框一样

    1. 可能使用Shell32。FileRun()但是在这种情况下,如何请求 是否随意提升(UAC提示)?

    编辑:添加了MessageBox。显示以显示错误消息

    3 回复  |  直到 7 年前
        1
  •  1
  •   Uwe Keim    7 年前

    虽然我通常不喜欢将较长的代码转储到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;
    
        2
  •  0
  •   OverFloo    7 年前

    我会尝试这样拆分文本框字符串:

    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], " ", ...)
        3
  •  -1
  •   S-Wing    7 年前

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