【问题标题】:Escape string for Process.StartProcess.Start 的转义字符串
【发布时间】:2011-01-24 12:04:26
【问题描述】:

如何转义未知字符串以作为参数传递给 Process.Start?

我目前转义基本引号和反斜杠,但最近我的输入开始包含http://www.fileformat.info/info/unicode/char/ff02/index.htm(全角引号)之类的内容。

所以我的问题是,我需要转义什么才能安全地将字符串作为 Process.Start 的参数传递?

编辑: 所以我需要澄清这一点。我真正要寻找的是所有字符的列表,这些字符必须在 cmd.exe 的带引号的字符串(“foo”)中转义。我最初处理双引号字符和反斜杠字符,但我最终得到了一些包含全角引号(如上所述)的输入,该引号也需要转义。所以问题是,对于使用 Process.Start 传递给 cmd.exe 的带引号的字符串参数,我还需要转义什么?

【问题讨论】:

  • 您可能对MedallionShell 库感兴趣,它会自动处理转义和连接过程参数

标签: c# cmd escaping


【解决方案1】:

这可能有用:

  • 首先,多个参数通常由 空格。在图 2.3 中,命令有 三个参数,c:*.bak, e:\backup, 和/秒。偶尔会出现其他角色 用作参数分隔符。为了 例如,COPY 命令可以使用 + 分隔多个字符 文件名。

  • 其次,任何包含空格或以空格开头或结尾的参数 必须用双引号括起来。 当 使用长文件名和目录名, 经常包含一个或多个 空格。如果双引号参数 本身包含双引号 字符,双引号必须是 翻了一番。例如,输入“引用” 参数为“”“引用”“参数”。

  • 第三,命令开关总是以斜杠/字符开头。一种 switch 是一个修改参数 某些命令的操作 大大地。有时,开关以 + 或 - 字符。有些开关是 全局,并影响命令 无论他们在 参数列表。其他开关是 本地的,并影响特定的参数 (例如前一个 开关)。

  • 第四,所有非双引号的保留shell字符必须 被逃脱。这些字符有 对 Windows NT 的特殊意义 命令外壳。保留的外壳 字符是:

    & | ( ) ^

将保留的 shell 字符传递为 命令参数的一部分, 要么整个​​论点必须是 用双引号括起来,或 保留字符必须转义。 为保留字符添加前缀 克拉 (^) 字符来转义它。为了 例如,以下命令示例 不会按预期工作,因为 是保留的 shell 字符:

  1. C:\>echo <dir>
  2. The syntax of the command is incorrect.

  Instead, escape the two reserved characters, as follows:

  1. C:\>echo ^<dir^>
  2. <dir>

通常,保留外壳 命令中不使用字符, 所以碰撞需要使用 逃脱是罕见的。它们确实发生, 然而。例如,流行的 PKZIP 程序支持 -& 切换到 启用磁盘跨越。要使用这个 Windows NT下正确切换,-^& 必须输入。

提示:克拉字符本身就是一个保留的外壳字符。因此,对 键入克拉字符作为 a 的一部分 命令参数,键入两克拉 反而。只需要转义 当正常的shell解释 保留字符必须是 绕过。

  • 最后,允许的最大长度 一个shell命令似乎是 微软未记录。简单的 测试表明,Windows NT 命令 shell 允许很长时间 命令——超过 4,000 条 人物。实际上, 没有显着的上限 命令的长度。

http://technet.microsoft.com/en-us/library/cc723564.aspx

【讨论】:

  • 这有点帮助,但我真正要找的是:在带引号的字符串中,所有需要在引号内转义的内容。
  • 据我所知:您只需在全角引号内转义全角引号(通过将它们加倍)。文章的第四步提到了保留字符“不在双引号中”,我假设您可以使用双引号中的字符。而且我不会使用非 ASCII 字符。
  • 似乎反斜杠也应该通过加倍来转义。如果连续使用两个,则解释为一个;加倍似乎给出了一致的行为。
【解决方案2】:

This answer 是我所见过的最接近解释 Windows 命令行参数疯狂的方法。它并不像最初看起来那么简单。

一般情况下,您不需要转义 U+FF02。问题是,如果您最终将该字符传递给不支持 Unicode 的命令行,它将被贬低为不兼容的等价物,即 ASCII 引号,此时它变得危险。如果您的命令将发送到不支持 Unicode 的工具,您应该在 应用参数转义之前将其折叠为 ASCII,而不是让另一端的工具执行此操作。

(通常,问题出在该工具使用 C 标准库读取其参数时。这是根据 8 位 char 定义的;Windows 标准库实现使用默认(“ANSI”)系统代码页来将字符串编码为 8 位,并且该代码页绝不是 Unicode 转换格式,因此您总是会丢失字符。)

【讨论】:

    【解决方案3】:

    我的逃跑尝试:

        public static string QuoteArgument(string arg)
        {
            // The inverse of http://msdn.microsoft.com/en-us/library/system.environment.getcommandlineargs.aspx
    
            // Suppose we wish to get after unquoting: \\share\"some folder"\
            // We should provide: "\\share\\\"some folder\"\\"
    
            // Escape quotes ==> \\share\\\"some folder\"\
            // For quotes with N preceding backslashes, replace with 2k+1 preceding backslashes.
            var res = new StringBuilder();
            // For sequences of backslashes before quotes:
            // odd ==> 2x+1, even => 2x ==> "\\share\\\"some folder"
            var numBackslashes = 0;
            for (var i = 0; i < arg.Length; ++i)
            {
                if(arg[i] == '"')
                {
                    res.Append('\\', 2 * numBackslashes + 1);
                    res.Append('"');
                    numBackslashes = 0;
                }
                else if(arg[i] == '\\')
                {
                    numBackslashes++;
                }
                else
                {
                    res.Append('\\', numBackslashes);
                    res.Append(arg[i]);
                    numBackslashes = 0;
                }
            }
            res.Append('\\', numBackslashes);
    
            // Enquote, doubling last sequence of backslashes ==> "\\share\\\"some folder\"\\"
            var numTrailingBackslashes = 0;
            for (var i = res.Length - 1; i > 0; --i)
            {
                if (res[i] != '\\')
                {
                    numTrailingBackslashes = res.Length - 1 - i;
                    break;
                }
            }
            res.Append('\\', numTrailingBackslashes);
    
            return '"' + res.ToString() + '"';
        }
    

    【讨论】:

      【解决方案4】:

      这是一个如何在 google 搜索字符串中出现引号的示例:

      string link = @"https://www.google.com/search?q=\""Hello+World!\""";
      Process.Start("CHROME.EXE", link);
      

      【讨论】:

      • 问题的第一行指定 OP 希望“转义 unknown 字符串”。您提供的方法不能用于这样的字符串。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-17
      • 2016-04-15
      • 1970-01-01
      • 2010-12-09
      相关资源
      最近更新 更多