How can a FreeBasic program set a variable in windows batch file ?

Windows specific questions.
maTTse
Posts: 2
Joined: Mar 19, 2021 23:32

How can a FreeBasic program set a variable in windows batch file ?

Post by maTTse »

Hi!

I'm a novice programmer and I would like to create a CLI utility to provide Windows cmd.exe interpreter a simple string management tool.
My problem is: how can I return the result to the calling script?
(1)

Code: Select all

Errorlevel
isn't suitable for strings.
(2) The technique based on:
- Writing of a file '

Code: Select all

result.bat
' containing a command like

Code: Select all

set myVar = what_the_utility_returned
and after calling, it seems a bit naive; probably there exists a more professional way.

Can you, please, provide advices ?
Thanks in anticipation.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by jj2007 »

It's not entirely clear what you want to do. Something like this maybe?
FB:

Code: Select all

Shell "setenv.bat Hello"
Sleep
setenv.bat:

Code: Select all

@echo off
set NewVar=%1
echo The variable NewVar is "%NewVar%"
marcov
Posts: 3454
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by marcov »

The crucial line in the code below is the for /f line that captures the result of the dumptime call. The EnableDelayedExpansion might also be necessary, and this is a .cmd not a .bat, dunno if that matters.

dumptime is a simple program that works as a stopwatch. SET <xx> stores a timestamp in file <xx>; GET <xx> gets the timestamp in file <xx>, calculates the difference with NOW and prints it in hh:mm:ss format. It is not really important for this bit, except that it prints to something to stdout.

Code: Select all

@ECHO OFF
set dumptime=c:\usr\dumptime.exe
set %BITS%=32
setlocal EnableDelayedExpansion

if exist %DUMPTIME% (
echo settime
%DUMPTIME% set %temp%\stdbuild%BITS%.txt
type %temp%\stdbuild%BITS%.txt
)
timeout 9

set THETIME=
for /f "delims=#" %%i in ('%DUMPTIME% get %temp%\stdbuild%BITS%.txt') do set THETIME=%%i
echo Ok, building and installing took %THETIME%

echo %THETIME%
Last edited by marcov on Mar 20, 2021 22:02, edited 1 time in total.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by dodicat »

Simple find and replace within the batch file.

Code: Select all


#Include "file.bi"

Function SAR(s0 As String,s1 As String,s2 As String) As String 'SearchAndReplace s1 with s2 in s0
      Dim s As String=s0
      Var position=Instr(s,s1)
      While position>0
            s=Mid(s,1,position-1) & s2 & Mid(s,position+Len(s1))
            position=Instr(position+Len(s2),s,s1)
      Wend
      SAR=s
End Function

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

Function loadfile(file As String) As String
	If Fileexists(file)=0 Then Print file;" not found":Sleep:End
      Dim As Long  f=Freefile
      Open file For Binary Access Read As #f
      Dim As String text
      If Lof(f) > 0 Then
            text = String(Lof(f), 0)
            Get #f, , text
      End If
      Close #f
      Return text
End Function

Dim As String batchfile="batch.bat"

Dim As String s="dir /w"

savefile(batchfile,s)

Shell batchfile

print
print "-------  CHANGE INSTRUCTION from /w to /b ---------"
s=loadfile(batchfile)
Var g=SAR(s,"/w","/b")
savefile(batchfile,g)

Shell batchfile

kill batchfile
print
print iif(fileexists(batchfile),"Delete batch.bat manually","OK, batch.bat has been deleted")

Sleep


 
Maybe it is too simple.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by dodicat »

shell versus environ, (into strings)

Code: Select all

dim as string s(1 to 31)

s(1)="ALLUSERSPROFILE   Local returns the location of the All Users Profile."
s(2)="APPDATA   Local returns the location where applications store data by default."
s(3)="CD   Local returns the current directory string."
s(4)="CMDCMDLINE   Local returns the exact command line used to start the current cmd.exe."
s(5)="CMDEXTVERSION   System returns the version number of the current Command Processor Extensions."
s(6)="COMPUTERNAME   System returns the name of the computer."
s(7)="COMSPEC   System returns the exact path to the command shell executable."
s(8)="DATE   System returns the current date. This variable uses the same format as the date /t command. Cmd.exe generates this variable. For more information about the date command, see the Date command."
s(9)="ERRORLEVEL   System returns the error code of the most recently used command. A non-0 value usually indicates an error."
s(10)="HOMEDRIVE   System returns which local workstation drive letter is connected to the user's home directory. This variable is set based on the value of the home directory. The user's home directory is specified in Local Users and Groups."
s(11)="HOMEPATH   System returns the full path of the user's home directory. This variable is set based on the value of the home directory. The user's home directory is specified in Local Users and Groups."
s(12)="HOMESHARE   System returns the network path to the user's shared home directory. This variable is set based on the value of the home directory. The user's home directory is specified in Local Users and Groups."
s(13)="LOGONSEVER   Local returns the name of the domain controller that validated the current logon session."
s(14)="NUMBER_OF_PROCESSORS   System specifies the number of processors installed on the computer."
s(15)="OS   System returns the OS name. Windows XP and Windows 2000 display the OS as Windows_NT."
s(16)="PATH   System specifies the search path for executable files."
s(17)="PATHEXT   System returns a list of the file extensions that the OS considers to be executable."
s(18)="PROCESSOR_ARCHITECTURE   System returns the processor's chip architecture. Values: x86, IA64."
s(19)="PROCESSOR_IDENTFIER   System returns a description of the processor."
s(20)="PROCESSOR_LEVEL   System returns the model number of the computer's processor."
s(21)="PROCESSOR_REVISION   System returns the revision number of the processor."
s(22)="PROMPT   Local returns the command-prompt settings for the current interpreter. Cmd.exe generates this variable."
s(23)="RANDOM   System returns a random decimal number between 0 and 32767. Cmd.exe generates this variable."
s(24)="SYSTEMDRIVE   System returns the drive containing the Windows root directory (i.e., the system root)."
s(25)="SYSTEMROOT   System returns the location of the Windows root directory."
s(26)="TEMP or TMP   System and User return the default temporary directories for applications that are available to users who are currently logged on. Some applications require TEMP and others require TMP."
s(27)="TIME   System returns the current time. This variable uses the same format as the time /t command. Cmd.exe generates this variable. For more information about the time command, see the Time command."
s(28)="USERDOMAIN   Local returns the name of the domain that contains the user's account."
s(29)="USERNAME   Local returns the name of the user currently logged on."
s(30)="USERPROFILE   Local returns the location of the profile for the current user."
s(31)="WINDIR   System returns the location of the OS directory."


