hello
(im using c#, visual studio 2008)
I am trying to get Input/Output from a command prompt like process "scrds.exe".
If i try to start the process with standardInput = true, standardOutput = true, or standardError = true. The program cannot start.

after research the "scrds.exe" cant start due to it verifying the lines of output it has already written. I was wondering if there was a way to Redirect the output to my program or file. Save it in main memory or file, and then redirect it back to the process scrds.exe. I have tried lots of methods such as trying to put the process in debuging mode, and only redirecting certain things. Everytime it crashes at startup if Standard output is redirected. Or crashes because the StandardOutput could not be redirected.

Any ideas would be very welcome : )


also i am trying to just write or execute commands in the program from a c# program... If someone knows another way i am willing to do that as well.

Code so far

start.StartInfo.FileName = data;
                start.StartInfo.Arguments = argu;
                start.StartInfo.UseShellExecute = false;
                //start.StartInfo.RedirectStandardInput = true;
                //start.StartInfo.RedirectStandardOutput = true;
                //start.StartInfo.RedirectStandardError = true;
                start.Start();

Look when I was senior student my graduation project was about code generation I use a method to generate for me keyfile for libraries I used this method which helped me to do some redirection and so on.

public void GenerateKeyFile(string command)
{
ProcessStartInfo PSI = new ProcessStartInfo("your.exe");
PSI.RedirectStandardInput = true;
PSI.RedirectStandardOutput = true;
PSI.RedirectStandardError = true;
PSI.UseShellExecute = false;
Process p = Process.Start(PSI);
System.IO.StreamWriter SW = p.StandardInput;
System.IO.StreamReader SR = p.StandardOutput;
SW.WriteLine(command);
SW.Close();
}

Thanks for your input, but once again RedirectStandardInput, Output, Error all cause this program to crash upon startup... I know how to do that, however is there a way to direct the output to my program then direct it back to the EXE that i started so that program does not crash.

Again the program i am starting is SRCDS.EXE. It tries to verify its output when run and crashes if nothing is written.

I am trying to run srcds.exe. This is a command line based server for steam products such as team fortress 2, left 4 dead, counter strike, exc.... I am starting the program using:

Process start = new Process();
start.StartInfo.FileName = data;
start.StartInfo.Arguments = argu;
start.StartInfo.UseShellExecute = false;
start.Start();

If i use these commands:

start.StartInfo.RedirectStandardInput = true;
start.StartInfo.RedirectStandardOutput = true;
start.StartInfo.RedirectStandardError = true;

The Srcds.exe program will crash
The reason it crashes is because the output is not being written to the programs command lines. Aka you see no output to the console like window.
The srcds crashs because it checks to see if it wrote certain lines, since the output has been redirected, obviously it cant see the lines it wrote.

If i try to let the srcds start then redirect standard output using the commands above... it gives me the error standard output was not redirected.

I was wondering if anyone knew a way to redirect the output of the Srcds to my C# program.... then Direct that same output back to the Srcds program.... Or possibly instead of redirecting... just reading the output, if that is possible.

Ultimately i want to be able to give commands to this commandline based program and recieve the output so i can use my C# program as a sort of wrapper.

Thank you for any responses

If you can contact who developed Srcds they can give you the proper solution, I just gave the standardized solution for such demands.

Although you've probably long ago forgotten about this I have not. It is not the output of SRCDS that is causing the error it is the input. SRCDS creates a number of threads and as such creates a very unstandardized member of the "ConsoleWindowClass". It will not run if inputRedirection is true. It will however run splendidly if OutputRedirection is true.

The following is code I wrote that works for getting the output but does not allow input:

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#using <System.dll>
//#include <Windows.h>

