mardi 25 septembre 2012

Clipper - OutputDebugString en Harbour

Parmi mes premiers articles relatifs au développement clipper sous Harbour, l'un me mes principaux problème était l'obtention de message de débuggogage.

Ce problème fut solutionné en mettant en place un fichier "debug" dans lequel j'envoyais les messages par l'intermédiaire d'une fonction DMSG.

Aujourd'hui j'ai amélioré la fonction DMSG avec un simple appel de fonction qui envoi également le message de débogage au Kernel de Windows.
Du coup, je peux tracer les activités de mon programme à l'aide du DebugView de SysInternals :-)
Trop Top!!!

Appel à l'API OutputDebugString
Aussi simple que :

WAPI_OUTPUTDEBUGSTRING( sMsg )

Résultat dans DebugView
Vous pouvez trouvez DebugView en tapant "debugview" dans une recherche Google.
N'oubliez pas de démarrer DebugView en mode Administrateur... sinon vous ne verrez aucun message!

Yes!!!

Harbour et l'API Window
Vous trouverez une liste complète de l'API Windows supportée dans le fichier
c:\hb30\include\HbWin.hbx
A titre d'exemple, voici une liste complète de ce que j'ai trouvé dans ma release 3.0 d'Harbour.
Pour savoir comment les utilisés... il suffit de faire une recherche dans tous les fichiers de c:\hb30\ , il y a généralement des exemples d'utilisation