Function StringSplit(s_in As String,chars As String,result() As String) As Long
    Dim As Long ctr,ctr2,k,n,LC=Len(chars)
    Dim As boolean tally(Len(s_in))
    #macro check_instring()
    n=0
    While n<Lc
        If chars[n]=s_in[k] Then 
            tally(k)=true
            If (ctr2-1) Then ctr+=1
            ctr2=0
            Exit While
        End If
        n+=1
    Wend
    #endmacro
    
    #macro split()
    If tally(k) Then
        If (ctr2-1) Then ctr+=1:result(ctr)=Mid(s_in,k+2-ctr2,ctr2-1)
        ctr2=0
    End If
    #endmacro
    '==================  LOOP TWICE =======================
    For k  =0 To Len(s_in)-1
        ctr2+=1:check_instring()
    Next k
     if ctr=0 then
         if len(s_in) andalso instr(chars,chr(s_in[0])) then ctr=1':b
         end if
    If ctr Then Redim result(1 To ctr): ctr=0:ctr2=0 Else  Return 0
    For k  =0 To Len(s_in)-1
        ctr2+=1:split()
    Next k
    '===================== Last one ========================
    If ctr2>0 Then
        Redim Preserve result(1 To ctr+1)
        result(ctr+1)=Mid(s_in,k+1-ctr2,ctr2)
    End If
   
    Return Ubound(result)
End Function

Function pipeout(Byval s As String="")  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 


redim as string g()
dim as string sh,env
for n as long=1 to 31
    StringSplit(s(n),chr(9,32),g())
    sh=pipeout("echo "+"%"+g(1)+"%")
    env=environ(g(1))
    print "Environment variable = ";s(n)
    print "using shell    ";sh
    print "using environ: ";iif(len(env),env," NO RETURN")   
    print"______________________"
next
print "Done . . ."
sleep

 
  
Last edited by dodicat on Mar 21, 2021 12:07, edited 1 time in total.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by jj2007 »

maTTse wrote:My problem is: how can I return the result to the calling script?
Just a reminder... OP's problem is indeed a real one: he wants a string. I can't see a simple FreeBasic command like Launch$("...") that would allow the calling script or FB program to grab what the called program has to say. There is a 10-year-old thread regarding Open Pipe, perhaps that could point to a solution?
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by dodicat »

OK jj2007, strings to hold the answers, edited the post.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by jj2007 »

dodicat wrote:OK jj2007, strings to hold the answers, edited the post.
error 24: Invalid data types in line 100...
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by dodicat »

jj2007.
I tested 32/64/gas64 with the latest fb.
no errors given.
strange!
Has anybody else tested?
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by fxm »

IIF accepts strings and UDTs since fbc version 0.90.0 (former 0.25.0).
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by jj2007 »

Code: Select all

gcc version 8.1.0 (2018)
FreeBASIC Compiler - Version 1.07.1 (2019-09-27), built for win32 (32bit)
Copyright (C) 2004-2019 The FreeBASIC development team.
standalone
\AllBasics\FreeBasic\tmp\TmpFb.bas(100) error 24: Invalid data types
Tested with 3 versions. It works when commenting out ' print "using environ: ";iif(len(env),env," NO RETURN")
I rolled my own in the meantime, see Grabbing the output of a launched program ;-)
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by fxm »

For me, works with fbc 1.07.0 and fbc 1.08.0.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by dodicat »

To avoid iif, just
print "using environ: ";env
If the result is null then nothing is printed.
I do not have 32 bit + gcc 8.1, but the 64 bit 1.07 gcc 8.1 works OK.
So there must be a bug in the 32 bit gcc 8.1.

Many environ commands don't work, shell seems more powerful.
Here is a raw piped out string.

Code: Select all

Function pipeout(Byval s As String="")  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 as string s=pipeout("tasklist")
print s

sleep 
open pipe uses shell thus tasklist is OK, but environ wont do tasklist.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: How can a FreeBasic program set a variable in windows batch file ?

Post by jj2007 »

I tested it again, and found out it's the infamous BOM bug that is known to affect String() and, as of today, also IIF; see srvaldez's thread Function String don't work if unicode BOM

Besides, without the BOM the code compiles with fbc64.exe -gen gcc -Wc -O2 -s console (FreeBASIC Compiler - Version 1.07.1 (2019-09-27), built for win64 (64bit)) but crashes with an exception; the debugger shows that rbp has a strange value. The crash happens in the line sh=pipeout("echo "+"%"+g(1)+"%"); the following line env=environ(g(1)) crashes, too.

No crash with SARG's version: fbc64_gas64.exe -t 2000 -gen gas64 -g -Wc -O2 -s console works fine, with and without Utf-8 BOM.
Post Reply