You probably already know that Environment variables can be defined at either machine scope, or user scope. The value at the user scope typically overrides the value defined at machine scope.

Environment variables

However, there's a special case for Windows Services that run as the SYSTEM account. Given the following Windows Service:

public partial class Service1 : ServiceBase
{
    public Service1()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        File.WriteAllText("C:\\Temp\\Service.txt", 
            "Temp:        " + Environment.GetEnvironmentVariable("Temp") + Environment.NewLine +
            "Temp (User): " + Environment.GetEnvironmentVariable("Temp", EnvironmentVariableTarget.User) + Environment.NewLine);
    }
}

When the service runs as my user account, I get what I'd expect:

Temp:        C:\Users\Paul\AppData\Local\Temp
Temp (User): C:\Users\Paul\AppData\Local\Temp

However, run the service as the built-in SYSTEM (Local System) account, and you get different behavior:

Temp:        C:\WINDOWS\TEMP
Temp (User): C:\WINDOWS\system32\config\systemprofile\AppData\Local\Temp

It appears that for Windows Services that run under the SYSTEM account, even though there's a user-specific environment variable, a different %TEMP% is used.

This caused a bug in yesterday's 2.6 pre-release because we added a feature to automatically update environment variables prior to each script run (in case you've changed environment variables, and don't want to restart the Tentacle windows service). Of course, no good deed goes unpunished :-)

I can't find any documentation on this feature, but environment variables are inherited by processes from their parent. Services are owned by services.exe, which is owned by wininit.exe. Using Process Explorer, wininit.exe's environment variables set TEMP to C:\Windows\TEMP. My guess is this is probably a backwards compatibility feature for old Windows Services that relied on using C:\Windows\TEMP.

(We'll release a patch to 2.6 tomorrow with a fix for this)


Octopus Deploy is used by thousands of developers across the globe, from small companies to large enterprises. Find out if it meets your deployment automation needs by taking advantage of our free 30-day trial. You can spin up an instance with just a few clicks!

Lessons