2010-01-17 23 views
14

Ich möchte eine Datei simulieren, ohne sie auf der Festplatte zu schreiben. Ich habe eine Datei am Ende meiner ausführbaren Datei und ich würde gerne ihren Pfad zu einer DLL geben. Natürlich, da es keinen wirklichen Pfad hat, muss ich es fälschen.Wie erstelle ich eine virtuelle Datei?

Ich habe zuerst versucht, Named Pipes unter Windows zu verwenden. Das würde einen Pfad wie \\. \ Pipe \ mymemoryfile ermöglichen, aber ich kann es nicht funktionieren lassen, und ich bin mir nicht sicher, ob die DLL einen Pfad wie diesen unterstützen würde.

Zweitens habe ich CreateFileMapping und GetMappedFileName gefunden. Können sie verwendet werden, um eine Datei in einem Fragment eines anderen zu simulieren? Ich bin mir nicht sicher, ob dies die API ist.

Was ich versuche zu tun scheint Boxedapp ähnlich. Irgendwelche Ideen darüber, wie sie es machen? Ich nehme an, es ist etwas wie API Abfangen (Like Detour), aber das wäre eine Menge Arbeit. Gibt es einen anderen Weg, es zu tun?

Warum? Ich bin an dieser spezifischen Lösung interessiert, weil ich die Daten verstecken möchte und nur eine Datei verteile, aber auch aus verrückten Gründen, dass es so funktioniert;) Ich stimme zu, dass das Kopieren von Daten in eine temporäre Datei erfolgen würde arbeiten und eine viel einfachere Lösung sein.

Antwort

4

Sie können die Daten in einem NTFS-Stream speichern. Auf diese Weise können Sie einen echten Weg, um Ihre Daten zeigen, die Sie auf Ihre DLL in Form von

x:\myfile.exe:mystreamname 

wie eine normale Datei geben kann, aber Dies funktioniert nur genau es funktioniert, wenn das Dateisystem verwendet NTFS ist. Dies ist heutzutage unter Windows Standard, aber ist natürlich keine Option, wenn Sie ältere Systeme unterstützen möchten oder dies von einem USB-Stick oder ähnlichem ausführen möchten. Beachten Sie, dass alle in einer Datei vorhandenen Streams verloren gehen, wenn die Datei als Anhang in einer E-Mail gesendet oder einfach von einer NTFS-Partition auf eine FAT32-Partition kopiert wird.

Ich würde sagen, dass die kompatibelste Art wäre, Ihre Daten in eine tatsächliche Datei zu schreiben, aber Sie können es natürlich auch auf NTFS-Systemen und auf FAT-Systemen tun. Ich empfehle es wegen der zusätzlichen Komplexität dagegen. Der geeignete Weg wäre natürlich, Ihre Dateien separat zu verteilen, aber da Sie angegeben haben, dass Sie das nicht wollen, sollten Sie in diesem Fall in eine temporäre Datei schreiben und der DLL den Pfad zu dieser Datei geben. Stellen Sie sicher, dass Sie die temporäre Datei in das temporäre Verzeichnis des Benutzers schreiben (den Pfad finden Sie unter GetTempPath in C/C++).

Ihre andere Option wäre, einen Dateisystem-Filter-Treiber zu schreiben, aber das ist ein Weg, von dem ich dringend abraten. Das vereitelt auch den Zweck der Verwendung einer einzigen Datei ...

Wenn Sie nur eine einzige Datei für die Verteilung benötigen, wie wäre es mit einer Zip-Datei oder einem Installer?

+0

Und wie genau verteilst du die Datei? Ich würde sagen, Zippen oder Kopieren der Exe würde den NTFS-Stream verschwinden lassen? –

+0

@Gregory: Ja. Der Anwendungsfall ist in der Frage nicht wirklich klar, aber ich stimme zu, dass die Verwendung von Streams sehr wohl keine Option für das OP sein kann - hoffentlich wird dies auch deutlich in meiner Antwort angegeben. Der Hauptpunkt, den ich versuche, in der Antwort zu hämmern, ist, dass die Verwendung einer tatsächlichen Datei die beste Option ist. – villintehaspam

