我在Windows上使用Qt 5.4。我遇到了一个奇怪的问题。在非管理员用户访问级别,我尝试将文件写入程序文件目录。我希望它不要写。但是它写了!完全没有错误。好的,但真正奇怪的是,只有我的程序才能看到'该文件但资源管理器在我尝试dir
,dir /ah
或ls
时未显示该文件。
这是资源管理器可以看到的
这是我的程序可以看到的 请注意,我的程序每次启动时都可以看到该文件并浏览到该文件夹。
这里到底发生了什么?
答案 0 :(得分:3)
文件虚拟化。文件虚拟化是Windows Vista +操作系统用来解决应用程序想要写入只能由管理员写入的位置的情况的技术(如C:\Program Files
或C:\Windows
)。
当应用程序写入此类系统位置时,Windows会将所有此类文件操作重定向到位于%LOCALAPPDATA%\VirtualStore
的虚拟存储目录。稍后,当应用程序回读此文件时,计算机将提供虚拟存储中的文件。通过这种方式,Windows“愚弄”程序,使其相信它从受保护的位置读取并写入,而实际上它只处理虚拟位置。
清单是一个可以嵌入到应用程序中的XML文件。它告诉Windows应用程序是UAC感知的,因此它不应该执行任何文件虚拟化。因此,现在如果应用程序尝试访问受保护的资源,那么这些操作将会失败但操作系统不会虚拟化。
当您的应用程序包含指定了requestedExecutionLevel
值的应用程序清单时,Windows的注册表和文件系统的虚拟化将被关闭。
示例清单文件:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
将清单文件添加到Qt应用程序有几种不同的方法。我只提一个 - 我认为这是最简单的。如果您知道,可以在此答案中添加其他方法。
requestedExecutionLevel
标记(否则虚拟化将不会关闭)。mt.exe -nologo -manifest <your manifest file> -outputresource:<your executable>;#1
* 。 * 我在mt.exe
找到了"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\
文件,它可能略有不同,但肯定会在Microsoft SDKs\Windows
文件夹中子>
<子>来源子>
<子> 1。 Qt cannot cannot create/write to C:\ 子>
<子> 2。 http://msdn.microsoft.com/en-us/library/bb756960.aspx 子>
<子> 3。 http://blog.strixcode.com/2010/08/embedding-application-manifest-and.html 子>
<子> 4。 http://qt-project.org/forums/viewthread/36726 子>