...
DYNAMIC ANSITOWIDE
DYNAMIC CALLDLL
DYNAMIC CALLDLLBOOL
DYNAMIC CALLDLLTYPED
DYNAMIC CREATEOBJECT
DYNAMIC CREATEOLEOBJECT
DYNAMIC FREELIBRARY
DYNAMIC GETACTIVEOBJECT
DYNAMIC GETDEFAULTPRINTER
DYNAMIC GETLASTERROR
DYNAMIC GETPRINTERS
DYNAMIC GETPROCADDRESS
DYNAMIC LOADLIBRARY
DYNAMIC MESSAGEBOX
DYNAMIC OLE2TXTERROR
DYNAMIC OLEERROR
DYNAMIC PRINTEREXISTS
DYNAMIC PRINTERPORTTONAME
DYNAMIC PRINTFILERAW
DYNAMIC SETDEFAULTPRINTER
DYNAMIC SETLASTERROR
DYNAMIC TOLEAUTO
DYNAMIC WAPI_ABORTDOC
DYNAMIC WAPI_ADDFONTRESOURCEEX
DYNAMIC WAPI_APPENDMENU
DYNAMIC WAPI_ARC
DYNAMIC WAPI_CHECKMENUITEM
DYNAMIC WAPI_CHECKMENURADIOITEM
DYNAMIC WAPI_COMBOBOX_ADDSTRING
DYNAMIC WAPI_CREATEACCELERATORTABLE
DYNAMIC WAPI_CREATEDC
DYNAMIC WAPI_CREATEFONT
DYNAMIC WAPI_CREATEFONTINDIRECT
DYNAMIC WAPI_CREATEHATCHBRUSH
DYNAMIC WAPI_CREATEMENU
DYNAMIC WAPI_CREATEMUTEX
DYNAMIC WAPI_CREATEPEN
DYNAMIC WAPI_CREATEPOPUPMENU
DYNAMIC WAPI_CREATESOLIDBRUSH
DYNAMIC WAPI_CREATEWINDOWEX
DYNAMIC WAPI_DELETEMENU
DYNAMIC WAPI_DESTROYACCELERATORTABLE
DYNAMIC WAPI_DESTROYMENU
DYNAMIC WAPI_DESTROYWINDOW
DYNAMIC WAPI_DIALOGBOXPARAM
DYNAMIC WAPI_DRAWMENUBAR
DYNAMIC WAPI_DRAWTEXT
DYNAMIC WAPI_ELLIPSE
DYNAMIC WAPI_ENABLEMENUITEM
DYNAMIC WAPI_ENABLESCROLLBAR
DYNAMIC WAPI_ENDDIALOG
DYNAMIC WAPI_ENDDOC
DYNAMIC WAPI_ENDPAGE
DYNAMIC WAPI_EXTTEXTOUT
DYNAMIC WAPI_FILLRECT
DYNAMIC WAPI_FINDWINDOW
DYNAMIC WAPI_FORMATMESSAGE
DYNAMIC WAPI_FREELIBRARY
DYNAMIC WAPI_GETACP
DYNAMIC WAPI_GETACTIVEWINDOW
DYNAMIC WAPI_GETBKCOLOR
DYNAMIC WAPI_GETBKMODE
DYNAMIC WAPI_GETCOMMANDLINE
DYNAMIC WAPI_GETCURRENTPROCESS
DYNAMIC WAPI_GETCURRENTPROCESSID
DYNAMIC WAPI_GETCURRENTTHREAD
DYNAMIC WAPI_GETCURRENTTHREADID
DYNAMIC WAPI_GETDESKTOPWINDOW
DYNAMIC WAPI_GETDEVICECAPS
DYNAMIC WAPI_GETDLGITEM
DYNAMIC WAPI_GETDLGITEMTEXT
DYNAMIC WAPI_GETKEYSTATE
DYNAMIC WAPI_GETLASTERROR
DYNAMIC WAPI_GETLONGPATHNAME
DYNAMIC WAPI_GETMAPMODE
DYNAMIC WAPI_GETMENU
DYNAMIC WAPI_GETMENUDEFAULTITEM
DYNAMIC WAPI_GETMENUITEMCOUNT
DYNAMIC WAPI_GETMENUITEMID
DYNAMIC WAPI_GETMENUSTATE
DYNAMIC WAPI_GETMODULEHANDLE
DYNAMIC WAPI_GETOEMCP
DYNAMIC WAPI_GETPROCADDRESS
DYNAMIC WAPI_GETSCROLLINFO
DYNAMIC WAPI_GETSCROLLPOS
DYNAMIC WAPI_GETSCROLLRANGE
DYNAMIC WAPI_GETSHORTPATHNAME
DYNAMIC WAPI_GETSUBMENU
DYNAMIC WAPI_GETSYSTEMDIRECTORY
DYNAMIC WAPI_GETSYSTEMMENU
DYNAMIC WAPI_GETSYSTEMMETRICS
DYNAMIC WAPI_GETTEXTALIGN
DYNAMIC WAPI_GETTEXTCOLOR
DYNAMIC WAPI_GETTEXTFACE
DYNAMIC WAPI_GETWINDOWSDIRECTORY
DYNAMIC WAPI_IMAGELIST_ADD
DYNAMIC WAPI_IMAGELIST_ADDMASKED
DYNAMIC WAPI_IMAGELIST_BEGINDRAG
DYNAMIC WAPI_IMAGELIST_COPY
DYNAMIC WAPI_IMAGELIST_CREATE
DYNAMIC WAPI_IMAGELIST_DESTROY
DYNAMIC WAPI_IMAGELIST_DRAGENTER
DYNAMIC WAPI_IMAGELIST_DRAGLEAVE
DYNAMIC WAPI_IMAGELIST_DRAGMOVE
DYNAMIC WAPI_IMAGELIST_DRAGSHOWNOLOCK
DYNAMIC WAPI_IMAGELIST_DRAW
DYNAMIC WAPI_IMAGELIST_DRAWEX
DYNAMIC WAPI_IMAGELIST_DUPLICATE
DYNAMIC WAPI_IMAGELIST_GETBKCOLOR
DYNAMIC WAPI_IMAGELIST_GETICON
DYNAMIC WAPI_IMAGELIST_GETICONSIZE
DYNAMIC WAPI_IMAGELIST_GETIMAGECOUNT
DYNAMIC WAPI_IMAGELIST_GETIMAGEINFO
DYNAMIC WAPI_IMAGELIST_LOADIMAGE
DYNAMIC WAPI_IMAGELIST_MERGE
DYNAMIC WAPI_IMAGELIST_REMOVE
DYNAMIC WAPI_IMAGELIST_REPLACE
DYNAMIC WAPI_IMAGELIST_REPLACEICON
DYNAMIC WAPI_IMAGELIST_SETBKCOLOR
DYNAMIC WAPI_IMAGELIST_SETDRAGCURSORIMAGE
DYNAMIC WAPI_IMAGELIST_SETICONSIZE
DYNAMIC WAPI_IMAGELIST_SETIMAGECOUNT
DYNAMIC WAPI_INSERTMENU
DYNAMIC WAPI_ISICONIC
DYNAMIC WAPI_ISMENU
DYNAMIC WAPI_ISUSERANADMIN
DYNAMIC WAPI_ISWINDOW
DYNAMIC WAPI_ISZOOMED
DYNAMIC WAPI_LINETO
DYNAMIC WAPI_LOADIMAGE
DYNAMIC WAPI_LOADLIBRARY
DYNAMIC WAPI_LOADMENU
DYNAMIC WAPI_MESSAGEBEEP
DYNAMIC WAPI_MESSAGEBOX
DYNAMIC WAPI_MOVETOEX
DYNAMIC WAPI_MULDIV
DYNAMIC WAPI_OPENMUTEX
DYNAMIC WAPI_OUTPUTDEBUGSTRING
DYNAMIC WAPI_PLAYSOUND
DYNAMIC WAPI_RECTANGLE
DYNAMIC WAPI_RELEASEMUTEX
DYNAMIC WAPI_REMOVEFONTRESOURCEEX
DYNAMIC WAPI_REMOVEMENU
DYNAMIC WAPI_RESETDC
DYNAMIC WAPI_ROUNDRECT
DYNAMIC WAPI_SELECTOBJECT
DYNAMIC WAPI_SETACTIVEWINDOW
DYNAMIC WAPI_SETBKCOLOR
DYNAMIC WAPI_SETBKMODE
DYNAMIC WAPI_SETDLGITEMTEXT
DYNAMIC WAPI_SETERRORMODE
DYNAMIC WAPI_SETFOCUS
DYNAMIC WAPI_SETLASTERROR
DYNAMIC WAPI_SETMAPMODE
DYNAMIC WAPI_SETMENU
DYNAMIC WAPI_SETMENUDEFAULTITEM
DYNAMIC WAPI_SETPROCESSWORKINGSETSIZE
DYNAMIC WAPI_SETSCROLLINFO
DYNAMIC WAPI_SETSCROLLPOS
DYNAMIC WAPI_SETSCROLLRANGE
DYNAMIC WAPI_SETTEXTALIGN
DYNAMIC WAPI_SETTEXTCOLOR
DYNAMIC WAPI_SETWINDOWPOS
DYNAMIC WAPI_SHELLEXECUTE
DYNAMIC WAPI_SHOWSCROLLBAR
DYNAMIC WAPI_SLEEP
DYNAMIC WAPI_STARTDOC
DYNAMIC WAPI_STARTPAGE
DYNAMIC WAPI_TABCTRL_ADDITEM
DYNAMIC WAPI_TABCTRL_ADJUSTRECT
DYNAMIC WAPI_TABCTRL_CREATE
DYNAMIC WAPI_TABCTRL_DELETEALLITEMS
DYNAMIC WAPI_TABCTRL_DELETEITEM
DYNAMIC WAPI_TABCTRL_DESELECTALL
DYNAMIC WAPI_TABCTRL_GETCURFOCUS
DYNAMIC WAPI_TABCTRL_GETCURSEL
DYNAMIC WAPI_TABCTRL_GETEXTENDEDSTYLE
DYNAMIC WAPI_TABCTRL_GETIMAGELIST
DYNAMIC WAPI_TABCTRL_GETITEM
DYNAMIC WAPI_TABCTRL_GETITEMCOUNT
DYNAMIC WAPI_TABCTRL_GETITEMRECT
DYNAMIC WAPI_TABCTRL_GETROWCOUNT
DYNAMIC WAPI_TABCTRL_GETTOOLTIPS
DYNAMIC WAPI_TABCTRL_GETUNICODEFORMAT
DYNAMIC WAPI_TABCTRL_HIGHLIGHTITEM
DYNAMIC WAPI_TABCTRL_HITTEST
DYNAMIC WAPI_TABCTRL_INSERTITEM
DYNAMIC WAPI_TABCTRL_REMOVEIMAGE
DYNAMIC WAPI_TABCTRL_SETCURFOCUS
DYNAMIC WAPI_TABCTRL_SETCURSEL
DYNAMIC WAPI_TABCTRL_SETEXTENDEDSTYLE
DYNAMIC WAPI_TABCTRL_SETIMAGELIST
DYNAMIC WAPI_TABCTRL_SETITEM
DYNAMIC WAPI_TABCTRL_SETITEMEXTRA
DYNAMIC WAPI_TABCTRL_SETITEMSIZE
DYNAMIC WAPI_TABCTRL_SETMINTABWIDTH
DYNAMIC WAPI_TABCTRL_SETPADDING
DYNAMIC WAPI_TABCTRL_SETTOOLTIPS
DYNAMIC WAPI_TABCTRL_SETUNICODEFORMAT
DYNAMIC WAPI_TEXTOUT
DYNAMIC WAPI_TRACKPOPUPMENU
DYNAMIC WAPI_TREEVIEW_CREATEDRAGIMAGE
DYNAMIC WAPI_TREEVIEW_DELETEALLITEMS
DYNAMIC WAPI_TREEVIEW_EDITLABEL
DYNAMIC WAPI_TREEVIEW_ENDEDITLABELNOW
DYNAMIC WAPI_TREEVIEW_ENSUREVISIBLE
DYNAMIC WAPI_TREEVIEW_EXPAND
DYNAMIC WAPI_TREEVIEW_GETBKCOLOR
DYNAMIC WAPI_TREEVIEW_GETCHECKSTATE
DYNAMIC WAPI_TREEVIEW_GETCHILD
DYNAMIC WAPI_TREEVIEW_GETCOUNT
DYNAMIC WAPI_TREEVIEW_GETDROPHILIGHT
DYNAMIC WAPI_TREEVIEW_GETEDITCONTROL
DYNAMIC WAPI_TREEVIEW_GETFIRSTVISIBLE
DYNAMIC WAPI_TREEVIEW_GETIMAGELIST
DYNAMIC WAPI_TREEVIEW_GETINDENT
DYNAMIC WAPI_TREEVIEW_GETINSERTMARKCOLOR
DYNAMIC WAPI_TREEVIEW_GETISEARCHSTRING
DYNAMIC WAPI_TREEVIEW_GETITEM
DYNAMIC WAPI_TREEVIEW_GETITEMHEIGHT
DYNAMIC WAPI_TREEVIEW_GETITEMRECT
DYNAMIC WAPI_TREEVIEW_GETITEMSTATE
DYNAMIC WAPI_TREEVIEW_GETLASTVISIBLE
DYNAMIC WAPI_TREEVIEW_GETLINECOLOR
DYNAMIC WAPI_TREEVIEW_GETNEXTITEM
DYNAMIC WAPI_TREEVIEW_GETNEXTSIBLING
DYNAMIC WAPI_TREEVIEW_GETNEXTVISIBLE
DYNAMIC WAPI_TREEVIEW_GETPARENT
DYNAMIC WAPI_TREEVIEW_GETPREVSIBLING
DYNAMIC WAPI_TREEVIEW_GETPREVVISIBLE
DYNAMIC WAPI_TREEVIEW_GETROOT
DYNAMIC WAPI_TREEVIEW_GETSCROLLTIME
DYNAMIC WAPI_TREEVIEW_GETSELECTION
DYNAMIC WAPI_TREEVIEW_GETTEXTCOLOR
DYNAMIC WAPI_TREEVIEW_GETTOOLTIPS
DYNAMIC WAPI_TREEVIEW_GETUNICODEFORMAT
DYNAMIC WAPI_TREEVIEW_GETVISIBLECOUNT
DYNAMIC WAPI_TREEVIEW_HITTEST
DYNAMIC WAPI_TREEVIEW_INSERTITEM
DYNAMIC WAPI_TREEVIEW_SELECT
DYNAMIC WAPI_TREEVIEW_SELECTDROPTARGET
DYNAMIC WAPI_TREEVIEW_SELECTITEM
DYNAMIC WAPI_TREEVIEW_SELECTSETFIRSTVISIBLE
DYNAMIC WAPI_TREEVIEW_SETBKCOLOR
DYNAMIC WAPI_TREEVIEW_SETCHECKSTATE
DYNAMIC WAPI_TREEVIEW_SETIMAGELIST
DYNAMIC WAPI_TREEVIEW_SETINDENT
DYNAMIC WAPI_TREEVIEW_SETINSERTMARK
DYNAMIC WAPI_TREEVIEW_SETINSERTMARKCOLOR
DYNAMIC WAPI_TREEVIEW_SETITEM
DYNAMIC WAPI_TREEVIEW_SETITEMHEIGHT
DYNAMIC WAPI_TREEVIEW_SETITEMSTATE
DYNAMIC WAPI_TREEVIEW_SETLINECOLOR
DYNAMIC WAPI_TREEVIEW_SETSCROLLTIME
DYNAMIC WAPI_TREEVIEW_SETTEXTCOLOR
DYNAMIC WAPI_TREEVIEW_SETTOOLTIPS
DYNAMIC WAPI_TREEVIEW_SETUNICODEFORMAT
DYNAMIC WAPI_TREEVIEW_SORTCHILDREN
DYNAMIC WAPI_WAITFORMULTIPLEOBJECTS
DYNAMIC WAPI_WAITFORMULTIPLEOBJECTSEX
DYNAMIC WAPI_WAITFORSINGLEOBJECT
DYNAMIC WAPI_WAITFORSINGLEOBJECTEX
DYNAMIC WAPI_WNETGETLASTERROR
DYNAMIC WCE_SIM
DYNAMIC WCE_SIMDEINITIALIZE
DYNAMIC WCE_SIMDELETEPHONEBOOKENTRY
DYNAMIC WCE_SIMINITIALIZE
DYNAMIC WCE_SIMPHONEBOOKSTATUS
DYNAMIC WCE_SIMREADPHONEBOOKENTRY
DYNAMIC WCE_SIMWRITEPHONEBOOKENTRY
DYNAMIC WCE_SMSSENDMESSAGE
DYNAMIC WIDETOANSI
DYNAMIC WIN_ABORTDOC
DYNAMIC WIN_ANSITOWIDE
DYNAMIC WIN_ARC
DYNAMIC WIN_AXGETCONTROL
DYNAMIC WIN_AXINIT
DYNAMIC WIN_BITMAPDIMENSIONS
DYNAMIC WIN_BITMAPISSUPPORTED
DYNAMIC WIN_BITMAPSOK
DYNAMIC WIN_BITMAPTYPE
DYNAMIC WIN_BMP
DYNAMIC WIN_COM
DYNAMIC WIN_COMCLOSE
DYNAMIC WIN_COMDEBUGDCB
DYNAMIC WIN_COMDTRFLOW
DYNAMIC WIN_COMERROR
DYNAMIC WIN_COMERRORCLEAR
DYNAMIC WIN_COMFUNCLAST
DYNAMIC WIN_COMISVALID
DYNAMIC WIN_COMOPEN
DYNAMIC WIN_COMPURGE
DYNAMIC WIN_COMQUEUESTATUS
DYNAMIC WIN_COMREAD
DYNAMIC WIN_COMRECV
DYNAMIC WIN_COMRTSFLOW
DYNAMIC WIN_COMSETDTR
DYNAMIC WIN_COMSETQUEUESIZE
DYNAMIC WIN_COMSETRTS
DYNAMIC WIN_COMSETTIMEOUTS
DYNAMIC WIN_COMSTATUS
DYNAMIC WIN_COMWRITE
DYNAMIC WIN_COMXONXOFFFLOW
DYNAMIC WIN_CREATEDC
DYNAMIC WIN_CREATEFONT
DYNAMIC WIN_DELETEDC
DYNAMIC WIN_DRAWBITMAP
DYNAMIC WIN_ELLIPSE
DYNAMIC WIN_ENDDOC
DYNAMIC WIN_ENDPAGE
DYNAMIC WIN_ENUMFONTS
DYNAMIC WIN_FILLRECT
DYNAMIC WIN_GETCHARSIZE
DYNAMIC WIN_GETCOMMANDLINEPARAM
DYNAMIC WIN_GETDEVICECAPS
DYNAMIC WIN_GETDOCUMENTPROPERTIES
DYNAMIC WIN_GETEXEFILENAME
DYNAMIC WIN_GETOPENFILENAME
DYNAMIC WIN_GETPRINTERFONTNAME
DYNAMIC WIN_GETSAVEFILENAME
DYNAMIC WIN_GETTEXTSIZE
DYNAMIC WIN_HINSTANCE
DYNAMIC WIN_HIWORD
DYNAMIC WIN_HPREVINSTANCE
DYNAMIC WIN_LINETO
DYNAMIC WIN_LOADBITMAPFILE
DYNAMIC WIN_LOADRESOURCE
DYNAMIC WIN_LOWORD
DYNAMIC WIN_MAPISENDMAIL
DYNAMIC WIN_N2P
DYNAMIC WIN_NCMDSHOW
DYNAMIC WIN_OLEAUTO
DYNAMIC WIN_OLEAUTO___ONERROR
DYNAMIC WIN_OLEAUTO___OPINDEX
DYNAMIC WIN_OLECREATEOBJECT
DYNAMIC WIN_OLEERROR
DYNAMIC WIN_OLEERRORTEXT
DYNAMIC WIN_OLEGETACTIVEOBJECT
DYNAMIC WIN_OSIS2000
DYNAMIC WIN_OSIS2000ORUPPER
DYNAMIC WIN_OSIS2003
DYNAMIC WIN_OSIS7
DYNAMIC WIN_OSIS95
DYNAMIC WIN_OSIS98
DYNAMIC WIN_OSIS9X
DYNAMIC WIN_OSISME
DYNAMIC WIN_OSISNT
DYNAMIC WIN_OSISNT351
DYNAMIC WIN_OSISNT4
DYNAMIC WIN_OSISTSCLIENT
DYNAMIC WIN_OSISVISTA
DYNAMIC WIN_OSISVISTAORUPPER
DYNAMIC WIN_OSISWINXPORUPPER
DYNAMIC WIN_OSISXP
DYNAMIC WIN_OSNETREGOK
DYNAMIC WIN_OSNETVREDIROK
DYNAMIC WIN_OSVERSIONINFO
DYNAMIC WIN_P2N
DYNAMIC WIN_PRINTDLGDC
DYNAMIC WIN_PRINTEREXISTS
DYNAMIC WIN_PRINTERGETDEFAULT
DYNAMIC WIN_PRINTERLIST
DYNAMIC WIN_PRINTERPORTTONAME
DYNAMIC WIN_PRINTERSETDEFAULT
DYNAMIC WIN_PRINTERSTATUS
DYNAMIC WIN_PRINTFILERAW
DYNAMIC WIN_PRN
DYNAMIC WIN_RECTANGLE
DYNAMIC WIN_REGCLOSEKEY
DYNAMIC WIN_REGCREATEKEYEX
DYNAMIC WIN_REGDELETE
DYNAMIC WIN_REGDELETEKEY
DYNAMIC WIN_REGDELETEVALUE
DYNAMIC WIN_REGGET
DYNAMIC WIN_REGOPENKEYEX
DYNAMIC WIN_REGPATHSPLIT
DYNAMIC WIN_REGQUERY
DYNAMIC WIN_REGQUERYVALUEEX
DYNAMIC WIN_REGREAD
DYNAMIC WIN_REGSET
DYNAMIC WIN_REGSETVALUEEX
DYNAMIC WIN_REGWRITE
DYNAMIC WIN_REPORTEVENT
DYNAMIC WIN_RUNDETACHED
DYNAMIC WIN_SERVICEDELETE
DYNAMIC WIN_SERVICEGETSTATUS
DYNAMIC WIN_SERVICEINSTALL
DYNAMIC WIN_SERVICESETEXITCODE
DYNAMIC WIN_SERVICESETSTATUS
DYNAMIC WIN_SERVICESTART
DYNAMIC WIN_SERVICESTOP
DYNAMIC WIN_SETBKMODE
DYNAMIC WIN_SETCOLOR
DYNAMIC WIN_SETDOCUMENTPROPERTIES
DYNAMIC WIN_SETMAPMODE
DYNAMIC WIN_SETPEN
DYNAMIC WIN_SHELLNOTIFYICON
DYNAMIC WIN_SHFILEOPERATION
DYNAMIC WIN_STARTDOC
DYNAMIC WIN_STARTPAGE
DYNAMIC WIN_SYSREFRESH
DYNAMIC WIN_TEXTOUT
DYNAMIC WIN_UNICODE
DYNAMIC WIN_UUIDCREATESTRING
DYNAMIC WIN_WIDETOANSI
DYNAMIC XISPRINTER
DYNAMIC __AXDOVERB
DYNAMIC __AXGETCONTROL
DYNAMIC __AXREGISTERHANDLER
DYNAMIC __OLECREATEOBJECT
DYNAMIC __OLEENUMCREATE
DYNAMIC __OLEENUMNEXT
DYNAMIC __OLEGETACTIVEOBJECT
DYNAMIC __OLEPDISP
DYNAMIC __WAPI_DEVMODE_GET
DYNAMIC __WAPI_DEVMODE_NEW
DYNAMIC __WAPI_DEVMODE_SET
...

