Exécuter 2 appli console en mm tps

Résolu
cs_mounjetado Messages postés 66 Date d'inscription lundi 13 mars 2006 Statut Membre Dernière intervention 4 août 2008 - 22 oct. 2007 à 12:33
salim07360 Messages postés 17 Date d'inscription mardi 6 décembre 2005 Statut Membre Dernière intervention 22 janvier 2008 - 12 janv. 2008 à 18:12
bonjour,
j'ai deux appli console que je souhaite faire communiquer via des événements (mais si vous avez mieux à me proposer...), pour accéder tour à tour à une mémoire commune, soit en lecture, soit en écriture.
je souhaite déboguer les deux appli en mm tps, en particulier pour voirsi l'accès à la mémoire se fait bien, et si les données sont correctement écrites et lues. j'ai d'ores et déjà pu vérifier que j'écris bien mes valeurs dans ma mémoire (sous forme de tableau de record).
à savoir, mes appli console sont lancées depuis un appli VCL IHM, via CreateProcess, jusque-là l'une après l'autre, car j'enregistrais mes données dans un fichier.
merci pour votre aide.

<hr />si Delphi m'était conté...

11 réponses

cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
26 oct. 2007 à 09:08
Un petit exemple pour essayer de te faire saisir la chose.

Suppose que tu compile une appli VCL IHM.

Ta form sera une fille de TForm et serat déclarée en variable globale dans l'unité de ta fiche :
interface

type TMyForm = class(TForm)
private
public
end;

var
  MyForm: TMyForm;

implementation


Cette variable à tout à fait la même portée que ton tableau.

Maintenant, je compile.

Je fais une copie de l'exe, et je recompile.

Mes deux executable utilisent la même unité.


Eh bin avec ton point de vue, ils devraient utiliser la même fenêtre.
Genre tu lances le premier, une fenêtre s'affiche, tu lance le
deuxième, aucune fenêtre ne s'affiche, car elle utilise la même fenêtre
que celle de la première application...


De même tu peux executer deux fois la même appli sans que tes deux
processus utilise les mêmes variables... Tu l'a déjà fait un nombre
incalculable de fois sur ton PC je suis sûr. Bon après y a des
applications qui refusent de se lancer deux fois car elles vont
partager d'autres ressources, styles des fichiers...

3ème année en ecole d'ingé d'info cherche stage de 4 mois à partir du 01/04/08
3
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
23 oct. 2007 à 15:36
Salut,


Bin pour l'explication de ce que tu fais, c'est très compréhensible, mais... Il est où ton problème ???


Fait des recherches sur les SharedMemory. C'est pas proposé par la VCL/Delphi, mais par l'API Win32 (cf la doc du Win32 SDK fournie avec Delphi).
3ème année en ecole d'ingé d'info cherche stage de 4 mois à partir du 01/04/08
0
cs_mounjetado Messages postés 66 Date d'inscription lundi 13 mars 2006 Statut Membre Dernière intervention 4 août 2008
24 oct. 2007 à 12:32
lol ben en fait j'ai trouvé comment procéder...
en fait il me fallait aller dans "Fenêtres de débogage" et ouvrir "Threads" pour avoir l'état des threads (de mes applis console et de mon IHM) et les exécuter simultanément.
ceci résolu, en fait j'ai un problème effectivement pour récupérer mes valeurs dans mon appli de calcul, alors que celle de mesure remplit bien les tableaux alloués...
pour l'instant, je vérifie la bonne déclaration de mes variables, car j'utilise deux variables pointeurs sur deux tableaux d'enregistrement de mon crû, et qui permutent régulièrement pour permettre la lecture d'un tableau et son traitement, pendant que l'autre écrit les mesures. j'ai déclaré les tableaux en global, et les pointeurs en local, afin d'être sûr que les opérations simultanées ne cachent pas un bug.
je ne sais pas si j'ai bien fait...
en l'état actuel des choses, quand j'exécute en pas à pas, je vérifie que mes mesures sont bien prises et stockées dans un tableau, que les pointeurs permutent, mais qu'à la lecture du tableau, ma variable qui devrait recevoir les valeurs, ne reçoit en fait que des 0 partout, ou bien ne reçoit rien.

<hr />si Delphi m'était conté...
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
24 oct. 2007 à 16:17
Heu...


Tu m'arrêtes si je me trompe...

Tu as trois appli, une IHM et deux consoles.

Dans chaque appli console, tu as déclaré un tableau global.

Ces tableau sont suceptibles d'être accedés en écriture/lecture par l'une ou l'autre des deux applis console.


Lorsque l'on déclare un tableau de taille fixe en variable globale, le
compilo de Delphi réserve un espace de la bonne taille dans le fichier
.exe. Cette espace est souvent initialisé à 0. Lors du lancement de
l'appli, cette zone mémoire du fichier va être copié dans la RAM à une
certaine adresse. Cependant, tu es dans une application en mode mono
utilisateur, autrement dit, l'adressage est virtuel. Ce n'est pas parce
que tu as un pointeur sur l'adresse 12 que tu vas réellement taper dans
la RAM à l'adresse 12.


