wxString wxFileTypeImpl::GetCommand(const wxString& verb) const { // suppress possible error messages wxLogNull nolog; wxString strKey; { wxRegKey explorerKey(wxRegKey::HKCU, wxT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\") + m_ext); if (explorerKey.Exists()) { if (explorerKey.Open(wxRegKey::Read)) { if (explorerKey.QueryValue(wxT("Progid"), strKey)) { strKey = wxFileTypeImplGetCurVer(strKey); } } } } if (!strKey && wxRegKey(wxRegKey::HKCR, m_ext + wxT("\\shell")).Exists()) strKey = m_ext; if ( !strKey && !m_strFileType.empty()) { wxString fileType = wxFileTypeImplGetCurVer(m_strFileType); if (wxRegKey(wxRegKey::HKCR, fileType + wxT("\\shell")).Exists()) strKey = fileType; } if ( !strKey ) { // no info return wxEmptyString; } strKey << wxT("\\shell\\") << verb; wxRegKey key(wxRegKey::HKCR, strKey + wxT("\\command")); wxString command; if ( key.Open(wxRegKey::Read) ) { // it's the default value of the key if ( key.QueryValue(wxEmptyString, command) ) { bool foundFilename = CanonicalizeParams(command); #if wxUSE_IPC // look whether we must issue some DDE requests to the application // (and not just launch it) strKey += wxT("\\DDEExec"); wxRegKey keyDDE(wxRegKey::HKCR, strKey); if ( keyDDE.Open(wxRegKey::Read) ) { wxString ddeCommand, ddeServer, ddeTopic; keyDDE.QueryValue(wxEmptyString, ddeCommand); ddeCommand.Replace(wxT("%1"), wxT("%s")); wxRegKey keyServer(wxRegKey::HKCR, strKey + wxT("\\Application")); keyServer.QueryValue(wxEmptyString, ddeServer); wxRegKey keyTopic(wxRegKey::HKCR, strKey + wxT("\\Topic")); keyTopic.QueryValue(wxEmptyString, ddeTopic); if (ddeTopic.empty()) ddeTopic = wxT("System"); // HACK: we use a special feature of wxExecute which exists // just because we need it here: it will establish DDE // conversation with the program it just launched command.Prepend(wxT("WX_DDE#")); command << wxT('#') << ddeServer << wxT('#') << ddeTopic << wxT('#') << ddeCommand; } else #endif // wxUSE_IPC if ( !foundFilename ) { // we didn't find any '%1' - the application doesn't know which // file to open (note that we only do it if there is no DDEExec // subkey) // // HACK: append the filename at the end, hope that it will do command << wxT(" %s"); } } } //else: no such file type or no value, will return empty string return command; }
wxString wxFileTypeImpl::GetCommand(const wxString& verb) const { // suppress possible error messages wxLogNull nolog; wxString strKey; // Since Windows Vista the association used by Explorer is different from // the association information stored in the traditional part of the // registry. Unfortunately the new schema doesn't seem to be documented // anywhere so using it involves a bit of guesswork: // // The information is stored under Explorer-specific key whose path is // below. The interesting part is UserChoice subkey which is the only one // we use so far but there is also OpenWithProgids subkey which can exist // even if UserChoice doesn't. However in practice there doesn't seem to be // any cases when OpenWithProgids values for the given extension are // different from those found directly under HKCR\.ext, so for now we don't // bother to use this, apparently the programs registering their file type // associations do it in both places. We do use UserChoice because when the // association is manually changed by the user it's only recorded there and // so must override whatever value was created under HKCR by the setup // program. { wxRegKey explorerKey ( wxRegKey::HKCU, wxT("Software\\Microsoft\\Windows\\CurrentVersion\\") wxT("Explorer\\FileExts\\") + m_ext + wxT("\\UserChoice") ); if ( explorerKey.Open(wxRegKey::Read) && explorerKey.QueryValue(wxT("Progid"), strKey) ) { strKey = wxFileTypeImplGetCurVer(strKey); } } if (!strKey && wxRegKey(wxRegKey::HKCR, m_ext + wxT("\\shell")).Exists()) strKey = m_ext; if ( !strKey && !m_strFileType.empty()) { wxString fileType = wxFileTypeImplGetCurVer(m_strFileType); if (wxRegKey(wxRegKey::HKCR, fileType + wxT("\\shell")).Exists()) strKey = fileType; } if ( !strKey ) { // no info return wxEmptyString; } strKey << wxT("\\shell\\") << verb; wxRegKey key(wxRegKey::HKCR, strKey + wxT("\\command")); wxString command; if ( key.Open(wxRegKey::Read) ) { // it's the default value of the key if ( key.QueryValue(wxEmptyString, command) ) { bool foundFilename = CanonicalizeParams(command); #if wxUSE_IPC // look whether we must issue some DDE requests to the application // (and not just launch it) strKey += wxT("\\DDEExec"); wxRegKey keyDDE(wxRegKey::HKCR, strKey); if ( keyDDE.Open(wxRegKey::Read) ) { wxString ddeCommand, ddeServer, ddeTopic; keyDDE.QueryValue(wxEmptyString, ddeCommand); // in some cases "DDEExec" subkey exists but has no value, we // shouldn't use DDE in this case if ( !ddeCommand.empty() ) { ddeCommand.Replace(wxT("%1"), wxT("%s")); wxRegKey keyServer(wxRegKey::HKCR, strKey + wxT("\\Application")); keyServer.QueryValue(wxEmptyString, ddeServer); wxRegKey keyTopic(wxRegKey::HKCR, strKey + wxT("\\Topic")); keyTopic.QueryValue(wxEmptyString, ddeTopic); if (ddeTopic.empty()) ddeTopic = wxT("System"); // HACK: we use a special feature of wxExecute which exists // just because we need it here: it will establish DDE // conversation with the program it just launched command.Prepend(wxT("WX_DDE#")); command << wxT('#') << ddeServer << wxT('#') << ddeTopic << wxT('#') << ddeCommand; } } else #endif // wxUSE_IPC if ( !foundFilename ) { // we didn't find any '%1' - the application doesn't know which // file to open (note that we only do it if there is no DDEExec // subkey) // // HACK: append the filename at the end, hope that it will do command << wxT(" %s"); } } } //else: no such file type or no value, will return empty string return command; }
static bool wxLaunchDefaultBrowserBaseImpl(const wxString& url, int flags) { wxUnusedVar(flags); #if defined(__WXMSW__) #if wxUSE_IPC if ( flags & wxBROWSER_NEW_WINDOW ) { // ShellExecuteEx() opens the URL in an existing window by default so // we can't use it if we need a new window wxURI uri(url); wxRegKey key(wxRegKey::HKCR, uri.GetScheme() + _T("\\shell\\open")); if ( !key.Exists() ) { // try default browser, it must be registered at least for http URLs key.SetName(wxRegKey::HKCR, _T("http\\shell\\open")); } if ( key.Exists() ) { wxRegKey keyDDE(key, wxT("DDEExec")); if ( keyDDE.Exists() ) { // we only know the syntax of WWW_OpenURL DDE request for IE, // optimistically assume that all other browsers are compatible // with it static const wxString TOPIC_OPEN_URL = wxT("WWW_OpenURL"); wxString ddeCmd; wxRegKey keyTopic(keyDDE, wxT("topic")); bool ok = keyTopic.Exists() && (keyTopic.QueryDefaultValue() = TOPIC_OPEN_URL); if ( ok ) { ddeCmd = keyDDE.QueryDefaultValue(); ok = !ddeCmd.empty(); } if ( ok ) { // for WWW_OpenURL, the index of the window to open the URL // in is -1 (meaning "current") by default, replace it with // 0 which means "new" (see KB article 160957) ok = ddeCmd.Replace(wxT("-1"), wxT("0"), false /* only first occurence */) == 1; } if ( ok ) { // and also replace the parameters: the topic should // contain a placeholder for the URL ok = ddeCmd.Replace(wxT("%1"), url, false) == 1; } if ( ok ) { // try to send it the DDE request now but ignore the errors wxLogNull noLog; const wxString ddeServer = wxRegKey(keyDDE, wxT("application")).QueryDefaultValue(); if ( wxExecuteDDE(ddeServer, TOPIC_OPEN_URL, ddeCmd) ) return true; // this is not necessarily an error: maybe browser is // simply not running, but no matter, in any case we're // going to launch it using ShellExecuteEx() below now and // we shouldn't try to open a new window if we open a new // browser anyhow } } } } #endif // wxUSE_IPC WinStruct<SHELLEXECUTEINFO> sei; sei.lpFile = url.c_str(); sei.lpVerb = _T("open"); sei.nShow = SW_SHOWNORMAL; sei.fMask = SEE_MASK_FLAG_NO_UI; // we give error message ourselves BOOL nExecResult = ::ShellExecuteEx(&sei); //From MSDN for wince //hInstApp member is only valid if the function fails, in which case it //receives one of the following error values, which are less than or //equal to 32. const int nResult = (int) sei.hInstApp; // Firefox returns file not found for some reason, so make an exception // for it if ( nResult > 32 || nResult == SE_ERR_FNF || nExecResult == TRUE ) { #ifdef __WXDEBUG__ // Log something if SE_ERR_FNF happens if ( nResult == SE_ERR_FNF || nExecResult == FALSE ) wxLogDebug(wxT("SE_ERR_FNF from ShellExecute -- maybe FireFox?")); #endif // __WXDEBUG__ return true; } #elif defined(__WXMAC__) OSStatus err; ICInstance inst; long int startSel; long int endSel; err = ICStart(&inst, 'STKA'); // put your app creator code here if (err == noErr) { #if !TARGET_CARBON err = ICFindConfigFile(inst, 0, NULL); #endif if (err == noErr) { ConstStr255Param hint = 0; startSel = 0; endSel = url.length(); err = ICLaunchURL(inst, hint, url.fn_str(), endSel, &startSel, &endSel); if (err != noErr) wxLogDebug(wxT("ICLaunchURL error %d"), (int) err); } ICStop(inst); return true; } else { wxLogDebug(wxT("ICStart error %d"), (int) err); return false; } #else // (non-Mac, non-MSW) #ifdef __UNIX__ // Our best best is to use xdg-open from freedesktop.org cross-desktop // compatibility suite xdg-utils // (see http://portland.freedesktop.org/wiki/) -- this is installed on // most modern distributions and may be tweaked by them to handle // distribution specifics. Only if that fails, try to find the right // browser ourselves. wxString path, xdg_open; if ( wxGetEnv(_T("PATH"), &path) && wxFindFileInPath(&xdg_open, path, _T("xdg-open")) ) { if ( wxExecute(xdg_open + _T(" ") + url) ) return true; } wxString desktop = wxTheApp->GetTraits()->GetDesktopEnvironment(); // GNOME and KDE desktops have some applications which should be always installed // together with their main parts, which give us the if (desktop == wxT("GNOME")) { wxArrayString errors; wxArrayString output; // gconf will tell us the path of the application to use as browser long res = wxExecute( wxT("gconftool-2 --get /desktop/gnome/applications/browser/exec"), output, errors, wxEXEC_NODISABLE ); if (res >= 0 && errors.GetCount() == 0) { wxString cmd = output[0]; cmd << _T(' ') << url; if (wxExecute(cmd)) return true; } } else if (desktop == wxT("KDE")) { // kfmclient directly opens the given URL if (wxExecute(wxT("kfmclient openURL ") + url)) return true; } #endif bool ok = false; wxString cmd; #if wxUSE_MIMETYPE wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(_T("html")); if ( ft ) { wxString mt; ft->GetMimeType(&mt); ok = ft->GetOpenCommand(&cmd, wxFileType::MessageParameters(url)); delete ft; } #endif // wxUSE_MIMETYPE if ( !ok || cmd.empty() ) { // fallback to checking for the BROWSER environment variable cmd = wxGetenv(wxT("BROWSER")); if ( !cmd.empty() ) cmd << _T(' ') << url; } ok = ( !cmd.empty() && wxExecute(cmd) ); if (ok) return ok; // no file type for HTML extension wxLogError(_T("No default application configured for HTML files.")); #endif // !wxUSE_MIMETYPE && !__WXMSW__ return false; }
bool wxDoLaunchDefaultBrowser(const wxString& url, const wxString& scheme, int flags) { wxUnusedVar(flags); #if wxUSE_IPC if ( flags & wxBROWSER_NEW_WINDOW ) { // ShellExecuteEx() opens the URL in an existing window by default so // we can't use it if we need a new window wxRegKey key(wxRegKey::HKCR, scheme + wxT("\\shell\\open")); if ( !key.Exists() ) { // try the default browser, it must be registered at least for http URLs key.SetName(wxRegKey::HKCR, wxT("http\\shell\\open")); } if ( key.Exists() ) { wxRegKey keyDDE(key, wxT("DDEExec")); if ( keyDDE.Exists() ) { // we only know the syntax of WWW_OpenURL DDE request for IE, // optimistically assume that all other browsers are compatible // with it static const wxChar *TOPIC_OPEN_URL = wxT("WWW_OpenURL"); wxString ddeCmd; wxRegKey keyTopic(keyDDE, wxT("topic")); bool ok = keyTopic.Exists() && keyTopic.QueryDefaultValue() == TOPIC_OPEN_URL; if ( ok ) { ddeCmd = keyDDE.QueryDefaultValue(); ok = !ddeCmd.empty(); } if ( ok ) { // for WWW_OpenURL, the index of the window to open the URL // in is -1 (meaning "current") by default, replace it with // 0 which means "new" (see KB article 160957) ok = ddeCmd.Replace(wxT("-1"), wxT("0"), false /* only first occurrence */) == 1; } if ( ok ) { // and also replace the parameters: the topic should // contain a placeholder for the URL ok = ddeCmd.Replace(wxT("%1"), url, false) == 1; } if ( ok ) { // try to send it the DDE request now but ignore the errors wxLogNull noLog; const wxString ddeServer = wxRegKey(keyDDE, wxT("application")); if ( wxExecuteDDE(ddeServer, TOPIC_OPEN_URL, ddeCmd) ) return true; // this is not necessarily an error: maybe browser is // simply not running, but no matter, in any case we're // going to launch it using ShellExecuteEx() below now and // we shouldn't try to open a new window if we open a new // browser anyhow } } } } #endif // wxUSE_IPC WinStruct<SHELLEXECUTEINFO> sei; sei.lpFile = url.c_str(); sei.lpVerb = wxT("open"); sei.nShow = SW_SHOWNORMAL; sei.fMask = SEE_MASK_FLAG_NO_UI; // we give error message ourselves if ( ::ShellExecuteEx(&sei) ) return true; return false; }