Entwickler-Ecke
Windows API - Shellexecute unter Windows 7 - URL mit Sprunganker
trm - Do 01.07.10 00:28
Titel: Shellexecute unter Windows 7 - URL mit Sprunganker
Huhu,
ich habe schon etliche Beiträge durchsucht, jedoch keine Lösung für folgendes Probelem gefunden:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| if FileExists(HelpPfad + HelpFileName) then ShowURL('file:///' + HelpPfad + HelpFileName, '#' + Dummy_String);
procedure TForm1.ShowURL(URL, Nav: string); begin
if Length(Trim(Nav)) > 0 then URL := '"' + URL + Nav + '"'; ShellExecute(Application.Handle, PAnsiChar('open'), PAnsiChar(Url), PAnsiChar(Nav), nil, SW_SHOWNORMAL);
end; |
Das Problem hier ist: der Anker wird nicht mehr als Parameter weitergegeben. Unter Windows XP ging das noch einwandfrei.
Das gleiche Problem hatte auch Lemmy vor längerer Zeit [
http://www.delphiforum.de/viewtopic.php?t=80761], ich habe Windows7 erst seit ein paar Wochen und er gab leider keine Rückmeldung.
Nun stehe ich vor der gleichen Situation.
Die URL wird immer geöffnet ohne Anker.
Einen direkten Verweis auf den IE z.B. möchte ich nicht.
Hat jemand eine Idee bitte ?
Viele Grüße
~Mathias
Moderiert von
Narses: URL-Tags ergänzt.
Gerd Kayser - Mo 05.07.10 11:15
trm hat folgendes geschrieben : |
| Das Problem hier ist: der Anker wird nicht mehr als Parameter weitergegeben. |
So geht's (getestet unter Windows 7 mit BDS 2006 und dem Internet Explorer):
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TForm1.Button2Click(Sender: TObject); var Befehl : string; StartupInfo : TStartupInfo; ProcessInfo : TProcessInformation; begin FillChar(StartupInfo, SizeOf(TStartupInfo), 0); StartupInfo.cb := SizeOf(TStartupInfo); Befehl := '"c:\program files\internet explorer\iexplore.exe" File:///f:\test2\a_name.htm#kap02'; CreateProcess(nil, PChar(Befehl), nil, nil, false, 0, nil, 'c:\', StartupInfo, ProcessInfo); end; |
Andreas L. - Mo 05.07.10 11:35
@Gerd Kayser:
Einen Verweis auf den IE will er ja nicht.
@trm:
Wenn du den Anker nicht als Parameter übergibst sondern an die URL anhängst sollte es funktionieren.
Gerd Kayser - Mo 05.07.10 12:22
Andreas L. hat folgendes geschrieben : |
| Einen Verweis auf den IE will er ja nicht. |
Es führt kein Weg daran vorbei: Der Browser muß bei CreateProcess voll qualifiziert in Gänsefüßchen davor gesetzt werden. Wenn er das nicht will, dann muß er eben damit leben, daß die Sprungmarken nicht angesprungen werden können.
| Zitat: |
| Wenn du den Anker nicht als Parameter übergibst sondern an die URL anhängst sollte es funktionieren. |
Mit ShellExecute funktioniert es überhaupt nicht.
trm - Mo 05.07.10 12:25
Hallo ihr 2,
Gerd, Dein Beispiel mag funktionieren, ist aber leider wieder zu abhängig ;)
Andreas, bis Windows XP ging das auch noch. Aber mit der neuen Technik zu Codeausführungverhinderung hat Microsoft auch dieses Verhalten geändert (das habe ich jedenfalls so verstanden, als ich im msdn gestöbert habe).
Hier
http://newoldthing.wordpress.com/2007/03/23/how-does-your-browsers-know-that-its-not-the-default-browser/ ist ein schöner Artikel, den ich gefunden habe. Vielleicht werde ich damit etwas brauchbares hinbekommen. Dann würde Gerd sein Code hilfreich sein :)
MaPsTaR - Mo 05.07.10 12:30
Hallo,
leider hast du, während ich das hier geschrieben hab schon geantwortet... :-(
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| function TForm1.GetDefaultBrowserPath: String; var Reg: TRegistry; DefBrowser: String; begin result := ''; Reg := TRegistry.Create; Reg.RootKey := HKEY_CLASSES_ROOT; if Reg.OpenKey('.html', false) then begin DefBrowser := Reg.ReadString(''); Reg.CloseKey; if Reg.OpenKey(DefBrowser + '\shell\open\command', false) then begin result := Reg.ReadString(''); Reg.CloseKey; end; end; Reg.Free; end; |
Da ich Win 7 nicht benutze kann ich aber nicht garantieren, dass die Registry-Pfade dort auch stimmen, unter XP läuft das aber auf jeden Fall.
Gruß
trm - Mo 05.07.10 12:42
Huhu, ich nochmal :)
MaPsTaR, danke für Deine Hilfe.
Quelltext
1: 2: 3: 4: 5: 6: 7:
| Windows Vista+ HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice -> ProgID --> HKEY_CLASSES_ROOT\IE.HTTP\shell\open\command -> Standard IE --> HKEY_CLASSES_ROOT\FirefoxURL\shell\open\command -> Standard FF
Windows 9x+ HKEY_CLASSES_ROOT\http\shell\open\command |
Ich probiere das folgendermaßen. Erst teste ich, obe es einen Eintrag/ob es den Key UserChoice gibt.
Wenn ja, könnte es sein, dass ein Windows Vista oder höher vorhanden ist.
Dann lese ich HKEY_CLASSES_ROOT aus und schaue, ob dort ein korrektes Protokoll vorhanden ist. Wenn ja, prüfen, ob das programm dahinter auch existiert. Wenn ja, bin ich hier fertig.
Sollte oben irgendwann ein NEIN kommen, lese ich den Windowsstandard aus -> HKEY_CLASSES_ROOT\http\shell\open\command
Ich denke, das sollte so klappen - oder hat jemand einen Fehler entdeckt?
Gruß und danke nochmal an alle Helfer(innen) :D
~Mathias
Gerd Kayser - Mo 05.07.10 12:46
trm hat folgendes geschrieben : |
| Gerd, Dein Beispiel mag funktionieren, ist aber leider wieder zu abhängig ;) |
Mein Beispiel zeigt anhand des Internet Explorers, wie es geht, nämlich mit CreateProcess. Da ich andere Browser nicht installiert habe, mußt Du das noch austesten.
---
Moderiert von
Narses: Beiträge zusammengefasst---
trm hat folgendes geschrieben : |
| Wenn ja, könnte es sein, dass ein Windows Vista oder höher vorhanden ist. |
Dafür gibts die Funktion GetVersionEx. Damit bekommst Du die Windows-Version heraus.
trm - Mo 05.07.10 13:40
Huhu und
JUHU :D
Ich habs hinbekommen.
Hier mal mein Ergebnis.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109:
| function TForm1.GetDefaultBrowser(var _path, _browser: string): Boolean; var Reg: TRegistry; Dummy_String: string; Dummy_Bool: Boolean; DefBrowser: string; begin
Result := False; Reg := TRegistry.Create;
Reg.RootKey := HKEY_CURRENT_USER; Dummy_Bool := Reg.OpenKeyReadOnly('HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice'); if Dummy_Bool then begin Dummy_String := Reg.ReadString('ProgID'); Reg.CloseKey;
Reg.RootKey := HKEY_CLASSES_ROOT; Dummy_Bool := Reg.OpenKeyReadOnly(Dummy_String + '\shell\open\command'); if Dummy_Bool then begin DefBrowser := Reg.ReadString(''); Reg.CloseKey; end; end; Reg.CloseKey;
if not Dummy_Bool then begin Reg.RootKey := HKEY_CLASSES_ROOT; Dummy_Bool := Reg.OpenKeyReadOnly('.html'); if Dummy_Bool then begin DefBrowser := Reg.ReadString(''); Reg.CloseKey; Dummy_Bool := Reg.OpenKeyReadOnly(DefBrowser + '\shell\open\command'); if Dummy_Bool then DefBrowser := Reg.ReadString(''); Reg.CloseKey; end; end;
Reg.Free;
if Dummy_Bool then begin Dummy_Bool := Length(DefBrowser) > 0; while Pos('""', DefBrowser) > 0 do DefBrowser := StringReplace(DefBrowser, '""', '"', [rfReplaceAll]); if Pos('"', DefBrowser) > 0 then begin if DefBrowser[1] = '"' then DefBrowser := copy(DefBrowser, 2, MaxInt); DefBrowser := copy(DefBrowser, 0, Pos('"', DefBrowser) - 1); end; while Pos('"', DefBrowser) > 0 do DefBrowser := StringReplace(DefBrowser, '"', '', [rfReplaceAll]); _path := ExtractFilepath(DefBrowser); _browser := ExtractFilename(DefBrowser);
Result := Dummy_Bool; end;
end;
procedure TForm1.ShowURL(URL, Nav: string); var BrowserPfad, BrowserBin: string; Befehl: string; StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; Dummy_Bool: Boolean; begin
if Length(Trim(Nav)) > 0 then URL := URL + Nav;
Dummy_Bool := GetDefaultBrowser(BrowserPfad, BrowserBin);
if Dummy_Bool then begin FillChar(StartupInfo, SizeOf(TStartupInfo), 0); StartupInfo.cb := SizeOf(TStartupInfo); Befehl := Format('"%s" "%s"', [BrowserPfad + BrowserBin, URL]); CreateProcess(nil, PChar(Befehl), nil, nil, false, 0, nil, 'c:\', StartupInfo, ProcessInfo); end;
if not Dummy_Bool then ShellExecute(Handle, PAnsiChar('open'), PAnsiChar(Url), nil, nil, SW_SHOWNORMAL);
end; |
GetDefaultBrowser(var _path, _browser: string) habe ich mit Absicht mit 2 Variablen versehen, weil man so gleich auch einen Text hat, falls man was ausgeben muss. Damit erspart man sich manuelles Extract...
ShowURL(URL, Nav: string) ist auch geteilt, das blieb noch übrig vom Testen. So hat man für spätere Ereignisse auch gleich wieder mehr Flexibilität.
Falls möglich, kann das bitte jemand nochmal durchgucken, ob evtl. bei GetDefaultBrowser, bei den StringReplace etwas optimiert werden kann?
Ich musste das so machen, weil ein einfaches ExtractFileName nicht funktionierte, da z.B. beim Firefox-Protokoll noch Parameter dabei standen (
'"C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -requestPending -osint -url "%1"' -> Windows 7x64).
Ach, Gerd: Natürlich hast Du Recht, dass Dein Code ok war. Ich wollte Deine Hilfe auch nicht schlecht machen, es war nur eine Aussage von mir mit der Bindung..
..aber wie Du siehst, habe ich versucht eine Lösung für mich zu finden :)
Testen kann das eigentlich jeder, der verschiedene Browser installiert hat und Rechte zum Setzen eines neuen Standardbrowsers besitzt.
Rein theorethisch sollte es auch ab Windows95 laufen, ohne extra eine Windowsversionsprüfung vornehmen zu müssen.
Danke nochmal und bis bald,
~Mathias :)
Edit: RS-Fehler gefunden :(
Edit2: Fehler im Code gefunden (hatte begin .. end vergessen)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!