Conséquence, deux applis avec deux pointeurs qui pointe à l'adresse 12
ne pointent pas du tout sur la même chose (Sous XP du moins).


Une application ne peut en aucun cas lire la mémoire d'une autre application. Il sont dans des univers tout à fait différents.


C'est pour ça que Windows propose les SharedMemory, qui peuvent être
accèder par plusieurs application. C'est une zone de mémoire commune.


Une alternative est d'utiliser [msdn2.microsoft.com/en-us/library/ms680553.aspx Read/WriteProcessMemory.]


D'autre part, il faut s'assurer que les deux application n'écrivent pas en même temps au même endroit.


Tu peux montrer un peu de code, spécialement l'accès au tableau stocké dans une autre console ?
3ème année en ecole d'ingé d'info cherche stage de 4 mois à partir du 01/04/08
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_mounjetado Messages postés 66 Date d'inscription lundi 13 mars 2006 Statut Membre Dernière intervention 4 août 2008
25 oct. 2007 à 10:20
la variable tableau et son type sont déclarés dans une unité commune à tous les processus:




unit uCommonTypesandValues;


interface
const
    mcMax      =   4;

type
  TMeasure = Array[0..ChValFormat-1] of Word;


  TWholeMeasure = Array[0..mcMax-1] of TMeasure;


  TCompleteMeasure = Record
    elSystemClockCount : Int64;
    elDeviceClockCount : Int64;
    elMeasureCount : Int64;
    elDeviceValues : TWholeMeasure;
    elTORStatus : Byte;
  End;


  TCompleteMeasureArray = Array[0..1999] of TCompleteMeasure;

  CompleteMeasureArray : Array[0..1] of TCompleteMeasureArray;

implementation
begin
end.






le programme console de mesure:



program prjMesConsole;




 



{$APPTYPE CONSOLE}




 



{%File 'ModelSupport\uParalPortR\uParalPortR.txvpck'}
{%File 'ModelSupport\uCommonTypesandValues\uCommonTypesandValues.txvpck'}
{%File 'ModelSupport\Par défaut.txvpck'}




 



uses
  SysUtils,
  Windows,
  Dialogs,
  Classes,
  Consts,
  uCommonTypesandValues in '..\MesSources\uCommonTypesandValues.pas',
  uParalPortR in '..\MesSources\uParalPortR.pas';



const BUFSIZE = 4096;



var
  WalkMeasureAcquirer : TMeasureAcquirer;
  MeasureShouldCloseEvent: THandle;
  MeasureClosedEvent: THandle;
  MeasuresFullArrayEvent : THandle;
  ShouldClose: Boolean = False;
  sStoreDefaultPath : String;
  JournalList : TStringList;
  ConfigList : TStringList;
  TestInfoList : TStringList;
  sRead, sWrite : String;
  MeasureRTLCriticSection : TRTLCriticalSection;
  CpltMeasureArrayPtr : PCompleteMeasureArray;
  pchCmdLn : PAnsiChar;
  a : SmallInt;




 



    //  Liste de paires nom=valeur sauvegardées dans les fichiers textes
    //      en regard de la variable locale correspondante et de son type:




 



  iConverterAccuracy   : SmallInt;      // --->   ConverterAccuracy=12
  iPresentModulesCount : SmallInt;      // --->   PresentModulesCount=1
  iMeasureSize         : Integer;       // --->   MeasureSize=96
  bTOREnabled          : Boolean;       // --->   TOREnabled=False
  iFrequency           : Int64;         // --->   HRFrequency=3579545
  iMovingWay           : SmallInt;      // --->   MovingWay=1
  iMeasuresCount       : Int64;         // --->   MeasuresCount=16469
  bTestValidation      : Boolean;       // --->   TestValidation=True




 