+0

Dies ist eine sehr interessante Idee. Schade, es funktioniert nur auf NTFS. Da es keine perfekte Antwort gibt, ist diese die Beste. –

4

Pipes dienen zur Kommunikation zwischen Prozessen, die gleichzeitig ausgeführt werden. Sie speichern keine Daten für späteren Zugriff und sie haben nicht dieselbe Semantik wie Dateien (Sie können beispielsweise keine Pipe suchen oder zurückspulen).

Wenn Sie nach dateiähnlichem Verhalten suchen, ist Ihre beste Wette immer die Verwendung einer Datei. Unter Windows können Sie FILE_ATTRIBUTE_TEMPORARY an CreateFile als Hinweis an das System übergeben, um zu vermeiden, Daten auf die Festplatte zu spülen, wenn genügend Speicher vorhanden ist.

Wenn Sie sich Sorgen über die Leistungseinbußen beim Schreiben auf die Festplatte machen, sollte das oben Genannte ausreichen, um die Leistungseinbußen in den meisten Fällen zu vermeiden. (Wenn das System zu wenig Speicher hat, um die Dateidaten auf die Festplatte zu übertragen, wird es wahrscheinlich auch stark ausgelagert - Sie haben bereits ein Leistungsproblem.)

Wenn Sie versuchen, das Schreiben auf die Festplatte zu vermeiden Kannst du aus irgendeinem anderen Grund erklären warum? Im Allgemeinen ist es ziemlich schwierig zu verhindern, dass Daten jemals auf die Festplatte gelangen - der Benutzer kann zum Beispiel immer den Computer in den Ruhezustand versetzen.

+0

Die Dateien werden direkt in die .exe eingebettet, aber die DLL akzeptiert nur einen Pfad als Eingabe (kann nicht von iStream oder so ähnlich geladen werden) –

3

Da Sie keine Kontrolle über die DLL haben, müssen Sie davon ausgehen, dass die DLL eine tatsächliche Datei erwartet. Es macht wahrscheinlich irgendwann diese Annahme, weshalb Named Pipes Sie versagen.

Die einfachste Lösung besteht darin, eine temporäre Datei im temporären Verzeichnis zu erstellen, die Daten aus Ihrer EXE in die temporäre Datei zu schreiben und dann die temporäre Datei zu löschen.

Gibt es einen Grund, warum Sie diese "Pseudo-Datei" am Ende Ihrer EXE einbetten, statt sie nur mit unserer Anwendung zu verteilen? Sie verteilen diese Drittanbieter-DLL offensichtlich bereits mit Ihrer Anwendung, sodass eine weitere Datei nicht so aussieht, als würde es Sie verletzen?

Eine andere Frage, werden sich diese Daten ändern? Das heißt, Sie erwarten, diese "Pseudo-Datei" in Ihrer EXE zurückzuschreiben? Ich denke nicht, dass das gut funktionieren wird. Standardbenutzer haben möglicherweise keinen Schreibzugriff auf die EXE, und das würde wahrscheinlich Anti-Virus-Nüsse auslösen.

Und kein CreateFileMapping und GetMappedFileName wird definitiv nicht funktionieren, da sie Ihnen keinen Dateinamen geben, der an CreateFile übergeben werden kann. Wenn Sie diese DLL irgendwie dazu bringen könnten, ein HANDLE zu akzeptieren, dann würde das funktionieren.

Und ich würde nicht einmal mit API Abfangen stören. Geben Sie der DLL einfach einen Pfad zu einer aktuellen Datei.

1

