vb.net如何将包含空格的字符串传递给命令行

4

我正在尝试使用Process调用外部程序:

    Dim strExe As String = "E:\Projects\Common Files\mktorrent.exe"
    Dim p As New Process
    Dim pinfo As New ProcessStartInfo
    pinfo.UseShellExecute = False
    pinfo.RedirectStandardOutput = True
    pinfo.Arguments = " -a http://blah.com/announce.php -l " & FileSizeMarker & " " & fn
    pinfo.FileName = strExe
    pinfo.WorkingDirectory = fn.Substring(0, fn.LastIndexOf("\"))
    pinfo.WindowStyle = ProcessWindowStyle.Normal
    pinfo.CreateNoWindow = True
    p.StartInfo = pinfo
    p.Start()

问题出在文件名(上面的变量fn)上。如果文件名有空格,该命令将会失败 - 没有空格则正常工作。我尝试添加1、2或3个引号,例如:
    fn = Chr(34) & Chr(34) & Chr(34) & fn & Chr(34) & Chr(34) & Chr(34)

并且
    fn = "\") & Chr(34) & fn & "\"& Chr(34)

还有许多其他组合,但仍然会出现错误。您有什么想法,如何让它正常工作?谢谢您!


P.S. 我也尝试过单引号... - Chiwda
我被迫通过将空格替换为“_”(下划线)来解决这个问题。但是因为目录名也可以有空格,所以我必须先将文件名与目录名分开,用“_”(下划线)而不是“ ”重命名文件,然后添加回目录名,然后运行mktorrent。这起作用是因为我正在更改工作目录以便于torrent的文件,因此路径变得无关紧要。多么愚蠢的hack! :-( - Chiwda
6个回答

2

这确实是一道古老的问题 - 但尚未解决。

我的两分贡献:

使用CHR(34)在字符串前后添加引号,像这样定界:

Arg = "Name=" & chr(34) & "John Doe da Silva" & chr(34)

就是这样了!


1

Windows没有提供一种将带有空格的参数保留为单个参数的常见方法。但是,有许多相对常见的标准可以尝试。

因此,要么确定mktorrent.exe使用的参数处理方式,要么(由于您正在尝试传递文件名)使用“MSDOS” 8.3格式的路径,该路径不会包含空格。

对于后者,this answer 指向了Win32API GetShortPathName

当然,现代Windows(我相信所有基于Windows NT的系统都是如此--尽管它通常不是)可以禁用8.3文件名。因此,您唯一的完整解决方案是确定mktorrent提供的参数处理方式。

由于您的评论表明引号未被传递,我确认在此vbscript的MsgBox输出中看到'testing' 'testing' '1 2 3'

Option Explicit

Dim arg
Dim line

For Each arg in WScript.Arguments
  line = line & " '" & arg & "'"
Next

MsgBox Trim(line)

当使用以下方式执行时:

Dim strExe As String = "C:\Windows\System32\wscript.exe"
Dim p As New Process
Dim pinfo As New ProcessStartInfo
pinfo.UseShellExecute = False
pinfo.RedirectStandardOutput = True
pinfo.Arguments = " G:\Utils\Arguments.vbs testing ""testing"" ""1 2 3"""
pinfo.FileName = strExe
pinfo.WorkingDirectory = "G:\Utils"
pinfo.WindowStyle = ProcessWindowStyle.Normal
pinfo.CreateNoWindow = True
p.StartInfo = pinfo
p.Start()

所以 wscript 看到引号并累计了脚本的三个参数。

顺便提一下,我刚刚注意到你尝试在文件名周围加上引号的示例修改了变量 fn。你是否已经在 .WorkingDirectory 行中考虑了这个问题,该行应该使用未修改的文件名?


假设是同一个程序的同一版本,请注意此示例在此处从文件名中删除当前目录(该目录仍然具有自己的空格)。 - Mark Hurd
很遗憾,对于这么简单的问题没有解决方案。基本上,通过Process方法能够将引号传递到命令行。 - Chiwda

1
这使我能够将空格传递给cmd。数小时的研究没有发现任何结果;这个线程一直出现,希望这对其他人有所帮助。
Dim startprgm As New ProcessStartInfo("cmd.exe", "/C """"C:\Program Files (x86)\Folder\File""""" + strArguments)

请注意,4个双引号引导路径,这部分很重要。在参数(/C)前面加上5个引号是行不通的,但尾随的五个可以分为4和1; 并结构化如下:
Dim startprgm As New ProcessStartInfo("cmd.exe", "/C """"C:\Program Files (x86)""""\Folder\File" + strArguments)

如果您打开cmd.exe并发送一个命令,只需要路径上的第一个引号(不需要关闭),但VB需要尾随引号来“关闭”引号。

祝大家好运。


1

This WORKS:

Dim current_path, current_rulename, cmd1 as STRING

current_path = "C:\this folder\file name.exe"    
current_rulename = "file name.exe"

cmd1 = "netsh advfirewall firewall add rule name = """ + current_rulename + """ dir = in action = block program = """ + current_path + """"
cmd1 &= " & "
cmd1 &= "netsh advfirewall firewall add rule name = """ + current_rulename + """ dir = out action = block program = """ + current_path + """"
cmd1 &= " & pause"

Process.Start("cmd", "/c " + cmd1)

基本上,带有空格的变量需要像这样括起来:
""" + string_with_spaces + """

被分成几个部分:

cmd1 = 
"
netsh advfirewall firewall add rule name = 
""" + current_rulename + """
dir=in action=block
program=
""" + current_path + """
"

这段代码将使用带空格的字符串连接两个单独的命令。

1

0

简单明了:

Process.Start("c:\Your exe file", """" & "string with space" & """")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接