Code::Blocks Forums

Developer forums (C::B DEVELOPMENT STRICTLY!) => Plugins development => Topic started by: LETARTARE on February 21, 2012, 04:04:38 pm

Title: Script plugin : IO.Execute(cmd)
Post by: LETARTARE on February 21, 2012, 04:04:38 pm
reference : http://wiki.codeblocks.org/index.php?title=Scripting_commands#IO_namespace (http://wiki.codeblocks.org/index.php?title=Scripting_commands#IO_namespace)
In a script plugin during the use of
Code
local int_err = ::IO.Execute(cmd)
local str_out = ::IO.ExecuteAndGetOutput(cmd)
can not retrieve messages from any errors in 'cmd'
I also propose
Code
local str_error = ::IO.ExecuteAndGetError (cmd)

Is it possible to make this fix ?
Code
Index: src/sdk/scripting/bindings/sc_io.cpp
===================================================================
--- src/sdk/scripting/bindings/sc_io.cpp (révision 7820)
+++ src/sdk/scripting/bindings/sc_io.cpp (copie de travail)
@@ -188,6 +188,16 @@
             return wxExecute(command, output, wxEXEC_NODISABLE);
         }
 
+ wxString ExecuteAndGetError(const wxString& command)
+        {
+            if (!SecurityAllows(_T("Execute"), command))
+                return wxEmptyString;
+            wxArrayString output;
+            wxArrayString error;
+            wxExecute(command, output, error, wxEXEC_NODISABLE);
+            return GetStringFromArray(error, _T("\n"));
+        }
+
         wxString ExecuteAndGetOutput(const wxString& command)
         {
             if (!SecurityAllows(_T("Execute"), command))
@@ -216,7 +226,10 @@
                 staticFunc(&IOLib::RemoveFile, "RemoveFile").
                 staticFunc(&IOLib::WriteFileContents, "WriteFileContents").
                 staticFunc(&IOLib::Execute, "Execute").
+                staticFunc(&IOLib::ExecuteAndGetError, "ExecuteAndGetError").
                 staticFunc(&IOLib::ExecuteAndGetOutput, "ExecuteAndGetOutput").
+
+
                 #endif // NO_INSECURE_SCRIPTS
 
                 staticFunc(&IOLib::GetCwd, "GetCwd").
Title: Re: Script plugin : IO.Execute(cmd)
Post by: MortenMacFly on February 21, 2012, 04:16:11 pm
Is it possible to make this fix ?
Yes, but why don't you change the existing signature to return both: stdout and stderr instead of two? In your case, I would have to launch an application twice to get both messages which is not only lengthy, but may also result in different outputs.
Title: Re: Script plugin : IO.Execute(cmd)
Post by: LETARTARE on February 21, 2012, 04:20:31 pm
yes, but I do not see how, because it returns a single table?
Title: Re: Script plugin : IO.Execute(cmd)
Post by: MortenMacFly on February 21, 2012, 04:41:55 pm
yes, but I do not see how, because it returns a single table?
Well an easy way would be to have a boolean flag for that function "include_errors", which is false by default, and then append (or probably pre-pend) the errors to the string you return if it is true.
Title: Re: Script plugin : IO.Execute(cmd)
Post by: LETARTARE on February 21, 2012, 04:47:12 pm
@ MortenMacFly
thank you, I will try.
Title: Re: Script plugin : IO.Execute(cmd)
Post by: LETARTARE on February 24, 2012, 09:36:11 am
@MortenMacFly
I made many tests on this version with r7822
Code
wxString ExecuteAndGetOutputAndError(const wxString& command)
{
            if (!SecurityAllows(_T("Execute"), command))
                return wxEmptyString;
            wxArrayString output;
            wxArrayString error;
            wxString str_out;
            wxExecute(command, output, error, wxEXEC_NODISABLE);
        // first 'stderr'
            if (!error.IsEmpty())
str_out += _T("stderr :\n") + GetStringFromArray(error, _T("\n"));
   if (!output.IsEmpty())
str_out += _T("stdout :\n") + GetStringFromArray(output, _T("\n"));
            return  str_out;
}
especially for simultaneously 'sdtout' and 'stderr' (the latter with warnings and errors)
I put 'stderr' at the start to test it first.
what do you think?
Title: Re: Script plugin : IO.Execute(cmd)
Post by: MortenMacFly on February 24, 2012, 10:02:44 am
what do you think?
If it works - nice. All I would do (I forgot in the first place) is to have a flag to specify how you want the errors to appear. So the interface could be like:
wxString ExecuteAndGetOutput(const wxString& command, bool prepend_error = true)
This would enable you to get what you want in the order you want (pre-pended / appended).

Besides I'd rather not change the output of the executable by pre-pending "stdout/stderr". Because if you expect a certain output you want to operate on this will screw it otherwise.

EDIT: BTW: I just looked at you patch: I still don't believe you need an additional function. I thought you'd do it by extending the existing one?!
Title: Re: Script plugin : IO.Execute(cmd)
Post by: LETARTARE on February 24, 2012, 12:53:38 pm
@MortenMacFly
Quote
BTW: I just looked at you patch: I still don't believe you need an additional function. I thought you'd do it by extending the existing one?!
I had not read the correction message!, but of course this is possible.
I have considered your suggestion.
In my case 'stderr' can give me an ERROR or just a WARNING without error.
But it is the reading 'stderr' can I know!
If it's only a warning, I also need to read 'stdout'.
If it is an error, 'sdtout' will be empty.
This is why I commented on the 'else'.
In this version, I can either get or not the errors / warnings
With the command, I can always choose to use 'stdout or not

Code
wxString ExecuteAndGetOutputAndError(const wxString& command,  bool prepend_error = false)
{
        if (!SecurityAllows(_T("Execute"), command))
             return wxEmptyString;
        wxArrayString output;
        wxArrayString error;
        wxString str_out;
        wxExecute(command, output, error, wxEXEC_NODISABLE);
        // first 'stderr'
        if (prepend_error && !error.IsEmpty())
str_out += _T("stderr :\n") + GetStringFromArray(error, _T("\n"));
//else
if (!output.IsEmpty())
str_out += _T("stdout :\n") + GetStringFromArray(output, _T("\n"));
            return  str_out;
}
Title: Re: Script plugin : IO.Execute(cmd)
Post by: MortenMacFly on February 24, 2012, 01:07:31 pm
This is why I commented on the 'else'.
I guess there was a slight mis-understanding. What I mean was something like this:

Code
        wxString ExecuteAndGetOutputAndError(const wxString& command,  bool prepend_error = true)
        {
            if (!SecurityAllows(_T("Execute"), command))
                return wxEmptyString;

            wxArrayString output;
            wxArrayString error;
            wxExecute(command, output, error, wxEXEC_NODISABLE);

            wxString str_out;

            if (prepend_error && !error.IsEmpty())
                str_out += GetStringFromArray(error,  _T("\n"));

            if (!output.IsEmpty())
                str_out += GetStringFromArray(output, _T("\n"));

            if (!prepend_error && !error.IsEmpty())
                str_out += GetStringFromArray(error,  _T("\n"));

            return  str_out;
        }
(UNTESTED!)

As you see, I just wanted to give the user an option to append or prepend errors - depending what he believes is the best option to merge stdout and stderr. As errors are generally more important (and if not the user will use ExecuteAndGetOutput anyways) the default setting should be to pre-pend. Also, I skipped _T("stderr :\n") and _T("stdout :\n") as this screws the real output.
Title: Re: Script plugin : IO.Execute(cmd)
Post by: LETARTARE on February 24, 2012, 02:00:20 pm
Actually, I did not understand your intention to 'sdterr' before or after 'stdout'.
I just test it, it works well.
But after the removal of marks separating, I can not separate the flow 'stderr' and 'stdout',
especially in the case or 'stderr' provides me with warnings.
But it's better than nothing.
Thank you very much for your availability.
Especially with the number of patches that you realize right now.
Title: Re: Script plugin : IO.Execute(cmd)
Post by: MortenMacFly on February 24, 2012, 02:16:14 pm
But after the removal of marks separating, I can not separate the flow 'stderr' and 'stdout',
especially in the case or 'stderr' provides me with warnings.
But it's better than nothing.
OK - then provide another boolean parameter like "errors_only" which is false by default but if you enable it it will skip the stdout. This would then be your first solution, but with the advantage, then it can be used for even more than that (special) case. ;-)
Title: Re: Script plugin : IO.Execute(cmd)
Post by: LETARTARE on February 25, 2012, 07:39:26 am
After several tries, I think the best solution would be:
Code
wxString ExecuteAndGetOutputAndError(const wxString& command, bool with_error = false}
{
       if (!SecurityAllows(_T("Execute"), command))
           return wxEmptyString;
       wxArrayString output;
       wxArrayString error;
       wxString str_out;
       wxExecute(command, output, error, wxEXEC_NODISABLE);
       if (with_error && !error.IsEmpty() )
             str_out += GetStringFromArray(error,  _T("\n"));
       if (!output.IsEmpty())
    str_out += GetStringFromArray(output, _T("\n"));

       return  str_out;
}
well it looks like 'ExecuteAndGetOutput (const wxString & command)' plus 'stderr' option.
In 'command' you can always redirect 'stdout to a file and get only' stderr 'on the function.

