I hate shell

General FreeBASIC programming questions.
deltarho[1859]
Posts: 4308
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

I hate shell

Post by deltarho[1859] »

Well I don't really but when we start to add quotes to a command line with quotes I utter "Oh dear, here we go again." I know about adding chr(34), double quotes, but where is my problem.

This is the command line:

Code: Select all

tasklist /FI "IMAGENAME eq notepad.exe"
I want to shell that and redirect to Running.txt

It is normally hit-and-miss and when I get a hit I wish it had been the first attempt and not the fifteenth, or whatever. <smile>

Any ideas?
deltarho[1859]
Posts: 4308
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

(Solved) Re: I hate shell

Post by deltarho[1859] »

Sorry, I thought that I would at this until Christmas.

One solution:

Code: Select all

Dim As String temp = "IMAGENAME eq notepad.exe"
Shell( "tasklist /FI " + Chr(34) + temp + Chr(34) + " > Running.txt")
With Notepad running I get:
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
notepad.exe 19452 Console 1 13,596 K
and when not running I get

Code: Select all

INFO: No tasks are running which match the specified criteria.
I am not interested in Notepad but that is another story. <smile>
TeeEmCee
Posts: 375
Joined: Jul 22, 2006 0:54
Location: Auckland

Re: I hate shell

Post by TeeEmCee »

If you think it's bad, did you know that cmd.exe (Windows NT) and command.com (Windows 9X) have different rules for how you need to quote/escape filenames when passing them a string to execute? I guess that system() hides that difference.

I tried:

Code: Select all

shell "printcmdline /FI ""IMAGENAME eq notepad.exe"""
and it worked fine: COMMAND(2) is "IMAGENAME eq notepad.exe" (no quotes).