procedure ProceedMeasure;
begin
  with WalkMeasureAcquirer do
    begin
      iMeasuresCount := ProcessWholeMeasure;
      if iMeasuresCount<0
        then begin
               //Définit ExitCode pour indiquer la condition d'erreur (par convention)
               ExitCode := GetLastError;
               //Gérer la condition d'erreur
               if ExitCode<=3700   // Message d'erreur système
                 then begin
                        sWrite := SysErrorMessage(ExitCode);
                        JournalList.BeginUpdate;
                        JournalList.Add(sWrite);
                        JournalList.EndUpdate;
                        RaiseLastOSError(ExitCode);
                      end
                 else begin
                        sWrite := 'Exception imprévue ' + IntToStr(ExitCode)
                                 + ' dans la procédure de mesure. Mesure ratée à MeasuresCount='
                                 + IntToStr(WalkMeasureAcquirer.GetMeasuresCount)
                                 + '. iMeasuresCount=' + IntToStr(iMeasuresCount);
                        JournalList.BeginUpdate;
                        JournalList.Add(sWrite);
                        JournalList.EndUpdate;
                        raise Exception.Create(sWrite);
                      end;
             end
        else if (((iMeasuresCount mod 1000) = 0) and (iMeasuresCount>0))
               then begin
                      if Odd(iMeasuresCount div 1000) then a := 1
                                                      else a := 0;
                      CpltMeasureArrayPtr^ := CompleteMeasureArray[a];
                      SetEvent(MeasuresFullArrayEvent);
                    end;




 



      with CpltMeasureArrayPtr^[iMeasuresCount mod 1000]
        do begin
             elMeasureCount := GetMeasuresCount;
             elDeviceClockCount := GetDeviceClockCount;
             elSystemClockCount := GetSystemClockCount;
             elTORStatus := GetTORStatus;
             elDeviceValues := GetWholeMeasure;
           end;
    end;




 





    //////////////////////////////////////////////////////////////
    //                   TRAITEMENT DES ALARMES                 //
    //                       A PERSONNALISER                    //
    //////////////////////////////////////////////////////////////




 



end;




 





///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////// PROGRAMME PRINCIPAL /////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
begin  // de main
    //////////////////////////////////////////////////////////////
    //         PARAMETRES A ENVOYER LORS DE L'EXECUTION         //
    //                 PAR LIGNE DE COMMANDE OU                 //
    //                    EN TANT QUE SERVICE                   //
    //////////////////////////////////////////////////////////////




 



  // Lecture des paramètres de la ligne de commande pour déterminer
  //   le fichier de configuration à prendre en compte
  pchCmdLn := PAnsiChar('StrengthPlate');
//  pchCmdLn := GetCommandLine;
  sConfigFileName := String(pchCmdLn) + 'Config.txt';




 



  // Récupère le handle sur l'évenement créé par le programme principal
  //   grâce à son nom (il faut évidemment mettre le même dans les deux applis !!)
  MeasureShouldCloseEvent := OpenEvent(EVENT_ALL_ACCESS, False, 'MEASURE_CONSOLE_SHOULD_CLOSE_EVENT');
  MeasureClosedEvent := OpenEvent(EVENT_ALL_ACCESS, False, 'MEASURE_CONSOLE_CLOSED_EVENT');
  MeasuresFullArrayEvent := CreateEvent(nil, True, False, 'MEASURES_FULL_ARRAY_EVENT');
  sStoreDefaultPath := GetEnvironmentVariable(sStoreDirectory);




 



  // Initialisation des variables globales
  sRead := '';
  iMeasuresCount := -1;




 



  // Creation des variables listes de chaînes de caractères
  JournalList := TStringList.Create;
  JournalList.Clear;
  ConfigList := TStringList.Create;
  ConfigList.Clear;
  TestInfoList := TStringList.Create;
  TestInfoList.Clear;




 



  try  // ..finally n°1




 



    // Informations TextFile Opening for Reading
    try  // ..except n°2
      TestInfoList.LoadFromFile(sStoreDefaultPath + sResultsDirectory + sTestInfoFileName);




 



      iMovingWay := StrToInt(TestInfoList.ValueFromIndex[TestInfoList.IndexOfName('MovingWay')]);
    except  // de try n°2
      //Définit ExitCode pour indiquer la condition d'erreur (par convention)
      ExitCode := GetLastError;
      //Gérer la condition d'erreur
      sWrite := 'Exception imprévue dans la lecture du fichier texte d''informations ('
                  + IntToStr(ExitCode) + ')';
      JournalList.BeginUpdate;
      JournalList.Add(sWrite);
      JournalList.EndUpdate;
      raise Exception.Create(sWrite);
      ExitProcess(ExitCode);
    end;  // de try..except n°2




 



    // Configuration TextFile Opening for Reading
    try  // ..except n°3
      ConfigList.LoadFromFile(sStoreDefaultPath + sResultsDirectory + sConfigFileName);




 



      iConverterAccuracy := StrToInt(ConfigList.ValueFromIndex[ConfigList.IndexOfName('ConverterAccuracy')]);
      bTOREnabled := StrToBool(ConfigList.ValueFromIndex[ConfigList.IndexOfName('TOREnabled')]);
      iPresentModulesCount := StrToInt(ConfigList.ValueFromIndex[ConfigList.IndexOfName('PresentModulesCount')]);
    except  // de try n°3
      //Définit ExitCode pour indiquer la condition d'erreur (par convention)
      ExitCode := GetLastError;
      //Gérer la condition d'erreur
      sWrite := 'Exception imprévue dans la lecture du fichier texte de configuration ('
                  + IntToStr(ExitCode) + ')';
      JournalList.BeginUpdate;
      JournalList.Add(sWrite);
      JournalList.EndUpdate;
      raise Exception.Create(sWrite);
      ExitProcess(ExitCode);
    end;  // de try..except n°3
  finally  // de try n°1
    // Libération de la mémoire
    ConfigList.Free;
    TestInfoList.Free;
  end;  // de try..finally n°1




 



  try  // ..finally n°4




 





    // Acquisition Board Object Creation
    try  // ..except n°6
      WalkMeasureAcquirer := TMeasureAcquirer.CreateSelf( iPresentModulesCount,
                                                          iConverterAccuracy,
                                                          iMovingWay,
                                                          bTOREnabled );
    except  //de try n°6
      //Définit ExitCode pour indiquer la condition d'erreur (par convention)
      ExitCode := GetLastError;
      //Gérer la condition d'erreur
      sWrite := 'Exception imprévue dans la définition du système ('
                  + IntToStr(ExitCode) + ')';
      JournalList.BeginUpdate;
      JournalList.Add(sWrite);
      JournalList.EndUpdate;
      raise Exception.Create(sWrite);
      ExitProcess(ExitCode);
    end;  // de try..except n°6




 



    // Once Critical Section Initialization
    try  // ..except n°7
      InitializeCriticalSection(MeasureRTLCriticSection);
    except  // de try n°7
      //Définit ExitCode pour indiquer la condition d'erreur (par convention)
      ExitCode := GetLastError;
      //Gérer la condition d'erreur
      sWrite := 'Exception imprévue dans la création de la variable de données ('
                  + IntToStr(ExitCode) + ')';
      JournalList.BeginUpdate;
      JournalList.Add(sWrite);
      JournalList.EndUpdate;
      raise Exception.Create(sWrite);
      ExitProcess(ExitCode);
    end;  // de try..except n°7




 



    New( CpltMeasureArrayPtr );




 



    sWrite := 'TestBegin=' + DateTimeToStr(Now);
    JournalList.BeginUpdate;
    JournalList.Add(sWrite);
    JournalList.EndUpdate;




 



    // Program Main Loop




 



      while not ShouldClose   // Closing Condition
        do try  // ..except n°8
             // Prise de mesure
             EnterCriticalSection(MeasureRTLCriticSection);
             ProceedMeasure;
             LeaveCriticalSection(MeasureRTLCriticSection);




 



             // Test de la condition de fermeture de l'application console             ShouldClose :WaitForSingleObject( MeasureShouldCloseEvent, 0) WAIT_OBJECT_0;
             if ShouldClose
               then begin
                      sWrite := 'TestEnd=' + DateTimeToStr(Now);
                      JournalList.BeginUpdate;
                      JournalList.Add(sWrite);
                      JournalList.EndUpdate;
                      sWrite := 'MeasuresCount=' + IntToStr(Integer(WalkMeasureAcquirer.GetMeasuresCount));
                      JournalList.BeginUpdate;
                      JournalList.Add(sWrite);
                      JournalList.EndUpdate;
                      if ExitCode=MEASURE_NO_ERROR
                        then bTestValidation := TRUE
                        else bTestValidation := FALSE;
                      sWrite := 'TestValidation=' + BoolToStr(bTestValidation,TRUE);
                      JournalList.BeginUpdate;
                      JournalList.Add(sWrite);
                      JournalList.EndUpdate;
                      // Sauvegarde des évenements survenus pendant le test
                      JournalList.SaveToFile(sStoreDefaultPath + sResultsDirectory + sJournalFileName);
                    end;
           except  // de try n°8
             //Définit ExitCode pour indiquer la condition d'erreur (par convention)
             ExitCode := GetLastError;
             //Gérer la condition d'erreur
             sWrite := SysErrorMessage(ExitCode);
             sWrite := sWrite + 'Fin de programme dûe à une exception dans la boucle principale ('
                         + IntToStr(ExitCode) + ').';
             JournalList.BeginUpdate;
             JournalList.Add(sWrite);
             JournalList.EndUpdate;
             raise Exception.Create(sWrite);
//             ExitProcess(ExitCode);
           end;   // de try..except n°8




 



  finally  // de try n°4




 



    sWrite := 'TestEnd=' + DateTimeToStr(Now);
    JournalList.BeginUpdate;
    JournalList.Add(sWrite);
    JournalList.EndUpdate;
    sWrite := 'MeasuresCount=' + IntToStr(Integer(WalkMeasureAcquirer.GetMeasuresCount));
    JournalList.BeginUpdate;
    JournalList.Add(sWrite);
    JournalList.EndUpdate;
    if ExitCode=MEASURE_NO_ERROR
      then bTestValidation := TRUE
      else bTestValidation := FALSE;
    sWrite := 'TestValidation=' + BoolToStr(bTestValidation,TRUE);
    JournalList.BeginUpdate;
    JournalList.Add(sWrite);
    JournalList.EndUpdate;
    JournalList.SaveToFile(sStoreDefaultPath + sResultsDirectory + sJournalFileName);




 



    // Libération de la mémoire des objets et de l'événement
    Dispose( CpltMeasureArrayPtr );
    DeleteCriticalSection(MeasureRTLCriticSection);
