Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9063469
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 16, 20262026-06-16T16:00:40+00:00 2026-06-16T16:00:40+00:00

I’m developing a small C# GUI tool which is supposed to fetch some C++

  • 0

I’m developing a small C# GUI tool which is supposed to fetch some C++ code and compile it after going through some wizard. This works all nice if I run it from a command prompt after running the famous vcvarsall.bat. Now I would like the user not to go to a command prompt first but have the program call vcvars followed by nmake and other tools I need. For that to work the environment variables set by vcvars should obviously be kept.

How can I do that?

The best solution I could find yet was to create a temporary cmd/bat script which will call the other tools, but I wonder if there is a better way.


Update: I meanwhile experimented with batch files and cmd. When using batch files vcvars will terminate the complete batch execution so my second command (i.e. nmake) won’t be executed. My current workaround is like this (shortened):

string command = "nmake";
string args = "";
string vcvars = "...vcvarsall.bat";
ProcessStartInfo info = new ProcessStartInfo();
info.WorkingDirectory = workingdir;
info.FileName = "cmd";
info.Arguments = "/c \"" + vcvars + " x86 && " + command + " " + args + "\"";
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
Process p = Process.Start(info);

This works, but the output from the cmd call is not captured. Still looking for something better

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-16T16:00:41+00:00Added an answer on June 16, 2026 at 4:00 pm

    I have a couple of different suggestions

    1. You may want to research using MSBuild instead of NMake

      It’s more complex, but it can be controlled directly from .Net, and it is the format of VS project files for all projects starting with VS 2010, and for C#/VB/etc. projects earlier than that

    2. You could capture the environment using a small helper program and inject it into your processes

      This is probably a bit overkill, but it would work. vsvarsall.bat doesn’t do anything more magical than set a few environment variables, so all you have to do is record the result of running it, and then replay that into the environment of processes you create.

    The helper program (envcapture.exe) is trivial. It just lists all the variables in its environment and prints them to standard output. This is the entire program code; stick it in Main():

    XElement documentElement = new XElement("Environment");
    foreach (DictionaryEntry envVariable in Environment.GetEnvironmentVariables())
    {
        documentElement.Add(new XElement(
            "Variable",
            new XAttribute("Name", envVariable.Key),
            envVariable.Value
            ));
    }
    
    Console.WriteLine(documentElement);
    

    You might be able to get away with just calling set instead of this program and parsing that output, but that would likely break if any environment variables contained newlines.

    In your main program:

    First, the environment initialized by vcvarsall.bat must be captured. To do that, we’ll use a command line that looks like cmd.exe /s /c " "...\vcvarsall.bat" x86 && "...\envcapture.exe" ". vcvarsall.bat modifies the environment, and then envcapture.exe prints it out. Then, the main program captures that output and parses it into a dictionary. (note: vsVersion here would be something like 90 or 100 or 110)

    private static Dictionary<string, string> CaptureBuildEnvironment(
        int vsVersion, 
        string architectureName
        )
    {
        // assume the helper is in the same directory as this exe
        string myExeDir = Path.GetDirectoryName(
            Assembly.GetExecutingAssembly().Location
            );
        string envCaptureExe = Path.Combine(myExeDir, "envcapture.exe");
        string vsToolsVariableName = String.Format("VS{0}COMNTOOLS", vsVersion);
        string envSetupScript = Path.Combine(
            Environment.GetEnvironmentVariable(vsToolsVariableName),
            @"..\..\VC\vcvarsall.bat"
            );
    
        using (Process envCaptureProcess = new Process())
        {
            envCaptureProcess.StartInfo.FileName = "cmd.exe";
            // the /s and the extra quotes make sure that paths with
            // spaces in the names are handled properly
            envCaptureProcess.StartInfo.Arguments = String.Format(
                "/s /c \" \"{0}\" {1} && \"{2}\" \"",
                envSetupScript,
                architectureName,
                envCaptureExe
                );
            envCaptureProcess.StartInfo.RedirectStandardOutput = true;
            envCaptureProcess.StartInfo.RedirectStandardError = true;
            envCaptureProcess.StartInfo.UseShellExecute = false;
            envCaptureProcess.StartInfo.CreateNoWindow = true;
    
            envCaptureProcess.Start();
    
            // read and discard standard error, or else we won't get output from
            // envcapture.exe at all
            envCaptureProcess.ErrorDataReceived += (sender, e) => { };
            envCaptureProcess.BeginErrorReadLine();
    
            string outputString = envCaptureProcess.StandardOutput.ReadToEnd();
    
            // vsVersion < 110 prints out a line in vcvars*.bat. Ignore 
            // everything before the first '<'.
            int xmlStartIndex = outputString.IndexOf('<');
            if (xmlStartIndex == -1)
            {
                throw new Exception("No environment block was captured");
            }
            XElement documentElement = XElement.Parse(
                outputString.Substring(xmlStartIndex)
                );
    
            Dictionary<string, string> capturedVars 
                = new Dictionary<string, string>();
    
            foreach (XElement variable in documentElement.Elements("Variable"))
            {
                capturedVars.Add(
                    (string)variable.Attribute("Name"),
                    (string)variable
                    );
            }
            return capturedVars;
        }
    }
    

    Later, when you want to run a command in the build environment, you just have to replace the environment variables in the new process with the environment variables captured earlier. You should only need to call CaptureBuildEnvironment once per argument combination, each time your program is run. Don’t try to save it between runs though or it’ll get stale.

    static void Main()
    {
        string command = "nmake";
        string args = "";
    
        Dictionary<string, string> buildEnvironment = 
            CaptureBuildEnvironment(100, "x86");
    
        ProcessStartInfo info = new ProcessStartInfo();
        // the search path from the adjusted environment doesn't seem
        // to get used in Process.Start, but cmd will use it.
        info.FileName = "cmd.exe";
        info.Arguments = String.Format(
            "/s /c \" \"{0}\" {1} \"",
            command,
            args
            );
        info.CreateNoWindow = true;
        info.UseShellExecute = false;
        info.RedirectStandardOutput = true;
        info.RedirectStandardError = true;
        foreach (var i in buildEnvironment)
        {
            info.EnvironmentVariables[(string)i.Key] = (string)i.Value;
        }
    
        using (Process p = Process.Start(info))
        {
            // do something with your process. If you're capturing standard output,
            // you'll also need to capture standard error. Be careful to avoid the
            // deadlock bug mentioned in the docs for
            // ProcessStartInfo.RedirectStandardOutput. 
        }
    }
    

    If you use this, be aware that it will probably die horribly if vcvarsall.bat is missing or fails, and there may be problems with systems with locales other than en-US.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

For some reason, after submitting a string like this Jack’s Spindle from a text
I used javascript for loading a picture on my website depending on which small
I have an array which has BIG numbers and small numbers in it. I
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I have just tried to save a simple *.rtf file with some websites and
I am trying to understand how to use SyndicationItem to display feed which is
I have a small JavaScript validation script that validates inputs based on Regex. I
I have this code to decode numeric html entities to the UTF8 equivalent character.
I'm interested in microtypography issues on the web. I want a tool to fix:
I would like to run a str_replace or preg_replace which looks for certain words

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.