【问题标题】:How to remove the exe part of the command line如何删除命令行的exe部分
【发布时间】:2016-07-12 07:05:59
【问题描述】:

这是我的代码。输入命令行为var1 val1 var2 val2:

var rawCmd = Environment.CommandLine;
// Environment.CommandLine adds the .exe info that I don't want in my command line:
// rawCmd = "path\to\ProjectName.vshost.exe" var1 val1 var2 val2

// A. This correction makes it work, although it is pretty ugly:
var cleanCmd = rawCmd.Split(new string[] { ".exe\" " }, StringSplitOptions.None)[1];

// B. This alternative should be cleaner, but I can't make it work:
var exePath = System.Reflection.Assembly.GetCallingAssembly().Location;
cleanCmd = rawCmd.Replace(string.Format($"\"{exePath}\" "), "");

所以为了使 B 工作,我应该能够找到.vhost.exe 信息(我无法找到)。

但我也想知道是否有更清洁的方法来完成这一切。


至于我要实现这个的原因,解释如下(tl;dr:从命令行解析一个json):https://stackoverflow.com/a/36203572/831138

【问题讨论】:

  • 为什么不能将传递给Main 方法的args 参数存放在方便的位置?
  • 你为什么将命令行作为单个string 处理?据我了解,参数已经作为数组传递,如here 所述。
  • 原因是我在帖子底部链接的示例:stackoverflow.com/a/36203572/831138。目标是从命令行解析一个 json。
  • 您不能像myExe < file.jsonecho JSON | myExe 那样通过管道传输JSON 吗?
  • @AlexeiLevenkov 我从 VS2015 插入命令行以调试我的代码。然后即使代码在生产中,考虑到我的设置,只要能够摆脱 cmd 的 exe 部分就会更容易。

标签: c#


【解决方案1】:

我找到了获取虚拟主机路径的方法:

var exePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, System.AppDomain.CurrentDomain.FriendlyName);

...尽管我担心它可能会导致不一致,具体取决于代码的执行位置(调试/生产...)。我希望不会,我必须继续测试。

【讨论】:

    【解决方案2】:

    如果元素之间的空格数不重要,您可以只使用Join 参数数组,该数组在不带引号的空格字符上拆分,并且不包含可执行文件:

    void Main(string[] args)
    {
         var cleanCmd = string.Join(" ", args);
         // etc
    }
    

    【讨论】:

    • 但是这样会去掉输入json中的引号,我就解析不出来了。
    【解决方案3】:

    而不是使用

    var rawCmd = Environment.CommandLine;
    

    你可以使用:

    var rawCmd = Environment.CommandLine;
    var argsOnly = rawCmd.Replace("\"" + Environment.GetCommandLineArgs()[0] + "\"", "");
    

    这将在您的示例中返回“var1 val1 var2 val2”。它应该与另一篇文章中的 JSON 示例一起使用。

    【讨论】:

    • 但是这样会去掉输入json中的引号,我就解析不出来了。
    • 给我展示一个真实的例子,说明你希望你的命令行在应用程序运行时的样子。
    • 你可以看看我的另一篇帖子stackoverflow.com/a/36203572/831138。这篇其他帖子起源于我当前的问题,并包含有关该示例的所有详细信息。底线:我希望能够将纯 json 输入到 vs2015 的命令行中,并能够在代码中使其“未受破坏”。
    • 这个编辑很有意义......这是摆脱 exe 路径的聪明方法,无需使用复杂的调用来获取程序集名称。
    【解决方案4】:

    这只会剥离命令调用部分,无论你写成programprogram.exe.\programc:program"c:\Program Files\program""\Program Files\program.exe"等还是路径分隔符。

    var exe = Environment.GetCommandLineArgs()[0]; // Command invocation part
    var rawCmd = Environment.CommandLine;          // Complete command
    var argsOnly = rawCmd.Remove(rawCmd.IndexOf(exe),exe.Length).TrimStart('"').Substring(1);
    

    它不会改变参数之间的双引号、插入符号和空格,甚至是开头的空格,即紧跟在程序名称之后。注意开头有一个额外的空格,不要问我为什么。 如果这让您感到困扰,请删除第一个字符,这应该很容易。 因此最后的.Substring(1)。我定义了这两个变量以使其更具可读性。

    编辑:
    考虑到引用的调用以及程序名称字符串恰好作为参数的一部分出现的情况(例如,如果您的程序是 me.exe 并且您运行 me "Call me Ishmael".Replace 也会修剪第二个 me) .现在我也把多余的空间拿出来了。

    【讨论】:

    • .substring(1) 如果没有传递参数将会中断,可以使用 .TrimStart() 代替
    【解决方案5】:

    这是一个非常古老的问题,但从 Windows 10 20H2 和 .NET Framework 4.8 开始,上述所有解决方案似乎都以某种方式被破坏(例如,双引号分隔的 exe 路径)。

    我需要以一种更强大的方式从Environment.CommandLine 中删除 exe,因此我决定尝试基于正则表达式的方法。 (然后我遇到了 2 个问题,哈哈。)希望这对某人有帮助!

        internal static string GetRawCommandLineArgs( )
        {
            // Separate the args from the exe path.. incl handling of dquote-delimited full/relative paths.
            Regex fullCommandLinePattern = new Regex(@"
                ^ #anchor match to start of string
                    (?<exe> #capture the executable name; can be dquote-delimited or not
                        (\x22[^\x22]+\x22) #case: dquote-delimited
                        | #or
                        ([^\s]+) #case: no dquotes
                    )
                    \s* #chomp zero or more whitespace chars, after <exe>
                    (?<args>.*) #capture the remainder of the command line
                $ #match all the way to end of string
                ",
                RegexOptions.IgnorePatternWhitespace|
                RegexOptions.ExplicitCapture|
                RegexOptions.CultureInvariant
            );
    
            Match m = fullCommandLinePattern.Match(Environment.CommandLine);
            if (!m.Success) throw new ApplicationException("Failed to extract command line.");
    
            // Note: will return empty-string if no args after exe name.
            string commandLineArgs = m.Groups["args"].Value;
            return commandLineArgs;
        }
    

    测试完成:

    • 带/不带双引号的 exe 路径
    • args 包含双引号并引用 exe 名称
    • 调用不带参数的 exe 返回空字符串

    [编辑] 测试未完成:

    • .NET 5 或任何其他运行时或操作系统

    【讨论】:

      猜你喜欢
      • 2021-05-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-23
      • 1970-01-01
      • 2018-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多