Author Topic: Pipecom conversion to BAS only (MAJOR UPDATE!)  (Read 14490 times)

0 Members and 1 Guest are viewing this topic.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Pipecom conversion to BAS only (SOLVED!)
« Reply #30 on: February 11, 2021, 10:38:02 pm »
No. At this point, @NOVARSEG , it would be beneficial to you to try googling this yourself.
« Last Edit: February 11, 2021, 10:41:39 pm by SpriggsySpriggs »
Shuwatch!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Pipecom conversion to BAS only (SOLVED!)
« Reply #31 on: February 11, 2021, 10:55:37 pm »
So it works for 64 bit and not for 32 bit.  I'm trying to figure out a way without the compiler directives.

Even with the compiler directives will 64 bit EXE work on 32 bit computer?

No.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: Pipecom conversion to BAS only (SOLVED!)
« Reply #32 on: February 11, 2021, 11:27:26 pm »
google is mostly armchair experts

There is much talent on this forum.  I cant seem to tap into it.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Pipecom conversion to BAS only (SOLVED!)
« Reply #33 on: February 11, 2021, 11:35:34 pm »
@NOVARSEG

How do you think I learned most of what I know about C++ and WinAPI?

Google

&

 
msdn.png


I implore you.... Do some research on Google and the MSDN. IT WORKS
« Last Edit: February 11, 2021, 11:37:38 pm by SpriggsySpriggs »
Shuwatch!

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Pipecom conversion to BAS only (SOLVED!)
« Reply #34 on: February 12, 2021, 01:23:36 am »
DUCKDUCKGO

This message brought to as a public service message from people who don't want a bunch of communists running the planet.

In regard to talent on this forum, I agree, but a lot of that talent is being used on the pursuit of personal projects and work; so there isn't always the time or inclination to teach or contribute everything needed for a novice in a particular area. What I have always seen is people who make an effort, but get stuck at some point, they can usually just post what they have and more than likely, get the advice and help needed to move forward.

I've only done maybe four or five routines to date in Win API. That's enough to get me started, to know where to look, and if I get stuck on something, I would probably get helped by Zach, Dav, or someone else who has worked with something similar. The other thing is, this is a QB64 forum, and although QB64 can take advantage of other languages, not everyone here is an expert, or experienced, in those other languages, at least not to the degree they are in Qb64.
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: Pipecom conversion to BAS only (SOLVED!)
« Reply #35 on: February 12, 2021, 07:53:59 am »
While people are sharing places to learn/research windows api, I thought Id share a resource that has helped me for many years. The site is outdated now, but most api's listed come with great short examples in VB that helped me learn and get them going in QB64: http://allapi.mentalis.org/apilist/apilist.php.

Hey,@Pete, ever used startpage? Its been around a long time too, like duckduckgo (which i also use) , doesnt get much mention for some odd reason.  I get good results when searching for programming examples. My browser likes it.

- Dav
« Last Edit: February 12, 2021, 07:58:26 am by Dav »

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Pipecom conversion to BAS only (MAJOR UPDATE!)
« Reply #36 on: February 12, 2021, 06:55:54 pm »
pipecom is a cross-platform utility for directly obtaining console output in Windows, Mac, and Linux. Previously, one would need to use files.

Below is the current state of pipecom and some basic usage:

For those of you who only need the console output for a given command:
Code: QB64: [Select]
  1. Print pipecom_lite("dir")

If you want exit code, stdout (the output one sees on a successful console app run), and stderr (the output one sees when the console command/app has failed execution):
Code: QB64: [Select]
  1. Dim As Long exit_code
  2. Dim As String cmd, stdout, stderr
  3. cmd = "dir /b *.bas"
  4. exit_code = pipecom(cmd, stdout, stderr)
  5. If stderr <> "" Then
  6.     Print stderr
  7.     Print stdout
  8.  