Das Lesen Ihrer Frage ließ mich denken: Wenn Sie einen Bereich des Speichers als eine Datei vorgeben und eine Art "virtuellen Pfad" zu ihm haben, dann würde dies das Laden einer DLL direkt aus dem Speicher ermöglichen, was LoadLibrary verbietet indem Sie nach einem Pfadnamen fragen. Und deshalb schreiben Leute ihren eigenen PE-Loader, wenn sie das erreichen wollen.

Ich würde sagen, dass Sie mit File Mapping nicht erreichen können, was Sie wollen: Der Zweck der Dateizuordnung besteht darin, einen Teil einer Datei so zu behandeln, als wäre es physischer Speicher, und Sie wollen das Reziproke.

Die Verwendung von Umleitungen bedeutet, dass Sie alles, was die abgefangene DLL-Funktion macht, replizieren müssen, außer dass Sie Daten aus einer echten Datei erhalten; daher ist es nicht generisch. Oder, noch komplizierter, lassen Sie uns so tun, als ob die DLL verwendet; dann stellst du dir deine eigene vor, die ein spezielles Muster im Pfad erkennt und dir die C-Runtime-Interna imitiert ... Hmm, ist es wirklich den ganzen Schmerz wert? : D

+0

da c runtime eine Fassade für w32 Funktionen ist, würde ich nicht Sie müssen nicht jede Funktion außer Kraft setzen, die Datei verwendet, sondern die unterste Ebene. –

0

Wie wäre es mit einer Art von RamDisk und Schreiben der Datei auf diese Festplatte? Ich habe selbst einige Ramdisks ausprobiert, habe aber nie einen guten gefunden, sag mir, ob du erfolgreich bist.

0

Nun, wenn Sie die virtuelle Datei in Ihrer exe benötigen, müssen Sie ein Vektor-, Stream- oder Char-Array erstellen, das groß genug ist, um alle virtuellen Daten aufzunehmen, die Sie schreiben wollen.

das ist die einzige Lösung, die ich mir vorstellen kann, ohne irgendwelche I/O auf Festplatte (auch wenn Sie nicht in Datei schreiben).

Wenn Sie eine Datei wie Pfadsyntax beibehalten müssen, schreiben Sie einfach eine Klasse, die dieses Verhalten nachahmt und anstatt in eine Datei zu schreiben, schreiben Sie in Ihren Speicherpuffer. Es ist so einfach wie es geht. Denk an KISS.

Prost

0

Bitte beschreiben Sie, nicht die Daten aus Ihrer EXE extrahieren und sie in eine temporäre Datei schreiben. Viele Anwendungen tun dies - es ist die klassische Lösung für dieses Problem.

Wenn Sie wirklich eine "virtuelle Datei" bereitstellen müssen, ist die sauberste Lösung wahrscheinlich ein Dateisystemfiltertreiber. "sauber" bedeutet nicht "gut" - ein Filter ist eine vollständig dokumentierte und unterstützte Lösung, daher ist er sauberer als API-Hooking, -Injektion usw. Allerdings sind Dateisystemfilter nicht einfach.

OSR Online ist der beste Ort, um Windows-Dateisysteminformationen zu finden. Die Mailingliste NTFSD ist der Ort, an dem sich Dateisystementwickler aufhalten.

0

Öffnen Sie die Datei "NUL:" zum Schreiben. Es ist schreibbar, aber die Daten werden stillgelegt. Ein bisschen wie/dev/null von * nix Ruhm.

Sie können es jedoch nicht memory-map. Speicherzuordnung bedeutet Lese-/Schreibzugriff und NUL ist schreibgeschützt.

0

Ich vermute, dass diese dll kann nicht einen Stream nehmen? Es ist fast zu einfach zu fragen, aber wenn es kann, könnte man das einfach benutzen.

+0

Es ist eine DLL, die ich nicht besitze, noch habe ich Quellcode dafür, es hat nur eine Loadfile API mit einem Pfad. Also kann ich das nicht ändern. –

3

Verwenden Sie BoxedApp und keine Sorge.

+2

Coole App! Es funktioniert sogar mit der virtuellen Registrierung! –