Extra spaces with 'script_editor_argument' causes errors with VS

Posted by WillFa on Thu 15 Jul 2010 08:03 PM — 13 posts, 40,240 views.

USA #0
Hey Nick,

I wanted to check out the Visual Studio 2010 IDE with Lua. using

SetAlphaOption ("script_editor_argument", "/edit '%file'")

so that devenv would recycle the running instance and add a tab. This causes an error in devenv that " /edit 'C:\Users\Me\Documents\Scriptfile.lua'" can't find that file and will not be added.

So it doesn't open the file.

Without /edit, you get multiple instances. /edit works from a cmd prompt.


The Shell can be DL'd from http://www.microsoft.com/downloads/details.aspx?familyid=8E5AA7B6-8436-43F0-B778-00C3BCA733D3&displaylang=en

If you were curious.
Australia Forum Administrator #1
Are you saying the problem is with "<space>/edit", or is the problem that /edit is not recognized? If the problem is just the space, can't you omit it?
USA #2
Okay... looked at the code. Totally bogus guess to the problem before.

  // replace %file
  strArgument.Replace ("%file", strName);

  HINSTANCE hInst = ShellExecute (Frame, _T("open"), m_strScriptEditor, 
            CFormat ("\"%s\"", (LPCTSTR) strArgument),   // quote argument
            NULL, SW_SHOWNORMAL);
in doc.cpp


It's quoting everything.
"/edit C:\Users\Foo\Whatever\Blah.lua"


Amended on Thu 15 Jul 2010 09:40 PM by WillFa
USA #3
That does seem very plausible.
USA #4
In theory

// replace %file
  strArgument.Replace ("%file", "\"%file\""); //Should really check that the user didn't include quotes himself.
  strArgument.Replace ("%file", strName);

  HINSTANCE hInst = ShellExecute (Frame, _T("open"), m_strScriptEditor, 
            CFormat ("%s", (LPCTSTR) strArgument),   // This is unnecessary, but I'm unsure if 
                //strArgument needs to be cast for ShellExecute.
            NULL, SW_SHOWNORMAL);

Would rectify the problem?
Amended on Fri 16 Jul 2010 08:59 AM by WillFa
USA #5
WillFa said:

CFormat ("%s", (LPCTSTR) strArgument),   // This is unnecessary, but I'm unsure if 
    //strArgument needs to be cast for ShellExecute.


It is definitely unneccesary. A CString has an implicit LPCTSTR conversion where applicable; the only reason it's explicitly cast in CFormat is because it uses the varargs construct, which isn't type-safe. You could almost certainly pass in strArgument without any extras and it would work.


// replace %file
  strArgument.Replace ("%file", "\"%file\""); //Should really check that the user didn't include quotes himself.
  strArgument.Replace ("%file", strName);

  HINSTANCE hInst = ShellExecute (Frame, _T("open"), m_strScriptEditor, 
            strArgument,
            NULL, SW_SHOWNORMAL);


Theoretically, yeah, I think that would do it.
Amended on Fri 16 Jul 2010 10:14 AM by Twisol
Australia Forum Administrator #6
Twisol said:

It is definitely unneccesary. A CString has an implicit LPCTSTR conversion where applicable; the only reason it's explicitly cast in CFormat is because it uses the varargs construct, which isn't type-safe.


It's necessary because in a varargs situation it doesn't do the typecast, and it will crash if you don't explicitly cast. This is done all over the place in the code.
USA #7
Nick Gammon said:

Twisol said:

It is definitely unneccesary. A CString has an implicit LPCTSTR conversion where applicable; the only reason it's explicitly cast in CFormat is because it uses the varargs construct, which isn't type-safe.


It's necessary because in a varargs situation it doesn't do the typecast, and it will crash if you don't explicitly cast. This is done all over the place in the code.


I'm talking about removing the CFormat(), because it just does "%s", making CFormat() unneccesary as well as the explicit typecast used therein, as my example shows. ShellExecute doesn't use varargs, and I literally just explained the typecast issue and why the explicit cast was used in your quote. :P
Amended on Fri 16 Jul 2010 10:24 AM by Twisol
Australia Forum Administrator #8
Ah you see I read that in a linear way...

Quote:

Willfa: ... I'm unsure if strArgument needs to be cast for ShellExecute.

Twisol: It is definitely unneccesary.


So I took "it" to mean the cast.
USA #9
Heh, it was a bit muddy all around. I took this:

CFormat ("%s", (LPCTSTR) strArgument)


to be the intended target of the "unneccesary" note, because the "%s" is redundant, so you can just pass strArgument.
Amended on Fri 16 Jul 2010 06:39 PM by Twisol
USA #10
Twisol read it right. I was commenting on the line of code.

I was unsure what CFormat returned, what strArgument was to begin with, and what ShellExecute expected; and I was too tired to look it up so I figured that it'd work as is and the comment would lead to Twisol or Nick knowing a more efficient way. :)
Australia Forum Administrator #11
Well OK I changed it to get rid of the quotes, but I should warn you that I found without them that things like Crimson Editor failed with a path like:


C:\Program Files\MUSHclient\scripts\test.lua


It tried to open two files:


C:\Program
Files\MUSHclient\scripts\test.lua


So I made it do this:


  CString strArgument = m_strScriptEditorArgument;

  if (strArgument.IsEmpty ())
    strArgument = "\"%file\"";          // default

  // replace %file
  strArgument.Replace ("%file", strName);

  HINSTANCE hInst = ShellExecute (Frame, _T("open"), m_strScriptEditor, 
            strArgument,   // quote argument
            NULL, SW_SHOWNORMAL);


So the default behaviour (if you don't use 'script_editor_argument') is to take the supplied file name, and quote it.

However if you use the 'script_editor_argument' feature, then quoting the appropriate part of the string is your job.
USA #12
That sounds perfectly reasonable to me. :)