1
1
Fork 0
mirror of https://github.com/QB64Official/qb64.git synced 2024-07-16 21:15:15 +00:00
qb64/internal/help/SHELL.md

184 lines
8.2 KiB
Markdown
Raw Normal View History

The [SHELL](SHELL) statement allows a program to run external programs or command line statements in Windows, macOS and Linux.
## Syntax
> [SHELL](SHELL) [DOSCommand$]
> [SHELL](SHELL) [**_DONTWAIT**] [**_HIDE**] [DOSCommand$]
## Description
* If the *DOSCommand$* [STRING](STRING) parameter isn't used, the "command console" is opened and execution is halted until the user closes it manually.
* If [_DONTWAIT](_DONTWAIT) is used, the **QB64** program doesn't wait for the SHELLed program/command to end.
* When the [_HIDE](_HIDE) action is used, the [_CONSOLE](_CONSOLE) window is hidden and screen info can be "redirected" (using redirection characters like >) to a file (recommended).
* Commands are external commands, according to the user's operating system, passed as [STRING](STRING) enclosed in quotes or string variables.
* Commands can be a mixture of [STRING](STRING) and string variables added together using the + [concatenation](concatenation) operator.
* Command text can be in upper or lower case. Use single spacing between items and options.
* **QB64** automatically uses CMD /C when using [SHELL](SHELL), but it is allowed in a command string. Note: CMD alone may lock up program.
* **Note: Some commands may not work without adding CMD /C to the start of the command line.**
* **QB64** program screens will not get distorted, minimized or freeze the program like QBasic full-screen modes would.
* **QB64** can use long path folder names and file names and [SHELL](SHELL) command lines can be longer than 124 characters.
* In Windows, use additional [CHR$](CHR$)(34) quotation marks around folder or file names that contain spaces.
* For other operating systems, both the quotation mark character and the apostrophe can be used to enclose a file name that contains spaces.
* **NOTE: Use [CHDIR](CHDIR) instead of CD as SHELL commands cannot affect the current program path.**
## QBasic
* **QBasic BAS files could be run like compiled programs without returning to the IDE when [SYSTEM](SYSTEM) was used to [END](END) them.**
* A user would invoke it with `SHELL "QB.EXE /L /RUN program.BAS"`
## Example(s)
When working with file or folder names with spaces, add quotation marks around the path and/or file name with [CHR$](CHR$)(34).
```vb
SHELL _HIDE "dir " + CHR$(34) + "free cell.ico" + CHR$(34) + " /b > temp.dir"
SHELL "start Notepad temp.dir" ' display temp file contents in Notepad window
```
> Contents of *temp.dir* text file:
```text
Free Cell.ico
```
Opening a Windows program (Notepad) to read or print a Basic created text file.
```vb
INPUT "Enter a file name to read in Notepad: ", filename$
SHELL "CMD /C start /max notepad " + filename$ ' display in Notepad full screen in XP or NT
'SHELL "start /min notepad /p " + filename$ ' taskbar print using QB64 CMD /C not necessary
```
> *Explanation:* Notepad is an easy program to open in Windows as no path is needed. Windows NT computers, including XP, use CMD /C where older versions of DOS don't require any command reference. The top command opens Notepad in a normal window for a user to view the file. They can use Notepad to print it. The second command places Notepad file in the task-bar and prints it automatically. The filename variable is added by the program using proper spacing.
* **Start** is used to allow a Basic program to run without waiting for Notepad to be closed.
* **/min** places the window into the task-bar. **/max** is full-screen and no option is a normal window.
* Notepads **/p** option prints the file contents, even with USB printers.
Function that returns the program's current working path.
```vb
currentpath$ = Path$ ' function call saves a path for later program use
PRINT currentpath$
FUNCTION Path$
SHELL _HIDE "CD > D0S-DATA.INF" 'code to hide window in **QB64**
OPEN "D0S-DATA.INF" FOR APPEND AS #1 'this may create the file
L% = LOF(1) 'verify that file and data exist
CLOSE #1
IF L% THEN 'read file if it has data
OPEN "D0S-DATA.INF" FOR INPUT AS #1
LINE INPUT #1, line$ 'read only line in file
Path$ = line$ + "\" 'add slash to path so only a filename needs added later
CLOSE #1
ELSE : Path = "" 'returns zero length string if path not found
END IF
KILL "D0S-DATA.INF" 'deleting the file is optional
END FUNCTION
```
> *Explanation:* The **SHELL "CD"** statement requests the current working path. This info is normally printed to the screen, but the **>** pipe character sends the information to the DOS-DATA.INF file instead(**QB64** can use [_HIDE](_HIDE) to not display the DOS window). The function uses the [OPEN](OPEN) FOR [APPEND](APPEND) mode to check for the file and the data([INPUT (file mode)](INPUT-(file-mode)) would create an error if file does not exist). The current path is listed on one line of the file. The file is opened and [LINE INPUT (file statement)](LINE-INPUT-(file-statement)) returns one line of the file text. The function adds a "\" so that the Path$ returned can be used in another file statement by just adding a file name. Save the Path$ to another variable for later use when the program has moved to another directory.
> In **QB64** you can simply use the [_CWD$](_CWD$) statement for the same purpose of the example above.
Determining if a drive or path exists. Cannot use with a file name specification.
```vb
LINE INPUT "Enter a drive or path (no file name): ", DirPath$
IF PathExist%(DirPath$) THEN PRINT "Drive Path exists!" ELSE PRINT "Drive Path does not exist!"
END
FUNCTION PathExist% (Path$)
PathExist% = 0
IF LEN(Path$) = 0 THEN EXIT FUNCTION 'no entry
IF LEN(ENVIRON$("OS")) THEN CMD$ = "CMD /C " ELSE CMD$ = "COMMAND /C "
SHELL _HIDE CMD$ + "If Exist " + Path$ + "\nul echo yes > D0S-DATA.INF"
OPEN "D0S-DATA.INF" FOR APPEND AS #1
IF LOF(1) THEN PathExist% = -1 'yes will be in file if path exists
CLOSE #1
KILL "D0S-DATA.INF" 'delete data file optional
END FUNCTION
```
> *Explanation: IF Exist* checks for the drive path. *\Nul* allows an empty folder at end of path. *Echo* prints **yes** in the file if it exists.
> In **QB64** you can simply use the [_FILEEXISTS](_FILEEXISTS) statement for the same purpose of the example above.
*Snippet 1:* When looking for **printers** this command gives you a file list with the default printer marked as **TRUE**:
```vb
SHELL _HIDE "CMD /C" + "wmic printer get name,default > default.txt"
```
> Created file's text:
```text
Default Name
FALSE Microsoft XPS Document Writer
TRUE HP Photosmart C7200 series
FALSE HP Officejet Pro 8600
FALSE Fax
```
> *Explanation:* [LINE INPUT](LINE-INPUT) could be used to find the printer names as [STRING](STRING) variables.
*Snippet 2:* Here is the code to set the default printer to the "HP Officejet Pro 8600":
```vb
SHELL _HIDE "CMD /C" + "wmic printer where name='HP Officejet Pro 8600' call setdefaultprinter"
```
> After executing this program, and then running the first snippet again, we see the following contents of the text file:
```text
Default Name
FALSE Microsoft XPS Document Writer
FALSE HP Photosmart C7200 series
TRUE HP Officejet Pro 8600
FALSE Fax
```
### More examples
*See examples in:*
* [FILELIST$ (function)](FILELIST$-(function)) (member-contributed file search routine)
* *File Exist* C++ Function that does not create a temp file: [Windows Libraries](Windows-Libraries)
## See Also
* [SHELL (function)](SHELL-(function)), [_SHELLHIDE](_SHELLHIDE)
* [FILES](FILES), [CHDIR](CHDIR), [MKDIR](MKDIR)
* [_CWD$](_CWD$), [_STARTDIR$](_STARTDIR$)
* [_FILEEXISTS](_FILEEXISTS), [_DIREXISTS](_DIREXISTS)
* [RMDIR](RMDIR), [NAME](NAME), [KILL](KILL), [RUN](RUN)
* [_HIDE](_HIDE), [_DONTWAIT](_DONTWAIT)
* [_CONSOLE](_CONSOLE), [$CONSOLE]($CONSOLE)
* [$SCREENHIDE]($SCREENHIDE), [$SCREENSHOW]($SCREENSHOW) (QB64 [Metacommand](Metacommand)s)
* [_SCREENHIDE](_SCREENHIDE), [_SCREENSHOW](_SCREENSHOW)
* [FILELIST$](FILELIST$), [PDS (7.1) Procedures](PDS-(7.1)-Procedures) (member-contributed file list array function)
### Extra reference
* [Windows Libraries](Windows-Libraries)
* [C Libraries](C-Libraries)
* [Windows Printer Settings](Windows-Printer-Settings)