lundi 24 septembre 2012

Clipper - Gestion des Hash sous Harbour

Introduction
Les Hash (Hash Table) sont des structures qui, typiquement, permettent d'implémenter des dictionnaires.
Les dictionnaires permettent d'enregistrer des pairs CLE = VALEUR dans une liste... c'est pratique à de nombreux égards.

Le grand avantage d'un dictionnaire, c'est que l'on peut y lire une valeur grâce à une syntaxe simplifiée

ma_valeur := Le_dictionnaire[ "la_cle" ]

Un rapide coup d'oeil sur les fonctions Harbours
Voici quelques bouts de code ci-et-là qui permettent de se familiariser avec les instructions relatives au Hash.

 IF hb_isHash( xData ) .AND. hb_hHasKey( xData, "Today" )
      OutStd( xData[ "Today" ], hb_eol() )
   ENDIF

Il est possible de créer un hash grâce à l'instruction:
hParams := hb_Hash()

Mais j'ai le sentiment que l'instruction suivante produit aussi un Hash:
LOCAL hData := {=>}

Le fichier de compatibilité de Harbour (hbcompat.ch) nous apprend qu'il existe de nombreuses autre fonctions utilitaires autour des Hash:
   #xtranslate hb_HASH([<x,...>])          => HASH(<x>)
   #xtranslate hb_HHASKEY([<x,...>])       => HHASKEY(<x>)
   #xtranslate hb_HPOS([<x,...>])          => HGETPOS(<x>)
   #xtranslate hb_HGET([<x,...>])          => HGET(<x>)
   #xtranslate hb_HSET([<x,...>])          => HSET(<x>)
   #xtranslate hb_HDEL([<x,...>])          => HDEL(<x>)
   #xtranslate hb_HKEYAT([<x,...>])        => HGETKEYAT(<x>)
   #xtranslate hb_HVALUEAT([<x,...>])      => HGETVALUEAT(<x>)
   #xtranslate hb_HVALUEAT([<x,...>])      => HSETVALUEAT(<x>)
   #xtranslate hb_HPAIRAT([<x,...>])       => HGETPAIRAT(<x>)
   #xtranslate hb_HDELAT([<x,...>])        => HDELAT(<x>)
   #xtranslate hb_HKEYS([<x,...>])         => HGETKEYS(<x>)
   #xtranslate hb_HVALUES([<x,...>])       => HGETVALUES(<x>)
   #xtranslate hb_HFILL([<x,...>])         => HFILL(<x>)
   #xtranslate hb_HCLONE([<x,...>])        => HCLONE(<x>)
   #xtranslate hb_HCOPY([<x,...>])         => HCOPY(<x>)
   #xtranslate hb_HMERGE([<x,...>])        => HMERGE(<x>)
   #xtranslate hb_HEVAL([<x,...>])         => HEVAL(<x>)
   #xtranslate hb_HSCAN([<x,...>])         => HSCAN(<x>)
   #xtranslate hb_HSETCASEMATCH([<x,...>]) => HSETCASEMATCH(<x>)
   #xtranslate hb_HCASEMATCH([<x,...>])    => HGETCASEMATCH(<x>)
   #xtranslate hb_HSETAUTOADD([<x,...>])   => HSETAUTOADD(<x>)
   #xtranslate hb_HAUTOADD([<x,...>])      => HGETAUTOADD(<x>)
   #xtranslate hb_HALLOCATE([<x,...>])     => HALLOCATE(<x>)
   #xtranslate hb_HDEFAULT([<x,...>])      => HDEFAULT(<x>)

jeudi 20 septembre 2012

Environnement de developpement graphique + basic sous Ubuntu

C'est en prenant des renseignement sur Laurux (logiciel comptable OpenSource) que je découvre Gambas.

Gambas est un environnement de développement graphique en Basic supporté par les librairies Graphique Qt réputée pour sa grande qualité.



Ressource:

Backup d'une DB PostGreSql Windows avec PgAgent

Cet article présente toutes les étapes de mon périple pour exécuter un backup pg_dump avec pgAgent... y compris celles permettant la résolution des différents problèmes.

Je précise quand même que le backup pg_dump + pgAgent sur Windows Serveur 2008 est fonctionnel ;-)

Ce billet est rédigé en étapes... toutes les étapes par lesquelles je suis passé (dans l'ordre de lecture).
Qui sait, il sera peut être source d'inspiration si un jour vous en avez besoin.

Installation
J'utilise PostgreSQL 9.1, par conséquent, l'installation est des plus simple.
Il suffit d'utiliser l'utilitaire "StackBuilder" de PostgreSql et de selectionner l'utilitaire pgAgent

Commande pg_dump
Commencer par faire fonctionner une tâche de backup en utilisant l'instruction pg_dump
Ensuite, faite le nécessaire pour l'appeler depuis une ligne de commande sur le serveur.
Dans mon cas, j'obtiens la commande batch suivante:

"c:\Program Files\PostgreSQL\9.1\bin\pg_dump.exe" --no-password --host localhost --port 5432 --username "postgres" --role "postgres"  --format tar --blobs --encoding UTF8 --oids --verbose --file "d:\GGBackup\Serveur\StockProd.backup" "stockprod"

La commande pg_dump peut être obtenu à l'aide de l'utilitaire backup de pgAdmin III (qui indique la commande pg_dump à utiliser).
Voir l'article " PostgreSql - Backup et restaure d'une base de donnée" pour plus d'information.

Configuration d'un Job
La fin de l'article "Setting up pgAgent and schedule backup job" de PostGresOnline.com.
Il faut bien entendu stipuler une tâche de type BATCH pour pouvoir exécuter une commande DOS.

Service pgAgent
J'ai quand même eu quelques problèmes pour faire fonctionner mon Job de backup.
Le pire, c'est quand il reste dans l'état "running" alors que le job ne fonctionne visiblement pas.
Savoir qu'il y a un service Windows et pouvoir le démarrer et l'arrêter est une information utile pour gérer l'inattendu.

net stop pgAgent
net start pgAgent

Information utile trouvé sur cet article de Vibhor Kumar

Malheureusement, ma première tâche de backup ne cesse m'indiquer le message "failed" à chaque fois que j'essaye de l'exécuter.

J'ai donc créé une simple tâche qui fait une requête SQL dans une table.
Cette requête est "select * from FILE0050 LIMIT 12".
Malheureusement, cette tâche aussi ne retourne que des erreurs. Le problème est probablement la configuration du service!

pgAgent en mode DEBUG
En cas de problèmes, l'un des options est de démarrer le service en mode DEBUG.


net stop pgAgent


Localiser l'exécutable (qui se trouve en C:\Program Files (x86)\pgAgent\bin sur un système 64 bits).
Exécuter ensuite:


pgAgent.exe DEBUG hostaddr=127.0.0.1 dbname=postgres user=postgres password=xxx


Où xxx est le mot de passe que vous utilisez pour vous connecter sur la DB avec pgAdmin III.
User contient l'identification de l'utilisateur PostgreSql. Attention, il est sensible à la case. Dans mon premier essais j'ai utilisé user=Postgres alors que ma connexion avec pgAdmin III utilise postgres.

Si le nom d'utilisateur (ou mot de passe) est incorrect, vous obtenez un message du genre...
WARNING: Couldn't create the primary connection (attempt 1): FATAL:  authentification par mot de passe ÚchouÚe pour l'utilisateur  ½ Postgres ╗

pgAgent avec log DEBUG

Pour obtenir plus de message de log, il faut ajouter l'option -l 2 .
Cela donne la commande suivante:

pgAgent.exe DEBUG hostaddr=127.0.0.1 dbname=postgres user=postgres password=xxx -l 2

L'exécution en Mode Debug m'apprend que mon Job sql est exécuté mais n'indique pas pourquoi il continue à échouer!

Source de l'information:
  • L'article pgAgent sur Let's Prosgres
Le "Host Agent" du Job
Il semblerait que le paramètre "Host Agent" du job soit vraiment important.
Toujours en suivant les recommandation de l'article pgAgent, j'ai éxécuté la requête suivante sur le serveur.
Une info en provenance de PostgreSql.fr laisse à penser que cela n'est pas forcement utile (voir ce lien).

SELECT jagstation FROM pgagent.pga_jobagent;


pour apprendre que Host Agent devrait valoir exactement:
SERVEUR.home


Une fois le Job modifié et relancé, ma petite tâche SQL continue à échouer... sans plus d'information Arrghhh!?!?


Obtenir les messages d'outputs
Lorsqu'un JOB est exécuté, il est possible de retrouver le message d'output  d'un Step d'exéction du JOB.
En cas d'erreur, cet output peut devenir vraiment très utile.
Pour l'obtenir:
  1. Sélectionner le Step dans le Job
  2. Sélectionner le volet Statistique
  3. Chercher la colonne Output.
Il est également possible d'obtenir la liste des messages d'output exécutés par le l'Agent

SELECT jslid, jsloutput from pgagent.pga_jobsteplog WHERE jslstatus != 's' AND jsloutput != '' ORDER BY jslstart DESC; 

Attention: il faut copier coller le résultat dans notepad pour vraiment voir le message (la cellule est quelques-fois vide dans pgAdmin... pourtant elle contient quelque-chose :-) ).