using namespace System;
using namespace System::Diagnostics;
using namespace System::IO;
int _tmain(int argc, _TCHAR* argv[])
{
	SetConsoleTitle(_T("Output Example") );
	//HWND WindowHandle;

	Process^ myProcess = gcnew Process;
	//myProcess->EnableRaisingEvents = true;
	ProcessStartInfo^ myProcessStartInfo = gcnew ProcessStartInfo("srcds.exe","-console -nohltv -autoupdate -heapsize 524288 -game cstrike");
	myProcessStartInfo->UseShellExecute = false;
	myProcessStartInfo->RedirectStandardOutput = true;
	//myProcessStartInfo->RedirectStandardInput = false;
	myProcessStartInfo->RedirectStandardError = false;
	myProcess->StartInfo = myProcessStartInfo;
	myProcess->Start();

	//Hide the SRCDS Window
	//while((WindowHandle = FindWindow(_T("ConsoleWindowClass"), _T("SOURCE DEDICATED SERVER")))==NULL){};
	//ShowWindow(WindowHandle, SW_HIDE); //hide the window
	
	
	StreamReader^ myStreamReader = myProcess->StandardOutput;
	String^ myString;

	// Read the standard output of the spawned process.
	while(!(myProcess->HasExited)){
		if(myString = myStreamReader->ReadLine()){
			if (myString->IndexOf("DataTable")<0)
				Console::WriteLine( myString );
		}
	}
	myProcess->Close();
	
	return 0;
}

I'm working on using PostMessage() to send keystrokes to the srcds.exe window but as yet I cannot. Interestingly enough I can use PostMessage() to send keystrokes to a command prompt without a problem. This is how I discovered that the srcds application is extremely unique.

I have a larger multi-threaded application I'm experimenting with that I hope will allow me to send keystrokes to srcds seeing as how inputredirection crashes it.

Very good post.

I have create two console application. The below is a program takes argument and user input.

It is a code of sam1.exe

public class Test
{
    public static void Main(string[] args)
    {
        for (int i = 0; i < args.Length; i++)
        {
            System.Console.WriteLine(args[i]);
        }
        string name;

        System.Console.WriteLine("Enter your name : ");
        name = Console.ReadLine();

        System.Console.WriteLine("Welcome : " + name);
    }
}

Another program to execute process "sam1.exe"

class TestProcess
{
    static void Main()
    {
        Process p = new Process();
        p.StartInfo.UseShellExecute = false ;
        p.StartInfo.RedirectStandardInput = true;
        p.StartInfo.RedirectStandardOutput = true;
        
        p.StartInfo.FileName = @"c:\TC\sam1\bin\Debug\sam1.exe";
        p.StartInfo.Arguments = "tt dd ee rr";
        p.StartInfo.CreateNoWindow = true;
        
        p.Start();
       
        System.IO.StreamWriter wr = p.StandardInput;
        System.IO.StreamReader rr = p.StandardOutput;

        wr.Write("Rajeshn" + "\n");
        Console.WriteLine(rr.ReadToEnd());
        wr.Flush();
    }
}

Thank you for the new posts... i have since abandoned the idea of redirecting input/output and just went to socket programming. I will post some examples when my program is fully working. Thank you again, this is still very helpful !

DevC++4.9.9.2, I'm glad to see you're still working on this as it has been something that's bugged me for sometime now. I run a CS:S surf server and there is no built-in way to supress the million or so dataTable warnings that pop up every time a surfer exceeds the "speed-limit". There are some other features I wanted like automatic restarting on crashes (which I already coded in a seperate application).

I don't know anything about socket programming so I'm looking forward to your examples.

I got my code working using a C++ version of sendkeys I got here: http://www.codeproject.com/KB/cpp/sendkeys_cpp_Article.aspx
C# has sendkeys built in though it's a little messy and might require a class for certain functions.

Since I couldn't get postMessage() to work with the srcds window I had to use getfocus() every time I sent keys to srcds which is sloppy but it works. I attempted to hide the srcds window by making it small, moving it offscreen and only making it visible on the taskbar for the brief period when keys are sent.