//    CloseHandle(hMeasuresFileHandle);
    JournalList.Free;
    ResetEvent(MeasureShouldCloseEvent);
    SetEvent(MeasureClosedEvent);
    CloseHandle(MeasureShouldCloseEvent);
    CloseHandle(MeasureClosedEvent);
    CloseHandle(MeasuresFullArrayEvent);
    WalkMeasureAcquirer.Destroy;
  end;  // de try..finally n°4



end. // de main

le programme console de calcul:

program prjCalConsole;



{$APPTYPE CONSOLE}



{%File 'ModelSupport\uCommonTypesandValues\uCommonTypesandValues.txvpck'}
{%File 'ModelSupport\Par défaut.txvpck'}



uses
  SysUtils,
  Windows,
  Types,
  Classes,
  Math,
  uCommonTypesandValues in '..\MesSources\uCommonTypesandValues.pas';



const BUFSIZE = 4096;
      libCalcFct = 'C:\Documents and Settings\bq\Mes documents\Plateforme\CalculationDLL\libCalcFct.dll';
//..
// déclaration des méthodes de calcul de la dll libCalcFct.dll
//..



var dwRead, dwWritten : DWORD;
    cmReadMeasure : TCompleteMeasure;
    CalculRTLCriticSection : TRTLCriticalSection;
    CalcShouldCloseEvent : THandle;
    CalcClosedEvent : THandle;
    CalcCanCloseEvent : THandle;
    CalcCanTreatEvent : THandle;
    MeasuresFilledArrayEvent : THandle;
    ShouldClose : Boolean = False;
    CanClose : Boolean = False;
    CanTreat : Boolean = False;
    ConfigList : TStringList;
    TestInfoList : TStringList;
    JournalList : TStringList;
    sStoreDefaultPath : String;
    sRead, sWrite : String;
    mc : Integer;
    milliers : Integer = -1;



    SysFirstMeasureTime, DevFirstMeasureTime : TLargeInteger;
    SystemTime : TLargeInteger;
    DeviceTime : TLargeInteger;
    sz : SmallInt;
    blRslt : Boolean;



    pchCmdLn : PAnsiChar;



   
 //  Liste de paires nom=valeur sauvegardées dans les fichiers textes
    //      en regard de la variable locale correspondante et de son type:



    iConverterAccuracy   : SmallInt;      // --->   ConverterAccuracy=12
    iPresentModulesCount : SmallInt;      // --->   PresentModulesCount=1
    iMeasureSize         : Integer;       // --->   MeasureSize=96
    bTOREnabled          : Boolean;       // --->   TOREnabled=False
    iFrequency           : Int64;         // --->   HRFrequency=3579545
    iIPU                 : Integer;       // --->   IPU=4316469
    iFootLength          : SmallInt;      // --->   FootLength=31
    iWeight              : SmallInt;      // --->   Weight=83
    iAge                 : SmallInt;      // --->   Age=47
    iMovingWay           : SmallInt;      // --->   MovingWay=1
    dtDepart             : Extended;      // --->   Démarrage=39245,6600260417
    dtArret              : Extended;      // --->   Arrêt=39245,6601119329
    iMeasureCount        : Int64;         // --->   MeasuresCount=16469
    bValidTest           : Boolean;       // --->   TestValidation=True



    // Paramètres calculés ou déduits de la configuration
    iConverterRange      : SmallInt;   // Nombre de quanta sur la pleine échelle
    dQuantum             : Double;     // Valeur calculée du quantum  = FullScaleVoltRange/iConverterRange
    ch,modid             : SmallInt;
    CpltMeasArrPtr : PCompleteMeasureArray;



procedure ProceedTreatment;
var a,i : Integer;
begin
//  New(CpltMeasArrPtr);
  if not Odd(milliers) then a := 0
                       else a := 1;
//  CpltMeasArrPtr^ := CompleteMeasureArray[a];
//  for i:=Low(CpltMeasArrPtr^) to High(CpltMeasArrPtr^)
  for i:=Low(CompleteMeasureArray[a]) to High(CompleteMeasureArray[a])
    do begin
         cmReadMeasure := CompleteMeasureArray[a][i];
            try
              blRslt := WriteFile( hMeasuresFileHandle,
                                   cmReadMeasure,
                                   SizeOf(cmReadMeasure),
                                   dwWritten,
                                   nil );
              if blRslt then WriteLn(IntToStr(dwWritten));
            except
              //Définit ExitCode pour indiquer la condition d'erreur (par convention)
              ExitCode := GetLastError;
              //Gérer la condition d'erreur
              sWrite := 'Exception imprévue dans la création du fichier de données ('
                          + IntToStr(ExitCode) + ')';
              JournalList.BeginUpdate;
              JournalList.Add(sWrite);
              JournalList.EndUpdate;
              raise Exception.Create(sWrite);
              ExitProcess(ExitCode);
            end;
         if ShouldClose
           then if i=High(CompleteMeasureArray[a]) then SetEvent(CalcCanCloseEvent);
       end;
//  Dispose(CpltMeasArrPtr);
end;




 






//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/////////////////////// PROGRAMME PRINCIPAL //////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
begin
    //////////////////////////////////////////////////////////////
    //         PARAMETRES A ENVOYER LORS DE L'EXECUTION         //
    //                 PAR LIGNE DE COMMANDE OU                 //
    //                    EN TANT QUE SERVICE                   //
    //////////////////////////////////////////////////////////////



  try
  // Lecture des paramètres de la ligne de commande pour déterminer
  //   le fichier de configuration à prendre en compte
    pchCmdLn := PAnsiChar('StrengthPlate');
//    pchCmdLn := GetCommandLine;
    sConfigFileName := String(pchCmdLn) + 'Config.txt';



    // Récupère le handle sur l'évenement créé par le programme principal
    //   grâce à son nom (il faut évidemment mettre le même dans les deux applis !!)
    CalcShouldCloseEvent := OpenEvent(EVENT_ALL_ACCESS, False, 'CALCULATE_CONSOLE_SHOULD_CLOSE_EVENT');
    CalcCanCloseEvent := OpenEvent(EVENT_ALL_ACCESS, False, 'CALC_CAN_CLOSE_EVENT');
    CalcClosedEvent := OpenEvent(EVENT_ALL_ACCESS, False, 'CALCULATE_CONSOLE_CLOSED_EVENT');
    MeasuresFilledArrayEvent := OpenEvent(EVENT_ALL_ACCESS, False, 'MEASURES_FULL_ARRAY_EVENT');



    sStoreDefaultPath := GetEnvironmentVariable(sStoreDirectory);
    sRead := '';
    ConfigList := TStringList.Create;
    ConfigList.Clear;
    JournalList := TStringList.Create;
    JournalList.Clear;
    TestInfoList := TStringList.Create;
    TestInfoList.Clear;



    dwRead := 0;



    try
      // Lecture des listes de chaînes depuis les fichiers texte
      // Journal TextFile Creation for reading
      JournalList.LoadFromFile(sStoreDefaultPath + sResultsDirectory + sJournalFileName);
      // Informations TextFile Creation for reading
      TestInfoList.LoadFromFile(sStoreDefaultPath + sResultsDirectory + sTestInfoFileName);
      // Configuration TextFile Creation for reading
      ConfigList.LoadFromFile(sStoreDefaultPath + sResultsDirectory + sConfigFileName);



      // Chargement des paramètres depuis les listes de chaînes
      // Paramètres de configuration
      iConverterAccuracy := SmallInt(StrToInt(ConfigList.ValueFromIndex[ConfigList.IndexOfName('ConverterAccuracy')]));
      iPresentModulesCount := SmallInt(StrToInt(ConfigList.ValueFromIndex[ConfigList.IndexOfName('PresentModulesCount')]));
      bTOREnabled := StrToBool(ConfigList.ValueFromIndex[ConfigList.IndexOfName('TOREnabled')]);
      iFrequency := StrToInt64(ConfigList.ValueFromIndex[ConfigList.IndexOfName('Frequency')]);



      // Paramètres de conditions de test
      iIPU := StrToInt(TestInfoList.ValueFromIndex[TestInfoList.IndexOfName('IPU')]);
      iFootLength := SmallInt(StrToInt(TestInfoList.ValueFromIndex[TestInfoList.IndexOfName('FootLength')]));
      iWeight := SmallInt(StrToInt(TestInfoList.ValueFromIndex[TestInfoList.IndexOfName('Weight')]));
      iAge := SmallInt(StrToInt(TestInfoList.ValueFromIndex[TestInfoList.IndexOfName('Age')]));
      iMovingWay := SmallInt(StrToInt(TestInfoList.ValueFromIndex[TestInfoList.IndexOfName('MovingWay')]));



      // Résultats de validité de test
      dtDepart := StrToDateTime(JournalList.ValueFromIndex[JournalList.IndexOfName('TestBegin')]);
      dtArret := StrToDateTime(JournalList.ValueFromIndex[JournalList.IndexOfName('TestEnd')]);
      iMeasureCount := StrToInt(JournalList.ValueFromIndex[JournalList.IndexOfName('MeasuresCount')]);
      bValidTest := StrToBool(JournalList.ValueFromIndex[JournalList.IndexOfName('TestValidation')]);



      case iConverterAccuracy of
        caLow  : iConverterRange := crLow;
        caHigh : iConverterRange := crHigh;
      end;



      dQuantum := FullScaleVoltRange / iConverterRange;
    finally
      // On libère la variable chaînes
      ConfigList.Free;
      TestInfoList.Free;
    end;



    SetLength(DynRawMeasuresArray, iMeasureCount);
    SetLength(DynRawDataArray, iMeasureCount);
    mc := 0;
    // Initialize the critical section one time only.
    try
      InitializeCriticalSection(CalculRTLCriticSection);
    except
      //Définit ExitCode pour indiquer la condition d'erreur (par convention)
      ExitCode := GetLastError;
      //Gérer la condition d'erreur
      sWrite := 'Exception imprévue dans la création de la variable de données '
                  + IntToStr(GetLastError) + ' (' + IntToStr(ExitCode) + ')';
      JournalList.BeginUpdate;
      JournalList.Add(sWrite);
      JournalList.EndUpdate;
      raise Exception.Create(sWrite);
      ExitProcess(ExitCode);
    end;



      // Measures File Creation
      try
        // Ouverture du fichier de mesure
        hMeasuresFileHandle := CreateFile( PAnsiChar( sStoreDefaultPath
                                                        + sResultsDirectory
                                                        + sMeasuresFileName ),
                                           GENERIC_READ or GENERIC_WRITE,
                                           FILE_SHARE_READ,
                                           saMeasuresFileSecAttr,
                                           CREATE_ALWAYS,
                                           FILE_ATTRIBUTE_NORMAL,
                                           0 );
      except
        //Définit ExitCode pour indiquer la condition d'erreur (par convention)
        ExitCode := GetLastError;
        //Gérer la condition d'erreur
        sWrite := 'Exception imprévue dans la création du fichier de données ('
                    + IntToStr(ExitCode) + ')';
        Dec(mc);
        JournalList.BeginUpdate;
        JournalList.Add(sWrite);
        JournalList.EndUpdate;
        raise Exception.Create(sWrite);
        ExitProcess(ExitCode);
      end;



    while not ( ShouldClose and CanClose )
      do begin
                    Inc(milliers);           CanTreat :WaitForSingleObject(MeasuresFilledArrayEvent, 0) WAIT_OBJECT_0;
           if CanTreat
             then try
                    ResetEvent(MeasuresFilledArrayEvent);
                    EnterCriticalSection(CalculRTLCriticSection);
                    ProceedTreatment;
                  finally
                    LeaveCriticalSection(CalculRTLCriticSection);
                  end;
           // Condition de fermeture de l'application console           ShouldClose :WaitForSingleObject(CalcShouldCloseEvent, 0) WAIT_OBJECT_0;
           if ShouldClose then  begin                                  CanClose :WaitForSingleObject(CalcCanCloseEvent, 0) WAIT_OBJECT_0;
                                  ExitProcess(0);
                                end;
         end;





  finally
    // Consignation des informations du test
    JournalList.SaveToFile(sStoreDefaultPath + sResultsDirectory + sJournalFileName);
    // Libération de la mémoire
    JournalList.Free;
    DeleteCriticalSection(CalculRTLCriticSection);
    CloseHandle(hMeasuresFileHandle);
    // Libération de l'évenement
    CloseHandle(CalcShouldCloseEvent);
    CloseHandle(CalcCanTreatEvent);
    CloseHandle(CalcCanCloseEvent);
    SetEvent(CalcClosedEvent);
    CloseHandle(CalcClosedEvent);
  end;





