Question

I have a Windows service, written in C# (.NET 4.5). This service has a user scoped setting that is used to hold a timer variable. For debugging the service, I need to update this variable, so I need to know where the user.config file for the service is located. Hence I added the following code in the service's OnStart() method:

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

What is dumped into my logfile is the following path:

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

But when I try to open that file, it doesn't exist. After doing a Windows search, I found the actual file at:

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

Why is this? I'm assuming some 32-bit/64-bit compatibility magic, but what would be the correct code (if any) to get the actual path?

Additional info, if it helps: the service is running on a Windows Server 2008 R2 64-bit machine and it was installed via installutil. I'm not sure whether the 32-bit or 64-bit version of installutil was used though - would this make a difference?

Was it helpful?

Solution

This is happening because C:\Windows\system32 is a different directory for 64bit and 32bit processes. 32bit processes see content of C:\Windows\SysWOW64 in C:\Windows\system32. It is crazy, but that is how Microsoft decided to provide compatibility with hardcoded C:\Windows\system32 in many applications and allow to load correct version of .dlls for 32bit and 64bit processes (as a result 64bit dlls are in C:\Windows\system32 and 32bit dlls are in C:\Windows\SysWOW64).
Local system account which by default used for services has profile inside C:\Windows\system32 - so 32bit and 64bit services see different files in %LOCALAPPDATA% where applications supposed to store data. So for example when your 64bit service execute 32bit process, child process don't see files which parent process prepared for it in %LOCALAPPDATA%.

There are couple of workarounds for this:

  • you could start service from a different user (Service / Properties / Log on / Log on as: This account) - but in this case you have to provide password and if password will be changed or expired service would not be able to start until password will be changed for service too.
  • you could use other location for storing data instead of %LOCALAPPDATA% which is not always acceptable too.
  • you could create junction point to directory with your settings - so 32bit and 64bit applications will see the same directory:
    • run "psexec.exe -i -s cmd.exe" as admin (psexec is part of Sysinternal's PsTools) - in will open command prompt from system account (it is a great way to debug services too)
    • exec "mklink /J %SystemRoot%\SysWOW64\config\systemprofile\AppData\Local\company %LOCALAPPADATA%\company"

None of workarounds are perfect, but they provide relatively easy way to deal with this craziness.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top