Tuesday, February 16, 2010

Using batchfile to setup environment for running .NET Process

Today I faced a problem that I wanted to use a third party library, which depends on all kind of environment settings. Since this library came with an accompanying batch file for setting up this environment, I would like to reuse this batch file. After much googling I could not find a satisfying solution for my problem and decided to go for my own. The resulting code is here

// Run 3 commands in a "batch":
// setenv.bat: this will correctly setup the environment
// CLS: Ths will clear the screen (effectively sends a formfeed (\f) to the StandardOutput stream)
// SET: This will display the current environment variables (or send it to standard output
var processStartInfo = new ProcessStartInfo("cmd.exe")
{
Arguments = string.Format("/c {0} && CLS && SET", pathSetEnv),
RedirectStandardOutput = true,
CreateNoWindow = true,
UseShellExecute = false,
};
var process = Process.Start(processStartInfo);

// Wait until all commands have been processed
process.WaitForExit();

// Grab standard output
var standardOutput = process.StandardOutput.ReadToEnd();

// Grab all lines since last formfeed
var lastFormFeedIndex = standardOutput.LastIndexOf('\f');
var environmentSettings = standardOutput.Substring(
lastFormFeedIndex).Split(new [] { Environment.NewLine },
StringSplitOptions.RemoveEmptyEntries);

// Adjust the current Environment Variables with the ones grabbed
foreach (var environmentSetting in environmentSettings)
{
SetEnvironmentVar(environmentSetting);
}


With the following helper for setting the environment:



[DllImport("msvcrt.dll")]
public static extern int _putenv(string varName);

private static void SetEnvironmentVar(string environmentSetting)
{
// We can not use Environment.SetEnvironmentVariable(variable, value);
// The problem relates to an unbalanced environment string encoding (ANSI/UNICODE).
//
// To prevent such errors, pair the getenv() call with a _putenv call to set
// the environment variables in C#. When using SetEnvironmentVariable() (from
// Kernel32.dll) pair it with a GetEnvironmentVariable in C++ and match your
// string encodings.
//
// So what uou need to do is replace your SetEnvironmentVariable call with ...
// [DllImport( "msvcrt.dll")]
// public static extern int _putenv( string varName);

// Environment.SetEnvironmentVariable(variable, value);
if (_putenv(environmentSetting) == -1)
{
throw new TcliWrapperException("Unable to set environment variable");
}
}

No comments: