none
SHGetFolderPath unter 64-bit-Windows mit gemischtbittiger Anwendung RRS feed

  • Frage

  • Guten Tag,

    Ich wurde vor Kurzem dankenswerterweise von Martin Richter darauf hingewiesen, dass ich ein sehr böser Junge war, als ich mir Systemverzeichnisse direkt aus der Registy holte. Ich bin gerade dabei, den betreffenden Code auf ShGetFolderPath umzustellen, laufe dabei allerdings in ein Problem: Unter 64-bit-Windows bekomme ich damit und mit CSIDL_PROGRAM_FILES "C:\Program Files (x86)", was in diesem speziellen Fall keinen Sinn ergibt.

    Mir ist klar, dass 32-bit-Anwendungen da hingehören, aber es handelt sich in meinem Fall um eine Anwendung, die zur Laufzeit das native Backend auswählt (ein Office-Plugin). Die Installationsroutine, um die es hier geht, wird in 32 bit ausgeliefert, damit sie überall läuft, sie installiert aber eine Anwendung, die in C:\Program Files (x86) beim besten Willen nichts zu suchen hat und dort auch ziemlich deplaziert wirkt.

    Meine Frage ist also Folgende: Was ist die beste Möglichkeit, mit einer 32-bit-Anwendung unter 64-bit-Windows das 64-bit-Programmdateiverzeichnis auszulesen?

    Freundliche Grüße.

     

    Montag, 21. März 2011 07:19

Antworten

  • Ich sehe überhaupt kein Problem, dass eigentliche Setup als 32bit Programm auszuliefern und eine weitere EXE die den 64bit Part kann, zu starten, wenn das 32bit Programm erkennt, dass es auf WOW64 läuft.
    Das entspräche genau dem Konzept, wie es zuvor auch schon geschrieben habe.

    Du kannst sagen was Du willst. Nach den MS Reglementarien gehört Dein Programm nicht in den 64bit Zweig.
    Just my 2 cents. Wir können diese Diskussion beenden. Zertifiziert bekommst Du Deine Software IMHO so auf jeden Fall so nicht...


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    • Als Antwort markiert Burzmali Dienstag, 22. März 2011 05:25
    Montag, 21. März 2011 17:20
    Moderator

Alle Antworten

  • Microsoft sagt eigentlich etwas anderes:

    FOLDERID_ProgramFiles

    OS

    Application

    KNOWNFOLDERID

    Default Path

    CSIDL Equivalent

    32 bit

    32 bit

    FOLDERID_ProgramFiles

    %SystemDrive%\Program Files

    CSIDL_PROGRAM_FILES

    32 bit

    32 bit

    FOLDERID_ProgramFilesX86

    %SystemDrive%\Program Files

    CSIDL_PROGRAM_FILESX86

    32 bit

    32 bit

    FOLDERID_ProgramFilesX64 (undefined)

    Not applicable

    Not applicable

     

    64 bit

    64 bit

    FOLDERID_ProgramFiles

    %SystemDrive%\Program Files

    CSIDL_PROGRAM_FILES

    64 bit

    64 bit

    FOLDERID_ProgramFilesX86

    %SystemDrive%\Program Files (x86)

    CSIDL_PROGRAM_FILESX86

    64 bit

    64 bit

    FOLDERID_ProgramFilesX64

    %SystemDrive%\Program Files

    None

     

    64 bit

    32 bit

    FOLDERID_ProgramFiles

    %SystemDrive%\Program Files (x86)

    CSIDL_PROGRAM_FILES

    64 bit

    32 bit

    FOLDERID_ProgramFilesX86

    %SystemDrive%\Program Files (x86)

    CSIDL_PROGRAM_FILESX86

    64 bit

    32 bit

    FOLDERID_ProgramFilesX64

    %SystemDrive%\Program Files

    None

     

    Montag, 21. März 2011 08:03
  • Eine 32bit Anwednung gehört nur nach C:\Program Files (x86) und sonst nirgend wohin.
    Sie ist genau dort richtig platziert. Du würdest kein "Windows compatible" erhalten wenn Du einen anderen Folder verwendest.

    Ansonsten gibt es netterweise auch noch Environment Variablen auf einem 64bit System

    ProgramFiles=C:\Program Files (x86)
    ProgramFiles(x86)=C:\Program Files (x86)
    ProgramW6432=C:\Program Files

    Wobei natürlich ProgramFiles(x86) und ProgramW6432 nur auf 64bit Rechnern vorhanden sind ... ;

    PS: Ich habe nie behauptet, dass Du ein "böser Junge" bist/warst. Du hast nur Code verwendet, den man nicht verwenden soll... ;)


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Montag, 21. März 2011 09:36
    Moderator
  • Es handelt sich aber bei der Anwendung nicht um eine 32-Bit-Anwendung. Die nativen Teile der Applikation liegen als 32- und 64-Bit-Version vor, und die nicht-nativen Teile suchen das benötigte Backend zur Laufzeit aus und laden es nach bzw. lassen es nachladen. Es ist die Installationsroutine, die unabhängig von alledem als 32-Bit-Anwendung vorliegt und das normale Programmdateiverzeichnis benötigt. Es macht ja wenig Sinn, ein Verzeichnis C:\Program Files (x86)\Programmname\x64 aufzumachen.

    Eine Umgebungsvariable ProgramW6432 habe ich unter Windows XP 64 bit nicht; set zeigt mir auch nichts Vergleichbares an.

    Ich kann natürlich dieses spezielle Verzeichnis weiter aus der Registry auslesen (HKLM\Software\Microsoft\Windows\CurrentVersion\ProgramFilesDir), und für den Moment werde ich das auch tun, aber ich fühle mich deshalb ein bisschen wie ein böser Junge. ;) Wenn es im API (oder sonstwo) eine dokumentierte Möglichkeit gibt, wäre mir das natürlich lieber.

    @Praktikant: Das Problem ist, dass es für FOLDERID_ProgramFilesX64 keine CSIDL gibt, wie SHGetFolderPath sie benötigt. SHGetKnownFolderPath ist keine Option, weil die Funktion erst seit Vista existiert und XP noch unterstützt werden muss.

     Nachtrag: Der Registry-Pfad oben ist nicht mal richtig; man wird anscheinend als 32-Bit-Anwendung unter 64-Bit-Windows in einen besonderen Unterschlüssel von HKLM\Software umgeleitet. Der Hack, der funktioniert, ist so dreckig, dass ich mich nicht traue, ihn hier anzusprechen.

    • Bearbeitet Burzmali Montag, 21. März 2011 12:01 Nachtrag
    Montag, 21. März 2011 11:51
  • Wie Du selbst siehst ist auch Dein Registry Ast nur eine Map in den WOW Ast der eigentlichen Registry unter 64bit. War Dir das nicht klar? ;)

    Wenn es ein Installer ist, dann schreib diesen Installer als 64bit Version und Du kanst Zugreifen wo Du willst und unterliegst keinen Restriktionen. Zusätzlich kannst Du auch den 32bit Ast manipulieren., oder den entsprechenden 32bit Installer starten, den Du aus dem selben Code erzeugst.

    Übrigends: Auch hier macht es VS vor:
    Ist die Anwednung "hauptsächlich" 32bit, dann gehört Sie nach x86! In diesem Unterfoldern gibt es einige x64 Äste... ;)

    BTW: XP 64bit würde ich glattweg ignorieren. (Meine persönliche Meinung)


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Montag, 21. März 2011 14:30
    Moderator
  • Nur könnte eine 64-Bit-Installationsroutine nicht auf 32-Bit-Windows laufen, was sich verbietet, wenn die Anwendung für beide Architekturen auf einmal ausgeliefert werden soll. Auch ist keine der Architekturen "hauptsächlich" - es kann durchaus vorkommen, dass ein Benutzer mit einer Office-Version die eine und mit der anderen die andere Version braucht.

    Die Anwendung gehört nicht nach C:\Program Files (x86), und das Installationsprogramm kann nicht als 64-Bit-Programm kommen. Womöglich könnte ich das Raussuchen des Programmdateiverzeichnisses in eigene Prozesse auslagern und per Pipe in den Hauptprozess zurückgeben, aber damit fange ich erst an, wenn eine zukünftige Windows-Version den bisherigen Hack kaputtmacht.

    Dass HKLM\Software für 32-Bit-Anwendungen umgeleitet wird, wusste ich schon, hatte aber in dem Moment nicht dran gedacht - ich bin letztendlich an dem Versuch gescheitert, den alten Code (welcher HKLM\System benutzt) etwas weniger abenteuerlich zu gestalten.

    Also sehe ich das richtig, dass es keine vernünftige Lösung für mein Problem gibt? Zur Not muss halt eine unvernünftige herhalten. Ich hätte große Schwierigkeiten, zu erklären, dass das auf einmal nicht mehr gehen soll.

     

    Montag, 21. März 2011 14:51
  • Ich sehe überhaupt kein Problem, dass eigentliche Setup als 32bit Programm auszuliefern und eine weitere EXE die den 64bit Part kann, zu starten, wenn das 32bit Programm erkennt, dass es auf WOW64 läuft.
    Das entspräche genau dem Konzept, wie es zuvor auch schon geschrieben habe.

    Du kannst sagen was Du willst. Nach den MS Reglementarien gehört Dein Programm nicht in den 64bit Zweig.
    Just my 2 cents. Wir können diese Diskussion beenden. Zertifiziert bekommst Du Deine Software IMHO so auf jeden Fall so nicht...


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    • Als Antwort markiert Burzmali Dienstag, 22. März 2011 05:25
    Montag, 21. März 2011 17:20
    Moderator
  • Naja, jetzt muss man aber schon ein bisschen die Praxis sehen. Wenn ich jemandem etwas mit der Aufschrift "jetzt auch für 64 Bit" verkaufe, kann ich ihm bei der Installation kein Verzeichnis anbieten, das dem Namen nach explizit für 32-Bit-Programme gedacht ist. Wenn das in den Microsoft-Richtlinien tatsächlich so drinsteht, habe ich wenig Bedenken, mich darüber hinwegzusetzen - den Benutzer zu verwirren bereitet mir größere Sorgen als ein Zertifikat, nach dem in bald 20 Jahren noch niemand gefragt hat.

    Ich habe derzeit einen Hack, der unter allen bisherigen Windows-Versionen zuverlässig funktioniert, und wenn er fehlschlägt, falle ich halt auf %SystemDrive%\Program Files zurück, wo neuere Windows-Versionen ja eine Junction haben sollten. Ich hätte das gerne sauberer, aber wenn die Alternative aus einem pipe/fork/exec-Trick besteht - das kann ja wohl nicht ernsthaft der kanonische Weg sein, einem 32-Bit-Programm Informationen über ein 64-Bit-System beizubringen.

    Wie dem auch sei, die Frage ist wohl beantwortet. Danke für Deine Mühe.

     

    Dienstag, 22. März 2011 05:25