[attachment deleted by admin]
Title: Re: Script plugin : IO.Execute(cmd)
Post by: MortenMacFly on February 25, 2012, 09:23:01 am
In 'command' you can always redirect 'stdout to a file and get only' stderr 'on the function.
You mean doing something like "mytool.exe 2>nul" is possible with wxExecute? Did you try? If so, then in fact this would be the best solution. :D
Title: Re: Script plugin : IO.Execute(cmd)
Post by: LETARTARE on February 27, 2012, 04:54:44 pm
yes, I tested with 'wxUSE_STREAMS = 1' for 'wxmsw28u_gcc_custom.dll'.
For an external command 'mytool.exe 1> foo.txt',
for an internal command 'cmd / C dir 1> foo.txt'
and I get errors with 'ExecuteAndGetOutputAndError (command, true)'
or the opposite '... 2> err.txt '  and  ' ExecuteAndGetOutputAndError (command) '

Can be simplified by 'ExecuteAndGetOutput (wxString, bool = false)'
without affecting existing programs :
Code
wxString ExecuteAndGetOutput(const wxString& command,  bool with_error = false
{
      if (!SecurityAllows(_T("Execute"), command))
           return wxEmptyString;
      wxArrayString output;
      wxArrayString error;
      wxString str_out;
      wxExecute(command, output, error, wxEXEC_NODISABLE);
      if (with_error && !error.IsEmpty() )
str_out += GetStringFromArray(error,  _T("\n"));
      if (!output.IsEmpty())
str_out += GetStringFromArray(output, _T("\n"));

      return  str_out;
}
Title: Re: Script plugin : IO.Execute(cmd)
Post by: LETARTARE on March 16, 2012, 08:26:20 am
@MortenMacFly
I use this patch since February 27 and I've had no problem on my setup.
Is it possible to integrate it into 'C :: B'?
Good day.
Title: Re: Script plugin : IO.Execute(cmd)
Post by: LETARTARE on June 16, 2012, 11:22:46 am
@MortenMacFly
Thank you for the integration of this function in C::B (svn 8051)
I will test it at some future time.