end.









voilà, je crois qu'avec ça tu as toutes les billes pour comprendre mon problème, puisque j'arrive à exécuter sans souci les 2 appli console en mm tps sous le débogueur, et à les arrêter. et pour l'affichage, je lis le fichier sauvegardé dans l'appli console de calcul dans un TStringList que j'affiche ensuite dans un TMemo.
mon chef m'a expliqué qu'en faisant New(monpointeur) dans chaque appli console, en fait je créais 2 instances différentes de la variable, et donc qu'il est normal que j'aie des 0 partout dans mon appli de calcul.
pourtant je pensais instancier 2 pointeurs distincts sur une même variable.
j'attends de tes nouvelles, avec commentaires, critiques et recommendations à l'appui.

<hr />







si Delphi m'était conté...
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
25 oct. 2007 à 16:36
la variable tableau et son type sont déclarés dans une unité commune à tous les processus

Partager une unité n'a aucune influence sur le partage de la mémoire.





Je trouve pas mes mots.


Chaque processus est de son point de vue tout seul avec Windows. Ils ne
communiquent pas entre eux si on ne les forces pas. Et c'est pas un
inclusion d'unité, qui n'est qu'un simple partage de code source, pas
executable (Il y aura qu'un .dcu, certe, mais il serat lié autant de
fois qu'il y a d'exes.)

C'est écrit là.


All threads of a process can access its virtual address space. However, threads cannot
access memory that belongs to another process, which protects a process from being corrupted by another
process.


