2010-06-02 17 views
7

ben pencerelerde ve unix içinde mono altında çalıştırmak için gereken bir C# komut satırı uygulaması vardır (Ya yasal arg dizeye agrv dönüştürmek). Bir noktada, komut satırından geçirilen bir dizi keyfi paramater verilen bir alt işlem başlatmak istiyorum. Örneğin: C# içinde bir argv ile bir alt işlemi nasıl başlatırım?

Usage: mycommandline [-args] -- [arbitrary program] 

Maalesef System.Diagnostics.ProcessStartInfo sadece args için bir dize alır. Bu gibi komutlar için bir sorundur:

Bu durumda argv ise
./my_commandline myarg1 myarg2 -- grep "a b c" foo.txt 

benziyor: Ben sadece argümanlar bitiştirmek eğer öyleyse tırnak etrafında "abc" kabuk tarafından soyulduğunu

argv = {"my_commandline", "myarg1", "myarg2", "--", "grep", "a b c", "foo.txt"} 

Not ProcessStartInfo için arg dizesini oluşturmak için şunu elde ederim:

args = "my_commandline myarg1 myarg2 -- grep a b c foo.txt" 

İstediğim bu değil.

C# OR altında bir argv'yi alt işlem başlatmaya geçirmenin basit bir yolu var mıdır, isteğe bağlı bir argvayı windows ve linux kabuğu için yasal olan bir dizeye dönüştürmek için?

Herhangi bir yardım büyük memnuniyetle karşılanacaktır.

+1

Sadece bir not: Windows'un teknik olarak bir argv'si olmadığı için C# üstünde bu sorun yok. Komut satırının tamamı işleme aktarılır ve argümanların ayrılması, işletim sisteminin değil, yeni sürecin görevidir.Unix, karşı yaklaşımı benimsiyor: İşletim sistemi bir dizi dizeden geçmekten sorumlu, bu yüzden joker karakter genişletme gibi şeyler çağrı işlemiyle halledilebilir. –

+0

@DanielPryden bu doğru değil. windows programları POSIX olanlar gibi bir argv listesine sahiptir. .Net sadece bu listeyi kayıtsızca gizler. Bana sorarsan çok rahatsız edici olur. – IanNorton

+0

@IanNorton: Aksine, "CreateProcess" sadece tek bir argüman dizesi alır. Microsoft C Çalıştırıcısı (MSVCRT) bu dizeyi ayrıştırır ve onu argv olarak kullanıma sunar, ancak programların CRT uygulamasını kullanması gerekmez ve CRT'nin başlatılması için kullanılan aynı belirti kümesini döndürmenin ayrıştırılmasının garanti edilmez. süreç. –

cevap

0

grep ve grep'un gerekeceği tüm argümanları kullanarak yeni bir alt işlem çalıştırmanız gerekir. taşıma Güncelleme args:

void runProcess(string processName, string args) 
{ 
    using (Process p = new Process()) 
    { 
     ProcessStartInfo info = new ProcessStartInfo(processName); 
     info.Arguments = args; 
     info.RedirectStandardInput = true; 
     info.RedirectStandardOutput = true; 
     info.UseShellExecute = false; 
     p.StartInfo = info; 
     p.Start(); 
     string output = p.StandardOutput.ReadToEnd(); 
     // process output 
    } 
} 

sonra runProcess("grep", "a", "b", "c", "foo.txt");

Düzenleme için bir çağrı yapmak.

+2

"args" dizisindeki argümanlar beyaz boşluk içeriyorsa, bu çalışmaz. Ayrıca, çağıran sözdiziminden, 'args'ı bir' params' dizisi olarak ilan etmek mi istediniz? Çünkü sahip olduğunuz örnek gösterdiğiniz gibi kullanılamaz. –

+0

@Daniel Pryden Params hakkında haklısınız, ve bu betiğin kendi kodunda onu kullanma noktasına kadar geliştirmesi için geliştiriciye kaldığını düşünüyorum. Bu gönderi, mevcut sisteminize bütünleşik bir program oluşturmak için tam işlevli bir programdan ziyade bir alt işlemin nasıl başlatılacağı konusunda genel bir rehber olarak görülmelidir. – Jake

0

Sadece bir dize her türlü boşluklar varsa kontrol etmek için bir Regex kullanabilir ve tırnak yenisi ile orijinal dize değiştirin: windowsland olarak

using System.Text.RegularExpressions; 
// ... 
for(int i=0; i<argv.Length; i++) { 
    if (Regex.IsMatch(i, "(\s|\")+")) { 
     argv[i] = "\"" + argv[i] + "\""; 
     argv[i].Replace("\"", "\\\""); 
    } 
} 
+0

Dizede tırnak işareti varsa bu işe yaramaz: yani "a \" b "argümanı üretir, a" b, tırnak işaretleri ile çevrelenmişse "a" b ", hem yanlış hem de yasa dışı bir dize. – lucas

+0

Öyleyse, regex'i genişletmeniz ve bir string.replace eklemeniz yeterlidir. – supercheetah

1

, gerçekten ... ekstra tırnak eklemek basit System.Diagnostics.ProcessStartInfo nesnesine ilettiğiniz dizede işaretler.

örn. "./my_commandline" "myarg1 myarg2 - grep \" a b c \ "foo.txt"

+0

Cygwin'de kullandığım tüm ortamlarda iyi çalışmalıyım. Dizenin aslında kaçmış ters eğik çizgi kullandığından emin olun - yani, tam anlamıyla kodunuzda, @ "myarg1 myarg2 - grep \" "abc \" "foo.txt" veya "myarg1 myarg2 - grep \\\" abc \\\ "foo.txt" olacaktır. –

İlgili konular