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

VB.NET Discussion :

Synchronisation de SetWindwosPos avec un process.start (fichier exe)


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé Avatar de excalybur
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Novembre 2014
    Messages
    317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Chargé d'affaire
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2014
    Messages : 317
    Par défaut Synchronisation de SetWindwosPos avec un process.start (fichier exe)
    Bonjour,

    Je lance un fichier exécutable (notepad.exe pour exemple) depuis le Form.

    Par défaut il s'affiche en format minimized (1/4 de l'écran) à un emplacement aléatoire.

    Je dimensionne et positionne la fenêtre du process en cours avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SetWindowPos(myProcess1.MainWindowHandle, IntPtr.Zero, 0, 0, 800, 1000, 0)
    Mon programme :

    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
     Using myProcess1 As New Process()
     
     
                                                myProcess1.StartInfo.FileName = "C:\notepad.exe"   'charge le processus 
     
                                                myProcess1.Start() 'lance le process
     
                                                Thread.Sleep(100) 'laisse le temps au pocess de se lancer
     
                                                SetWindowPos(myProcess1.MainWindowHandle, IntPtr.Zero, 0, 0, 800, 1000, 0)  'dimensionner la fenêtre process 
     
                                                SetWindowText(myProcess1.MainWindowHandle, "TITRE NUMERO UN")  'change le titre de la fenêtre process
     
                                                'fermer la fenêtre en fin de processus :
                                                myProcess1.WaitForExit()  'attend qu'il soit terminé avant d'aller plus loin
                                                myProcess1.Close()  'ferme le process
                                            End Using
    On note que laisse le temps au pocess de se lancer sauf que dans certains cas (mise à jour du PC, etc.) ce délai est trop court et le process démarre définitivement dans le format aléatoire vu plus haut.

    Si j'augmente la durée de Thread.Sleep l'écran va flasher une fraction de seconde sur le format aléatoire avant de passer au format imposé. => pas terrible !

    Bien sur on ne peut pas mettre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SetWindowPos(myProcess1.MainWindowHandle, IntPtr.Zero, 0, 0, 800, 1000, 0)
    avant myProcess1.Start

    Ma question :

    Comment synchroniser SetWindowPos avec myProcess1.Start pour éviter les problèmes évoqués ci-dessus. Je n'ai rien trouvé sur les rares sujets traitant du sujet

    En vous remerciant pour votre aide.

    Bien à vous

  2. #2
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    bonjour

    Code exemple qui fera peut être ton bonheur:
    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
     
    Imports System.Runtime.InteropServices
    Public Class Form1
        Private myProcess As Process
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            'Dim pi As New ProcessStartInfo
            'pi.FileName = "notepad"
            'myProcess = New Process
            'myProcess.StartInfo = pi
            'myProcess.Start()
        End Sub
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
     
            StartProcess()
            If myProcess Is Nothing Then Return
            myProcess.WaitForInputIdle()
            Dim handle As IntPtr = myProcess.MainWindowHandle
            If handle <> IntPtr.Zero Then
                SetWindowPos(handle, 0, 150, 0, 400, 250, 0)
            End If
     
     
        End Sub
        Private Sub StartProcess()
            Dim pi As New ProcessStartInfo
            pi.FileName = "notepad"
            myProcess = New Process
            myProcess.StartInfo = pi
            myProcess.Start()
     
        End Sub
      Private Sub Form1_FormClosing(sender As System.Object, e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
            If myProcess IsNot Nothing Then
                myProcess.WaitForExit()
                myProcess.CloseMainWindow()
            End If
        End Sub
     
        <DllImport("user32.dll", EntryPoint:="SetWindowPos")>
        Public Shared Function SetWindowPos(HWND As IntPtr,
                                            hWndInsertAfter As IntPtr,
                                            Xpos As Integer, Ypos As Integer, xSize As Integer, ySize As Integer, wFlags As Integer) As IntPtr
        End Function
     
     
    End Class
    bon code ...

  3. #3
    Membre éprouvé Avatar de excalybur
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Novembre 2014
    Messages
    317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Chargé d'affaire
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2014
    Messages : 317
    Par défaut
    Merci pour la réponse,

    J'étudie la chose car apparemment cela ne marche pas avec tous les exe.

    Je reviens vers vous après mon analyse.

  4. #4
    Membre éprouvé Avatar de excalybur
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Novembre 2014
    Messages
    317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Chargé d'affaire
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2014
    Messages : 317
    Par défaut
    Bonsoir,

    Excusez-moi pour ce retard j'ai dû régler des urgences en ces temps compliqué.

    Pour revenir au sujet de la discussion, j'ai essayé le code proposé et il fonctionne parfaitement avec Notepad.exe

    Par contre en remplaçant notepad.exe avec mon exe

    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
    Imports System.Runtime.InteropServices
    Imports System.Threading
     
    Public Class Form1
        Private myProcess As Process
     
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
     
            Dim pi As New ProcessStartInfo
            '  pi.FileName = "notepad"
            pi.FileName = "d:\sbwin\py483USR\pywin64.exe"
            myProcess = New Process
            myProcess.StartInfo = pi
            myProcess.Start()
     
            If myProcess Is Nothing Then Return
            myProcess.WaitForInputIdle()
            Dim handle As IntPtr = myProcess.MainWindowHandle
            If handle <> IntPtr.Zero Then
                SetWindowPos(handle, 0, 150, 0, 600, 250, 0)
            End If
        End Sub
     
        Private Sub Form1_FormClosing(sender As System.Object, e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
            If myProcess IsNot Nothing Then
                myProcess.WaitForExit()
                myProcess.CloseMainWindow()
            End If
        End Sub
     
        <DllImport("user32.dll", EntryPoint:="SetWindowPos")>
        Public Shared Function SetWindowPos(HWND As IntPtr,
                                            hWndInsertAfter As IntPtr,
                                            Xpos As Integer, Ypos As Integer, xSize As Integer, ySize As Integer, wFlags As Integer) As IntPtr
        End Function
     
    End Class
    j'obtiens une erreur à la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    myProcess.WaitForInputIdle()
    qui précise : "Echec de WaitForInputIdle. Cet échec est peut-être dû à l'absence d'interface graphique pour le processus"

    Cette curieuse erreur n'a pas de sens (pour l'interface graphique) à mon avis car avec la version que je propose dans le topic initial mon EXE fonctionne nickel sauf pour ce qui est du problème d'affichage parfois aléatoire.

    En fait la fenêtre minimized et à une position aléatoire de mon application apparait bien et de plus fonctionne bien. Sauf que la fenêtre n'a pas pris la bonne taille. Il y a un autre problème avec SetWindowsPos. (Problème inexistant dans mon application initiale).

    Je pense que le problème est dû à la configuration de certains EXE. Il manque peut être un Import et une précision du WaitForInputIdle ?

    J'ai passé beaucoup de temps à essayer de trouver une explication et là j'avoue je cale !

    Si quelqu'un à une idée car on est pas loin d'une application utile pour tous les EXE.

    A vous lire

  5. #5
    Membre extrêmement actif
    Inscrit en
    Avril 2008
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Âge : 65

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 573
    Par défaut
    bonjour

    Je pense qu'il faut sortir le code de positionnement dans un second button:
    code vb.net modifie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
            If myProcess IsNot Nothing Then
                myProcess.WaitForInputIdle()
                Dim handle As IntPtr = myProcess.MainWindowHandle
                If handle <> IntPtr.Zero Then
                    Dim retval = SetWindowPos(handle, 0, 400, 400, 100, 100, 0)
                End If
            End If
        End Sub

  6. #6
    Membre éprouvé Avatar de excalybur
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Novembre 2014
    Messages
    317
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Chargé d'affaire
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2014
    Messages : 317
    Par défaut
    Bonsoir,

    Merci pour ta réponse. Je ne vois pas pourquoi avec un deuxième bouton cela devrait fonctionner car je ne comprends pas la logique. A moins que tu ne veuille donner du temps à mon exe. c'est vrai qu'il met une bonne seconde pour s'afficher.

    En rendant ton sub public et en le testant avec un deuxième bouton j'ai toujours le retour de la même erreur.

    Précision cet exe a été écrit en langage C sous Linux mais pour application Windows 64.

    Il serait intéressant de faire le test avec d'autre exe pour console.

    Je continu à creuser !

    [Edit - complément]

    En recherchant sur les sites anglophones, le problème est récurant. Si notepad marche il n'en est rien pour cmd.exe

    Avec le test avec cmd.exe j'obtiens le même message d'erreur que pour mon programme pywin64

    Il semblerait (version du topic pour VB de 2014 ) qu'il s'agirait d'un problème lié aux UI sans autres explications.

    Si vous avez une idée ?

    A vous lire.

    Bien à vous

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

Discussions similaires

  1. process.start et .exe cmd
    Par GrosF***.fr dans le forum C#
    Réponses: 0
    Dernier message: 08/07/2010, 20h15
  2. [VB.NET 1.1] Ping silencieux avec Process.Start()
    Par toniolol dans le forum Windows Forms
    Réponses: 6
    Dernier message: 30/09/2008, 13h35
  3. Process.start avec un processus père
    Par DranDane dans le forum C#
    Réponses: 2
    Dernier message: 24/09/2008, 14h02
  4. Réponses: 4
    Dernier message: 02/04/2008, 15h19
  5. Probleme avec Process.Start
    Par lucyole dans le forum VB.NET
    Réponses: 4
    Dernier message: 03/01/2008, 18h42

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