IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

[D7] Utilisation de CreateProcess


Sujet :

Langage Delphi

  1. #1
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 370
    Points : 3 144
    Points
    3 144
    Par défaut [D7] Utilisation de CreateProcess
    Bonjour,

    dans mes applications, pour afficher du texte dans NotePad, j'utilise CreateProcess comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    { ====================================================================== }
    Function TF_Princ.LanceNotePad(Fichier : String): dword;
    // Lancement de Notepad avec CreateProcess
    //  renvoie le Handle du process
    //  il faut ajouter la déclaration :
    //      function GetThreadId(Thread: THandle): dword; stdcall; external 'Kernel32.dll';
    var
      StartupInfo: TStartupInfo;
      ProcessInfo: TProcessInformation;
      CommandLine: {$IFDEF UNICODE}WideString{$ELSE}string{$ENDIF};
    Begin
      Result := 0 ;
      If not FileExists(Fichier) Then
        Begin
          MessageDlg('Fichier '+Fichier+' introuvable' , mtError, [mbOk], 0) ;
          Exit ;
        End ;
      CommandLine := '"Notepad.exe" "'+Fichier+'"' ;
      ZeroMemory(@StartupInfo, SizeOf(StartupInfo)) ;
      StartupInfo.cb := SizeOf(StartupInfo) ;
      if CreateProcess(nil, PChar(CommandLine), nil, nil, FALSE, 0, nil, nil, StartupInfo, ProcessInfo) then
        Begin
          Result := GetThreadID(ProcessInfo.hThread);
          CloseHandle(ProcessInfo.hProcess);
          CloseHandle(ProcessInfo.hThread);
        End;
    End ;
    { ====================================================================== }
    Est il possible de donner la position, la taille et le titre du Notepad qui s'ouvre ?

    C'est dans StartupInfo ?

    Merci
    A+
    Charly

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    CreateProcess & FindWindow, code très court et possible mais un peu hazardeux

    CreateProcess, EnumWindows & GetWindowThreadProcessId avec l'ID du process retourné par CreateProcess

    Ce sujet devrait te plaire : Mettre une fenêtre externe au premier plan !

    Perso, j'ai une classe TSLTShellExecuteWrapper, on la trouve sur le forum en entier, je m'en sers pour échanger des données au démarrage, un peu comme DDE mais via un échange de message via une fenêtre invisble (comme le TTimer par exemple), l'application appelée peut me retouner des infos dont le Handle de sa MainForm mais cela implique de coder l'appelant et l'appelé

    Dans un projet vieux de 10 ans, une sorte d'application portail, elle lançait d'autres EXE, à sa fermeture, elle fermait toutes les fenêtres des EXE lancés qui est une démonstration de EnumWindows & GetWindowThreadProcessId

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    //------------------------------------------------------------------------------
    function TModuleXXXXMainForm.CloseChildProcesses(): Boolean;
    type
      PBufferWindowTexts = ^TBufferWindowTexts;
      TBufferWindowTexts = record
        Data: PChar;
        Position: PByte;
        Size: Integer;
        Count: Integer;
      end;
     
      function EnumWindowsCallback(hWnd: HWND; lParam: LPARAM): BOOL; stdcall;
      var
        ProcessIdOfWnd: DWORD;
        I: Integer;
        TextOfWnd: array[0..255] of Char;
        WindowText: string;
        Len: Integer;
      begin
        Result := True;
        if GetWindowThreadProcessId(hWnd, ProcessIdOfWnd) > 0 then
        begin
          for I := 0 to TModuleXXXX.ModuleTool.ShellExecuteProcessIdList.Count - 1 do
          begin
            if ProcessIdOfWnd = TModuleXXXX.ModuleTool.ShellExecuteProcessIdList[I] then
            begin
              // Que les fenêtres visibles !
              if IsWindowVisible(hWnd) then
              begin
                if GetWindowText(hWnd, TextOfWnd, Length(TextOfWnd)) > 0 then
                begin
                  WindowText := ' - ' + TextOfWnd + string(sLineBreak);
                  Len := Length(WindowText) * SizeOf(WindowText[1]);
                  if PBufferWindowTexts(lParam).Position + Len <= PBufferWindowTexts(lParam).Data + PBufferWindowTexts(lParam).Size then
                  begin
                    CopyMemory(PBufferWindowTexts(lParam).Position, @WindowText[1], Len);
                    Inc(PBufferWindowTexts(lParam).Position, Len);
                    Inc(PBufferWindowTexts(lParam).Count);
                  end
                  else
                    Result := False; // Buffer plein !
                end;
              end;
            end;
          end;
        end;
      end;
     
    var
      MsgConfirm: string;
      I: Integer;
      HandleFunctionProcess: THandle;
      BufferWindowTexts: TBufferWindowTexts;
    begin
      Result := True;
      if TModuleXXXX.ModuleTool.IsCitrix() then
      begin
        if TModuleXXXX.ModuleTool.ShellExecuteProcessIdList.Count >= 1 then
        begin
          BufferWindowTexts.Count := 0;
          BufferWindowTexts.Size := 1024;
          GetMem(BufferWindowTexts.Data, BufferWindowTexts.Size);
          try
            ZeroMemory(BufferWindowTexts.Data, BufferWindowTexts.Size);
            BufferWindowTexts.Position := PByte(BufferWindowTexts.Data);
            EnumWindows(@EnumWindowsCallback, LPARAM(@BufferWindowTexts));
            if BufferWindowTexts.Count > 0 then
            begin
              MsgConfirm := 'Fermer le Module XXXX et les modules liés ?'+sLineBreak+'Attention, il y a un risque de perte de données dans les modules liés!'+sLineBreak;
              if BufferWindowTexts.Count = 1 then
                MsgConfirm := MsgConfirm + 'Le module lié : '
              else
                MsgConfirm := MsgConfirm +Format('Les %d modules liés : ', [TModuleXXXX.ModuleTool.ShellExecuteProcessIdList.Count]);
     
              Result :=  MessageDlg(MsgConfirm + sLineBreak + BufferWindowTexts.Data, mtWarning, mbYesNo, 0) = mrYes;
              if Result then
              begin
                for I := 0 to TModuleXXXX.ModuleTool.ShellExecuteProcessIdList.Count - 1 do
                begin
                  HandleFunctionProcess := OpenProcess(PROCESS_TERMINATE, False, TModuleXXXX.ModuleTool.ShellExecuteProcessIdList[I]);
                  if HandleFunctionProcess > 0 then
                  begin
                    // Arrêt du process désigné par HandleProcess. Tous ses threads sont également arrétés.
                    // C'est brutal
                    if not TerminateProcess(HandleFunctionProcess, 0) then
                      MessageDlg('Echec de fermeture d''un module lié !', mtError, [mbIgnore], 0);
     
                    CloseHandle(HandleFunctionProcess);
                  end;
                end;
              end;
            end;
          finally
            FreeMem(BufferWindowTexts.Data);
          end;
        end;
      end;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 370
    Points : 3 144
    Points
    3 144
    Par défaut
    Bonjour Shai,
    Merci, je vais examiner ton lien.

    mon code marche très bien et je ferme automatiquement NotePad en fin d'appli avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    { ====================================================================== }
    Function TF_Princ.FermeNotePad(ImpID : dWord ) : Boolean ;
    // Fermeture du Process ImpID (par exemple Notepad
    //  Lancé par LanceNotePad
    Begin
      Result := PostThreadMessage(ImpID, WM_QUIT, 0, 0);
    End ;
    { ====================================================================== }
    Pourquoi mon code est il hasardeux ?

    A+
    Charly

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Citation Envoyé par Charly910 Voir le message
    Pourquoi mon code est il hasardeux ?
    C'est la combinaison "CreateProcess & FindWindow" qui est hasardeurse comparée à "CreateProcess, EnumWindows", comme vous n'avez pas utiliser FindWindow, cela ne vous concerne pas


    Sinon, vous n'aviez pas précisé que le besoin était de fermer NotePad mais de trouver la fenêtre pour en changer sa taille, sa position et son texte, cette partie, vous n'avez pas donnée votre approche
    Je suppose dwFlags à STARTF_USEPOSITION et dwX; dwY; dwXSize; et dwYSize ainsi que lpTitle mais parfois c'est totalement ignoré il faut compenser en trouvant la fenêtre et faire un SetWindowPos et SetWindowText
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 370
    Points : 3 144
    Points
    3 144
    Par défaut
    Ok, merci,
    effectivement dwx et dwy ne fonctionnent pas avec la fenêtre Notepad. Il faudrait que je fasse un FindWindow

    A+
    Charly

  6. #6
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 504
    Points : 2 773
    Points
    2 773
    Billets dans le blog
    10
    Par défaut
    Bonjour J'ai trouvé cette ligne de code qui permet de changer de Main Form il y a quelques temps
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Pointer((@Application.MainForm)^) := FormAPP
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    procedure TFormDemarre.FormActivate(Sender: TObject);
    begin
    .../...
      if not assigned(FormAPP) then
      begin
        Application.CreateForm(TFormAPP, FormAPP);
        Pointer((@Application.MainForm)^) := FormAPP;
    Ainsi FormDemarre fait son travail d'initialisations et quand tout est OK crée et passe la main à la fiche principale

  7. #7
    Membre expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 370
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 370
    Points : 3 144
    Points
    3 144
    Par défaut
    Bonjour,
    j'ai utilisé le code de illuch dans le lien fourni par ShaiLeTroll :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    procedure TForm2.FormShow(Sender: TObject);
    var Hdl:Thandle;
        TitreFenetre:string;
        X,Y:integer;
        i:integer;
     
    begin
      CentrerFichesurFicheAvecOffet(Form2,Form1,0,0); //procedure pour centrer une fiche par rapport à une autre avec offsets (ici offsets nuls)
     // Affichage du fichier texte externe
     ShellExecute(Handle,'open',PChar(Nom_Fichier),nil,nil,SW_SHOW); 
     
     // Position voulue de la fenêtre de notepad     
     X:=Form2.left-320;
     Y:=Form1.Top;
     
     TitreFenetre := ExtractFileName(Nom_Fichier)+#160'- Bloc-notes'; // indispensable de mettre #160 sinon on ne retrouve pas la fenêtre
     
     // Boucle d'attente pour laisser le temps à notepad de s'afficher
     for i := 1 to 40 do begin
       Hdl := FindWindow('NotePad', Pchar(TitreFenetre));
       if Hdl <> 0 then Break;
       Sleep( 50 );
      end;
     
     SetWindowPos(hdl,HWND_TOPMOST,X,Y,300,500,0);  // Pour forcer le placement de la fenêtre notepad à gauche de Form2
     
    end;
    Merci à tous

    A+
    Charly

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Utilisation de CreateProcess()
    Par Stochelo dans le forum Threads & Processus
    Réponses: 5
    Dernier message: 05/06/2013, 11h52
  2. Utilisation de CreateProcess
    Par Faern dans le forum Threads & Processus
    Réponses: 1
    Dernier message: 02/11/2010, 03h20
  3. Problème d'utilisation de CreateProcess
    Par Mister Nowis dans le forum Windows
    Réponses: 4
    Dernier message: 22/03/2010, 11h34
  4. Réponses: 5
    Dernier message: 14/02/2007, 17h06
  5. Réponses: 2
    Dernier message: 05/04/2004, 23h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo