Page 1 sur 1

Prototype de Shell Terminal

Publié : dim. 09/oct./2016 12:46
par JohnJohnsonSHERMAN
Voici un de mes derniers projets : un shell intérpréteur de commandes en mode console.
Il suffit d'entrer une commande et le shell l'exécute. Pour l'instant le choix des commandes est encore trés restreint, mais je compte en ajouter par la suite.
Les commandes de bases sont :
  • cmd : ouvre l'invite de commandes Windows (cmd.exe) dans le terminal
  • help : Affiche l'aide
  • clear : Devrait effacer la console avec ClearConsole(), mais ne fait rien
  • date : Affiche la date
  • system : Librairie System
    • name : Donne le nom de l'ordinateur
    • serial : Donne le numéro de série de l'ordinateur
    • username : Renvoie le nom de l'utilisateur connecté
    • cpu : Renvoie le modéle du CPU installé
    • help : Aide de la lib System
  • dir : Librairie Directory
    • home : Affiche le répertoire de l'utilisateur
    • current : Affiche le répertoire courant (équivalent à pwd sous Linux)
    • temporary : Affiche le rép. temporaire
    • set : Change le répertoire de travail (celui du prompt). Il faut préciser entre " le nouveau répertoire : dir.set "nouveau répertoire"
    • help : Affiche l'aide de la lib direrctory
Les commandes seront organisées par librairies, et entrées à la "mode POO". Oui je sais il y en a qui n'aiment pas ca, mais c'est juste pour simplifier l'écriture de mon code. Exemple : system.name renverra le résultat de la fonction PB ComputerName de la librairie System. Exit les trucs du genre system.computer.name.get à la facon du java, ce qui est pour moi imbuvable :P
J'ai ajouté de l'aide sur les commandes en entrant 'help' ou le nom de la lib + '.help'.
Pour l'instant, il n'y a que deux librairies : system et dir (gestion des répertoires, création, suppression, répertoires courants, récursivité).
J'ajouterai par la suite d'autres librairies comme 'file' pour gérer et ouvrir des fichiers, 'date' pour gérer les heures, 'process' pour les processus (pid, liste des process, kill de process), et pourquoi pas 'web' pour ce qui est de l'internet (dl de fichiers, connections, ping...), voire d'autres encore...

A savoir que ce n'est pas un simple wrapper de fonctions pb, c'est plus pour moi un outil de remplacement à cmd que je trouve un peu chiant. Seules les bases étant posées pour l'instant, il n'y a presque rien a voir :mrgreen:

Le code :

Code : Tout sélectionner

prompt$ = "SH_SHELL 1.0 :: "+GetCurrentDirectory()+">"
help$ = ~"Sherman Shell Terminal Help page\nThis is the help of the ShermanShell Terminal.\nUse one of the following commands on the terminal when the prompt is visible on the terminal.\nCommands are :\nexit : Exits the terminal.\nclear : Clears the terminal's screen.\ncmd : Run the Windows's cmd.exe terminal.\nhelp : Displays this page.\n"
help_System$ = ~"System Lib Help\nThis page refers to the help of the System Library Commands in the Sherman Shell Terminal.\nCommands : \nsystem.name\t: returns the name of the current computer.\nsystem.cpu\t: Returns the name of the current used CPU.\nsystem.username : returns the name of the user currently logged on.\nsystem.serial\t: Returns the serial number of this computer.\nsystem.help\t: Displays this page.\n"
help_Directory$= ~"Directory lib Help\nThis page refers to the help of the Directory (dir) library\ndir.home\t:Returns the home directory.\ndir.current\t:Returns the current working directory. Same as 'pwd'.\ndir.temporary\t:Returns the temporary directory.\ndir.set\t:Changes the working directory to the new one (must be typed with \"  before and after).\ndir.help\t:Displays this page.\n"
OpenConsole("Sherman Shell Terminal (SHSHELL)")
ConsoleColor(0,7)
PrintN("          (c)ShermanSoftware - Sherman Command-line Terminal           ")
ConsoleColor(7,0)
PrintN("Console initializated. Command-line is now enabled.")


Repeat
  
  Print(prompt$)
  re$ = Input()
  command$ = StringField(re$,1," ")
  param$= StringField(re$,2," ")
  lib$ = StringField(command$,1,".")
  Select lib$
    Case "cmd"
      ExternalProg = RunProgram("cmd.exe","-help","",#PB_Program_Hide | #PB_Program_Open | #PB_Program_Read | #PB_Program_UTF8)
      If ExternalProg
        While ProgramRunning(ExternalProg)
          If AvailableProgramOutput(ExternalProg)
            PrintN(ReadProgramString(ExternalProg))
          EndIf
        Wend
        PrintN("Execution finished")
      Else
        PrintN("Unable to run cmd.exe.")
      EndIf
    Case "exit"
      End
    Case "clear"
      ClearConsole()
    Case "-help"
      PrintN(help$)
    Case "help"
      PrintN(help$)
    Case "-h"
      PrintN(help$)
    Case "date"
      PrintN(FormatDate("%dd/%mm/%yyyy, %hh:%ii:%ss",Date()))
    Case "system"
      Select StringField(re$,2,".")
        Case "name"
          PrintN(ComputerName())
        Case "serial"
          PrintN(ComputerSerialNumber())
        Case "username"
          PrintN(UserName())
        Case "cpu"
          PrintN(CPUName())
        Case "help"
          PrintN(help_System$)
        Default 
          PrintN("This is not a command of the 'system' interface. Please refer to the related help by typing 'system.help' to see the System commands.")
      EndSelect
    Case "pwd"
      PrintN(GetCurrentDirectory())
    Case "dir"
      Select StringField(command$,2,".")
        Case "temporary"
          PrintN(GetTemporaryDirectory())
        Case "current"
          PrintN(GetCurrentDirectory())
        Case "home"
          PrintN(GetHomeDirectory())
        Case "help"
          PrintN(help_Directory$)
        Case "set"
          currentDir$ = StringField(param$,2,~"\"")
          If SetCurrentDirectory(currentDir$)
            PrintN("Working directory changed to '"+currentDir$+"'.")
            prompt$ = "SH_SHELL 1.0 :: "+GetCurrentDirectory()+">"
          Else
            PrintN("Unable to change the working directory to '"+currentDir$+"'. Make sure you entered a real directory name.")
          EndIf
          
        Default
          PrintN("This is not a command of the 'dir' (Directory) interface. To see the list of available commands, please type 'dir.help'.")
      EndSelect
      
    
    Default
      PrintN("'"+re$ + "' is not a command currently available in this terminal. Enter -h or -help for more help about the Sherman Shell Terminal.")
      
  EndSelect
ForEver
Bugs : la redirection de Cmd ne se fait ni en unicode, ni en UTF-8, ni en ASCII, mais dans une Codepage de Microsoft. Donc les caractéres spéciaux ne s'affichent pas.
Le prompt de cmd ne se réaffiche pas tout seul aprés une fonction de cmd.
L'autocomplétion avec Tab ne marche pas non plus.

Re: Prototype de Shell Terminal

Publié : dim. 09/oct./2016 22:34
par PAPIPP
Bonjour JohnJohnsonSHERMAN

EN 2009 j'avais réalisé un prg PUNCH d'aide à MSDOS

Pour obtenir des résultats lisible dans window il faut utiliser OemToChar_(@text$, @text$), pour convertir ASCII (MSDOS) en ANSI

http://msdn.microsoft.com/en-us/library ... S.85).aspx

En ASCII (contrairement donc au mode UNICODE) pas besoin d'allouer une variable pour le résultat,
il suffit de mettre le même pointeur qu'en entrée : OemToChar_(@text$, @text$),
un remplacement octet par octet est effectué dans la chaine passée en premier argument.

Code : Tout sélectionner

;*****************************************************************************
;*
;* PurePunch Contest #3
;*
;* Name     : "Help MSDOS Normal" Aide Msdos Double cliquez sur une ligne
;* Author   : PAPIPP
;* Category : UTIL
;* Date     : 15 / 07 / 09
;*
;*****************************************************************************
;----0---_____1____----2-----_____3____-----4----_____5____-----6----_____7____-
;2345678901234567890123456789012345678901234567890123456789012345678901234567890
Ci$="CMD COMP DATE LABEL MORE PAUSE SORT TIME"
Macro M:Macro : EndMacro:M AGI:AddGadgetItem:EndMacro:#W0=0:#L0=0:#L1=1:#G=2
M RPS :ReadProgramString:EndMacro
:Procedure OW0():
If OpenWindow(#W0, 0, 0, 800, 600, "Dbl Clic")
:ListViewGadget(#L0, 0, 0, 800, 300)
:EditorGadget(#L1, 0, 300, 800, 300,#PB_Editor_ReadOnly)
GadgetToolTip(#L0, "Double Cliquez sur une des ligne pour une aide")
:EndIf
EndProcedure
:Procedure AFCH(Gd,Cm$)
prg=RunProgram("cmd"," /C "+CM$,"",30)
As$=Space($FFFF):ClearGadgetItems(Gd)
:If prg:As$=RPS(prg)
OemToChar_(@as$,@as$)
:AGI(gd,-1,Cm$+" :"+As$)
While ProgramRunning(prg)
:As$ =RPS(prg)
:OemToChar_(@as$,@as$)
;
; Petite remarque sur a fonction OemToChar() :
; [url]http://msdn.microsoft.com/en-us/library/ms647493(VS.85).aspx[/url]
; En ASCII (contrairement donc au mode UNICODE) pas besoin d'allouer une variable pour le résultat,
; il suffit de mettre le même pointeur qu'en entrée : OemToChar_(@text$, @text$),
;  un remplacement octet par octet est effectué dans la chaine passée en premier argument.

:AGI(Gd,-1, As$)
Wend
:EndIf
:EndProcedure
:OW0():Font1 = LoadFont(#PB_Any, "Courier New",8)
SetGadgetFont(#L0, FontID(Font1)):SetGadgetFont(#L1, FontID(Font1))
AFCH(#L0,"Help ")
:Repeat: WWE = WaitWindowEvent()
:Select WWE
:Case #PB_Event_Gadget
:EG = EventGadget():ET = EventType()
:If EG = #L0
 : EL.l=GetGadgetState(#L0)
 :EL$= GetGadgetItemText(#L0, El):Pos= FindString(el$, " ", 1):
 :CMD$=Mid(el$,1,pos-1)
; :If ET = #PB_EventType_LeftClick ;= 0
   If ET=0
    cmd$="Help "+CMD$
   :AFCH(#L1, CMD$)
   EndIf
: If ET=2
     
   If FindString(Ci$,cmd$, 0)=0
     rs=MessageRequester ("EXECUTION DE "+CMD$,"Voulez vous exécutez cette Cmd", #PB_MessageRequester_YesNo )
     If rs=#PB_MessageRequester_Yes
      Texte$ = InputRequester("EXECUTION "+cmd$ , "Complétez la commande", cmd$+" ")
     ; Controler la commande pour éviter les conneries
      cmd$=texte$
     :AFCH(#L1, CMD$)
     EndIf
     Else
     MessageRequester(cmd$+" Interdite"," Cette cmd : "+ cmd$+" bloque le prg",#PB_MessageRequester_Ok)
    EndIf 
 :EndIf
:EndIf
:Case #PB_Event_CloseWindow
:EW = EventWindow()
:If EW = #W0:CloseWindow(#W0)
:Break
:EndIf
:EndSelect
ForEver
; **********************************

A+

Re: Prototype de Shell Terminal

Publié : lun. 10/oct./2016 18:21
par JohnJohnsonSHERMAN
Merci PAPIPP !
Mais du coup en Unicode, il faut utiliser un pointeur si j'ai bien lu?