1

Currently I'm porting a c++ exe launch to c#. I'm able to read through and understand the c++ code, but I'm struggling to find the c# equivalent. I believe that the original code launches the exe by utilizing the command prompt.

I think it would be best to display the code that I am porting, so here it is:

  // This is basically running an exe to compile a file that I create
  short rtncod;

  int GPDataAge = FileAge(SelectedPath + GPDATA); //Checks age of GPDATA if it exists

  STARTUPINFO si;         // Startup information structure
  PROCESS_INFORMATION pi; // Process information structure

  memset(&si, 0, sizeof(STARTUPINFO)); // Initializes STARTUPINFO to 0
  si.cb = sizeof(STARTUPINFO); // Set the size of STARTUPINFO struct
  AnsiString CmdLine = Config->ReadString("Configuration","CRTVSM","CRTVSM.EXE . -a"); // Windows version requires path

  rtncod = (short)CreateProcess(
                  NULL,   // pointer to name of executable module
                  CmdLine.c_str(), // pointer to command line string
                  NULL,   // pointer to process security attributes
                  NULL,   // pointer to thread security attributes
                  FALSE,   // handle inheritance flag
                  CREATE_NEW_CONSOLE, // creation flags
                  NULL,   // pointer to new environment block
                  NULL,   // pointer to current directory name
                  &si,    // pointer to STARTUPINFO
                  &pi);   // pointer to PROCESS_INFORMATION
  if (!rtncod) /*If rtncod was returned successful**/ {
    int LastError = GetLastError();
    if (LastError == 87 /* Lookup 87 error **/ && AnsiString(SelectedPath + GPDATA).Length() > 99)
      ShowMessage("CRTASM could not run due to extremely long path name.  Please map or move the folder to shorten the path");
    else
      ShowMessage("Could not compile VSMInfo.dat =>" + IntToStr(LastError));
  }
  else /* If successful **/ {
    unsigned long ExitCode;
    // CartTools will 'lock up' while waiting for CRTASM
    do {
      rtncod = GetExitCodeProcess(pi.hProcess,&ExitCode);
    } while (rtncod && ExitCode == STILL_ACTIVE);
    if (rtncod == 0) {
      rtncod = GetLastError();
      ShowMessage("Could not watch CRTVSM compile VSMInfo.dat =>" + IntToStr(GetLastError()));
    }
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
  }

  if (GPDataAge == FileAge(SelectedPath + GPDATA)) // date/time didn't change!
    Application->MessageBox(AnsiString("Output blocking file (" + SelectedPath + GPDATA") failed to be updated.  Check operation of CRTVSM.EXE before using "GPDATA" with SAM/CMS!").c_str(),"CRTVSM Error",MB_OK|MB_ICONHAND);

All of this may not be relevant, and you may not know where my personal elements come from, but that is okay as I am only concerned with the MICROSOFT process elements (such as CreateProcess and STARTUPINFO).

So far I have looked at the Process.Start method provided in this question, but do not think that it allows me to go through the same processes as the ones listed above.

My question is, what class or methods can I use to customize my exe launch in a equivalent manner to the launch that is performed in the c++ code above?

UPDATE: Currently, I have the executable file located inside a folder that I created in the solution of my program. To launch the executable I am using the ProcessStartInfo class.

//The folder that the exe is located in is called "Executables"
ProcessStartInfo startInfo = new ProcessStartInfo("Executables\\MYEXECUTABLE.EXE");
Process.Start(startInfo);

Whenever I run the above lines of code I get a Win32Exception was unhandled, and it says that "The system cannot find the file specified".

Community
  • 1
  • 1
Eric after dark
  • 1,768
  • 4
  • 31
  • 79

2 Answers2

1

The C++ code isn't using a command 'prompt', per se, but launching a process by providing a path the the executable to CreateProcess. You can accomplish the same thing in C# with the Process class. Configure Process.StartInfo and call the Start method.

Regarding launching the executable with a specific path: if you don't specify a full path then you are at the mercy of the working directory. If the exe is the same directory as the running executable, or a subdirectory of it, then you can construct the path like this:

