【问题标题】:Get real path of a log file stored in VirtualStore获取存储在 VirtualStore 中的日志文件的真实路径
【发布时间】:2013-12-13 16:02:28
【问题描述】:

我的应用程序将日志文件存储在一个位置,根据管理员设置,该位置可以重定向到 VirtualStore 中的文件夹。例如,它们有时会出现在:

日志文件在:

C:\Users\-my username-\AppData\Local\VirtualStore\Program Files (x86)\ *my-application* \logs

C# 认为它在这里:

C:\Program Files (x86)\ 我的应用程序 \logs

这只是代码的一部分的问题 - 一个试图在记事本中打开日志文件的按钮。它运行 Process.Start(path-where-application-thinks-log-files-are);

如果我使用 File.Exists( path-where-application-thinks-log-files-are ) 进行测试;我是真的 - 因为 c# 知道要查看 VirtualStore 位置。但是当我尝试启动文件时,它失败了。

所以我的问题是,从 Process.Start() 命令的角度来看,有没有办法将路径转换为正确的位置?

【问题讨论】:

    标签: c# uac virtualstore


    【解决方案1】:

    你的问题的答案是你不能。

    文件和注册表虚拟化是一种临时的兼容性黑客,存在于当前版本的 Windows 中,因此有缺陷的应用程序将暂时继续工作。 Microsoft 不提供处理重定向文件的能力。这样做的应用程序处于错误状态,需要修复。

    来自Developing for Windows blog

    用户帐户控制数据重定向

    今天,许多应用程序仍然设计为将文件写入 Program Files、Windows 目录或系统根目录(通常是 C 驱动器)文件夹。

    虚拟化仅用于协助应用程序与现有程序的兼容性。为 Microsoft Windows 7 设计的新应用程序不应对敏感的系统区域执行写入操作,也不应依赖虚拟化来纠正不正确的应用程序行为。 始终开发以标准用户权限使用的应用程序,并且不要指望以管理员权限运行的应用程序。使用标准用户权限而非管理员权限测试您的应用程序。

    如果您正在使用在 Windows 7 之前开发的应用程序体验 UAC 虚拟化,请重新设计您的应用程序以将文件写入适当的位置。

    解决您的问题的理想方法是禁用应用程序的文件和注册表虚拟化。这样,您的应用程序将无法再将文件保存到敏感位置 - 并且会收到 Access denied 错误。

    您可以通过在应用程序的程序集清单中添加一个条目来执行此操作,告诉 Windows 您的应用程序已正确编写:

    AssemblyManifest.xml

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
       <assemblyIdentity 
          version="1.0.0.0"
          processorArchitecture="X86"
          name="client"
          type="win32"
       /> 
    
       <description>Sugrue Contoso</description> 
    
       <!-- Disable file and registry virtualization -->
       <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
          <security>
             <requestedPrivileges>
                <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
             </requestedPrivileges>
          </security>
       </trustInfo>
    </assembly>
    

    这样,任何将日志文件写入%ProgramFiles% 子树的尝试都会正确失败。

    正确编写的 Windows 应用程序不会将数据存储在 Program Files 中。来自Technical requirements for the Windows 7 Client Software Logo Program,第 8-9 页:

    默认安装到正确的文件夹

    用户应该在默认情况下获得一致且安全的体验 文件的安装位置,同时保持选项 将应用程序安装到他们选择的位置。也是 有必要将应用程序数据存储在正确的位置以允许 几个人使用同一台计算机而不会损坏或 覆盖彼此的数据和设置。


    Windows 提供文件系统中的特定位置来存储 程序和软件组件、共享的应用程序数据,以及 特定于用户的应用程序数据:

    • 默认情况下应将应用程序安装到 Program Files 文件夹。 不得将用户数据或应用程序数据存储在此 位置,因为为此配置了安全权限 文件夹强调
    • 必须在计算机上的用户之间共享的所有应用程序数据都应存储在 ProgramData 中
    • 特定用户专有且不与计算机的其他用户共享的所有应用程序数据必须存储在 用户\\AppData
    • 切勿直接写入“Windows”目录和/或子目录。使用正确的方法安装文件,例如 字体或驱动程序
    • 在“每台机器”安装中,用户数据必须在首次运行时写入,而不是在安装期间写入。这是因为没有 正确的用户位置以在安装时存储数据。尝试 由应用程序修改机器上的默认关联行为 水平安装后将不成功。相反,默认值必须 在每个用户级别上声明,这可以防止多个用户 覆盖彼此的默认值。

    在您的情况下,应该存储日志文件:

    • 在每个用户的 LocalAppData 文件夹中(通常解析为 C:\Users\Sugrue\AppData\Local
    • CommonAppData 文件夹中(通常解析为C:\ProgramData

    选择权在你。大概您想要一个多个用户可以添加到的日志文件。在这种情况下,您需要 Common AppData 文件夹。您可以使用SHGetFolderPathCSIDL_COMMON_APPDATA 或更新的SHGetKnownFolderPath 检索此路径:

    SHGetFolderPath(0, CSIDL_COMMON_APPDATA, SHGFP_TYPE_CURRENT, out path);
    

    用户可以写入这个文件夹,因为创建文件和文件夹的权限默认授予用户

    总结

    你不能。
    但同时:你不应该。

    考虑如果没有发生重定向会发生什么。当您在 Windows XP 上以标准用户身份运行时会发生什么?

    【讨论】:

    • 在 C# 中,您不需要使用那些非托管函数。只需使用Enviorement.GetFolderPath 并使用枚举LocalApplicationDataCommonApplicationData 来表示这两个文件夹。
    • 感谢您抽出宝贵的时间来写这个详细的回复,伊恩。现在一切都清楚了。
    • @ScottChamberlain 确实如此。我的母语是 Delphi,所以本机 API 概念应该对任何人都有帮助。但是,是的,如果您在 CLR 中,您最好使用纯框架类。
    【解决方案2】:

    我也遇到过类似的情况;我能够通过将安装路径限制为与 Program Files (x86) 不同的路径来解决它。你可以说 C:\Program Files\Program

    如果您尝试过这个,那么您会注意到应用程序不会创建带有扩展名的虚拟商店文件夹:\AppData\Local\VirtualStore..

    【讨论】:

      【解决方案3】:

      我尝试的不是很优雅的解决方案是测试VirtualStore路径位置是否存在。如果是这样,请使用它。

      但必须有更强大的方法来做到这一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-03
        • 1970-01-01
        • 1970-01-01
        • 2014-06-28
        • 1970-01-01
        • 1970-01-01
        • 2016-02-19
        • 2015-05-02
        相关资源
        最近更新 更多