3

first time asking a question here so hopefully it conforms to the etiquette. Does anyone know how to use the C#

process.UseShellExecute = false;

when in Unity3D? Using it set to false causes the exe to crash. But setting it to true disables ability to send writeline commands.Thoughts, suggestions and solutions all welcome. Thanks everyone! Code example below:

    ProcessStartInfo processinfo = new 
    ProcessStartInfo("C:/ConsoleExample/bin/Debug/ConsoleExample.exe");
    processinfo.RedirectStandardOutput = false;
    processinfo.RedirectStandardError = false;
    processinfo.RedirectStandardInput = true;
    processinfo.UseShellExecute = false; //<----Causes program to crash exe when launched, but is required for write console key.
    processinfo.CreateNoWindow = false;

    Process.Start(processinfo);

    Thread.Sleep(1000);


    //Write text to console exe file from unity as a command.
    processinfo.StandardInput.Write(ConsoleKey.Escape);
mdk_john
  • 71
  • 1
  • 6
  • Crash or freeze Unity? These are two different stuff. By the way, don't use `Thread.Sleep(1000)` on the main Thread – Programmer Jun 04 '18 at 18:33
  • It crashes the exe file on the line Process.Start(processinfo); In other words the exe won't start properly. Unity is fine and does not crash or fail. – mdk_john Jun 04 '18 at 19:27
  • Just use the `Process` instead of `ProcessStartInfo` and see what happens – Programmer Jun 04 '18 at 19:33
  • Ok. Trying it now. – mdk_john Jun 04 '18 at 19:34
  • If I change `Process.Start(processinfo);` to `Process.Start(Process);` I get a debug error with: _Process is a type, which is not valid in the given context_ – mdk_john Jun 04 '18 at 19:43
  • I also removed `Thread.Sleep(1000);` – mdk_john Jun 04 '18 at 19:44
  • `Process p = new Process();` then `p.StartInfo = new System.Diagnostics.ProcessStartInfo("C:\\ConsoleExample\\bin\\Debug\\ConsoleExample.exe");` and then `p.StartInfo.UseShellExecute = false;` and then `p.Start();`. Is this what you did? What makes you think it is crashing? – Programmer Jun 04 '18 at 20:04
  • P.s. Thank you for comments and helping. I just want to be clear that I really appreciate all and any help on this. – mdk_john Jun 04 '18 at 20:05
  • Yes that's what I did. The exe that starts usually has a window that waits text entry, but instead I get the windows 7 debug option and recovery asking if I want to troubleshoot the failed exe file. But when I remove the line `processinfo.UseShellExecute = false;` or change it to true it works perfectly and runs the exe file. Which is great, but I need that useshellexecute to be false so I can use `processinfo.RedirectStandardInput = true;` – mdk_john Jun 04 '18 at 20:12
  • Long story short I'm trying to have Unity send a key command to safely stop my console exe file without just using process.kill as the exe has a loop running that is interrupted by a listening for key command. – mdk_john Jun 04 '18 at 20:14
  • Maybe the problem is the program you are trying to open? Can you try this with another exe program and see what happens? – Programmer Jun 04 '18 at 20:23
  • Yep tried it with a very simple exe console app on Saturday and it did the exact same thing (works without shellexecute =false). I thought it may be due to Unity monodevelop not letting the command through somehow? – mdk_john Jun 04 '18 at 21:00
  • It could be. What if you try that code without Unity? Try it with a console app with Visual Studio. With that we will know if this is Unity's mono issue or not – Programmer Jun 04 '18 at 21:50
  • Yep. Ok will try that. – mdk_john Jun 04 '18 at 21:59
  • @Programmer Actually that is exactly what I ended up using for my problem. I created a `batch` file with a few basic commands, I appended some commands from `Unity` by editing the file. And then I just started the process without the `UseShellExecute` flag. Maybe that could be a solution for OP. – Hristo Jun 05 '18 at 09:01
  • @Hristo That wouldn't be the solution because the default value of `UseShellExecute` is `true`. If you don't set it, it will be `true` but OP want's it to be `false` so that OP can send input to it. – Programmer Jun 05 '18 at 09:41
  • @Programmer What I mean (as a workaround) is that OP can write his commands as text to a `batch` file and just execute that file with the `UseShellExecute` set to true. Now in that file will open his `.exe` or whatever necessary. – Hristo Jun 05 '18 at 09:47
  • I understand what you mean but OP cannot send input to that opened exe program while it is running. I think with this, OP can only add input to execute before opening the program. Maybe I am wrong? – Programmer Jun 05 '18 at 09:51
  • So thanks to @Programmer I went away and confirmed this is a problem with my receiving script and that this can be done from unity with more work on the send and receive methods. Small work arounds are needed for Unity though. Here is a link to Akanaro's work that does something very similar. [Unity Forum Example](https://forum.unity.com/threads/c-standardinput-writeline-is-sending-strange-characters-to-external-console-application-solved.410154/) – mdk_john Jun 05 '18 at 16:31
  • Hopefully I'll be back here with the code and working example. – mdk_john Jun 05 '18 at 22:54

1 Answers1

4

So I got this working in the end. Thanks to @Hristo and @Programmer for help and comments. Much appreciated. Here is the final code that fires up the console app and sends keys. If anyone has questions or need more details let me know by post or message and I'll post more on this.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
using System.Threading;
using UnityEngine.UI;
using UnityStandardAssets.CrossPlatformInput;

public class Camera_controller : MonoBehaviour {
public int caminterrupt;
private IEnumerator coroutine;

// Use this for initialization
void Start () {
    caminterrupt = 0;
    coroutine = startcamera();
}

// Update is called once per frame
void Update () {

}

public void button1(string pressed)
{

    if (caminterrupt == 0)
    {
        caminterrupt = 1;

        StartCoroutine(coroutine);



    }
    else
    { caminterrupt = 0;
        StopCoroutine("coroutine");
    }


}

public IEnumerator startcamera() {

    //string strOutput;

    //Starting Information for process like its path, use system shell i.e. 
control process by system etc.

    ProcessStartInfo psi = new 
ProcessStartInfo(@"C:\ConsoleExample\bin\Debug\ConsoleExample.exe");
    // its states that system shell will not be used to control the process 
instead program will handle the process
    psi.UseShellExecute = false;
    psi.ErrorDialog = false;
    // Do not show command prompt window separately
    //psi.CreateNoWindow = true;
    //psi.WindowStyle = ProcessWindowStyle.Hidden;
    //redirect all standard inout to program
    psi.RedirectStandardError = true;
    psi.RedirectStandardInput = true;
    psi.RedirectStandardOutput = true;
    //create the process with above infor and start it
    Process plinkProcess = new Process();
    plinkProcess.StartInfo = psi;
    plinkProcess.Start();
    //link the streams to standard inout of process
    StreamWriter myStream = new 
 StreamWriter(plinkProcess.StandardInput.BaseStream, Encoding.ASCII);

    //send command to cmd prompt and wait for command to execute with thread 
 sleep


    refire:
        if (caminterrupt == 1)
        {

            myStream.WriteLine("y");
        yield return new WaitForSeconds(1);
        goto refire;

        }
        if (caminterrupt == 0)
        {
            myStream.WriteLine("e");

        }


    myStream.WriteLine("e");

    // flush the input stream before sending exit command to end process for 
any unwanted characters

    myStream.Close();

    plinkProcess.Close();
    caminterrupt = 0;

    }
 }

This is the Unity side that calls the console file and interacts by sending key commands.

mdk_john
  • 71
  • 1
  • 6