

Cmd - A saner way to running external programs from C# - manojlds
https://github.com/manojlds/cmd

======
ComputerGuru
This won't work for one very simple reason: Windows apps, unlike their *nix
counterparts, do not have a unified command line switch format. This will only
really be useful for standard getopt(long) implementations, which is a very
small portion of the software available on Windows.

~~~
manojlds
Very valid point. I am working on the powershell equivalent for this, and I
would be happy to support only powershell commands and standard getopt
commands.

------
MichaelGG
This is a neat use of dynamic/reflection. But why is it "saner"? What's wrong
with wrapping the normal process I/O stuff and just doing: cmd("git clone") ?

This is the same question I have when I see dynamic typing used to access data
sources. Like reading a CSV file and doing 'row.Field1' instead of
'row["Field1"]'.

Is there really any benefit or point, other than being a cute hack?

~~~
manojlds
Yes, it started out as a hack. I wanted to see how close I can get to the
Python implementation. I am not envisioning it to be used, but would be happy
if someone found it useful :)

------
duncans
Nice idea. A few problems spring to mind:

* Doing the following will hang if the stdout buffer fills up:
    
    
        var output = process.StandardOutput.ReadToEnd();
        process.WaitForExit();
    

Take a look at Kudu (Azure's Git publishing platform) for the way they do it:
[https://github.com/projectkudu/kudu/blob/master/Kudu.Core/In...](https://github.com/projectkudu/kudu/blob/master/Kudu.Core/Infrastructure/Executable.cs)

* You need to expose a way to capture `StandardError`.

~~~
timrobinson
It won't hang as long as you're redirecting only standard output. If you want
to read both StandardOutput and StandardError, you need to do it from separate
threads: either with explicit BeginInvoke/EndInvoke calls as in Kudu, or more
simply, by listening on the OutputDataReceived/ErrorDataReceived events then
calling BeginOutputReadLine/BeginErrorReadLine.

(The reason for this is that the two streams are redirected to separate pipes,
each of which has its own fixed-size buffer. If you forget to read from one
pipe while you read from the other, its buffer fills up, and the writer - the
program being executed - blocks. With standard error redirection turned off,
the program writes directly to the console, which is safe.)

------
daeken
This looks quite awesome overall. I do wonder, though, why you can't do the
actual invokation in Cmd.TryInvokeMember rather than Cmd.TryInvoke? That'll
get rid of the () at the end of commands, from my quick read.

~~~
manojlds
I was thinking the same. I wanted to support cmd.git(git_dir : blah).branch(a:
true) kind of scenarios however. Think I would just not go with it if it means
removing the extra (). Thanks

~~~
daeken
Yeah, I think skipping the extra () is worth giving that up. Plus, you could
do this in most cases: cmd.git.branch(a: true, git_dir: blah)

~~~
manojlds
The ugly () are now gone. :)

