获取存储在VirtualStore中的日志文件的真实路径

4

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

日志文件在以下位置:

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

C#认为它在这里:

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

这只是代码中的一个问题 - 一个按钮试图在记事本中打开日志文件。 它运行Process.Start( 应用程序认为日志文件所在的路径 );

如果我使用File.Exists( 应用程序认为日志文件所在的路径 ); 进行测试,我会得到true - 因为C#知道要查找VirtualStore位置。 但是当我尝试启动文件时,它失败了。

因此,我的问题是,是否有一种方法可以将路径转换为Process.Start()命令的正确位置?

3个回答

7
你的问题无解。文件和注册表虚拟化只是一种临时的兼容性方案,现在的Windows版本中存在此方案,以使错误的应用程序暂时继续工作。微软不提供处理重定向文件的能力。这样做的应用程序处于错误状态,需要修复。
引用自Developing for Windows blog
“用户帐户控制数据重定向 如今,许多应用程序仍设计为将文件写入Program Files、Windows目录或系统根目录(通常是C驱动器)文件夹。 虚拟化仅旨在通过现有程序提高应用程序兼容性。为Microsoft Windows 7设计的新应用程序不应执行对敏感系统区域的写操作,并且也不应该依赖于虚拟化来纠正不正确的应用程序行为。始终将应用程序开发为使用标准用户权限,并且不要指望应用程序在管理员权限下运行。使用标准用户权限而不是管理员权限测试您的应用程序。 如果你正在使用Windows 7之前的应用程序遇到UAC虚拟化问题,请重新设计你的应用程序以写入适当的位置。” 解决你的问题的理想方法是禁用应用程序的文件和注册表虚拟化。这样,你的应用程序将无法将文件保存到敏感位置,并会得到访问被拒绝的错误提示。
你可以通过在应用程序的程序集清单中添加一个条目来告诉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中存储数据。从Windows 7客户端软件徽标计划技术要求第8-9页可见:

默认情况下安装到正确的文件夹中

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


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

  • 默认情况下,应将应用程序安装到“Program Files”文件夹中。由于为此文件夹配置的安全权限,用户数据或应用程序数据绝不能存储在此位置加重强调
  • 所有必须在计算机上共享的应用程序数据应存储在ProgramData中
  • 所有专门为特定用户而非与计算机上其他用户共享的应用程序数据必须存储在Users\<username>\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);

用户可以向此文件夹写入内容,因为默认情况下创建文件和文件夹的权限已经授予给了用户:

enter image description here

总结

你不能这样做。
但同时,也不应该这样做。

考虑一下如果没有重定向会发生什么。在Windows XP上作为标准用户运行时会发生什么?


1
在C#中,您不需要使用那些未受管理的函数。只需使用Enviorement.GetFolderPath并使用枚举LocalApplicationDataCommonApplicationData来表示这两个文件夹。 - Scott Chamberlain
感谢您抽出时间写下这份详细的回复,Ian。现在一切都清楚了。 - Sugrue
@ScottChamberlain 确实如此。我的母语是Delphi,因此原生API概念对任何人都应该有所帮助。但是,如果您在CLR中,最好使用纯Framework类。 - Ian Boyd

1
我曾经遇到过类似的情况;通过将安装路径限制在与Program Files (x86)不同的位置,我成功解决了这个问题。你可以选择C:\Program Files\Program。
如果你尝试了这种方法,那么你会发现该应用程序不会创建带有扩展名为\AppData\Local\VirtualStore的虚拟存储文件夹。

0

我尝试过的解决方案并不十分优雅,就是测试是否存在VirtualStore路径位置。如果存在,则使用该路径。

但肯定有更加健壮的方法来做这件事。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接