Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in /homepages/13/d92059571/htdocs/jeremymurray/inc/parser/handler.php on line 1458

Directories popping up named %SystemDrive%

Had an issue today where people were noticing that on some machines, whenever a utility was run it would create a new %SystemDrive% folder with some subfolders leading to a set of .db files. That is literally %SystemDrive%, what you would expect on most systems to automatically expand to “c:”.

I decided to do a quick google search on the GUID .db filenames and I found many projects with a similar issue (utorrent especially). I think we tracked down the cause, though.

Investigation

First, we need to illustrate the problem.

|h ProcessStartTest.cs
using System.Diagnostics;
using System.Linq;
 
/// <summary>
/// Runs a command in a subprocess.
/// </summary>
class ProcessStartTest
{
    static int Main(string[] args)
    {
        int commandReturnInt = RunCommand(args);
        return commandReturnInt;
    }
 
    // In a shell that is missing both the ProgramData and SystemDrive environment variables, this produces:
    // .\%SystemDrive%\ProgramData
    // .\%SystemDrive%\ProgramData\Microsoft
    // .\%SystemDrive%\ProgramData\Microsoft\Windows
    // .\%SystemDrive%\ProgramData\Microsoft\Windows\Caches
    // .\%SystemDrive%\ProgramData\Microsoft\Windows\Caches\cversions.2.db
    // .\%SystemDrive%\ProgramData\Microsoft\Windows\Caches\{4E4260A4-7E39-442E-BC22-7FF751D1C161}.2.ver0x0000000000000001.db
    // .\%SystemDrive%\ProgramData\Microsoft\Windows\Caches\{6AF0698E-D558-4F6E-9B3C-3716689AF493}.2.ver0x0000000000000001.db
    // .\%SystemDrive%\ProgramData\Microsoft\Windows\Caches\{DDF571F2-BE98-426D-8288-1A9A39C3FDA2}.2.ver0x0000000000000001.db
    // This runs thorugh System.Diagnostics.Process.StartWithShellExecuteEx
    public static int RunCommand (string[] args)
    {
        var filename = args[0];
        var argumentArray = args.Skip(1).ToArray();
        var argumentString = string.Join(" ", argumentArray);
        var subProcess = Process.Start(filename, argumentString);
        subProcess.WaitForExit();
 
        return subProcess.ExitCode;
    }
}   

As the comment says, if you run this normally, it should work without problem. But if you clear out the two environment variables ProgramData and SystemDrive, it will run but also create a new, unwanted subfolder.

After some digging, this appears to be a bug in System.Diagnostics.Process.StartWithShellExecuteEx - which is the default method called if you do a standard Process.Start(“command”). A lot of projects use this form and can be subject to this bug.

To get around it, we can have the subprocess start without creating a shell. This is usually what I want when I am calling a subprocess, anyway - it should be hidden and if I want to display the output I will gather the output from the process and display it within my app. It isn't a big change to remove the shell.

|h ProcessStartFix.cs
using System.Diagnostics;
using System.Linq;
 
/// <summary>
/// Runs a command in a subprocess.
/// </summary>
class ProcessStartFix
{
    static int Main(string[] args)
    {
        int commandReturnInt = RunCommand(args);
        return commandReturnInt;
    }
 
    // This runs through System.Diagnostics.Process.StartWithCreateProcess
    public static int RunCommand (string[] args)
    {
        var subProcess = new Process();
        var filename = args[0];
        var argumentArray = args.Skip(1).ToArray();
        var argumentString = string.Join(" ", argumentArray);
        subProcess.StartInfo = new ProcessStartInfo
        {
            FileName = filename,
            Arguments = argumentString,
            UseShellExecute = false,
        };
        subProcess.Start();
        subProcess.WaitForExit();
 
        return subProcess.ExitCode;
    }
}

If you actually need to have a shell execute, you can follow the second method and just inspect the StartInfo object to make sure that either or both of those environment variables are set or set them yourself.

I wouldn't think this would come up very often, as those variables both seem to be expected by many programs. Even the Windows Start Menu shortcuts depend on the %WinDir% environment variable. In any case, there are several ways where those variables can be lost and cause the bug to occur.

Conclusion

It is a bug in System.Diagnostics.Process.StartWithShellExecuteEx if both the ProgramData and SystemDrive environment variables are unset, apparently. Either make sure one of these variables exists before calling Process.Start or instead create a ProcessStartInfo and disable shell execution.

Acknowledgements

Thanks to Adam Meyer for both the original mass mail with the problem and help digging in to see what was wrong.

 
blog/20110804_directories_popping_up_named_systemdrive.txt · Last modified: 2011/08/04 17:54 by Jeremy Murray · []
Recent changes RSS feed Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki