views:

295

answers:

4

Hello, I am using the code below to start a executable file from a windows service and I need to pass html code (stored in a variable) as an argument. I am escaping with double quotes but this is not working. What do I need to do in order to pass this correctly? Thanks in advance for any guidance that is offered.

Inside the service:

Process.Start(@"E:\Program Files\MyApp.exe", dr["rec"].ToString() +
                                  " \"" + subject + "\" \"" + htmlVar);

and then within MyApp.exe:

static void Main(string[] args)
{
    Program MyProg = new Program();
    MyProg.MyMeth(args[0].ToString(), args[1].ToString(), args[2].ToString());
}

The exe file is just a simple app that handles the sending of emails. dr["rec"].ToString() is the email address of the recipient. The variable "subject" will contain the subject of the email. The variable "htmlVar" could contain anything, divs, images, hyperlinks, etc.. and the html code could be quite lengthy. Should I not be trying to pass this much data as an argument? Thanks again for the help.

+4  A: 

You may need to encode the following characters to make them passable in a command line argument:

  • Double quotes
  • Carriage returns
  • Line feeds
LBushkin
Spaces can cause problems too.
Jared Updike
+1  A: 

From MSDN documentation: http://msdn.microsoft.com/en-us/library/h6ak8zt5.aspx

  // Opens urls and .html documents using Internet Explorer.
   void OpenWithArguments()
   {
      // url's are not considered documents. They can only be opened
      // by passing them as arguments.
      Process.Start("IExplore.exe", "www.northwindtraders.com");

      // Start a Web page using a browser associated with .html and .asp files.
      Process.Start("IExplore.exe", "C:\\myPath\\myFile.htm");
      Process.Start("IExplore.exe", "C:\\myPath\\myFile.asp");
   }

Edit: AaronLS made it a little more clear as to what you're trying to accomplish. to pass multiple arguments

Process myProcess = new Process();
string arg = String.Format("{0} {1}{2}{1} {1}{3}{1}", dr["rec"], '"',htmlVar); 
myProcess.StartInfo.FileName = @"E:\Program Files\MyApp.exe";
myProcess.StartInfo.Arguments = ArgvToCommandLine(new string[] { arg });

myProcess.Start();

The following methods were taken from the MSDN page for ProcessStartInfo arguments: http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.arguments.aspx

 public static string ArgvToCommandLine(IEnumerable<string> args)
    {
        StringBuilder sb = new StringBuilder();
        foreach (string s in args)
        {
            sb.Append('"');
            // Escape double quotes (") and backslashes (\).
            int searchIndex = 0;
            while (true)
            {
                // Put this test first to support zero length strings.
                if (searchIndex >= s.Length)
                {
                    break;
                }
                int quoteIndex = s.IndexOf('"', searchIndex);
                if (quoteIndex < 0)
                {
                    break;
                }
                sb.Append(s, searchIndex, quoteIndex - searchIndex);
                EscapeBackslashes(sb, s, quoteIndex - 1);
                sb.Append('\\');
                sb.Append('"');
                searchIndex = quoteIndex + 1;
            }
            sb.Append(s, searchIndex, s.Length - searchIndex);
            EscapeBackslashes(sb, s, s.Length - 1);
            sb.Append(@""" ");
        }
        return sb.ToString(0, Math.Max(0, sb.Length - 1));
    }
    private static void EscapeBackslashes(StringBuilder sb, string s, int lastSearchIndex)
    {
        // Backslashes must be escaped if and only if they precede a double quote.
        for (int i = lastSearchIndex; i >= 0; i--)
        {
            if (s[i] != '\\')
            {
                break;
            }
            sb.Append('\\');
        }
    }

That's not the most efficient solution to your problem, but I just copied the code so you could see how to properly escape characters that may be present in your htmlvars variable.

Jim Schubert
It's not 100% clear if you're passing HTML or a URL. If you're passing HTML, you'll have to wrap the htmlvar in quotes. And, remember, Process.Start will run this process as you would from the command line. If the quotes don't work from the command line, it won't work from Process.Start
Jim Schubert
@Jim Maybe you reallize this, but the poster didn't say anything at all about Internet Explorer. Whether or not MyApp.exe can handle html, as opposed to url's/paths, is dependent on MyApp.exe's implementation. Although maybe you are recommending to the poster that he try a different approach, assuming he has the ability to change MyApp.exe's implementation? Cheers
AaronLS
@AaronLS: That's copy/pasted from MSDN documentation to demonstrate passing variables to his *.exe. As you can see, you'd call from the command line: `IExplore.exe "C:\myPath\myFile.htm"` while Process.Start apparently handles the quoting of paths for you. My point is that if `htmlVar` contains quotes, his method of relying on Process.Start to wrap the second argument in quotes won't work.
Jim Schubert
Thanks for the responses. @AaronLS/@Jim: the both of you were correct in that I had left off the closing quotes for htmlVar but after correcting this, I am still unable to pass html as an argument. Even a simple string such as "<div style="text-align: center">test</div>" will not pass correctly as it is just dropped. I have tried using String.Replace('"', '\"') thinking that it was the quotes causing it to fail but this does not help either. Any suggestions?
dkirk
+1  A: 

" \"" + subject + "\" \"" + htmlVar

Becomes

"SomeSubject" "SomeHTMLVar

Notice there is no closing quote. Maybe you wanted this:

" \"" + subject + "\" \"" + htmlVar + "\""

AaronLS
+3  A: 

Be careful not to pass too much on the command-line:

I think 2000+ characters is starting to get too long.

Jared Updike