зеркало из https://github.com/mono/mail-archives.git
223 строки
11 KiB
HTML
223 строки
11 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<HTML>
|
|
<HEAD>
|
|
<TITLE> [Mono-dev] sub-process invocation on posix
|
|
</TITLE>
|
|
<LINK REL="Index" HREF="index.html" >
|
|
<LINK REL="made" HREF="mailto:mono-devel-list%40lists.ximian.com?Subject=Re%3A%20%5BMono-dev%5D%20sub-process%20invocation%20on%20posix&In-Reply-To=%3CCACk-zm9y8%2BqWMEakVwb8eUcwm%3DG6TZPK6zSYSsMGqRL1c2mvDg%40mail.gmail.com%3E">
|
|
<META NAME="robots" CONTENT="index,nofollow">
|
|
<style type="text/css">
|
|
pre {
|
|
white-space: pre-wrap; /* css-2.1, curent FF, Opera, Safari */
|
|
}
|
|
</style>
|
|
<META http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
|
<LINK REL="Previous" HREF="040511.html">
|
|
<LINK REL="Next" HREF="040515.html">
|
|
</HEAD>
|
|
<BODY BGCOLOR="#ffffff">
|
|
<H1>[Mono-dev] sub-process invocation on posix</H1>
|
|
<B>Greg Najda</B>
|
|
<A HREF="mailto:mono-devel-list%40lists.ximian.com?Subject=Re%3A%20%5BMono-dev%5D%20sub-process%20invocation%20on%20posix&In-Reply-To=%3CCACk-zm9y8%2BqWMEakVwb8eUcwm%3DG6TZPK6zSYSsMGqRL1c2mvDg%40mail.gmail.com%3E"
|
|
TITLE="[Mono-dev] sub-process invocation on posix">gregnajda at gmail.com
|
|
</A><BR>
|
|
<I>Tue Jun 11 00:59:34 UTC 2013</I>
|
|
<P><UL>
|
|
<LI>Previous message: <A HREF="040511.html">[Mono-dev] sub-process invocation on posix
|
|
</A></li>
|
|
<LI>Next message: <A HREF="040515.html">[Mono-dev] sub-process invocation on posix
|
|
</A></li>
|
|
<LI> <B>Messages sorted by:</B>
|
|
<a href="date.html#40512">[ date ]</a>
|
|
<a href="thread.html#40512">[ thread ]</a>
|
|
<a href="subject.html#40512">[ subject ]</a>
|
|
<a href="author.html#40512">[ author ]</a>
|
|
</LI>
|
|
</UL>
|
|
<HR>
|
|
<!--beginarticle-->
|
|
<PRE>The Windows CreateProcess<<A HREF="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx">http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx</A>>function
|
|
takes command line arguments as a single string. This detail
|
|
leaked into the .NET Process class. Windows programs with a
|
|
WinMain<<A HREF="http://msdn.microsoft.com/en-us/library/windows/desktop/ms633559%28v=vs.85%29.aspx">http://msdn.microsoft.com/en-us/library/windows/desktop/ms633559%28v=vs.85%29.aspx</A>>entry
|
|
point typically break that argument string into arguments using
|
|
CommandLineToArgvW<<A HREF="http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391%28v=vs.85%29.aspx">http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391%28v=vs.85%29.aspx</A>>.
|
|
With a regular "main" entry point, the C runtime does that for you.
|
|
Unfortunately there is no ArgvToCommandLine function, which is a shame
|
|
because CommandLineToArgvW has pretty funky rules for quotes and
|
|
backslashes. See the docs for
|
|
CommandLineToArgvW<<A HREF="http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391%28v=vs.85%29.aspx">http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391%28v=vs.85%29.aspx</A>>and
|
|
Raymond Chen's blog
|
|
post <<A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx">http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx</A>>for
|
|
info. Simply enclosing in quotes and putting a backslash before quotes
|
|
and backslashes is not good enough for Windows.
|
|
|
|
I was curious about this myself a week or two ago because I had to pass
|
|
some dynamic arguments to a process so I dove into the Mono source. On
|
|
Windows Mono passes the argument string as is to CreateProcess. On Unix
|
|
platforms Mono uses the GNOME
|
|
g_shell_parse_argv()<<A HREF="https://developer.gnome.org/glib/2.34/glib-Shell-related-Utilities.html#g-shell-parse-argv">https://developer.gnome.org/glib/2.34/glib-Shell-related-Utilities.html#g-shell-parse-argv</A>>function
|
|
to convert the arg string into an argv before starting the process.
|
|
|
|
Feel free to use the following code taken from a personal project of
|
|
mine<<A HREF="https://bitbucket.org/LHCGreg/dbsc/src/c3cca47e6b190f7b6fad47c12d781e445e962acc/mydbsc/MySqlDbscEngine.cs?at=master">https://bitbucket.org/LHCGreg/dbsc/src/c3cca47e6b190f7b6fad47c12d781e445e962acc/mydbsc/MySqlDbscEngine.cs?at=master</A>>.
|
|
It passes the unit tests I threw it.
|
|
|
|
private string QuoteCommandLineArg(string arg)
|
|
{
|
|
if (Environment.OSVersion.Platform == PlatformID.Unix ||
|
|
Environment.OSVersion.Platform == PlatformID.MacOSX)
|
|
{
|
|
return QuoteCommandLineArgUnix(arg);
|
|
}
|
|
else
|
|
{
|
|
return QuoteCommandLineArgWindows(arg);
|
|
}
|
|
}
|
|
|
|
internal static string QuoteCommandLineArgWindows(string arg)
|
|
{
|
|
// If a double quotation mark follows two or an even number of
|
|
backslashes,
|
|
// each proceeding backslash pair is replaced with one
|
|
backslash and the double quotation mark is removed.
|
|
// If a double quotation mark follows an odd number of
|
|
backslashes, including just one,
|
|
// each preceding pair is replaced with one backslash and the
|
|
remaining backslash is removed;
|
|
// however, in this case the double quotation mark is not
|
|
removed.
|
|
// -
|
|
<A HREF="http://msdn.microsoft.com/en-us/library/system.environment.getcommandlineargs.aspx">http://msdn.microsoft.com/en-us/library/system.environment.getcommandlineargs.aspx</A>
|
|
//
|
|
// Windows command line processing is funky
|
|
|
|
string escapedArg;
|
|
Regex backslashSequenceBeforeQuotes = new Regex(@"(\\+)""");
|
|
// Double \ sequences before "s, Replace " with \", double \
|
|
sequences at end
|
|
escapedArg = backslashSequenceBeforeQuotes.Replace(arg, (match)
|
|
=> new string('\\', match.Groups[1].Length * 2) + "\"");
|
|
escapedArg = escapedArg.Replace("\"", @"\""");
|
|
Regex backslashSequenceAtEnd = new Regex(@"(\\+)$");
|
|
escapedArg = backslashSequenceAtEnd.Replace(escapedArg, (match)
|
|
=> new string('\\', match.Groups[1].Length * 2));
|
|
// C:\blah\"\\
|
|
// "C:\blah\\\"\\\\"
|
|
escapedArg = "\"" + escapedArg + "\"";
|
|
return escapedArg;
|
|
}
|
|
|
|
internal static string QuoteCommandLineArgUnix(string arg)
|
|
{
|
|
// Mono uses the GNOME g_shell_parse_argv() function to convert
|
|
the arg string into an argv
|
|
// Just prepend " and \ with \ and enclose in quotes.
|
|
// Much simpler than Windows!
|
|
|
|
Regex backslashOrQuote = new Regex(@"\\|""");
|
|
return "\"" + backslashOrQuote.Replace(arg, (match) => @"\" +
|
|
match.ToString()) + "\"";
|
|
}
|
|
|
|
|
|
Hope that helps.
|
|
|
|
- Greg
|
|
|
|
|
|
On Mon, Jun 10, 2013 at 3:46 PM, Ian Norton <<A HREF="http://lists.ximian.com/mailman/listinfo/mono-devel-list">inorton at gmail.com</A>> wrote:
|
|
|
|
><i> I kind of already have a thing to do that, feels a bit icky though,
|
|
</I>><i> especially as there must be some thing lower down that undoes the joined up
|
|
</I>><i> string into a char** again. :)
|
|
</I>><i>
|
|
</I>><i>
|
|
</I>><i> On 10 June 2013 16:06, Michael Hutchinson <<A HREF="http://lists.ximian.com/mailman/listinfo/mono-devel-list">m.j.hutchinson at gmail.com</A>>wrote:
|
|
</I>><i>
|
|
</I>>><i> FWIW, you actually just need to double quote each argument and escape
|
|
</I>>><i> double quotes so you can very easily write a helper to do this in a way
|
|
</I>>><i> that works on both Mono and .NET:
|
|
</I>>><i>
|
|
</I>>><i> static Process StartProcess (string name, params string[] args)
|
|
</I>>><i> {
|
|
</I>>><i> string a = null;
|
|
</I>>><i> if (args != null && args.Length > 0)
|
|
</I>>><i> a = "\"" + string.Join (args.Select (s => s.Replace ("\"",
|
|
</I>>><i> "\\\"")).ToArray (), "\" \"") + "\"";
|
|
</I>>><i> return Process.Start (
|
|
</I>>><i> new ProcessStartInfo (name, a) {
|
|
</I>>><i> ShellExecute = false,
|
|
</I>>><i> }
|
|
</I>>><i> );
|
|
</I>>><i> }
|
|
</I>>><i>
|
|
</I>>><i> Obviously this could be done more efficiently with a StringBuilder.
|
|
</I>>><i>
|
|
</I>>><i> Apologies for any errors, I'm writing this on my phone...
|
|
</I>>><i>
|
|
</I>>><i> - Michael
|
|
</I>>><i> On Jun 6, 2013 1:18 PM, "Ian Norton" <<A HREF="http://lists.ximian.com/mailman/listinfo/mono-devel-list">inorton at gmail.com</A>> wrote:
|
|
</I>>><i>
|
|
</I>>>><i> Hiya, I'm aware that I can use Process.Start() but I'd really really
|
|
</I>>>><i> like to be able to directly pass a list of strings to my child process as
|
|
</I>>>><i> arguments rather than having to escape shell characters and spaces etc.
|
|
</I>>>><i>
|
|
</I>>>><i> Ie, In perl or C I'd do:
|
|
</I>>>><i>
|
|
</I>>>><i> system("df","-m","/home/foo/Documents/Pictures/My Holiday");
|
|
</I>>>><i>
|
|
</I>>>><i> Where in c# I'm forced to escape the space -> "My\ Holiday"
|
|
</I>>>><i>
|
|
</I>>>><i> Ian
|
|
</I>>>><i>
|
|
</I>>>><i> _______________________________________________
|
|
</I>>>><i> Mono-devel-list mailing list
|
|
</I>>>><i> <A HREF="http://lists.ximian.com/mailman/listinfo/mono-devel-list">Mono-devel-list at lists.ximian.com</A>
|
|
</I>>>><i> <A HREF="http://lists.ximian.com/mailman/listinfo/mono-devel-list">http://lists.ximian.com/mailman/listinfo/mono-devel-list</A>
|
|
</I>>>><i>
|
|
</I>>>><i>
|
|
</I>><i>
|
|
</I>><i> _______________________________________________
|
|
</I>><i> Mono-devel-list mailing list
|
|
</I>><i> <A HREF="http://lists.ximian.com/mailman/listinfo/mono-devel-list">Mono-devel-list at lists.ximian.com</A>
|
|
</I>><i> <A HREF="http://lists.ximian.com/mailman/listinfo/mono-devel-list">http://lists.ximian.com/mailman/listinfo/mono-devel-list</A>
|
|
</I>><i>
|
|
</I>><i>
|
|
</I>-------------- next part --------------
|
|
An HTML attachment was scrubbed...
|
|
URL: <<A HREF="http://lists.ximian.com/pipermail/mono-devel-list/attachments/20130610/e8736642/attachment-0001.html">http://lists.ximian.com/pipermail/mono-devel-list/attachments/20130610/e8736642/attachment-0001.html</A>>
|
|
</PRE>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!--endarticle-->
|
|
<HR>
|
|
<P><UL>
|
|
<!--threads-->
|
|
<LI>Previous message: <A HREF="040511.html">[Mono-dev] sub-process invocation on posix
|
|
</A></li>
|
|
<LI>Next message: <A HREF="040515.html">[Mono-dev] sub-process invocation on posix
|
|
</A></li>
|
|
<LI> <B>Messages sorted by:</B>
|
|
<a href="date.html#40512">[ date ]</a>
|
|
<a href="thread.html#40512">[ thread ]</a>
|
|
<a href="subject.html#40512">[ subject ]</a>
|
|
<a href="author.html#40512">[ author ]</a>
|
|
</LI>
|
|
</UL>
|
|
|
|
<hr>
|
|
<a href="http://lists.ximian.com/mailman/listinfo/mono-devel-list">More information about the Mono-devel-list
|
|
mailing list</a><br>
|
|
</body></html>
|