2010-01-17 104 views
14

我想模拟一个文件而不写入磁盘。我在可执行文件的末尾有一个文件,我想给它的路径指向一个dll。当然,因为它没有真正的道路,所以我不得不伪造它。如何创建虚拟文件?

我第一次尝试在Windows下使用命名管道来做到这一点。这将允许像\\。\ pipe \ mymemoryfile这样的路径,但是我无法使其工作,并且我不确定该dll是否会支持这样的路径。

其次,我发现CreateFileMapping和GetMappedFileName。他们可以用来模拟另一个片段中的文件吗?我不确定这是API的功能。

我想要做的似乎与boxedapp类似。有关他们如何做的任何想法?我猜这是API截取(Like Detour)之类的东西,但这将是很多工作。还有另一种方法可以做到吗?

为什么?我对这个特定的解决方案很感兴趣,因为我想隐藏数据并且只分发一个文件的好处,但也是为了使它以这种方式工作的奇怪原因;) 我同意将数据复制到临时文件会工作并成为一个更简单的解决方案。

回答

4

您可以将数据存储在NTFS流中。这样,你可以得到指向你的数据,你可以给你的DLL中的

x:\myfile.exe:mystreamname 

这个工作正是像一个正常的文件形式的真实路径,但它只能工作,如果使用的文件系统是NTFS。这在现在的Windows下是标准的,但如果您想要支持较旧的系统或希望能够通过USB或类似的方式运行,这当然不是一种选择。请注意,如果文件作为邮件附件发送或仅从NTFS分区复制到FAT32分区,则文件中存在的任何流都将丢失。

我想说最兼容的方法是将数据写入实际的文件,但当然可以在NTFS系统上和FAT系统上执行另一种方式。由于增加了复杂性,我建议不要这样做。适当的方法是当然分开你的文件,但是由于你已经指出你不想要这个,你应该在这种情况下把它写到一个临时文件,并给dll指向那个文件的路径。确保将临时文件写入用户的临时目录(可以在C/C++中使用GetTempPath找到路径)。

你的其他选择是编写一个文件系统过滤驱动程序,但这是我强烈建议的一条道路。这种类型的使用单一文件的目的也是如此...

另外,如果你只想要一个文件分发,怎么样使用zip文件或安装程序?

+0

你究竟如何分配文件?我会说压缩或复制exe文件会使NTFS流消失? – 2010-01-20 22:17:07

+0

@Gregory:是的。用例在这个问题中并不十分清楚,但我同意使用流可能不是OP的选项 - 希望这在我的答案中也清楚地表明了。我试图在答案中回答的主要观点是使用实际文件是最佳选择。 – villintehaspam 2010-01-20 22:41:51

+0

这是一个非常有趣的想法。太糟糕了,它只适用于ntfs。由于没有完美的答案,这个是最好的。 – 2010-01-25 15:14:22

4

管道用于同时运行的进程之间的通信。它们不会为稍后的访问存储数据,并且它们与文件不具有相同的语义(例如,您不能查找或倒回管道)。

如果您在处理类似文件的行为,最好的办法就是使用文件。在Windows下,您可以将FILE_ATTRIBUTE_TEMPORARY传递给CreateFile作为系统提示,以避免在有足够内存时将数据刷新到磁盘。

如果您担心写入磁盘的性能受到影响,上述内容应足以避免在大多数情况下的性能影响。 (如果系统在内存上足够低以迫使文件数据出现在磁盘上,则无论如何也可能会大量交换 - 您已经遇到了性能问题。)

如果您试图避免写入磁盘出于其他原因,你能解释为什么吗?一般来说,阻止数据永远不会碰到磁盘是非常困难的 - 例如,用户总是可以休眠机器。

+0

这些文件将直接嵌入到.exe中,但dll只接受一个路径作为输入(它不能从istream或类似的东西载入) – 2010-01-17 13:01:01

3

由于您无法控制该DLL,因此您必须假定该DLL需要一个实际的文件。它可能在某种程度上作出这种假设,这就是为什么命名管道失败。

最简单的解决方案是在临时目录中创建临时文件,将数据从EXE写入临时文件,然后删除临时文件。

是否有一个原因是您在您的EXE结尾处嵌入了这个“伪文件”而不是将其与我们的应用程序一起发布?你显然已经在使用你的应用程序发布这个第三方DLL,所以再多一个文件看起来好像不会伤害你?

另一个问题,这个数据会改变吗?那是你希望在EXE中写回这个“伪文件”的数据吗?我认为这不会奏效。标准用户可能没有对EXE的写入权限,这可能会驱动防病毒软件。

并且没有CreateFileMapping和GetMappedFileName肯定不会工作,因为它们不会给你一个可以传递给CreateFile的文件名。如果你能以某种方式让这个DLL接受一个HANDLE,那么这将起作用。

而我甚至不会打扰API截取。只需将DLL移动到一个acutal文件的路径即可。

1

读你的问题让我想:如果你可以假装内存区域是一个文件,并有一种“虚拟路径”,那么这将允许直接从内存中加载一个DLL,这是什么设计LoadLibrary禁止通过询问路径名称。这就是为什么人们想要实现这一目标时自己写PE加载程序的原因。

我会说你无法实现你想要的文件映射:文件映射的目的是将文件的一部分视为物理内存,而你想要的是互惠。

使用Detours意味着您将不得不复制拦截的DLL函数执行的所有操作,除非从实际文件获取数据;因此它不是通用的。或者,甚至更复杂,让我们假装DLL使用fopen;那么你提供了你自己的fopen,它检测路径中的特殊模式,并且你模拟了C运行时内部...嗯,它真的值得所有的痛苦? :D

+0

因为c运行时是w32函数的外观,所以我会不需要覆盖每个使用文件的函数,但是需要覆盖低级别的函数。 – 2010-01-25 12:41:14

0

如何使用某种RamDisk并将文件写入此磁盘?我自己尝试过一些ramdisks,虽然从来没有找到好的,告诉我你是否成功。

0

那么,如果你需要在你的exe文件中分配虚拟文件,你需要创建一个足够大的矢量,流或char数组来存放你想写的所有虚拟数据。

这是我能想到的唯一解决方案,无需对磁盘执行任何I/O(即使您不写入文件)。

如果您需要保留一个类似路径语法的文件,只需编写一个模仿该行为的类,而不是写入文件写入您的内存缓冲区。它很简单。记住KISS。

干杯

0

请解释为什么你不能从你的EXE中提取数据,并将其写入到一个临时文件。许多应用程序都这样做 - 这是解决此问题的经典解决方案。

如果您确实需要提供“虚拟文件”,最简洁的解决方案可能是文件系统过滤驱动程序。 “干净”并不意味着“好” - 过滤器是一个完整的文档和支持的解决方案,因此它比API挂钩,注入等更清洁。但是,文件系统过滤器并不容易。

OSR Online是找到Windows文件系统信息的最佳位置。 NTFSD邮件列表是文件系统开发者闲逛的地方。

0

打开名为“NUL:”的文件进行书写。它是可写的,但数据被无声丢弃。有点像/ dev/null的* nix名声。

虽然你不能记忆它。内存映射意味着读/写访问,而NUL是只写的。

0

我在猜测这个DLL不能采取流?它几乎要简单地问,但如果它可以使用它。

+0

这是一个我不拥有的DLL,我也没有它的源代码,它只有一个带有路径的loadfile api。所以我不能改变这一点。 – 2010-01-25 10:27:43

3

使用BoxedApp,不用担心。

+2

酷应用程序!它甚至可以与虚拟注册表一起使用! – 2011-12-08 19:49:38