使用 createprocess() 调用时,Windows 的 wget 会忽略选项
Posted
技术标签:
【中文标题】使用 createprocess() 调用时,Windows 的 wget 会忽略选项【英文标题】:wget for windows ignores options when called with createprocess() 【发布时间】:2019-03-23 04:07:34 【问题描述】:我正在尝试使用 c++ 程序中的wget for windows 从网站下载 6 个文件并将结果连接为一个文件。这不是批处理文件的问题。该命令将是:
wget -O bits.bin --wait=20 --random-wait --user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0" "http://url/to/the/file1" "http://url/to/the/file2" "http://url/to/the/file3" "http://url/to/the/file4" "http://url/to/the/file5" "http://url/to/the/file6"
当从 .bat 文件执行时,这已经过测试并按预期工作。使用 --output-file= 而不是 -O 也适用于批处理文件。
但是当我尝试使用CreateProcessA() 调用 wget 时,这些第一个选项被解释为 URL。 wget 尝试下载 bits.bin 例如作为 ftp 地址。它最终忽略了这些无意义的 URL,只是下载并存储了 6 个单独的文件作为 [URL1]、[URL2].1、[URL3].2 等,这些文件具有长而丑陋的 url-as-names。
我认为 CreateProcess 向被调用程序提供参数的方式可能与 wget for windows 所期望的方式不兼容,但我真的不明白为什么会有任何区别。
请注意,参数字符串几乎有 900 个字符长,因为 6 个 URL 很长。所以这在一定程度上限制了我的选择。我无法显示实际的 URL,因为它们包含密码和其他个人数据。
我尝试在参数字符串的不同部分添加引号,但没有成功。如果有的话,它似乎让事情变得更糟。我使用 sprintf 是因为在实际代码中,我必须在运行时将密码和其他选项插入每个 URL。
目前,除非这里有人有解决方案,否则我将放弃使用 CreateProcess() 来运行 wget。接下来,我将尝试 ShellExecute(),然后在必要时尝试 System()。想知道 MAXPATH 是否会成为问题。我可能需要调用 wget 6 次而不是一次,并自己管理随机延迟。我刚试过:
ShellExecuteA(NULL, NULL,"wget.exe", params, NULL, SW_SHOW);
它弹出了一个确认对话框,当我允许它运行时,wget 似乎并没有真正做任何事情。也许 System() 将是我唯一的选择。
注意:CreateProcess() 现在可以工作了,因为我在第二个参数中也包含了 wget.exe。谢谢大家。奇怪的是,ShellExecute 似乎根本不起作用,但我想这并不重要。也许是一些实现细节,比如 MAX_PATH 限制。
我知道我可以将 CreateProcess 中的第一个参数设置为 NULL,并将程序名称包含在第二个 CreateProcess() 参数中,但是我也引入了潜在的 MAX_PATH 问题。虽然我认为这并不比 ShellExecute() 差。我希望利用 CreateProcess 参数的 32768 字符限制。
char params[1024];
sprintf(params,"--output-file=bits.new --wait=20 --random-wait --user-agent=\"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0\" \"url/to/file1\" \"url/to/file2\" \"url/to/file3\"");
STARTUPINFOA startstruct = 0;
startstruct.cb = sizeof(startstruct);
PROCESS_INFORMATION procinfo;
CreateProcessA("wget.exe",params,0,0,0,CREATE_NEW_CONSOLE,0,0,&startstruct, &procinfo);
【问题讨论】:
请记住,当您从命令行调用 wget 时,最终会调用CreateProcess
。如果cmd.exe
可以按照您的意愿调用wget
,那么您也可以这样做。这可能并不容易,但肯定是有可能的。
【参考方案1】:
我使用 CreateProcess(),第一个参数是可执行文件名,第二个参数是进程名和其他参数,如
sprintf(params,"wget.exe --output-file=bits.new --wait=60 --random-wait --user-agent=\"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0\" \"url/to/file1\" \"url/to/file2\" \"url/to/file3\"");
【讨论】:
你是说我应该尝试在第二个 CreateProcess 参数中包含程序名称吗?基本上在第一个和第二个参数中都包含 wget.exe?你认为这会更好吗?为什么? @iamoumuamua "因为 argv[0] 是模块名称,C 程序员一般会重复模块名称作为命令行中的第一个标记。" 引用自您的文档链接. @iamoumuamua:将程序名称或其他词放在那里并不重要。重要的是提供一些东西变成argv[0]
,这样-O
就变成argv[1]
,因为命令行解析从argv[1]
开始。
@iamoumuamua:您是否知道可以在任务管理器中打开“命令行”列?启用它,然后比较在命令提示符下运行 wget
时生成的命令行与在代码中使用 CreateProcess
生成它时生成的命令行。
谢谢你我认为的工作。我也读过它,但我发现它太不清楚了,我真的无法用它做任何事情。我为什么要关心某些程序员通常做什么?他们没有告诉我为什么他们通常这样做。尽管 Ben Voight 解释了这一点。以上是关于使用 createprocess() 调用时,Windows 的 wget 会忽略选项的主要内容,如果未能解决你的问题,请参考以下文章