2

我有一个用 C# (.NET 4.5) 编写的 Windows 服务。此服务有一个user范围设置,用于保存计时器变量。为了调试服务,我需要更新这个变量,所以我需要知道user.config服务的文件在哪里。OnStart()因此,我在服务的方法中添加了以下代码:

Logger.InfoFormat("user.config at \"{0}\"", ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath);

转储到我的日志文件中的是以下路径:

C:\Windows\system32\config\systemprofile\AppData\Local\company\service.exe_Url_randomcharacters\1.0.0.0\user.config

但是当我尝试打开该文件时,它不存在。在进行 Windows 搜索后,我在以下位置找到了实际文件:

C:\Windows\SysWOW64\config\systemprofile\AppData\Local\company\service.exe_Url_randomcharacters\1.0.0.0\user.config

为什么是这样?我假设有一些 32 位/64 位兼容性魔法,但是获得实际路径的正确代码(如果有的话)是什么?

附加信息(如果有帮助):该服务正在 Windows Server 2008 R2 64 位计算机上运行,​​并且它是通过installutil. 我不确定是使用 32 位还是 64 位版本installutil- 这会有所不同吗?

4

1 回答 1

2

发生这种情况是因为 C:\Windows\system32 是 64 位和 32 位进程的不同目录。32 位进程在 C:\Windows\system32 中看到 C:\Windows\SysWOW64 的内容。这很疯狂,但这就是微软决定在许多应用程序中提供与硬编码 C:\Windows\system32 的兼容性并允许为 32 位和 64 位进程加载正确版本的 .dll 的方式(因此 64 位 dll 位于 C:\Windows \system32 和 32 位 dll 位于 C:\Windows\SysWOW64)。
默认情况下用于服务的本地系统帐户在 C:\Windows\system32 中有配置文件 - 因此 32 位和 64 位服务在 %LOCALAPPDATA% 中看到不同的文件,应用程序应该在其中存储数据。因此,例如,当您的 64 位服务执行 32 位进程时,子进程在 %LOCALAPPDATA% 中看不到父进程为其准备的文件。

有几个解决方法:

  • 您可以从其他用户启动服务(服务/属性/登录/登录为:此帐户)-但在这种情况下,您必须提供密码,如果密码将被更改或过期,服务将无法启动,直到密码也会因服务而改变。
  • 您可以使用其他位置而不是 %LOCALAPPDATA% 来存储数据,这也不是总是可以接受的。
  • 您可以使用您的设置创建指向目录的连接点 - 因此 32 位和 64 位应用程序将看到相同的目录:
    • 以管理员身份运行“psexec.exe -i -s cmd.exe”(psexec 是Sysinternal 的 PsTools 的一部分) - in 将从系统帐户打开命令提示符(这也是调试服务的好方法)
    • 执行“mklink /J %SystemRoot%\SysWOW64\config\systemprofile\AppData\Local\company %LOCALAPPADATA%\company”

没有一种解决方法是完美的,但它们提供了相对简单的方法来处理这种疯狂。

于 2014-09-03T16:59:02.883 回答