【问题标题】:C# Windows Program writes files to "sysWOW64" and to "Program Files(x86)". Using VS Setup Projects. 32bit App on 64bit SystemC# Windows 程序将文件写入“sysWOW64”和“Program Files(x86)”。使用 VS 设置项目。 64 位系统上的 32 位应用程序
【发布时间】:2017-06-09 15:03:37
【问题描述】:

有人能告诉我,为什么我的程序在使用 VS Setup Projects 安装后会向/从这两个文件夹写入/读取文件吗? 第一次启动时,当我启动程序并将程序中的某些内容保存到文件时,它会将其写入:

C:\Users\UserName\AppData\Local\VirtualStore\Program Files (x86)\Company Name\Program Name\"

设置“在系统启动时运行”后,我重新启动计算机并启动程序,但这次它从/写入此文件夹:

C:\Users\UserName\AppData\Local\VirtualStore\Windows\SysWOW64

以便它在第二次启动时加载错误的值或不加载任何内容。 看起来这取决于我如何启动程序,通过桌面符号或通过 Systemstart 上的自动运行。

如何防止这种情况发生?如何让程序始终从同一个文件夹读取/写入?我更愿意将文件始终保存在根文件夹中,exe 所在的文件夹为 (C:\Program Files(x86)\CompanyName\ProgramName)。

我认为问题出在 VS 设置项目中,或者是因为它是在 64 位系统上运行的 32 位应用程序。我已经在其他问题中寻找解决方案,但它没有帮助,而是没有阅读任何内容。 希望有人能帮帮我,谢谢!

这就是我写文件的方式:File.WriteAllText(@"mailstate2", "true"); 我不给路径...我只是希望它保存在根文件夹中...

【问题讨论】:

  • 问题是,您正在尝试以一种被 反对的方式编写软件。您的程序不应该定期将新文件写入C:\Program Files (x86)。阅读不同的文件系统位置以及每个位置意味着要存储的内容。

标签: c# windows winforms setup-project


【解决方案1】:

这里实际上发生了一些不同的事情。所有这些都与 Windows 如何运行程序和保护文件系统的关键部分免受恶意篡改有关。

首先,程序可以从任何目录启动。如果您没有指定将文件写入的特定位置,那么它将相对于程序启动的任何目录写入。您可以通过设置程序的快捷方式并更改快捷方式的“开始于”属性来测试这一点。因此,桌面快捷方式中的“Start in”文件夹与 Autorun 使用的文件夹不同。

其次,只有提升的用户和进程才能真正修改某些 windows 目录。其中包括 Program FilesProgram Files (x86)Windows 文件夹等。如果未提升的进程尝试将文件写入这些目录之一,Windows 会自动将它们重定向到windows VirtualStore directory 下的同一文件夹。这允许过去从这些受保护位置进行读写的遗留程序继续工作,同时仍然保护可执行文件不被恶意软件覆盖。无论如何,这种静默重定向是您的程序最终写入非常奇怪的位置的原因。

根据您要写入的数据类型,有几个位置适合写入不涉及虚拟存储的数据。

  • 如果您的用户可能希望将数据复制到另一台计算机或备份,那么在他的 Documents 文件夹中创建一个文件夹可能是合适的,尽管我个人讨厌有多少程序对我这样做。如果您发现自己这样做了,请问自己是否有某种方式可以让用户选择在哪里存储这些数据。可能通过首选项页面或首次运行配置。
  • 如果个人计算机用户可能希望相互独立地自定义首选项类型数据,但他们不需要查看或意识到,则使用用户的 AppData 文件夹 (C:\Users\username\AppData\) 是合适的。请注意,AppData 文件夹包含三个不同的子文件夹:Roaming、Local 和 LocalLow。这是excellent SuperUser topic on the differences between them
  • 如果需要保留的应用程序数据与用户无关,则 ApplicationData 文件夹 (C:\ProgramData) 是合适的,但您可能需要设置您在其中创建的任何文件\目录的权限以授予所有用户访问他们。另请注意,这样做会带来安全问题。

这里有几个有用的链接,通过快速的 google 搜索可以帮助您开始思考正确的方向。

【讨论】:

  • 哎呀,是的。感谢您的捕获!我已经在我的回答中修复了它。
  • “如果您的用户可能希望将数据复制到另一台计算机或备份,那么……”考虑让用户选择存储这些数据的位置。默认为 Documents 文件夹是正确的,但允许更多的计算机知识用户选择。
  • 另外,当您在AppData 中存储首选项时,请注意漫游和非漫游数据之间的区别。你的回答没有提到这一点。
  • 好点@CodyGray。我从来没有写过任何需要区分漫游和非漫游的东西,所以我什至没有想到。我将使用注释和指向不同 AppData 选项的相关主题的链接来更新我的答案,我也会添加您对文档文件夹的建议。
【解决方案2】:

Damien 有一个要点:您必须被提升(管理员)才能写入/更新共享公共文件夹中的文件,如 AppData 和程序文件(以及许多其他文件)。另一个问题是已经完成的虚拟化,以便您的程序在这样做违反安全性时不会简单地崩溃 - 它会写入虚拟存储。这是搜索会显示给您的内容:

https://www.curlybrace.com/words/2010/09/09/windows-vista7-file-system-virtualization/

解决此问题的简单方法是,如果您的程序需要运行提升以写入/更新 AppData 文件夹中的文件,则为您的程序提供提升清单。这种事:

https://blogs.msdn.microsoft.com/nikhiln/2007/04/19/using-manifests-to-elevate-an-application-in-vista/

尽管 Visual Studio 应该为您提供清单的 IDE 支持,以便您的代码具有 requestedExecutionLevel level=“requireAdministrator.它会在启动时要求提升,UAC 系统上需要提升的所有程序也是如此。

清单的存在也会关闭虚拟化,因此您的应用将崩溃而不是被重定向到虚拟存储(如果您违反了对受限位置的文件写入操作)。

如果您要求有限的用户能够运行您的应用程序,那么请为您的文件选择另一个位置,ashbygeek 曾提到过该位置。

【讨论】:

  • 以管理员身份运行程序是否足够?现在我通过保存到 "C:\ProgramData\ProgramName\" 解决了这个问题
  • 还不够,因为如果再次出现与其他问题类似的问题,您将遇到同样的问题。如果现在您不需要管理员来运行应用程序,因为您已经移动了文件,那么您仍然应该有一个带有 requestedExecutionLevel = asInvoker 的清单,因为这告诉 Windows 您不需要提升,并且您不会遇到任何虚拟存储问题- 相反,你会崩溃,这就是你想要的,信不信由你:),因为这就是导致你原来问题的原因。如果你崩溃了,你会说“哦,一个安全问题”。
猜你喜欢
  • 1970-01-01
  • 2010-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-19
  • 2012-09-01
  • 2011-07-07
  • 1970-01-01
相关资源
最近更新 更多