Le problème est donc d'autoriser l'utilisateur normal à accéder à certains ports, ceux utiles pour la mesure.
La solution que je propose est la suivante :
- écrire et compiler les bibliothèques dynamiques en
tant que «root», qui sera donc le légitime propriétaire
et utilisateur de cette bibliothèque dynamique.
- ensuite, toujours en tant que «root», modifier les droits
d'accès de cette bibliothèque dynamique, en déclarant
que tous les utilisateurs pourront s'en servir, avec les mêmes droits
que «root».
Deux méthodes sont possibles pour donner cette autorisation :
- la méthode «ligne de commande» (Merci à
Georges Khaznadar): si la bibliothèque à utiliser s'appelle
liblxmachine.so, il faut entrer la commande :
chmod 4755 liblxmachine.so
Le nombre mystérieux 4755 signifie que toute personne ayant
droit d'exécution a les mêmes droits que le propriétaire
initial, et que tout utilisateur aura le droit d'exécution.
- la méthode «cliquage de souris» avec les versions
modernes de Linux, comme par exemple Mandrake 8.
En mode graphique, lorsqu'on clique avec le bouton droit de la souris
sur l'icône représentant le fichier liblxmachine.so, on peut
modifier les propriétés de ce fichier, et donc donner les
droits précédents.
Ensuite, après ces opérations faites en tant que «root», les utilisateurs normaux pourront utiliser la bibliothèque liblxmachine.so qui accèdera aux ports de mesure.
library xadestar_linux;
uses
SysUtils,uades1,
Classes;
const NumFuncts = 17;
type array100= array[0..100] of char;
type pdouble=^double;
var memosb:array[0..3]of boolean;
memosad:double;
function ea(n:integer):integer;
var o:integer;
n1,n2:word;
begin
o:=n;
ea:=-777;
if (n=0)or(n=1)then lit_niveau(n1,n2);
case o of 0: ea:=n1;
1: ea:=n2;
2: ades_off;
3: ades_on;
end;
end;
function nea(n:integer):pchar;
var chloc:string[20]; tabcarloc:array[0..20] of char;
begin
str(n,chloc);
if (n<2) and (n>-1)
then strpcopy(tabcarloc,'CAN voie '+chloc)
else if n=2 then strpcopy(tabcarloc,'RAZ pour
impression')
else if n=3 then strpcopy(tabcarloc,'Réinitialisation')
else strpcopy(tabcarloc,'');
nea:=tabcarloc;
end;
function ead(n:integer):double;
var aux:integer;
begin
if (n=0) or (n=1)or (n=2) or (n=3)
then begin
aux:=ea(n);
ead:=(5.0*aux)/1024;
end
else ead:=-777;
end;
function nead(n:integer):pchar;
var chloc:string[20]; tabcarloc:array[0..20] of char;
begin
if (n=0)
then nead:='E. analogique 0'
else if n=1 then nead:='E. analogique
1'
else if n=2 then nead:='RAZ pour
impression'
else if n=3 then nead:='Réinitialisation'
else nead:='';
end;
function sa(n:integer; valeur:integer):integer;
begin
sa:=-777;
end;
function nsa(n:word):pchar;
var tabcarloc:array[0..20] of char;
begin
if n=0 then
nsa:='SA fictive'+chr(0)
else nsa:=''+chr(0);
end;
function sad(n:integer ; valeur:double):double;
begin
MEMOsad:=valeur;
sad:=0;
end;
function nsad(n:integer):pchar;
var tabcarloc:array[0..20] of char;
begin
if n=0 then nsad:='SA fictive'+chr(0)
else nsad:=''+chr(0);
end;
function rsa(n:integer):integer;
begin
if n=0 then rsa:=2 else rsa:=-777;
end;
function rsad(n:integer):double;
begin
if n=0 then rsad:=2 else rsad:=-777;
end;
function eb(n:integer):integer;
begin
if n=0 then eb:=0
else if n=1 then eb:=1
else eb:=-777;
end;
function neb(n:integer):pchar;
var tabcarloc:array[0..20] of char;
begin
if n=0 then neb:='EB fictive 0'+chr(0)
else if n=1 then neb:='EB
fictive 1'+chr(0)
else neb:=chr(0);
end;
Const tabmasque : array[0..7] of byte = (1,2,4,8,16,32,64,128);
memosl1:byte=0;
function testebit(nombre:word ; numbit:byte):boolean;
begin testeBit:=odd(nombre shr numbit);end;
procedure forcebit(var octet :byte ; numbit:byte ; etat:boolean);
begin
if etat then octet :=octet or tabmasque[numbit]
else octet
:=octet and (not tabmasque[numbit]);
end;
function sb(n:integer; etat:integer):integer;
begin
case n of
0..3 : begin relais[n+1]:=(etat=1);
sb:=n*100+etat;
pilote_relais(0);
//forcebit(memosl1,n,(etat=1));
memosb[n]:=(etat=1);
end;
else sb:=-777;
end;
end;
function nsb(n:integer):pchar;
var chloc:string[20]; tabcarloc:array[0..20] of char;
begin
result:=chr(0);
if n=0 then result:='relais A'+chr(0);
if n=1 then result:='relais B'+chr(0);
if n=2 then result:='relais C'+ chr(0);
if n=3 then result:='relais D'+chr(0);
end;
function rsb(n:integer):integer;
begin
(* if n in [0..3]
then if testebit(memosl1,n)
then
rsb:=1
else
rsb:=0
else rsb:=-777 ;
*)
if n in [0..3] then if memosb[n] then rsb:=1 else rsb:=0
else rsb:=-777;
end;
function titre : pchar;
begin titre:='ADES en LPT1:';end;
function detail : pchar;
begin detail:='DLL (32 bits) pour ADES 10 bits en LPT1:, par P.
Dieumegard, le 20 février 2001';end;
(*les deux fonctions qui suivent sont pour EXCEL*)
function peaD(n:integer):pdouble;
var dloc:double;
begin dloc:=eaD(n);pead:=@dloc;end;
function psad(n:integer;valeur:pdouble):pdouble;
var dloc1,dloc2:double;
begin dloc1:=valeur^;dloc2:=SAD(n,dloc1);psad:=@dloc2;end;
(*les fonctions " double " qui suivent sont pour StarOffice*)
function eadouble(x:double):double;
var nloc:word;
begin
nloc:=round(x);
eadouble:=ead(nloc);
end;
function neadouble(x:double):pchar;
var nloc:word;
begin
nloc:=round(x);
neadouble:=nead(nloc);
end;
function sadouble(x:double;xval:double):double;
begin sadouble:=sad(round(x),xval);end;
function nsadouble(x:double):pchar;
begin nsadouble:=nsad(round(x));end;
function rsadouble(x:double):double;
begin rsadouble:=rsad(round(x));end;
function ebdouble(x:double):double;
begin ebdouble:=eb(round(x));end;
function nebdouble(x:double):pchar;
begin nebdouble:=neb(round(x));end;
function sbdouble(n:double;etat:double):double;
begin sbdouble:=sb(round(n),round(etat));end;
function nsbdouble(n:double):pchar;
begin nsbdouble:=nsb(round(n));end;
function rsbdouble(n:double):double;
begin rsbdouble:=rsb(round(n));end;
function ea(n:integer):integer; begin ea:=stdea(n);end;stdcall;
function stdnea(n:integer):pchar; begin stdnea:=nea(n);end;stdcall;
function stdead(n:integer):double; begin stdead:=ead(n);end;stdcall;
function stdnead(n:integer):pchar; begin stdnead:=nead(n);end;stdcall;
function stdsa(n:integer ;valeur:integer):integer;begin stdsa:=sa(n,valeur);end;stdcall;
function stdnsa(n:integer):pchar; begin stdnsa:=nsa(n);end;stdcall;
function stdrsa(n:integer):integer; begin stdrsa:=stdrsa(n);end;stdcall;
function stdsad(n:integer; valeur:double):double; begin stdsad:=sad(n,valeur);end;stdcall;
function stdrsad(n:integer):double; begin stdrsad:=rsad(n);end;stdcall;
function stdeb(n:integer):integer; begin stdeb:=eb(n);end;stdcall;
function stdneb(n:integer):pchar; begin stdneb:=neb(n);end;stdcall;
function stdsb(n:integer;etat:integer):integer; begin stdsb:=sb(n,etat);end;stdcall;
function stdnsb(n:integer):pchar; begin stdnsb:=stdnsb(n);end;stdcall;
function stdrsb(n:integer):integer; begin stdrsb:=stdrsb(n);end;stdcall;
function stdtitre:pchar; begin stdtitre:=titre;end;stdcall;
function stddetail:pchar; begin stddetail:=detail;end;stdcall;
(*stdtitre et stddetail ne sont pas indispensables, car ils
sont sans paramètres*)
(* comme titre et detail*)
exports
ea , nea ,ead ,nead,
sa ,nsa,sad , nsad ,rsa,rsad,
eb , neb , sb , nsb ,rsb,
titre , detail,
pead , psad ,
stdea,stdnea,stdead,stdnead,
stdsa,stdnsa,stdrsa,stdsad,stdnsad,stdrsad,
stdeb,stdneb,stdsb,stdnsb,stdrsb,
eadouble , neadouble ,
sadouble,nsadouble,rsadouble,
ebdouble,nebdouble,
sbdouble, nsbdouble,rsbdouble;
var i:word;
begin
nbitades:=10;
initialise_ades(888);
ades_on;
for i:=0 to 3 do memosb[i]:=false;
end.
(Début de page)
uses
SysUtils,linux,
uades1;
type array100= array[0..100] of char;
type pdouble=^double;
var memosb:array[0..3]of boolean;
memosad:double;
function ea(n:integer):integer; pascal;export;
var o:integer;
n1,n2:word;
begin
o:=n;
ea:=-777;
if (n=0)or(n=1)then lit_niveau(n1,n2);
case o of 0: ea:=n1;
1: ea:=n2;
2: ades_off;
3: ades_on;
end;
end;
Les fonctions de la bibliothèque sont identiques à celles
de Kylix, mais à la fin, il faut ajouter une ligne pour donner le
droit d'accéder aux ports :
var i:word;
begin
ioperm(888,3,1);
nbitades:=10;
initialise_ades(888);
ades_on;
for i:=0 to 3 do memosb[i]:=false;
end.
La ligne ioperm(888,3,1) signifie «permettre l'entrée et
la sortie d'information à partir de l'adresse de port 888 (qui est
l'adresse de base de l'interface parallèle utilisée par ADES),
sur 3 octets successifs (l'adresse de lecture et d'écriture d'information
sont deux adresses successives)». Cette instruction ioperm sera à
utiliser pour tous les appareils de mesure devant accéder aux ports,
avec bien sûr des valeurs différentes selon les ports à
utiliser.
Cette bibliothèque a été rendue possible grâce aux renseignements fournis sur le site http://www.wachtler.de/dynamischeBibliotheken.
extern "C" int stdea(int n)
{ if (n>-1&&n<3) {return n*3;}else {return -777;}}
extern "C" tpchar stdnea(int n)
{
tpchar chloc;
chloc="\0";
if (n==0) chloc="entrée analogique 0\0";
if (n==1) chloc="EA 1 (volts)\0";
if (n==2) chloc="température °C\0";
return chloc; }
extern "C" double stdead(int n)
{
double varloc;
if (n>-1&&n<3) {varloc= n*3.33;}else{varloc= -777;}
return varloc;
}
extern "C" tpchar stdnead(int n)
{
tpchar chloc;
chloc="\0";
if (n==0) chloc="entrée analogique 0\0";
if (n==1) chloc="EA 1 (volts)\0";
if (n==2) chloc="température °C\0";
return chloc; }
extern "C" int stdsa(int n , int val)
{ if (n==0) {memosa=val ;return val;}else{return -777;}
}
extern "C" tpchar stdnsa(int n)
{ tpchar chloc;
if (n==0) chloc="sortie analogique\0"; else chloc="\0";
return chloc; }
extern "C" double stdsad(int n, double val)
{ if (n==0){memosad=val; return val;} else return -777;
}
extern "C" tpchar stdnsad(int n)
{if (n==0) return "SA 0 (volts)\0"; else return "\0"; }
extern "C" int stdrsa(int n)
{ if (n==0) return memosa; else return -777; }
extern "C" double stdrsad(int n)
{ if(n==0) return memosad; else return -777;}
extern "C" int stdeb(int n)
{
if (n==0)
return 0;
else if (n==1)
return 1;
else return -777;
}
extern "C" tpchar stdneb(int n)
{ if (n==0)
return "EB fictive 0\0";
else if (n==1)
return "EB fictive 1\0";
else return "\0";
}
extern "C" int stdsb(int n, int etat)
{ int varloc;
varloc=-777;
//mettre ici la commande des sorties binaires,
// ainsi que la mémorisation dans le tableau memosb;
if (n==0) varloc=0;
if (n==1) varloc=1;
if (n==2) varloc=1;
if (n==3) varloc=0;
return varloc;
}
extern "C" tpchar stdnsb(int n)
{tpchar varloc;
varloc=="\0";
if (n==0) varloc="Relais 0\0";
if (n==1) varloc="Relais 1\0";
if (n==2) varloc="Relais 2\0";
if (n==3) varloc="Relais 3\0";
return varloc; }
extern "C" int stdrsb(int n)
{int varloc;
varloc=-777;
if (n==0) varloc=memosb[0];
if (n==1) varloc=memosb[1];
if (n==2) varloc=memosb[2];
if (n==3) varloc=memosb[3];
return varloc ;}
extern "C" tpchar stdtitre(void)
{return "Appareil fictif\0";}
extern "C" tpchar stddetail(void)
{return "Appareil fictif, bibliothèque programmée
en C++ par P. Dieumegard, le 19 nov 2002\0";
}
Voici un petit programme appelant une bibliothèque de mesure, et affichant les fonctions «detail», «stdead(1)» et «stdnead(1)».
//testdll_linux.c : essai de programme en C appelant les bibliothèques
.so
//à compiler par
//g++ -rdynamic -ldl -o testdll_linux testdll_linux.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <string>
main()
{
typedef char *(*detailtype)();
typedef double (*stdeadtype) (int numvoie);
typedef char *(*stdneadtype) (int numvoie);
void *handle=NULL;
detailtype detail;
stdeadtype stdead;
stdneadtype stdnead;
double mondouble;
char repchar[60];
char * moncar;
int a;
handle=dlopen("./liblxdllvide.so",RTLD_NOW);
detail=(detailtype)dlsym(handle,"detail");
stdead=(stdeadtype)dlsym(handle,"stdead");
stdnead=(stdneadtype)dlsym(handle,"stdnead");
mondouble=stdead(2);
mach2="44.44";
moncar=detail();
printf(moncar);
printf("\n");
machaine="simple essai de chaîne";
gcvt(mondouble,5,repchar);
printf(repchar);
printf(stdnead(1));
return 0;
}
function dlopen(afile:pchar;mode:longint):pointer;cdecl;external
'dl';
function LoadLibrary(name:pchar):thandle;
begin
Result:=LongWord(dlopen(name,$101 {RTLD_GLOBAL or
RTLD_LAZY}));
end;
function dlclose(handle:pointer):longint;external 'dl';
procedure FreeLibrary(handle:thandle);
begin dlclose(pointer(handle));end;
function dlsym(handle:pointer;name:pchar):pointer;external 'dl';
function getprocaddress(handle:thandle;name : pchar):pointer;
//begin result:=dlsym(pointer(handle),name);end;
begin result:=dlsym(pointer(handle),name );end;
Dans la réalité, c'est moins simple...
- StarOffice existe aussi en version Linux, mais la version 5.2 ne semble pas capable d'appeler les fichiers .so
- PureBasic existe aussi pour Linux, mais la version actuelle (décembre 2002) est un prototype, et ne semble pas capable d'utiliser les bibliothèques partagées de Linux.
Comment faire ?
La seule solution pour StarOffice et PureBasic semble d'utiliser les «pilotes enregistrant leurs résultats dans un fichier», tels qu'ils sont décrits pour Windows dans le paragraphe 5.8.2. Ce n'est pas très simple.
- Python sous Windows peut utiliser les DLL, à condition de passer par la méthode de PythonForDelphi. Normalement, d'après la documentation, ce doit être aussi possible pour Python sous Linux. Malheureusement, jusqu'ici, je n'ai pas réussi. Heureusement, Python sous Linux possède un module «commands», qui le rend capable d'utiliser les «pilotes exécutables dont on récupère le résultat» (comme pour Scilab : voir paragraphes suivants).
program pdll32;
{$APPTYPE CONSOLE}
uses
SysUtils,
wintypes;
var l:thandle;
var repchar:array[0..80] of char;
var ea:function(n:integer):integer;
var nea:function(n:integer):pchar;
var stdea:function(n:integer):integer;stdcall;
var stdnea:function(n:integer):pchar ;stdcall;
var nead:function(n:integer):pchar;
var ead:function(n:integer):double;
var stdead:function(n:integer):double;
stdcall;
var stdnead:function(n:integer):pchar;
stdcall;
var sa:function(n:integer;valeur:integer):integer;
var nsa:function(n:integer):pchar;
var rsa:function(n:integer):integer;
var stdsa:function(n:integer;valeur:integer):integer;stdcall;
var stdnsa:function(n:integer):pchar;stdcall;
var stdrsa:function(n:integer):integer;stdcall;
var sad:function(n:integer;valeur:double):double;
var nsad:function(n:integer):pchar;
var rsad:function(n:integer):double;
var stdsad:function(n:integer;valeur:double):double;stdcall;
var stdnsad:function(n:integer):pchar;stdcall;
var stdrsad:function(n:integer):double;stdcall;
var eb:function(n:integer):integer;
var neb:function(n:integer):pchar;
var stdeb:function(n:integer):integer;stdcall;
var stdneb:function(n:integer):pchar;stdcall;
var sb:function(n:integer;valeur:integer):integer;
var nsb:function(n:integer):pchar;
var rsb:function(n:integer):integer;
var stdsb:function(n:integer;valeur:integer):integer;stdcall;
var stdnsb:function(n:integer):pchar;stdcall;
var stdrsb:function(n:integer):integer;stdcall;
var detail,titre:function : pchar;
var stddetail,stdtitre:function:pchar;stdcall;
var chemindll,nomfonction,chparam1,chparam2:string;
var valparam1:double;
var valparam2:double;
var i:integer;
begin
// Insérer le code utilisateur ici
//for i:=0 to paramcount do writeln('paramètre ',i,':',paramstr(i));
valparam1:=11;valparam2:=22;
chemindll:=paramstr(1);
//chemindll:='/home/pierre/libxdllpython.so';
nomfonction:=paramstr(2);
if paramcount>=3 then valparam1:=strtofloat(paramstr(3));
if paramcount>=4 then valparam2:=strtofloat(paramstr(4));
strpcopy(repchar,chemindll);
@ea:=nil;@nea:=nil; @nead:=nil; @ead:=nil;
@sa:=nil;@nsa:=nil;@rsa:=nil;@sad:=nil;@nsad:=nil;@rsad:=nil;
@eb:=nil;@neb:=nil;@sb:=nil;@nsb:=nil;@rsb:=nil;
@detail:=nil;@titre:=nil;@stddetail:=nil;@stdtitre:=nil;
@stdea:=nil;@stdnea:=nil; @stdead:=nil;@stdnead:=nil;
@stdsa:=nil;@stdnsa:=nil;@stdrsa:=nil;
@stdsad:=nil;@stdnsad:=nil;@stdrsad:=nil;
@stdeb:=nil;@stdneb:=nil;@stdsb:=nil;@stdnsb:=nil;@stdrsb:=nil;
// l:=loadlibrary('home/pierre/libxdllpython.so');
l:=loadlibrary(repchar);
@ea:=getprocaddress(L,'ea');
@nea:=getprocaddress(L,'nea');
@nead:=getprocaddress(L,'nead');
@ead:=getprocaddress(L,'ead');
@sa:=getprocaddress(L,'sa');
@nsa:=getprocaddress(L,'nsa');
@rsa:=getprocaddress(L,'rsa');
@sad:=getprocaddress(L,'sad');
@nsad:=getprocaddress(L,'nsad');
@rsad:=getprocaddress(L,'rsad');
@eb:=getprocaddress(L,'eb');
@neb:=getprocaddress(L,'neb');
@sb:=getprocaddress(L,'sb');
@nsb:=getprocaddress(L,'nsb');
@rsb:=getprocaddress(L,'rsb');
@detail:=getprocaddress(L,'detail');
@titre:=getprocaddress(L,'titre');
@stddetail:=getprocaddress(L,'stddetail');
@stdtitre:=getprocaddress(L,'stdtitre');
@stdea:=getprocaddress(L,'stdea');
@stdnea:=getprocaddress(L,'stdnea');
@stdead:=getprocaddress(L,'stdead');
@stdnead:=getprocaddress(L,'stdnead');
@stdsa:=getprocaddress(L,'stdsa');
@stdnsa:=getprocaddress(L,'stdnsa');
@stdrsa:=getprocaddress(L,'stdrsa');
@stdsad:=getprocaddress(L,'stdsad');
@stdnsad:=getprocaddress(L,'stdnsad');
@stdrsad:=getprocaddress(L,'stdrsad');
@stdeb:=getprocaddress(L,'stdeb');
@stdneb:=getprocaddress(L,'stdneb');
@stdsb:=getprocaddress(L,'stdsb');
@stdnsb:=getprocaddress(L,'stdnsb');
@stdrsb:=getprocaddress(L,'stdrsb');
//writeln('nombre de paramètres :',paramstr(0));
//writeln('nomdll:',chemindll);
//writeln('nomfonction:',nomfonction);
//writeln(valparam1:8:2);
if nomfonction='ea' then writeln(ea(round(valparam1)));
if nomfonction='nea' then writeln(nea(round(valparam1)));
if nomfonction='ead' then writeln(ead(round(valparam1)):10:5);
if nomfonction='nead' then writeln(nead(round(valparam1)));
if nomfonction='sa' then writeln(sa(round(valparam1),round(valparam2)));
if nomfonction='nsa' then writeln(nsa(round(valparam1)));
if nomfonction='rsa' then writeln(rsa(round(valparam1)));
if nomfonction='sad' then writeln(sad(round(valparam1),valparam2):10:5);
if nomfonction='nsad' then writeln(nsad(round(valparam1)));
if nomfonction='rsad' then writeln(rsad(round(valparam1)):10:5);
if nomfonction='eb' then writeln(eb(round(valparam1)));
if nomfonction='neb' then writeln(neb(round(valparam1)));
if nomfonction='sb' then writeln(sb(round(valparam1),round(valparam2)));
if nomfonction='nsb' then writeln(nsb(round(valparam1)));
if nomfonction='rsb' then writeln(rsb(round(valparam1)));
if nomfonction='titre' then writeln(titre);
if nomfonction='detail' then writeln(detail);
if nomfonction='stdea' then writeln(stdea(round(valparam1)));
if nomfonction='stdnea' then writeln(stdnea(round(valparam1)));
if nomfonction='stdead' then writeln(stdead(round(valparam1)):10:5);
if nomfonction='stdnead' then writeln(stdnead(round(valparam1)));
if nomfonction='stdsa' then writeln(stdsa(round(valparam1),round(valparam2)));
if nomfonction='stdnsa' then writeln(stdnsa(round(valparam1)));
if nomfonction='stdrsa' then writeln(stdrsa(round(valparam1)));
if nomfonction='stdsad' then writeln(stdsad(round(valparam1),valparam2):10:5);
if nomfonction='stdnsad' then writeln(stdnsad(round(valparam1)));
if nomfonction='stdrsad' then writeln(stdrsad(round(valparam1)):10:5);
if nomfonction='stdeb' then writeln(stdeb(round(valparam1)));
if nomfonction='stdneb' then writeln(stdneb(round(valparam1)));
if nomfonction='stdsb' then writeln(stdsb(round(valparam1),round(valparam2)));
if nomfonction='stdnsb' then writeln(stdnsb(round(valparam1)));
if nomfonction='stdrsb' then writeln(stdrsb(round(valparam1)));
if nomfonction='stdtitre' then writeln(stdtitre);
if nomfonction='stddetail' then writeln(stddetail);
freelibrary(L);
end.
(Début de page)
Les commandes précédentes mettent comme répertoire courant «/home/utilisateur/travaildll», puis lancent le pilote «scidll32» qui appelle la bibliothèque «liblxdllvide.so» et lui demande l'entrée analogique réelle 1 («ead(1)»). Le résultat de cet appel est envoyé dans la variable x, qui est finalement affiché.
sub afficheead1
Dim iNumber As Integer
Dim aFile As String
dim sline as string
dim temps0 as long
rem dim commande$ as string
lignecommande$=dirdll$+"\fdll32.exe xdllvide.dll ead 1"
aFile = "fdll32.txt"
iNumber=Freefile
open aFile for output as #inumber
close #inumber
temps0=getsystemticks()
shell(lignecommande$,false)
while (filelen(afile)<2)and(getsystemticks()-temps0<1000)
wend
iNumber = Freefile
Open aFile For input As #iNumber
Line Input #iNumber, sLine
close #inumber
msgbox(val(sline))
end sub