2017-07-03 25 views
2

私はC++ Builder XE7でプロジェクトを作成しています。このプロジェクトでは、ボタンをクリックしてWebリンクを開くことができます。サポートページを開いたり、ソーシャルメディアで彼の経験を共有したりすることができます。そのために、私はShellExecute()関数を使用し、1つのボタンを除いてうまくいきます。ShellExecute(およびShellExecuteEx)はURLには何もしません

このボタンをクリックすると、何も起こりません。 ShellExecute()関数はエラーなしで返されます(戻り値は42)が、デフォルトのブラウザは開かず、Webページはまったく表示されません。

::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パラメータは、私がオープンしようとしているWebサイトのリンクが含まれています

は、ここに私のShellExecute()実装

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

私もShellExecuteEx()機能を試してみましたです。セキュリティ上の理由から、私はサンプルとしてここに投稿することはできませんが、ブラウザ(FireFox)でテストしてもうまく動作します。一方、urlのコンテンツをGoogleのウェブサイトに置き換えてコードを実行すると、すべて正常に動作します。

handleは、親フレームのパラメータのちょうどHandleです。

また、hwndフィールドとnShowフィールドのように、ShellExecute/Ex()のパラメータを微調整しようとしましたが、変更はありませんでした。

誰かが間違っていることを指摘できますか?

+1

あなたは[MCVE]投稿もらえますか?また、デフォルトのブラウザは何ですか?もしあなたがStart-Runを実行し、 'http:// www.stackoverflow.com /'のようなURLを入力すればどうなるでしょう。 –

+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に置き換えてください。 URLを正しくエンコードするには、UrlEscape()のような関数を使うことをお勧めします。

ほとんどのブラウザは、ユーザーの入力のための許容誤差を有し、また、有効なエンコーディングを持っていない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(); 
} 
+1

スペース文字も '%20'と同様にエンコードする必要があります:' 'http://www.google.de/search?q=ShellExecuteEx%20URL%20%22double%20quotes%22" '。しかし、もっと重要なことに、 'lpVerb'は' open'の代わりに 'NULL'でなければなりません。 –

+0

@RemyLebeauなぜですか? – zett42

+3

URLのクエリコンポーネントでは、[RFC 3986セクション3.4](https://tools.ietf.org/html/rfc3986#section-3.4)に従って、エンコードされていないスペースが許可されていないためです。クエリには 'pchar'、'/'、'? '文字しかないので、' pchar'の定義にはエンコードされていない空白文字は含まれません。 'pchar'で明示的に許可されていない文字はパーセント記号でなければなりません。スペース文字では'%20'です。 –

関連する問題