And the full include:
Code: QB64: [Select]
  1. $If PIPECOM = UNDEFINED Then
  2.     $Let PIPECOM = TRUE
  3.     Function pipecom& (cmd As String, stdout As String, stderr As String)
  4.         stdout = "": stderr = ""
  5.         $If WIN Then
  6.             Type SECURITY_ATTRIBUTES
  7.                 As Long nLength
  8.                 $If 64BIT Then
  9.                     As Long padding
  10.                 $End If
  11.                 As _Offset lpSecurityDescriptor
  12.                 As Long bInheritHandle
  13.                 $If 64BIT Then
  14.                     As Long padding2
  15.                 $End If
  16.             End Type
  17.  
  18.             Type STARTUPINFO
  19.                 As Long cb
  20.                 $If 64BIT Then
  21.                     As Long padding
  22.                 $End If
  23.                 As _Offset lpReserved, lpDesktop, lpTitle
  24.                 As Long dwX, dwY, dwXSize, dwYSize, dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags
  25.                 As Integer wShowWindow, cbReserved2
  26.                 $If 64BIT Then
  27.                     As Long padding2
  28.                 $End If
  29.                 As _Offset lpReserved2, hStdInput, hStdOutput, hStdError
  30.             End Type
  31.  
  32.             Type PROCESS_INFORMATION
  33.                 As _Offset hProcess, hThread
  34.                 As Long dwProcessId
  35.                 $If 64BIT Then
  36.                     As Long padding
  37.                 $End If
  38.             End Type
  39.  
  40.             Const STARTF_USESTDHANDLES = &H00000100
  41.             Const CREATE_NO_WINDOW = &H8000000
  42.  
  43.             Const INFINITE = 4294967295
  44.             Const WAIT_FAILED = &HFFFFFFFF
  45.  
  46.             Declare CustomType Library
  47.                 Function CreatePipe%% (ByVal hReadPipe As _Offset, Byval hWritePipe As _Offset, Byval lpPipeAttributes As _Offset, Byval nSize As Long)
  48.                 Function CreateProcess%% Alias "CreateProcessA" (ByVal lpApplicationName As _Offset, Byval lpCommandLine As _Offset, Byval lpProcessAttributes As _Offset, Byval lpThreadAttributes As _Offset, Byval bInheritHandles As Integer, Byval dwCreationFlags As Long, Byval lpEnvironment As _Offset, Byval lpCurrentDirectory As _Offset, Byval lpStartupInfor As _Offset, Byval lpProcessInformation As _Offset)
  49.                 Function GetExitCodeProcess%% (ByVal hProcess As _Offset, Byval lpExitCode As _Offset)
  50.                 Sub HandleClose Alias "CloseHandle" (ByVal hObject As _Offset)
  51.                 Function ReadFile%% (ByVal hFile As _Offset, Byval lpBuffer As _Offset, Byval nNumberOfBytesToRead As Long, Byval lpNumberOfBytesRead As _Offset, Byval lpOverlapped As _Offset)
  52.                 Function WaitForSingleObject& (ByVal hHandle As _Offset, Byval dwMilliseconds As Long)
  53.             End Declare
  54.  
  55.             Dim As _Byte ok: ok = 1
  56.             Dim As _Offset hStdOutPipeRead, hStdOutPipeWrite, hStdReadPipeError, hStdOutPipeError
  57.             Dim As SECURITY_ATTRIBUTES sa: sa.nLength = Len(sa): sa.lpSecurityDescriptor = 0: sa.bInheritHandle = 1
  58.  
  59.             If CreatePipe(_Offset(hStdOutPipeRead), _Offset(hStdOutPipeWrite), _Offset(sa), 0) = 0 Then
  60.                 pipecom = -1
  61.                 Exit Function
  62.             End If
  63.  
  64.             If CreatePipe(_Offset(hStdReadPipeError), _Offset(hStdOutPipeError), _Offset(sa), 0) = 0 Then
  65.                 pipecom = -1
  66.                 Exit Function
  67.             End If
  68.  
  69.             Dim As STARTUPINFO si
  70.             si.cb = Len(si)
  71.             si.dwFlags = STARTF_USESTDHANDLES
  72.             si.hStdError = hStdOutPipeError
  73.             si.hStdOutput = hStdOutPipeWrite
  74.             si.hStdInput = 0
  75.             Dim As PROCESS_INFORMATION procinfo
  76.             Dim As _Offset lpApplicationName
  77.             Dim As String fullcmd: fullcmd = "cmd /c " + cmd + Chr$(0)
  78.             Dim As String lpCommandLine: lpCommandLine = fullcmd
  79.             Dim As _Offset lpProcessAttributes, lpThreadAttributes
  80.             Dim As Integer bInheritHandles: bInheritHandles = 1
  81.             Dim As Long dwCreationFlags: dwCreationFlags = CREATE_NO_WINDOW
  82.             Dim As _Offset lpEnvironment, lpCurrentDirectory
  83.             ok = CreateProcess(lpApplicationName, _Offset(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, _Offset(si), _Offset(procinfo))
  84.  
  85.             If ok = 0 Then
  86.                 pipecom = -1
  87.                 Exit Function
  88.             End If
  89.  
  90.             HandleClose hStdOutPipeWrite
  91.             HandleClose hStdOutPipeError
  92.  
  93.             Dim As String buf: buf = Space$(4096 + 1)
  94.             Dim As Long dwRead
  95.             While ReadFile(hStdOutPipeRead, _Offset(buf), 4096, _Offset(dwRead), 0) <> 0 And dwRead > 0
  96.                 buf = Mid$(buf, 1, dwRead)
  97.                 GoSub RemoveChr13
  98.                 stdout = stdout + buf
  99.                 buf = Space$(4096 + 1)
  100.             Wend
  101.  
  102.             While ReadFile(hStdReadPipeError, _Offset(buf), 4096, _Offset(dwRead), 0) <> 0 And dwRead > 0
  103.                 buf = Mid$(buf, 1, dwRead)
  104.                 GoSub RemoveChr13
  105.                 stderr = stderr + buf
  106.                 buf = Space$(4096 + 1)
  107.             Wend
  108.  
  109.             Dim As Long exit_code, ex_stat
  110.             If WaitForSingleObject(procinfo.hProcess, INFINITE) <> WAIT_FAILED Then
  111.                 If GetExitCodeProcess(procinfo.hProcess, _Offset(exit_code)) Then
  112.                     ex_stat = 1
  113.                 End If
  114.             End If
  115.  
  116.             HandleClose hStdOutPipeRead
  117.             HandleClose hStdReadPipeError
  118.             If ex_stat = 1 Then
  119.                 pipecom = exit_code
  120.             Else
  121.                 pipecom = -1
  122.             End If
  123.  
  124.             Exit Function
  125.  
  126.             RemoveChr13:
  127.             Dim As Long j
  128.             j = InStr(buf, Chr$(13))
  129.             Do While j
  130.                 buf = Left$(buf, j - 1) + Mid$(buf, j + 1)
  131.                 j = InStr(buf, Chr$(13))
  132.             Loop
  133.             Return
  134.         $Else
  135.             Declare CustomType Library
  136.             Function popen%& (cmd As String, readtype As String)
  137.             Function feof& (ByVal stream As _Offset)
  138.             Function fgets$ (str As String, Byval n As Long, Byval stream As _Offset)
  139.             Function pclose& (ByVal stream As _Offset)
  140.             End Declare
  141.  
  142.             Declare Library
  143.             Function WEXITSTATUS& (ByVal stat_val As Long)
  144.             End Declare
  145.  
  146.             Dim As String pipecom_buffer
  147.             Dim As _Offset stream
  148.  
  149.             Dim buffer As String * 4096
  150.             If _FileExists("pipestderr") Then
  151.             Kill "pipestderr"
  152.             End If
  153.             stream = popen(cmd + " 2>pipestderr", "r")
  154.             If stream Then
  155.             While feof(stream) = 0
  156.             If fgets(buffer, 4096, stream) <> "" And feof(stream) = 0 Then
  157.             stdout = stdout + Mid$(buffer, 1, InStr(buffer, Chr$(0)) - 1)
  158.             End If
  159.             Wend
  160.             Dim As Long status, exit_code
  161.             status = pclose(stream)
  162.             exit_code = WEXITSTATUS(status)
  163.             If _FileExists("pipestderr") Then
  164.             Dim As Integer errfile
  165.             errfile = FreeFile
  166.             Open "pipestderr" For Binary As #errfile
  167.             If LOF(errfile) > 0 Then
  168.             stderr = Space$(LOF(errfile))
  169.             Get #errfile, , stderr
  170.             End If
  171.             Close #errfile
  172.             Kill "pipestderr"
  173.             End If
  174.             pipecom = exit_code
  175.             Else
  176.             pipecom = -1
  177.             End If
  178.         $End If
  179.  
  180.     Function pipecom_lite$ (cmd As String)
  181.         Dim As Long a
  182.         Dim As String stdout, stderr
  183.         a = pipecom(cmd, stdout, stderr)
  184.         If stderr <> "" Then
  185.             pipecom_lite = stderr
  186.         Else
  187.             pipecom_lite = stdout
  188.         End If
« Last Edit: June 24, 2021, 09:19:54 am by SpriggsySpriggs »
Shuwatch!

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Pipecom conversion to BAS only (MAJOR UPDATE!)
« Reply #37 on: February 12, 2021, 08:02:53 pm »
Alright, the bug is fixed. Download and run, my minions!
Shuwatch!

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Pipecom update ($NOPREFIX compatible and precompile checks)
« Reply #38 on: June 13, 2021, 12:07:31 pm »
I've updated pipecom to be $NOPREFIX compatible and use precompiler checks to make sure you don't have issues including it if it is already $INCLUDEd somewhere else in your code.
« Last Edit: June 13, 2021, 12:14:27 pm by SpriggsySpriggs »
Shuwatch!

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Pipecom conversion to BAS only (MAJOR UPDATE!)
« Reply #39 on: June 17, 2021, 05:00:04 pm »
Fixed a bug (from copying and pasting) where a variable wasn't declared.
Shuwatch!

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: Pipecom conversion to BAS only (MAJOR UPDATE!)
« Reply #40 on: June 20, 2021, 04:17:02 pm »
I have this version of pipecom. I am running this on Linux.

I have a program using Zenity as my GUI. I execute pipecom (not the lite one) as I need to know what stderr and stdout is. My program loops and does the Form a second time, based on the selection of the user.

However, pipecom is returning an exit_code of 2, which is causing me headaches.

If I execute pipecom more than once, do I need to kill it before executing it again?

Why would it work correctly the first time through the code and then not any subsequent times?

I have verified that it is not an issue with Zenity (As I executed my commands in the terminal and using SHELL in the program and it works fine).

UPDATE: I've decided to only use pipecom when I am retrieving data from a form. All else I am using the SHELL statement, which works.

« Last Edit: June 20, 2021, 06:47:21 pm by George McGinn »
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Pipecom conversion to BAS only (MAJOR UPDATE!)
« Reply #41 on: June 20, 2021, 06:45:45 pm »
Try using _CLIPBOARD$ to capture the second call and paste it in your terminal
Shuwatch!

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: Pipecom conversion to BAS only (MAJOR UPDATE!)
« Reply #42 on: June 20, 2021, 06:58:41 pm »
I'll take a look at that. Thanks.

Try using _CLIPBOARD$ to capture the second call and paste it in your terminal
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Pipecom conversion to BAS only (bug fix)
« Reply #43 on: June 24, 2021, 09:21:41 am »
I have fixed a bug, mentioned by @George McGinn , that would cause stdout and stderr to be accumulated if reusing the variables for the call. I'm clearing out stdout and stderr before running the code which shouldn't cause this. I'd never experienced this because I was never making multiple calls per code.
Shuwatch!

Marked as best answer by SpriggsySpriggs on August 24, 2021, 10:35:24 am

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Pipecom minor fixes
« Reply #44 on: August 24, 2021, 02:35:08 pm »
Updated pipecom to fix some typos and some incorrect variable declarations. So far, I don't notice any change in behavior so you might not have to download the latest version unless you absolutely want to.
* pipecomqb64.bas (Filesize: 7.66 KB, Downloads: 267)
Shuwatch!