2017-07-03 137 views
2

我使用C++ Builder XE7創建項目,在該項目中用戶可以單擊按鈕以打開Web鏈接,例如打開支持頁面,或在社交媒體上分享他的體驗。爲此,我使用ShellExecute()函數,除了一個按鈕,它運行良好。ShellExecute(和ShellExecuteEx)對我的網址不做任何操作

當我點擊這個按鈕時,根本沒有任何反應。 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)中對其進行了測試,效果良好。另一方面,如果我只用GOOGLE的網站替換url的內容來執行我的代碼,那麼所有的代碼都可以按預期運行。

handle只是父框架的Handle參數。

我還試圖調整ShellExecute/Ex()參數,如hwndnShow字段,但沒有變化。

有人可以指我什麼是錯的?

+1

你能發佈[MCVE]另外你是什麼默認瀏覽器?如果你開始運行,然後輸入一些url,例如'http:// www.stackoverflow.com /',會發生什麼情況。 –

+0

不幸的是,我無法發佈更多代碼。調用ShellExecute()之前的代碼僅僅是URL的構建,在函數內部,我不允許展示它。在調用者方面,這個函數只是在按鈕事件中調用,並且按鈕父項的句柄。所以上面的代碼已經是我允許提供的最簡單的代碼示例了。 –

+0

我的Windows配置一切正常。正如我在上面的帖子中所說的,我的默認瀏覽器是FireFox,Start-Run會按照預期打開它提供的鏈接。而且,在我的代碼中,同樣的ShellExecute()可以很好地處理簡單的鏈接,例如http://www.google.com。但是,ShellExecute()的行爲本身對我的url非常奇怪:爲什麼它返回而沒有做任何事情,並且沒有錯誤?可能是ShellExecute()錯誤? –

回答

3

url的格式如下:http:// www。 mysite.xxx/selectPage.php?arg1=xxx & arg2 = yyy & ... & argX =包含文本 「quotes」和一些%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中有未編碼的雙引號,顯然會搞砸了。

示例正確編碼中使用的URL與ShellExecuteEx()

#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(); 
} 
+1

您還應該將空格字符編碼爲'%20':'「http://www.google.de/search?q=ShellExecuteEx%20URL%20%22double%20quotes%22」'。但更重要的是,'lpVerb'應該是'NULL'而不是''open''來啓動用戶的默認瀏覽器。 –

+0

@RemyLebeau爲什麼? – zett42

+3

由於根據[RFC 3986第3.4節](https://tools.ietf.org/html/rfc3986#section-3.4),URL的查詢組件中不允許未經過編碼的空格。查詢只能包含'pchar','/'和'?'字符,並且'pchar'的定義不包含未編碼的空格字符。在'pchar'中沒有明確允許的任何字符必須是百分比編碼,而空格字符是'%20'。 –