string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Executables\MYEXECUTABLE.EXE");
ProcessStartInfo startInfo = new ProcessStartInfo(path);
Process.Start(startInfo);
jltrem
  • 12,124
  • 4
  • 40
  • 50
  • So I can basically do all of that with the `Process` class? http://msdn.microsoft.com/en-us/library/vstudio/System.Diagnostics.Process(v=vs.110).aspx – Eric after dark Apr 15 '14 at 21:00
  • I think everything is configurable through StartInfo. Which params are you having a problem with? CREATE_NEW_CONSOLE is based off CreateNoWindow=false. – jltrem Apr 15 '14 at 21:07
  • I'm actually just starting and wondering what to use in place of `STARTUPINFO` – Eric after dark Apr 15 '14 at 21:10
  • This info is very helpful, but I am having trouble placing the file in the correct area and then locating it through my code. I will post my updated code in my question. – Eric after dark Apr 21 '14 at 18:22
  • @Ericafterdark I updated my answer with exe path info – jltrem Apr 21 '14 at 18:39
  • It looks like I still end up with the same error on the `Process.Start();` line. I've verfied that the exe is in the location that I stated above – Eric after dark Apr 21 '14 at 19:54
  • @Ericafterdark "The system cannot find the file specified"? Then something is wrong with the path you are giving it. Log it or look at it in the debugger to verify the path. – jltrem Apr 21 '14 at 20:00
  • Okay, it looks like it is tracing to bin->debug->(then looking for my "Executables" folder here). This is strange because "Executables" is on the same level as bin. – Eric after dark Apr 21 '14 at 20:14
  • 1
    @Ericafterdark this q/a on SO is veering from the original question. For the purposes of answering your original question, hardcode the path and confirm that you can launch the exe. – jltrem Apr 21 '14 at 20:20
  • Yeah, it worked. Thank you. Now I need to know how to make that path more dynamic so that it will work on other systems too. – Eric after dark Apr 21 '14 at 20:24
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/51125/discussion-between-jltrem-and-eric-after-dark) – jltrem Apr 21 '14 at 20:26
  • @jltrem: _"CREATE_NEW_CONSOLE is based off CreateNoWindow=false"_ -- this is not correct. The `CreateNoWindow` option controls the use of the `CREATE_NO_WINDOW` flag. There is no `Process` option that gives control over the `CREATE_NEW_CONSOLE` flag. One would have to call the unmanaged `CreateProcess()` directly to be able to specify that flag. – Peter Duniho Dec 07 '15 at 01:03
0

Adding on to jltrem, an example of Process.Start is: http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo(v=vs.110).aspx

using System;
using System.Diagnostics;
using System.ComponentModel;

namespace MyProcessSample
{
class MyProcess
{
    // Opens the Internet Explorer application. 
    void OpenApplication(string myFavoritesPath)
    {
        // Start Internet Explorer. Defaults to the home page.
        Process.Start("IExplore.exe");

        // Display the contents of the favorites folder in the browser.
        Process.Start(myFavoritesPath);
    }

    // Opens urls and .html documents using Internet Explorer. 
    void OpenWithArguments()
    {
        // url's are not considered documents. They can only be opened 
        // by passing them as arguments.
        Process.Start("IExplore.exe", "www.northwindtraders.com");

        // Start a Web page using a browser associated with .html and .asp files.
        Process.Start("IExplore.exe", "C:\\myPath\\myFile.htm");
        Process.Start("IExplore.exe", "C:\\myPath\\myFile.asp");
    }

    // Uses the ProcessStartInfo class to start new processes, 
    // both in a minimized mode. 
    void OpenWithStartInfo()
    {
        ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe");
        startInfo.WindowStyle = ProcessWindowStyle.Minimized;

        Process.Start(startInfo);

        startInfo.Arguments = "www.northwindtraders.com";

        Process.Start(startInfo);
    }

    static void Main()
    {
        // Get the path that stores favorite links. 
        string myFavoritesPath =
            Environment.GetFolderPath(Environment.SpecialFolder.Favorites);

        MyProcess myProcess = new MyProcess();

        myProcess.OpenApplication(myFavoritesPath);
        myProcess.OpenWithArguments();
        myProcess.OpenWithStartInfo(); 
    }
}
}
Barry West
  • 530
  • 3
  • 11
  • This exe that I want to launch is going to be packaged with the program. So can I just add it to the main folder directory of the program and use `Process.Start()` to launch it from there? I ask because it is currently not working. – Eric after dark Apr 21 '14 at 17:17
  • And I am not launching a program that is located on the windows path, like Internet Explorer. – Eric after dark Apr 21 '14 at 17:24
  • In this example you would modify the code to point to your executable filename, and not call IExplorer.exe. This is just an example. With start info you can change to add parameters, starting path, etc. It will cover anything you need, just read the documentation. – Barry West Apr 21 '14 at 20:02