Thursday, August 30, 2012

Interacting with a sub-processed shell in .Net

Moved to http://www.isonix.ch/DevBlog/?p=3

9 comments:

Unknown said...

Hi Ludo
I am just go through your code and try to implement my requirement with your example but no luck.
I am trying to execute "psexec" command like "psexec \\testmac -u domain\admin -p abcd1234 powercfg /a" with "cmd.exe"
I am calling like this....
FcshProcess p = new FcshProcess();
p.Start(@"cmd.exe", @"C:\Windows\System32");
var fcshHelp = p.SendAndReceive(@"psexec \\testmac -u domain\admin -p abcd1234 powercfg /a");
p.Terminate();
Debug.Print(fcshHelp.Item1);

my code was fall into a loop in ReadToPrompt()method and after some time it will show timeout.
Please help me asap.

Ludo said...

Firstly, if you mean to interact with psexec, you should start it directly rather than start cmd.exe.

Secondly, you must subclass ShellProcess to match the psexec shell. It seems you are using the FcshProcess class as-is. If you modified it to match psexec, please provide the code so I can have a look.

alex said...

it works great! thank you very much for sharing, you saved a lot of mine time.

Seungweon Park said...

Hi Ludo,

I followed your instruction, and try to run python 2.7.3 from windows machine. It doesn't look like running correctly. As you see my code at http://sdrv.ms/14TWjQK , once I execute Python.exe and send a command: help(), then wants to get the help page. Would you give me a feedback what's wrong in my code in order to get the output result? Thank you.

Seungweon Park said...

For better understanding, I'm using Windows 2008 R2 with VS2012 for testing.

Seungweon Park said...

I have tried with very simple test with

namespace npythontest
{
public class Program
{
static void Main(string[] args)
{
PythonWrapper pw = new PythonWrapper();
pw.Start(@"C:\Windows\System32\cmd.exe", @"C:\Windows\System32\");

var pyHelp = pw.SendAndReceive(@"dir");
pw.Terminate();
Console.Write(pyHelp.Item1);
}
}
}

namespace Python
{
public sealed class PythonWrapper : ShellProcess
{
protected override string Prompt
{
get { return ">"; }
}

protected override string ExitCommand
{
get { return "exit"; }
}

protected override Encoding Encoding
{
get { return Encoding.UTF8; }
}
}
}

It is running ReadToPrompt()infinitely, and stdOut doesn't get any string.

I tried

pw.Start(@"C:\Python27\python.exe", @"C:\Python27\");

with prompt string ">>> ", but no success. the result is same. Any idea?

Seungweon Park said...

From the previous comments, I figured out how I resolved the issue of "cmd.exe" with

protected override string Prompt
{
get
{
var utf8 = Encoding.UTF8;
//byte[] utfBytes = utf8.GetBytes(@"C:\Windows\System32>");
byte[] utfBytes = utf8.GetBytes(@">>> ");
return utf8.GetString(utfBytes);
}
}

It looks like it has a problem in string comparison in ReadToPrompt between 'stdOut' and 'Prompt' in my windows system, so I added this and it works fine with cmd.exe.

However, I don't still get any stream output (stdOut) from ReadToPrompt() when tried "python.exe". I think It has to have any output although unicode is different in stdOut, but it doesn't capture any output. Any idea? Is it related to any CreatePipe() or SetHandleInformation in Start in ShellProcess.cs? Thanks.

Seungweon Park said...

Python.exe seems to send any prompt string to stdErr. Once I added stdErr checking from ReadToPrompt(), it works great!! Thank you.

Seungweon Park said...

Hi Ludo,

Have you ever tested with powershell.exe? It doesn't seem to work with powershell correctly. Would you give me any suggestion for powershell execution with this library?

Thanks,