On Unix, the shell splits up the commandline into arguments and passes them to the invoked program, but on Windows each program is responsible for splitting the arguments itself! The C runtime (msvcrt) implements splitting of arguments (the parse_cmdline() internal function) which it passes to main(), but not all Windows programs use msvcrt, so handling of escaping could technically be inconsistent (I don't know if exceptions exist in practice)
deltarho[1859]
Posts: 4308
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: I hate shell

Post by deltarho[1859] »

TeeEmCee wrote:have different rules for how you need to quote/escape filenames when passing them a string to execute?
I didn't know that.

I thought that "" in the middle of a command line and breaking it was still the case even for filenames.

Anyway how do we redirect using your approach? As usual, I have tried a few ways and I am getting nowhere.
angros47
Posts: 2323
Joined: Jun 21, 2005 19:04

Re: I hate shell

Post by angros47 »

I personally think that the SHELL command should be removed (or at least issue a warning message each time it is used), since it is often used improperly.

I saw people using things like:

Code: Select all

SHELL "dir >output.txt"
OPEN "output.txt" FOR INPUT AS #1
...
KILL "output.txt"
(or SHELL "del output.txt" )
Absolutely horrible.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: I hate shell

Post by dodicat »

Shell saves you dipping into windows.bi.
And gives an additional OS tool.
The dos style commands are very powerful and should be treated carefully.
Notwithstanding any of that, I shell and pipe and terminate in windows.

Code: Select all

 


function pipeout(byval s as string="") byref as string
    var f=freefile
    dim as string tmp
    Open Pipe s For Input As #f 
     s=""
    Do Until EOF(f)
    Line Input #f,tmp
    s+=tmp+chr(10)
    Loop
    close #f
    return s
end function



shell(" start notepad.exe ")
 
var list= pipeout( "tasklist /FI  ""IMAGENAME eq notepad.exe""  " )
print list




shell "taskkill /F /IM notepad.exe"

sleep


 
badidea
Posts: 2591
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: I hate shell

Post by badidea »

? !"tasklist /FI \"IMAGENAME eq notepad.exe\""
TeeEmCee
Posts: 375
Joined: Jul 22, 2006 0:54
Location: Auckland

Re: I hate shell

Post by TeeEmCee »

I think the difference between cmd.exe and command.com only matters if you're invoking them directly by calling cmd or command. But if you think *that's* bad, it turns out that the winapi OpenProcess() call itself behaves very differently on Win NT and 9X when it comes to console (non-gui) mode programs (and the various flags do different things), and there's just no way to hide the difference.

Because of that kind of pain, I recommend using system/SHELL instead of the winapi if you can.
Anyway how do we redirect using your approach? As usual, I have tried a few ways and I am getting nowhere.
Well I forgot to add " > output.txt" to the end of the string. But that's exactly what you did, so I don't know know what you're asking. Anyway I greatly prefer using "" or \" instead of "&CHR(34)&" as you wrote it.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: I hate shell

Post by dodicat »

A key shell and the disadvantages of using escape sequences willy- nilly.
Works on the 64 bit compiler only.
tested on fb 1.7.

Code: Select all


dim as string k= _
!"Set WshShell = CreateObject(""WScript.Shell"")\n" + _
"MsgBox ConvertToKey(WshShell.RegRead(""HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DigitalProductId""))"+ chr(10)+ _
!"Function ConvertToKey(Key)\n" + _
!"Const KeyOffset = 52\n"+ _
!"i = 28\n"+ _
!"Chars = ""BCDFGHJKMPQRTVWXY2346789""\n"+ _
!"Do\n"+_
!"Cur = 0\n" + _
!"x = 14\n"+ _
!"Do\n"+ _
!"Cur = Cur * 256\n"+ _
!"Cur = Key(x + KeyOffset) + Cur\n"+ _
"Key(x + KeyOffset) = (Cur \ 24) And 255"+ chr(10)+ _
!"Cur = Cur Mod 24\n"+ _
!"x = x -1\n"+ _
!"Loop While x >= 0\n"+ _
!"i = i -1\n"+ _
!"KeyOutput = Mid(Chars, Cur + 1, 1) & KeyOutput\n"+ _
!"If (((29 - i) Mod 6) = 0) And (i <> -1) Then\n"+ _
!"i = i -1\n"+ _
!"KeyOutput = ""-"" & KeyOutput\n"+ _
!"End If\n"+ _
!"Loop While i >= 0\n"+ _
!"ConvertToKey = KeyOutput\n"+ _
!"End Function\n"

locate 5
print "Your product key"


Sub savefile(filename As String,p As String)
    Dim As Integer n
    n=Freefile
    If Open (filename For Binary Access Write As #n)=0 Then
        Put #n,,p
        Close
    Else
        Print "Unable to save " + filename
    End If
End Sub


sub runscript(filename as string) 
    shell "cscript.exe /Nologo "+ filename  ' or wscript.exe
end sub


savefile("keycode.vbs",k)
runscript("keycode.vbs")
kill "keycode.vbs"
sleep

 
jdmcbride
Posts: 28
Joined: Aug 06, 2016 16:13

Re: I hate shell

Post by jdmcbride »

Hello to a very old post....

Maybe we just need a new SHELL option. Ideally your should be able to:

dim rc as string
rc = shell("dir /")

And rc being a string, would return the output of the command or the error text if it fails.

Would really be much better!
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: I hate shell

Post by marcov »

jdmcbride wrote:
And rc being a string, would return the output of the command or the error text if it fails.
And how would the user differentiate between those two options?
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: I hate shell

Post by dodicat »

freebasic has an easy pipe method.

Code: Select all


Function Shellout(Byval s As String="") Byref As String
    Var f=Freefile
    Dim As String tmp
    Open Pipe s For Input As #f 
    s=""
    Do Until Eof(f)
        Line Input #f,tmp
        s+=tmp+Chr(10)
    Loop
    Close #f
    Return s
End Function 

dim rc as string
rc = Shellout("dir")

print rc

shellout "dir > myfile.txt"

print
print "Press a key to continue . . ."
sleep
shellout "powershell_ise " + "myfile.txt"


sleep
kill  "myfile.txt"

 
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: I hate shell

Post by marcov »

Same question. How do you know if the executed program/command returns an errorlevel?
jdmcbride
Posts: 28
Joined: Aug 06, 2016 16:13

Re: I hate shell

Post by jdmcbride »

marcov wrote:
jdmcbride wrote:
And rc being a string, would return the output of the command or the error text if it fails.
And how would the user differentiate between those two options?

Dim rc as string to get the text output from the command. Return the string or an error... This would be way much better than the current shell command that just returns a "success" or "fail".

Yeah, you can pipe the output, but it would be so much cleaner to ahve shell do what you want.
paul doe
Moderator
Posts: 1733
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: I hate shell

Post by paul doe »

jdmcbride wrote:...Return the string or an error...
Again: how would you discriminate the two?
Post Reply