Ma tâche SQL - toujours en failed mais exécutée!!!
En y regardant de plus près, les statistiques du step (commande SQL) sont à failed mais retourne un "result" de 12.
C'est bien le nombre d'enregistrement retourner par la requête.
La requête est donc bien exécutée... mais est interprétée comme "failed" pour une raison que j'ignore.


En replaçant ma requête sql avec 
   SELECT "HELLO"
le result de la statistique indique "1" (une row).

Le problème est donc ailleurs que dans l'exécution... c'est déjà une bonne nouvelle.

Retour sur ma tâche de backup
La tâche était donc définie comme
"c:\Program Files\PostgreSQL\9.1\bin\pg_dump.exe" --no-password --host localhost --port 5432 --username "postgres" --role "postgres"  --format tar --blobs --encoding UTF8 --oids --verbose --file "d:\GGBackup\Serveur\StockProd.backup" "stockprod"

De l'expérience juste acquise, je peux consulter l'output.
Je note le message d'erreur suivant:

"
C:\Program Files (x86)\pgAgent\bin>"c:\Program Files\PostgreSQL\9.1\bin\pg_dump.exe" --no-password --host localhost --port 5432 --username "postgres" --role "postgres"  --format tar --blobs --encoding UTF8 --oids --verbose --file "d:\GGBackup\Serveur\StockProd.backup" "stockprod"
pg_dump: [programme d'archivage (db)] la connexion à la base de données « stockprod » a échoué : fe_sendauth: no password supplied
pg_dump: *** interrompu du fait d'erreurs
"


C'est donc un problème de mot de passe... pourtant pg_dump.exe n'accepte pas de mot de passe en ligne de commande. Il faut donc absolument l'option --no-password sinon la tâche restera en cours d'exécution (en demandant un mot de passe qui ne peu pas être encoder puisque la session n'est pas interactive!).

Astuce:
L'erreur est plus facile à repérer en utilisant le SQL


SELECT jslid, jsloutput from pgagent.pga_jobsteplog WHERE jslstatus != 's' AND jsloutput != '' ORDER BY jslstart DESC; 

Et en copiant/collant le résultat des cellule (apparemment vide mais pas tellement que cela) dans notepad ;-)

Un password pour mon pg_dump
En se référant à l'article "The password file" de PostgreSql, j'apprends que le fichier pgpass.conf doit se trouver dans le répertoire %APPDATA%\postgresql\pgpass.conf
En vérifiant sur mon Windows Serveur 2008, je trouve le fichier pgpass.conf de l'administrateur dans le répertoire de Roaming.
c:\Users\Administrateur\AppData\Roaming\postgresql\pgpass.conf

Je vais commencer par modifier ce pgpass.conf car je fais des tests en mode DEBUG... et donc avec l'utilisateur interactif qui n'est autre que Administrateur!

Le fichier pgpass.conf d'Administrateur est modifier pour contenir une ligne pour ma DB stockprod.
Ce fichier devient donc:

localhost:5432:postgres:postgres:SECRET
localhost:5432:stockprod:postgres:SECRET

Ensuite, je fais un essai en ligne de commande avec:
"c:\Program Files\PostgreSQL\9.1\bin\pg_dump.exe" --no-password --host localhost --port 5432 --username "postgres" --role "postgres"  --format tar --blobs --encoding UTF8 --oids --verbose --file "d:\GGBackup\Serveur\StockProd.backup" "stockprod"
 
et cette fois, le pg_dump s'exécute immédiatement!

Tester la tâche pg_dump avec pgAgent en DEBUG
Finalement, un dernier essai avec pgAgent en mode DEBUG.
Je démarre le pgAgent en mode DEBUG avec l'instruction:
pgAgent.exe DEBUG hostaddr=127.0.0.1 dbname=postgres user=postgres password=SECRET -l 2

Cette session s'exécute en mode interactif et utilisera donc le pgpass.conf de le l'utilisateur Administrateur.
En utilisant pgAdmin III, on redemande l'exécution de la tâche de Backup.
Cette fois aussi la tâche fonctionne, le backup est créé... même si la tâche est indiquée "failed" (mon pgAgent est certainement en pleine crise d'opposition :-) )

pgpass.conf pour le service pgAgent
Le service pgAgent ne fonctionne pas avec le crédential de l'utilisateur Administrateur mais avec celui de son propre utilisateur Windows. Cet utilisateur qui ne nomme normalement "postgres".
Il faut donc créer le fichier avec un contenu identique (voir ci-dessus).

c:\Users\postgres\AppData\Roaming\postgresql\pgpass.conf 

Un essai avec pgAgent
J'arrête mon pgAgent en mode DEBUG pour ensuite démarrer mon service pgAgent à l'aide de 
NET START pgAgent 
Le service est normalement configuré correctement avec l'utilisateur Windows "postgres", celui utilisé durant l'installation avec StackBuilder.

En utilisant pgAdmin III, on redemande l'exécution de la tâche de Backup.
Cette fois-ci, cette tâche sera exécutée par le service pgAgent.
Maintenant, la tâche de backup fonctionne correctement   YES!!!

Ressources
Proposition d'installation du Service
Au détour de mes lecture, j'ai trouver une instruction d'installation du service pgAgent
“C:\Program Files\PostgreSQL\8.2\bin\pgAgent" INSTALL pgAgent –l 2 -u postgres -p XXXX hostaddr=127.0.0.1 dbname=postgres user=Postgres

Un fichier backup par jour
J'ai aussi trouvé cet autre batch qui crée un fichier de backup différent chaque jour.
Bonne idée que j'exploiterais plus tard.
    @echo off
   for /f "tokens=1-4 delims=/ " %%i in ("%date%") do (
     set dow=%%i
     set month=%%j
     set day=%%k
     set year=%%l
   )
   set datestr=%month%_%day%_%year%
   echo datestr is %datestr%
    
   set BACKUP_FILE=<NameOfTheFile>_%datestr%.backup
   echo backup file name is %BACKUP_FILE%
   SET PGPASSWORD=<PassWord>
   echo on
   bin\pg_dump -i -h <HostName> -p 5432 -U <UserName> -F c -b -v -f %BACKUP_FILE% <DATABASENAME>

Source: Automated Backup on Windows sur le woki de postgresql.org 

Output message d'un JOB
Voici une petite requête SQL permettant d'obtenir les messages d'output d'un Job pgAgent.
Merci à rjuju (sur forums.postgresql.fr).

SELECT jsloutput
FROM pgagent.pga_job j
JOIN pgagent.pga_jobstep js ON jstjobid = jobid
JOIN pgagent.pga_jobsteplog jsl ON jsljstid = jstid
WHERE jobname = 'Test'

jeudi 13 septembre 2012

Informations métriques sur une DB PostgreSql

Voici comment obtenir toute une série d'information utile concernant une ou plusieurs bases de donnée installée sur un serveur PostgreSql

Taille des DB
Taille de toutes les bases de données sur le serveur
select datname,pg_database_size(datname) from pg_database
mais aussi l'espace utilisé par les bases de données
select sum(pg_database_size(datname)) from pg_database

Les tables
Nbre de tables dans une DB
Cette requête est idéale pour évaluer la complexité d'une base de données
select count(*) as TableCount 
from information_schema.tables 
where table_schema not in ('information_schema', 'pg_catalog')

Lister les tables d'une DB
select table_schema, table_name 
from information_schema.tables 
where table_schema not in ('information_schema', 'pg_catalog')

Taille des tables d'une DB
select table_schema, table_name, pg_relation_size('"'||table_name||'"')
from information_schema.tables 
where table_schema not in ('information_schema', 'pg_catalog')

Pourquoi la notation bizarre '"'||table_name||'"' ?
Hé bien parce que j'ai eu la malheur de définir une table avec un lettre capitale (Counters).
Ainsi, l'instruction select pg_relation_size('Counters') m'indique que la table counters n'existe pas.
Par contre, l'intruction select pg_relation_size('"Counters"') retourne le résultat attendu.

Voici une petite version améliorée qui affiche la taille en Ko
select table_schema, table_name, pg_relation_size('"'||table_name||'"')/1024 as Table_size_Kb
from information_schema.tables 
where table_schema not in ('information_schema', 'pg_catalog')

jeudi 6 septembre 2012

PostgreSql - Backup et restaure d'une base de donnée

Voici quelques références relatifs au opérations de backup et restore d'une base de donnée PostgreSql.

Impossible de restaurer un backup créé avec with pgAdmin III

J'ai créé un fichier de backup en utilisant pgAdmin III, mais quand j'ai voulu le restaurer (restore), le bouton OK restait grisé.
pgAdmin III utilise l'outil PostgreSQL nommé pg_restore, ce dernier supporte seulement les formats compressés (COMRESS) et les archives (TAR). Le backup fait avec pg_dump (ou l'interface pgAdmin III doit donc utiliser ces options. Un fichier de backup compressé est alors accepté sans problème par pgAdmin (et le bouton est dégrisé).

Note: le format PLAIN ne peut pas être interprété par pgAdmin III et pg_restore (il peut être édité manuellement et exécuté avec l'outil SQL de pgAdmin III), c'est la raison pour laquelle il n'est pas accepté comme un fichier valide.

Je recommande l'utilisation du format COMPRESS pour les backups journaliers. Le format PLAIN est réservé à aux modifications manuelle avant exécution du SCRIPT. Le format PLAIN à d'ailleurs quelques restrictions (pas les blobs) qui rend se format moins utile pour les tâches de backup standard.

Création du backup
Notez l'encodage en UTF8 (plus répandu).

J'ai activé les OIDs pour avoir les clés numérotés
 Ce backup correspond à la commande sql suivante:

C:/Program Files/PostgreSQL/9.1/bin\pg_dump.exe --host localhost --port 5432 --username "postgres" --role "postgres" --no-password  --format tar --blobs --encoding UTF8 --oids --verbose --file "c:\temp\stockdev.backup" "stockdev"

Restaurer le backup
Le plus simplement du monde, je me suis rendu sur l'autre serveur. J'ai effacé et recréé une DB vide.
Ensuite, j'ai utilisé l'outil de restauration de pgAdminIII avec mon fichier de backup (sans changer aucune option).
Résultat: Nickel !

Ressources

lundi 3 septembre 2012

Pour nos enfants handicapés/différents, A la TEC et à nos ministres je crie mon INDIGNATION

Vous qui passez par là, prenez le temps de lire et de relayer cette information car l'histoire quelle contient est vraie... c'est la notre!

Je vous présente Benjamin
Mon fils Benjamin à 11 ans, issus d'un premier mariage, il est différent... assez pour se faire traiter de Mongole quand il va  au stages normaux durant les vacances.
Pas fortement atteint, les gens ne regardent pas ailleurs quand ils le croise! N'empêche dans sa tête, il est plus proches des huit ans, il additionne difficilement au delà de 10 et a accumulé un retard scolaire conséquent (il est en "2 et 1/2" année primaire pour vous aider à situer ce retard).
Nous avons une chance inouï, j'ai réussi à lui apprendre à lire mais cela ne suffit pas a combler son inconscience et, il faut l'avouer, il reste un peu dans sa bulle.
Malgré nos efforts de structuration, mon fils reste aussi différent d'un point de vue caractériel. Il oscille entre type 8 (retard d'apprentissage) et type 3 (caractériel)... mais c'est le type 8 qui le caractérise administrativement.
Finalement, un point important à ajouter dans ce billet, Benjamin reste atteint d'un trouble psychomoteur important pour vivre en société... il a du mal à se repérer dans le temps et dans l'espace.
Benjamin est donc en enseignement spécial dans une école de Court-Saint-Etienn.
Comme elle est située à 20 minutes de routes (au minimum), c'est la TEC qui prends gratuitement ce déplacement en charge.

Notre cadre de vie
Une semaine sur deux, Benjamin vis avec sa soeur et ses deux demi-frères/soeur en garde alternée.
Pour assumer toutes ces bouches, ma femme et moi travaillons à temps plein. Mon horaire se termine à 18h00 dans mon cas et celui de ma femme à 17h00. Et forcement, nous n'avons pas la chance de travailler tous les deux à "deux pas" de la maison.
Le prix des assurances et de l'essence ne nous permet plus d'avoir deux véhicules. Nous nous débrouillons donc avec une seule voiture.
Qu'elle foire d'empoigne pour satisfaire à nos déplacements, nos employeurs et les exigences de la vie de famille (nous vivons à 6 sous le toit). Quel Rodéo épuisant et pourtant nous nous efforçons de faire au mieux.

La prise en charge du TEC
Le transport de Benjamin, souffrant de son handicap, est prit en charge par la TEC. Mais depuis la première année, nous devons faire face a une forme de mauvais vouloir de la part de cette administration qui essaye sans cesse de comprimer leurs budgets.
Paraît-il que c'est a cause de nos ministres... bien commode de se laver les mains de la sorte.

Donc, chaque année, la rentrée de Septembre est un moment de tension où il faut s'assurer que Benjamin soit bien déposé au pas de la porte (il souffre de problèmes d'orientation et temporel) et nous avons toujours fait au mieux pour qu'il y ait quelqu'un pour l’accueillir.
A ce sujet, je remercie mon beau fils de 14 ans qui coopère beaucoup pour nous aider... à son age, beaucoup d'autres Ado font/impose autre chose quand à l'occupation de leur horaire. Merci Didi!

Mais arranger ce dépôt ne se passe pas sans mal. Nous contactons la TEC (je meurs d'envie de mettre des nom!!!) mais aussi l'école réintroduire un dossier pour que le cas de Benjamin soit correctement prit en compte.
L'année dernière c'est à la gare que l'on voulait déposer mon fils!!!! Un enfant retardé (même légèrement)... inconscient.... et ayant des troubles de l'orientation.
Situation inacceptable à laquelle nous avons échappé de peu... Benjamin ayant encore été déposé chez nous. Et à nous de nous organiser pour le recevoir à des horaires où nous ne savons pas être disponible car "il nous faut bosser pour gagner notre croûte".

Prise en otage pernicieuse
Durant les deux mois de vacances, nous avons reçu un courrier nous indiquant que l'enlèvement se ferait à un autre arrêt de bus.
Pour nous, pas de problème... le plus important étant le retour chez nous... celui que nous avons déjà tant de mal à organiser correctement (pour maintenir un bon cadre de vie... dans les meilleures conditions).
Rien à propos du dépôt donc pas de quoi d’inquiété même si l'on reste échaudé du coup du "dépôt à la gare" de l'année dernière.

Par contre, ce matin, à l’enlèvement, nous avons appris que le dépôt à la maison c'est fini.
Ce sera vers 16h30 à la gare!!!! ça y est, la TEC remet encore cela!!!.
Et lorsque nous contactons la TEC, nous apprenons que le dossier mentionne déjà un dépôt à la gare toute l'année précédente... et donc, difficile pour nous de faire valoir notre bonne foi puisque les éléments en possession de la TEC sont en contradiction avec la réalité. Pratique non?!?!
Paraît-il d'ailleurs que les Type 8 sont maintenant délesté sur des lignes de BUS normal (La TEC affirmant officieusement que c'est l'oeuvre de notre ministre de tutelle... pas de chance pour nous... nous n'avons plus le temps de regarder la télévision depuis longtemps.).
J'ai un peu de mal à accepter cette argumentation en contradiction avec la nécessité social du service!

Pas la gare s'il vous plait!
En ce matin, nous nous battons pour que le lieu de dépôt ne soit pas une gare mais à l'arrêt de bus d'enlèvement, il se trouve à un kilomètre de chez nous.
Ce dernier kilomètre, mon fils devra apprendre à le faire seul, dans la bonne direction et en faisant attention à ne pas se faire renverser... et à ne pas être distrait en traversant.
Le retard apprentissage s'accompagne souvent de trouble de l'attention. Si la Rilatine l'aide, il est des heures où elles ne fait plus effet... comme la fin d'après-midi!!!

Malheureusement pour nous, mon beau fils n'a pas toujours terminé à 16h00 pour aller le chercher à l'arrêt de bus...et nous... et bien nous travaillons pour payer nos impôts, notre maison, notre croûte, etc!
 
Proposition à nos ministres concernés - Emploi, Enseignement et transport - : la solution la plus simple serait peut être encore que je sois chômeur complet indemnisé, en tant que chef de ménage... ce serait peut être plus simple pour tout le monde "non"? Au moins j'aurais le temps d'être là à l'heure imposée, à l'endroit imposé pour prendre mon enfant en charge... au lieu de me crever comme un imbécile 8 heures par jours pour soutenir le système social et me retrouver année après année des situations aussi absurdes que celle-ci! 

La colère et l'indignation
Je suis fâche (les mots qui me passent pas la tête sont... inappropriés). Que me reste t'il d'autre que cela!
Même les animaux sont traités avec plus d'égard. 
Sommes nous donc devenu une sous classe de la société... du genre Cafard que l'on peut écrasé sans autre chose qu'un petit "haut le coeur"?

Ces Messieurs et Mesdames de la TEC, ces Messieurs et Mesdames de la politique, je suis écœuré... et c'est peu dire.

Notre cas, et bien, ce n'est pas grand chose dans notre société de plus de 10 millions d'habitants.
Et nos enfants différents sont une charge pour la société... pour nos politiciens... et pour la TEC.

Et les cas difficiles, tout le monde le sait, c'est mieux de s'en débarrasser vite fait...
La TEC s'y emploi d'ailleurs très bien... année après année... à user administrativement ces parents déjà fatigués par une vie déjà "plus compliquée".
Etes-vous seulement humains?

La vie est déjà bien difficile comme ça. Avec un enfant en handicap (même léger comme mon fils) c'est encore plus difficile. Pas question de simplement rentrer le soir, souper et passer une vie de famille en toute simplicité.
Pourquoi faut-il donc que cela soit rendu encore plus compliqué? Pourquoi charger les affaiblis? Pourquoi cette administration "destructrice" (elle nous nous enfonce dans nos difficultés au lieu de nous aider et nous guider) ?

Et tout ces autres parents
J'ai une pensée pour ces parents, qui comme nous, ont un enfant différent, que l'on menace de déposer dans la nature avec pour seul message "Débrouiller vous parents!".
Le kilomètre que mon fils devra apprendre à parcourir à pied (si on nous le dépose à l'arrêt demandé!), en toute sécurité, sera un vrai challenge pour lui. Pour nous ce sera une inquiétude mordante chaque jours entre 16h30 et 18h00 (le temps que nous rentrions constater sa "survie" après notre travail).

Et dire que notre cas est encore "soft". Je suis certain que de nombreux autres parents sont aussi démunis que nous ce 3 septembre 2012... certains d'entre eux avec des cas et des situations encore plus dramatiques.

Qu'elle est belle ma société...
Qu'ils sont bons à la TEC...
Qu'ils sont bien nos ministres...
    Vous l'aurez compris, c'est l'humour mordant.
    Je suis fatigué de me battre...