Tous les threads d'un processus peuvent accèder à sont espace d'adresse
virtuel. Cependant, les threads ne peuvent accèder à la mémoire qui
appartient à un autre processus, ce qui protège une processus d'être
corrompus par un autre processus.
3ème année en ecole d'ingé d'info cherche stage de 4 mois à partir du 01/04/08
0
cs_mounjetado Messages postés 66 Date d'inscription lundi 13 mars 2006 Statut Membre Dernière intervention 4 août 2008
26 oct. 2007 à 09:15
ben à vrai dire, j'avais pensé à élaborer un objet interfacé, afin de protéger son accès par les différents processus. cela aurait-il pu résoudre mon problème?
le hic, c'est que je ne sais pas trop comment m'y prendre même si j'ai lu la marche à suivre sur différents sites et dans divers tutoriels.
en fait mon application toute entière demanderait une refonte toute entière pour mettre en oeuvre tout cela. et la direction s'impatiente et demande des résultats. il faut que je te précise un détail: à part qqs notions de C sous DOS, et l'assembleur Motorola, je n'ai pas vraiment de connaissances en programmation. je suis en fait électronicien, et autodidacte en langage de haut niveau
j'avais déjà essayé d'utiliser la mémoire partagée avec les accès sécurisés par sections critiques et autres mutex et sémaphores, les threads (mais ça ralentit au niveau performances), les interfaces (trop compliqué à ce stade ou alors je dois tout reprendre et je n'ai pas le temps), les services (mais je bute vite pour déboguer). bref, j'ai de sérieuses lacunes, et quand j'avance une solution, je n'ai pas les arguments ni, encore moins, les résultats pour étayer mon point de vue.
en tout cas, j'ai très bien compris maintenant ce qui coince, grâce à toi.
<hr />
si Delphi m'était conté...
0
cs_mounjetado Messages postés 66 Date d'inscription lundi 13 mars 2006 Statut Membre Dernière intervention 4 août 2008
26 oct. 2007 à 09:36
au fait rt15,
penses-tu que je pourrais instancier mon WalkMeasureAcquirer dans la fiche principale, et l'utiliser ensuite dans mes applis console, par le biais d'interfaces (1 de mesure, 1 de calcul), car cette variable représente une classe perso qui définit les fonctions de prises de mesure, dans une unité à part? mais je ne sais pas vraiment comment m'y prendre ni surtout l'ampleur des modifications à apporter! et si en plus, au bout du compte, ça ne marche pas...
<hr />
si Delphi m'était conté...
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
26 oct. 2007 à 12:27
Faire partager un objet et le faire accèder par des applis tierce via
une interface, c'est possible... en théorie. C'est pas courant du tout.
Difficile de trouver des exemples ou des tutos sur le sujet.


Par contre, mettre ton tableau dans une mémoire partagé et gérer les accès concurrent de manière basique, ça se fait très simplement.

3ème année en ecole d'ingé d'info cherche stage de 4 mois à partir du 01/04/08
0
cs_mounjetado Messages postés 66 Date d'inscription lundi 13 mars 2006 Statut Membre Dernière intervention 4 août 2008
5 nov. 2007 à 15:30
désolé, j'ai essayé et réessayé mais je n'ai jamais réussi à faire reconnaître ma mémoire partagée par les différents processus...
merci quand même pour cet exemple, même si on le retrouve partout, mais il est très mal documenté et nullement expliqué quant à son utilisation.aurais-tu un meilleur exemple d'utilisation?
le fait que je veuille partager de la mémoire entre application console n'est-il pas à la base de mon problème? sinon comment puis-je passer en paramètre le handle de la mémoire créée avec CreateFileMapping?
actuellement je crée un handle sur ma mémoire dans mon appli VCL et ensuite je crée un pointeur (mais est-ce bien utile à cet endroit?) sur la mémoire mappée. comment récupérer le handle dans mes appli console pour créer un pointeur dans chacune d'entre elles?
j'ai également mis en place des événements, pour tenter de synchroniser les actions des différentes applications, ainsi qu'une RTLCriticalSection. ne faut-il pas retirer la section critique, peut-être? je me dis que trop de sécurité peut être plutôt néfaste...
merci pour tes commentaires éclairés
<hr />
si Delphi m'était conté...
0
salim07360 Messages postés 17 Date d'inscription mardi 6 décembre 2005 Statut Membre Dernière intervention 22 janvier 2008
12 janv. 2008 à 18:12
salut , j bien lu ton message , mais je trouve qu'il ya des fautes au niveau des procedures , je c pas , mais , apparament c un grand probleme , j essayer d'appliquer , ce que tu vuens de dire , mais ça marche pas tjrs , essaye d'organizer 1 peu la liaison entre ton programme et les procedures et les fonctions que tu'utilises , komça , ça ira mieux , a mon avis ....voilà , et j'attend ta reponse .....merçi
0
Rejoignez-nous