【问题标题】:ShellExecute (and ShellExecuteEx) do nothing with my URLShellExecute(和 ShellExecuteEx)对我的 URL 不执行任何操作
【发布时间】:2017-07-03 15:47:47
【问题描述】:

我正在使用 C++Builder XE7 创建一个项目,其中用户可以单击一个按钮来打开一个 Web 链接,例如打开支持页面,或在社交媒体上分享他的经验。为此,我使用了ShellExecute() 函数,它运行良好,除了一个按钮。

当我点击这个按钮时,什么都没有发生。 ShellExecute()函数返回无误(返回值为42),但是我的默认浏览器打不开,网页根本不显示。

这是我的ShellExecute() 实现

const HINSTANCE result = ::ShellExecute(handle, "open", url.c_str(), NULL, NULL, SW_SHOWDEFAULT);

我也试过ShellExecuteEx()函数:

::SHELLEXECUTEINFO info;
std::memset(&info, 0, sizeof(info));
info.cbSize = sizeof(info);
info.hwnd   = handle;
info.lpVerb = "open";
info.lpFile = url.c_str();
info.nShow  = SW_SHOWDEFAULT;

if (!::ShellExecuteEx(&info))

url 参数包含我要打开的网站链接。出于安全原因,我不能将它作为示例发布在这里,但是我在浏览器(FireFox)中对其进行了测试,它运行良好。另一方面,如果我通过将 url 内容替换为 Google 的网站来执行我的代码,则一切正常。

handle 只是父框架的Handle 参数。

我还尝试调整 ShellExecute/Ex() 参数,例如 hwndnShow 字段,但没有改变。

谁能指出哪里出了问题?

【问题讨论】:

  • 你能发一个minimal reproducible example吗?另外你的默认浏览器是什么?如果您执行 Start-Run 然后键入一些 url,例如 http://www.stackoverflow.com/,会发生什么。
  • 很遗憾,我无法发布更多代码。调用 ShellExecute() 之前的代码只是在函数内部构建 URL,我不允许展示它。在调用方,这个函数只是在按钮事件内部调用,带有按钮父级的句柄。所以上面的代码已经是我允许提供的最简单的代码示例了。
  • 我的 Windows 配置一切正常。正如我在上面的帖子中所说,我的默认浏览器是 FireFox,并且 Start-Run 按预期使用提供的链接打开它。而且,我的代码中的同一个 ShellExecute() 可以很好地使用一个简单的链接,比如google.com。但是 ShellExecute() 本身的行为对我的 url 来说很奇怪:为什么它什么都不做就返回,而且没有错误?可能是 ShellExecute() 错误?
  • a text contains \"quotes\" ...您是否真的对双引号进行了编码,或者这就是您从 C++ 源中复制字符串的方式?
  • argX=a text containing ... 中,您是否以%HH 格式编码空格字符和其他保留字符?如果没有,您需要这样做。

标签: c++ windows browser shellexecute c++builder-xe7


【解决方案1】:

网址格式如下:http://www。 mysite.xxx/selectPage.php?arg1=xxx&arg2=yyy&...&argX=包含的文本 “引号”和一些 %26amp%3b 特殊字符!

在本例中,您必须对双引号和空格进行URL 编码,因为这些对于query part of an URL 来说是无效字符。

通过用%22 替换双引号和用%20 替换空格来修复它。我建议使用 UrlEscape() 之类的函数来正确编码 URL。

虽然大多数浏览器对用户输入具有容错性,并且也会接受没有有效编码的 URL,但最好严格遵守规范,因为不能保证该容错性。

此外,当 URL 作为命令行参数传递给与 URL 协议关联的命令时,双引号会产生问题。这是因为双引号是用于定义包含空格的命令行参数的保留字符

例如,在我的机器上,http 协议与以下命令相关联(请参阅HKEY_CLASSES_ROOT\http\shell\open\command):

"C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -osint -url "%1"

您可以看到双引号已用于将最后一个参数括起来,如果您在 URL 中使用 未编码 双引号,这显然会变得混乱。

正确编码与ShellExecuteEx() 一起使用的 URL 的示例:

#include <windows.h>
#include <Shellapi.h>

int main()
{
    ::CoInitialize(nullptr);

    SHELLEXECUTEINFOW info{ sizeof(info) };
    info.fMask  = SEE_MASK_NOASYNC; // because we exit process after ShellExecuteEx()
    info.lpVerb = L"open";
    info.lpFile = L"http://www.google.de/search?q=ShellExecuteEx%20URL%20%22double%20quotes%22";
    info.nShow  = SW_SHOWDEFAULT;

    if( !::ShellExecuteExW( &info ) )
    {
        DWORD err = ::GetLastError();
        printf("ShellExecuteEx failed with error %d\n", err );
    }

    ::CoUninitialize();
}

【讨论】:

  • 您还应该将空格字符编码为%20"http://www.google.de/search?q=ShellExecuteEx%20URL%20%22double%20quotes%22"。但更重要的是,lpVerb 应该是 NULL 而不是 "open" 以启动用户的默认浏览器。
  • @RemyLebeau 为什么?
  • 因为根据RFC 3986 Section 3.4,URL 的查询组件中不允许使用未编码的空格。一个查询中只能有pchar/?字符,pchar的定义不包括未编码的空格字符。 pchar 中未明确允许的任何字符都必须改为百分比编码,即 %20 用于空格字符。
  • @RemyLebeau 已修复,感谢您的链接。在测试代​​码时,它可以在没有编码空格的情况下工作,但是最好遵循规范。
  • 对包含文本的部分进行编码解决了该问题。非常感谢所有花时间回答我的人
猜你喜欢
  • 2018-04-27
  • 2015-05-30
  • 1970-01-01
  • 1970-01-01
  • 2018-04-28
  • 1970-01-01
  • 2020-07-11
  • 1970-01-01
  • 2020-07-30
相关资源
最近更新 更多