I know this is in C++ but it is really easy to convert to C# and won't require my sloppy type conversions. I have done very little bug testing and the only obvious issue is that when you type in a command it spits out twice (once from you typing it and the other from srcds getting it and sending it back).

I code this in VS2008. I'll post a full project zip just as soon as I read the license for the version of sendkeys I'm using.

#include "stdafx.h"
#include "SendKeys.h"
#include <stdio.h>
#include <string.h>
#include <Windows.h>
#include <tchar.h>
#include <time.h>
#using <System.dll>

using namespace System;
using namespace System::Diagnostics;
using namespace System::IO;
using namespace System::Threading;

ref class MyThread{
public:    
	static void GetInput(Object ^Name);
};

void MyThread::GetInput(Object ^Name){
	HWND WindowHandle;
	HWND RestoreMain;
	String^ inputText;
	String^ check;
	LPCTSTR	inputConv;

	//http://www.codeproject.com/KB/cpp/sendkeys_cpp_Article.aspx
	CSendKeys sk;

	//Get Window handles
	while((WindowHandle = FindWindow(_T("ConsoleWindowClass"), _T("SOURCE DEDICATED SERVER")))==NULL){};
	while((RestoreMain = FindWindow(_T("ConsoleWindowClass"), _T("Surf Mod")))==NULL){};
	
	//Always wait for commands from user
	while(true)        
	{   
		inputText=Console::ReadLine();
		if ( inputText && inputText->Length > 0 )
        {
			//This is a sloppy function which converts String^ to LPCTSTR one character at a time
			//In C# this loop wouldn't be necessary
			for(int i=0; i<inputText->Length;i++){
				sk.AppActivate(WindowHandle);
				check=inputText->Substring(i,1);
				inputConv = (LPCTSTR)System::Runtime::InteropServices::Marshal::StringToCoTaskMemAnsi(check).ToInt32();
				sk.SendKeys(inputConv);
			}
			sk.SendKeys("{ENTER}");

			//Once keys are sent hide the srcds window
			while(SetForegroundWindow(RestoreMain)==0){}
			ShowWindow(WindowHandle, SW_HIDE);

			//Detect user exit and break read loop
			if(inputText->IndexOf("exit")>=0){
				break;
			}
        }
	}        
	return;    
}

int _tmain(int argc, _TCHAR* argv[])
{
	SetConsoleTitle(_T("Surf Mod") );
	HWND WindowHandle;

	//Prepare the srcds process
	Process^ myProcess = gcnew Process;
	ProcessStartInfo^ myProcessStartInfo = gcnew ProcessStartInfo("srcds.exe","-console -game cstrike");
	myProcessStartInfo->UseShellExecute = false;
	myProcessStartInfo->RedirectStandardOutput = true;
	myProcessStartInfo->RedirectStandardError = false;
	myProcess->StartInfo = myProcessStartInfo;
	myProcess->Start();

	//Hide the SRCDS Window
	while((WindowHandle = FindWindow(NULL, _T("SOURCE DEDICATED SERVER")))==NULL){};
	MoveWindow(WindowHandle,-200,-200,120,120,true);
	ShowWindow(WindowHandle, SW_HIDE);

	//Start thread to get commands to send to srcds
	Thread ^thr1 = gcnew Thread(gcnew ParameterizedThreadStart(&MyThread::GetInput));    
	thr1->Start("SOURCE DEDICATED SERVER");

	//Prepare Stream Reader
	StreamReader^ myStreamReader = myProcess->StandardOutput;
	String^ myString;

	// Read the standard output of the spawned process.
	while(!(myProcess->HasExited)){
		if(myString = myStreamReader->ReadLine()){
			if (myString->IndexOf("DataTable")<0)
				Console::WriteLine( myString );
		}
	}
	myProcess->Close();
	thr1->Abort();
	return 0;
}
This article has been dead for over six months. Start a new discussion instead.