ShellExecute对于本地html或文件URL失败 [英] ShellExecute fails for local html or file URLs

查看:325
本文介绍了ShellExecute对于本地html或文件URL失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们公司正在将我们的帮助系统迁移到Flare下的HTML5格式.我们还在URI命令行上使用Flare CSHID的帮助系统添加了基于主题的访问权限,以直接访问主题,例如index.html#CSHID=GettingStarted以启动GettingStarted.html帮助页面.

我们的应用程序是用C ++编写的,并利用Win32 ShellExecute()函数生成与HTTP关联的默认应用程序以显示帮助系统.我们注意到,如果未指定井号,例如

void WebDrive_ShellExecute(LPCTSTR szURL)
{
    if ( _tcschr(szURL,_T('#')) )
    {
        //
        //Get Default Browser from Registry, then launch it.
        //
        ::RegGetStr(HKCR,_T("HTTP\\Shell\\Open\\Command"),szBrowser);
        ::CreateProcess ( NULL, szBrowser + _T(" ") + szURL, NULL, NULL, FALSE, 0, NULL, NULL, &sui, &pi);
    }
    else
        ShellExecute(NULL,_T("open"),szURL,NULL,NULL,SW_SHOWNORMAL);
}

,则ShellExecute()可以正常工作

ShellExecute(NULL, _T("open"), _T("c:\\Help\\index.html"), NULL, NULL, SW_SHOWNORMAL);

此功能将启动与查看HTML页面关联的默认浏览器,在这种情况下,File:///协议处理程序将启动,浏览器将启动,并且您将在地址栏中看到file:///c:/Help/index.html.

但是,一旦添加了主题的#信息,ShellExecute()将无法打开页面

ShellExecute(NULL,_T("open"),_T("c:\\Help\\index.html#cshid=GettingStarted"),NULL,NULL,SW_SHOWNORMAL);

如果浏览器完全打开,您将直接进入file:///c:/Help/index.htm l而没有#cshid=GettingStarted主题标识.

请注意,只有通过ShellExecute()使用文件协议处理程序,帮助系统在网络上运行并且使用Http或Https协议处理程序时,这才是问题.

对于我们的客户(其中一些客户位于专用LAN上),我们不能始终依赖于Internet访问,因此我们的帮助系统必须随应用程序一起提供.

解决方案

在与Microsoft的MSDN团队反复交流之后,他们检查了ShellExecute()调用的源代码,并确定是,在处理File时在ShellExecute()中基于:///URL,ShellExecute()调用将剥离#及其在#之后找到的所有数据,然后启动默认浏览器并发送HTML页面以打开. MS的立场是,他们故意这样做是为了防止对该功能进行注入.

解决方案是通过在URL中搜索#来增强ShellExecute()调用,如果找到了#,则我们将使用URL手动启动默认浏览器.这是伪代码

void WebDrive_ShellExecute(LPCTSTR szURL)
{
    if ( _tcschr(szURL,_T('#')) )
    {
        //
        //Get Default Browser from Registry, then launch it.
        //
        ::RegGetStr(HKCR,_T("HTTP\\Shell\\Open\\Command"),szBrowser);
        ::CreateProcess ( NULL, szBrowser + _T(" ") + szURL, NULL, NULL, FALSE, 0, NULL, NULL, &sui, &pi);
    }
    else
        ShellExecute(NULL,_T("open"),szURL,NULL,NULL,SW_SHOWNORMAL);
}

当然,c ++代码还有很多,但是这种通用设计对我们有用.

Our company is migrating our help systems over to HTML5 format under Flare. We've also added Topic based access to the help systems using Flare CSHID's on the URI command line for accessing the topic directly, such as index.html#CSHID=GettingStarted to launch the GettingStarted.html help page.

Our apps are written in C++ and leverage the Win32 ShellExecute() function to spawn the default application associated with HTTP to display the help system. We've noticed that ShellExecute() works fine when no hashtag is specified, such as

ShellExecute(NULL, _T("open"), _T("c:\\Help\\index.html"), NULL, NULL, SW_SHOWNORMAL);

This function will launch the default browser associated with viewing HTML pages and in this case, the File:/// protocol handler will kick in, the browser will launch and you will see file:///c:/Help/index.html in the address bar.

However, once you add the # information for the topic, ShellExecute() fails to open the page

ShellExecute(NULL,_T("open"),_T("c:\\Help\\index.html#cshid=GettingStarted"),NULL,NULL,SW_SHOWNORMAL);

If the browser opens at all, you'll be directed to file:///c:/Help/index.html without the #cshid=GettingStarted topic identification.

Note that this is only a problem if the File protocol handler is engaged through ShellExecute(), if the help system lives out on the web, and the Http or Https protocol handler is engaged, everything works great.

For our customers, some of whom are on a private LAN, we cannot always rely on Internet access, so our help systems must ship with the application.

解决方案

After some back-and-forth with Microsoft's MSDN team, they reviewed the source code to the ShellExecute() call and it was determined that yes, when processing File:/// based URLs in ShellExecute(), the ShellExecute() call will strip off the # and any data it finds after the # before launching the default browser and sending in the HTML page to open. MS's stance is that they do this deliberately to prevent injections into the function.

The solution was to beef up the ShellExecute() call by searching the URL for a # and if one was found, then we would manually launch the default browser with the URL. Here's the pseudocode

void WebDrive_ShellExecute(LPCTSTR szURL)
{
    if ( _tcschr(szURL,_T('#')) )
    {
        //
        //Get Default Browser from Registry, then launch it.
        //
        ::RegGetStr(HKCR,_T("HTTP\\Shell\\Open\\Command"),szBrowser);
        ::CreateProcess ( NULL, szBrowser + _T(" ") + szURL, NULL, NULL, FALSE, 0, NULL, NULL, &sui, &pi);
    }
    else
        ShellExecute(NULL,_T("open"),szURL,NULL,NULL,SW_SHOWNORMAL);
}

Granted there's a bit more to the c++ code, but this general design worked for us.

这篇关于ShellExecute对于本地html或文件URL失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