violent_ken
Messages postés1812Date d'inscriptionmardi 31 mai 2005StatutMembreDernière intervention26 octobre 2010
-
31 août 2006 à 18:09
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 2021
-
16 mai 2011 à 09:46
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 16 mai 2011 à 09:46
AppActivate ne saurait donc pas restaurer une application minimisée, mais uniquement celles qui seraient masquées par une autre fenêtre ?
Philippe734
Messages postés308Date d'inscriptionlundi 16 décembre 2002StatutMembreDernière intervention15 juin 20151 13 mai 2011 à 21:24
J'utilise cette source dans plusieurs de mes programmes.
Alors, ok, je reformule.
L'objet de la source, est d'afficher une application déjà exécutée, si on exécute de nouveau le programme.
En principe, la ligne suivante, doit afficher l'application, si elle déjà exécutée :
AppActivate hPid
Dans la plupart des cas, ça fonctionne très bien.
Mais, parfois, pour une raison que j'ignore, au passage de la ligne, rien ne se passe. L'application déjà exécutée, ne s'affiche pas.
Alors, j'ai remplacé la ligne par l'usage de ces 3 API :
SetForegroundWindow hPid
ShowWindow hPid, SW_RESTORE
BringWindowToTop hPid
Alors dans ce cas, à chaque fois, l'application déjà exécutée est affichée.
Bon, tout ça pour informer les usager de cette source. Si leur programme n'est pas affichée - alors qu'il était déjà exécutée - ils peuvent donc utiliser ces 3 API.
:-)
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 11 mai 2011 à 08:25
j'ai pas compris ce post scriptum...
Philippe734
Messages postés308Date d'inscriptionlundi 16 décembre 2002StatutMembreDernière intervention15 juin 20151 10 mai 2011 à 21:02
J'ai oublié de préciser que mon hFrm est le hPid de la source originale
Philippe734
Messages postés308Date d'inscriptionlundi 16 décembre 2002StatutMembreDernière intervention15 juin 20151 10 mai 2011 à 20:47
Pour une raison que je ne comprend pas, la ligne suivante ne fonctionne pas tout le temps. Elle doit afficher l'application déjà ouverte.
AppActivate hPid
Comme je n'ai pas cherché la raison, je l'ai remplacé par :
SetForegroundWindow hFrm
ShowWindow hFrm, SW_RESTORE
BringWindowToTop hFrm
:-)
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 12 mars 2010 à 06:55
exact^^
Philippe734
Messages postés308Date d'inscriptionlundi 16 décembre 2002StatutMembreDernière intervention15 juin 20151 12 mars 2010 à 00:20
manque la déclaration : Private mbHasBeenQueriedOnce As Boolean
Merci pour la source
violent_ken
Messages postés1812Date d'inscriptionmardi 31 mai 2005StatutMembreDernière intervention26 octobre 20102 7 mai 2009 à 17:03
Salut,
voilà la conversion VB.Net.
Il manque quelques déclarations (CloseHandle... ) faciles à convertir un VB.Net.
J'ai gardé AppActivate pour pas se prendre la tête même si çà fait pas trop VB.Net...
Public Const FILE_MAP_READ As Integer = SECTION_MAP_READ
Public Const FILE_MAP_WRITE As Integer = SECTION_MAP_WRITE
Public Const PAGE_READWRITE As Integer = &H4
Public Const SECTION_MAP_READ As Integer = &H4
Public Const SECTION_MAP_WRITE As Integer = &H2
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function CreateFileMapping(ByVal hFile As IntPtr, ByVal lpFileMappingAttributes As IntPtr, ByVal flProtect As FileMapProtection, ByVal dwMaximumSizeHigh As UInteger, ByVal dwMaximumSizeLow As UInteger, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpName As String) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Public Shared Function OpenFileMapping(ByVal dwDesiredAccess As UInteger, ByVal bInheritHandle As Boolean, ByVal lpName As String) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Public Shared Function UnmapViewOfFile(ByVal lpBaseAddress As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Public Shared Function MapViewOfFile(ByVal hFileMappingObject As IntPtr, ByVal dwDesiredAccess As FileMapAccess, ByVal dwFileOffsetHigh As UInteger, ByVal dwFileOffsetLow As UInteger, ByVal dwNumberOfBytesToMap As UInteger) As IntPtr
End Function
<Flags()> _
Public Enum FileMapAccess As UInteger
FileMapCopy = &H1
FileMapWrite = &H2
FileMapRead = &H4
FileMapAllAccess = &H1F
fileMapExecute = &H20
End Enum
Private Function IsAlreadyRunning() As Boolean
Dim hMap As IntPtr
Dim pMem As IntPtr
Dim hPid As Integer
Const FILE_NAME As String = "TITLE OF THE APP"
'# Nous tentons ici d'acceder au mappage (précedemment créé ?)
hMap = OpenFileMapping(FILE_MAP_READ, False, FILE_NAME)
If hMap <> IntPtr.Zero Then
'# L'application est déjà lancée.
pMem = MapViewOfFile(hMap, FileMapAccess.FileMapRead, 0, 0, 0)
If pMem <> IntPtr.Zero Then
'# On récupère le handle vers la précédente fenêtre
hPid = Marshal.ReadInt32(pMem, 0)
If hPid <> 0 Then
'# On active l'instance précedente
AppActivate(hPid)
End If
UnmapViewOfFile(pMem)
End If
'# On libère le handle hmap
CloseHandle(hMap)
'# et on prévient l'appelant que l'application avait dejà été lancée.
Return True
Else
'# Nous sommes dans la première instance de l'application.
'# Nous allons laisser une marque en mémoire, pour l'indiquer
hMap = CreateFileMapping(New IntPtr(-1), IntPtr.Zero, FileMapProtection.PageReadWrite, 0, 4, FILE_NAME)
If hMap <> IntPtr.Zero Then
'# On ouvre le 'fichier' en écriture
pMem = MapViewOfFile(hMap, FileMapAccess.FileMapWrite, 0, 0, 0)
If pMem <> IntPtr.Zero Then
'# On y écrit l'ID du process courant
Marshal.WriteInt32(pMem, 0, GetCurrentProcessId)
UnmapViewOfFile(pMem)
End If
'# Pas de CloseHandle hMap ici, sous peine de détruire le mappage lui-même...
End If
End If
Return False
End Function
@+
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 13 juil. 2007 à 04:01
SECTION_MAP_READ est définie juste en dessous :
Private Const SECTION_MAP_READ As Long = &H4
étrange qu'il m'ai laissé les inverser :/
cs_piluc
Messages postés2Date d'inscriptionjeudi 9 février 2006StatutMembreDernière intervention11 juillet 2007 11 juil. 2007 à 23:56
Ça marche pas ça me fait une Compile error: Constant expression required à la ligne:
Private Const FILE_MAP_READ As Long = SECTION_MAP_READ
Dommage,
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 5 sept. 2006 à 16:11
Bien d'accord avec toi EB, là, l'utilisateur n'a plus a mofifier son code IDE/EXE
cs_EBArtSoft
Messages postés4525Date d'inscriptiondimanche 29 septembre 2002StatutModérateurDernière intervention22 avril 20199 5 sept. 2006 à 15:43
Tient on rentre dans des considerations Vébésienne ?
Utiliser cette fonction dans l'IDE n'a strictement aucun sens...
@+
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 5 sept. 2006 à 14:57
Bonne remarque.
La fonction renvoie désormais toujours False, si elle est appelée depuis l'IDE.
cs_moustachu
Messages postés1079Date d'inscriptionjeudi 14 novembre 2002StatutMembreDernière intervention 1 janvier 2012 5 sept. 2006 à 14:04
Merci pour ces précisions.
++
Moustachu
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 5 sept. 2006 à 13:46
Dans l'IDE, ton prog n'est pas autonome, il tourne dans la VM au complet donc doit rester en mémoire.
Windows ne libère les handle qu'en cas de démappage mémoire du prog, serait en ce cas la VM.
cs_moustachu
Messages postés1079Date d'inscriptionjeudi 14 novembre 2002StatutMembreDernière intervention 1 janvier 2012 5 sept. 2006 à 13:33
Bonjour à tous,
J'ai un petit soucis lorsque que je lance depuis l'ide : au deuxième lancement, l'appli ne se lance pas. J'ai l'impression que l'info reste en mémoire tant que l'IDE reste ouvert. Je teste donc si l'appli est lancée depuis l'IDE. Peut-être que mon appli ne se ferme pas correctement ?
++
Moustachu
cs_kalif
Messages postés362Date d'inscriptionmardi 18 décembre 2001StatutMembreDernière intervention24 août 2012 3 sept. 2006 à 23:04
ha j'avais pas compris qu'il fallais le mettre au premier plan dsl
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 3 sept. 2006 à 19:38
Ce n'est pas un mutex qui aidera à ramener l'ancienne instance au 1er plan et c'est précisément ce que l'utilisateur attend quand il lance un prog, qu'il soit devant.
cs_kalif
Messages postés362Date d'inscriptionmardi 18 décembre 2001StatutMembreDernière intervention24 août 2012 3 sept. 2006 à 12:21
si mes souvenirs sont bons on peut aussi utiliser l'API CreateMutexA...
cs_EBArtSoft
Messages postés4525Date d'inscriptiondimanche 29 septembre 2002StatutModérateurDernière intervention22 avril 20199 1 sept. 2006 à 12:38
Attention pour repredre la remarque de BruNews si vous utilisz le code de Renfield dans l'evenemtn Load d'une form ou d'un control il ce pourrait bien que qu'il soit executé plusieurs fois si l'on ne fait pas gaffe ex:
Form1.show...
'Puis on clique sur la croix pour fermé le fenetre
'plus loin
if form1.xxx = yyy then
Dans ce cas et dans bien d'autre VB recharge la fenetre mieux vaux utiliser ce code uniquement dans une "sub main"
@+
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 1 sept. 2006 à 11:32
vi, c'est ce que j'ai mis dans le commentaire sur la source....
là, on active même l'ancienne instance ^^
violent_ken
Messages postés1812Date d'inscriptionmardi 31 mai 2005StatutMembreDernière intervention26 octobre 20102 1 sept. 2006 à 11:25
Non (dans le cas ou tu as copié l'exécutable dans un autre dossier).
@+
cuq
Messages postés345Date d'inscriptionmardi 3 juin 2003StatutMembreDernière intervention21 mars 20082 1 sept. 2006 à 11:24
Alors je vais jouer les naifs mais moi j'utilise simplement dans le form_load
If App.PrevInstance Then End
C'est pas suffisant ?
cs_moustachu
Messages postés1079Date d'inscriptionjeudi 14 novembre 2002StatutMembreDernière intervention 1 janvier 2012 1 sept. 2006 à 10:17
Bonjour,
Joli tout ça, j'avais essayé de résoudre ce "problème" de manière bien moins propre et pas du tout sûre à 100%.
Je préfère pas raconter ce que j'avais fait ;o)
J'adopte !!
Moustachu
cs_EBArtSoft
Messages postés4525Date d'inscriptiondimanche 29 septembre 2002StatutModérateurDernière intervention22 avril 20199 31 août 2006 à 19:25
Autant fermé VBFrance et ouvrir une boite d'interim spécialisé !
Le mot "Apte" perd tout son sens ici bas...
:)
@+
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 31 août 2006 à 18:53
La fonction a un rôle précis, être appelée UNE SEULE FOIS au point d'entrée du prog et absolument pas nimporte comment.
Comme toute portion de code, elle doit être utilisée par des personnes aptes à le faire sinon conseiller le recyclage dans le terrassement ou autre.
cs_EBArtSoft
Messages postés4525Date d'inscriptiondimanche 29 septembre 2002StatutModérateurDernière intervention22 avril 20199 31 août 2006 à 18:34
Probleme de fuite si on appel plusieurs fois IsAlreadyRunning !
Le mieu serait d'en faire une classe et de liberer le handle dans "Terminate"
@+
violent_ken
Messages postés1812Date d'inscriptionmardi 31 mai 2005StatutMembreDernière intervention26 octobre 20102 31 août 2006 à 18:09
Cà fait beaucoup de lignes de code ;)
On pourrait aussi checker que le path (+exename) de notre application n'est pas le path (+exename) d'un processus déjà lancé, quoique ce serait plus lourd. Quoique.
16 mai 2011 à 09:46
13 mai 2011 à 21:24
Alors, ok, je reformule.
L'objet de la source, est d'afficher une application déjà exécutée, si on exécute de nouveau le programme.
En principe, la ligne suivante, doit afficher l'application, si elle déjà exécutée :
AppActivate hPid
Dans la plupart des cas, ça fonctionne très bien.
Mais, parfois, pour une raison que j'ignore, au passage de la ligne, rien ne se passe. L'application déjà exécutée, ne s'affiche pas.
Alors, j'ai remplacé la ligne par l'usage de ces 3 API :
SetForegroundWindow hPid
ShowWindow hPid, SW_RESTORE
BringWindowToTop hPid
Alors dans ce cas, à chaque fois, l'application déjà exécutée est affichée.
Bon, tout ça pour informer les usager de cette source. Si leur programme n'est pas affichée - alors qu'il était déjà exécutée - ils peuvent donc utiliser ces 3 API.
:-)
11 mai 2011 à 08:25
10 mai 2011 à 21:02
10 mai 2011 à 20:47
AppActivate hPid
Comme je n'ai pas cherché la raison, je l'ai remplacé par :
SetForegroundWindow hFrm
ShowWindow hFrm, SW_RESTORE
BringWindowToTop hFrm
:-)
12 mars 2010 à 06:55
12 mars 2010 à 00:20
Merci pour la source
7 mai 2009 à 17:03
voilà la conversion VB.Net.
Il manque quelques déclarations (CloseHandle... ) faciles à convertir un VB.Net.
J'ai gardé AppActivate pour pas se prendre la tête même si çà fait pas trop VB.Net...
Public Const FILE_MAP_READ As Integer = SECTION_MAP_READ
Public Const FILE_MAP_WRITE As Integer = SECTION_MAP_WRITE
Public Const PAGE_READWRITE As Integer = &H4
Public Const SECTION_MAP_READ As Integer = &H4
Public Const SECTION_MAP_WRITE As Integer = &H2
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function CreateFileMapping(ByVal hFile As IntPtr, ByVal lpFileMappingAttributes As IntPtr, ByVal flProtect As FileMapProtection, ByVal dwMaximumSizeHigh As UInteger, ByVal dwMaximumSizeLow As UInteger, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpName As String) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Public Shared Function OpenFileMapping(ByVal dwDesiredAccess As UInteger, ByVal bInheritHandle As Boolean, ByVal lpName As String) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Public Shared Function UnmapViewOfFile(ByVal lpBaseAddress As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Public Shared Function MapViewOfFile(ByVal hFileMappingObject As IntPtr, ByVal dwDesiredAccess As FileMapAccess, ByVal dwFileOffsetHigh As UInteger, ByVal dwFileOffsetLow As UInteger, ByVal dwNumberOfBytesToMap As UInteger) As IntPtr
End Function
<Flags()> _
Public Enum FileMapAccess As UInteger
FileMapCopy = &H1
FileMapWrite = &H2
FileMapRead = &H4
FileMapAllAccess = &H1F
fileMapExecute = &H20
End Enum
<Flags()> _
Public Enum FileMapProtection As UInteger
PageReadonly = &H2
PageReadWrite = &H4
PageWriteCopy = &H8
PageExecuteRead = &H20
PageExecuteReadWrite = &H40
SectionCommit = &H8000000
SectionImage = &H1000000
SectionNoCache = &H10000000
SectionReserve = &H4000000
End Enum
Private Function IsAlreadyRunning() As Boolean
Dim hMap As IntPtr
Dim pMem As IntPtr
Dim hPid As Integer
Const FILE_NAME As String = "TITLE OF THE APP"
'# Nous tentons ici d'acceder au mappage (précedemment créé ?)
hMap = OpenFileMapping(FILE_MAP_READ, False, FILE_NAME)
If hMap <> IntPtr.Zero Then
'# L'application est déjà lancée.
pMem = MapViewOfFile(hMap, FileMapAccess.FileMapRead, 0, 0, 0)
If pMem <> IntPtr.Zero Then
'# On récupère le handle vers la précédente fenêtre
hPid = Marshal.ReadInt32(pMem, 0)
If hPid <> 0 Then
'# On active l'instance précedente
AppActivate(hPid)
End If
UnmapViewOfFile(pMem)
End If
'# On libère le handle hmap
CloseHandle(hMap)
'# et on prévient l'appelant que l'application avait dejà été lancée.
Return True
Else
'# Nous sommes dans la première instance de l'application.
'# Nous allons laisser une marque en mémoire, pour l'indiquer
hMap = CreateFileMapping(New IntPtr(-1), IntPtr.Zero, FileMapProtection.PageReadWrite, 0, 4, FILE_NAME)
If hMap <> IntPtr.Zero Then
'# On ouvre le 'fichier' en écriture
pMem = MapViewOfFile(hMap, FileMapAccess.FileMapWrite, 0, 0, 0)
If pMem <> IntPtr.Zero Then
'# On y écrit l'ID du process courant
Marshal.WriteInt32(pMem, 0, GetCurrentProcessId)
UnmapViewOfFile(pMem)
End If
'# Pas de CloseHandle hMap ici, sous peine de détruire le mappage lui-même...
End If
End If
Return False
End Function
@+
13 juil. 2007 à 04:01
Private Const SECTION_MAP_READ As Long = &H4
étrange qu'il m'ai laissé les inverser :/
11 juil. 2007 à 23:56
Private Const FILE_MAP_READ As Long = SECTION_MAP_READ
Dommage,
5 sept. 2006 à 16:11
5 sept. 2006 à 15:43
Utiliser cette fonction dans l'IDE n'a strictement aucun sens...
@+
5 sept. 2006 à 14:57
La fonction renvoie désormais toujours False, si elle est appelée depuis l'IDE.
5 sept. 2006 à 14:04
++
Moustachu
5 sept. 2006 à 13:46
Windows ne libère les handle qu'en cas de démappage mémoire du prog, serait en ce cas la VM.
5 sept. 2006 à 13:33
J'ai un petit soucis lorsque que je lance depuis l'ide : au deuxième lancement, l'appli ne se lance pas. J'ai l'impression que l'info reste en mémoire tant que l'IDE reste ouvert. Je teste donc si l'appli est lancée depuis l'IDE. Peut-être que mon appli ne se ferme pas correctement ?
++
Moustachu
3 sept. 2006 à 23:04
3 sept. 2006 à 19:38
3 sept. 2006 à 12:21
1 sept. 2006 à 12:38
Form1.show...
'Puis on clique sur la croix pour fermé le fenetre
'plus loin
if form1.xxx = yyy then
Dans ce cas et dans bien d'autre VB recharge la fenetre mieux vaux utiliser ce code uniquement dans une "sub main"
@+
1 sept. 2006 à 11:32
là, on active même l'ancienne instance ^^
1 sept. 2006 à 11:25
@+
1 sept. 2006 à 11:24
If App.PrevInstance Then End
C'est pas suffisant ?
1 sept. 2006 à 10:17
Joli tout ça, j'avais essayé de résoudre ce "problème" de manière bien moins propre et pas du tout sûre à 100%.
Je préfère pas raconter ce que j'avais fait ;o)
J'adopte !!
Moustachu
31 août 2006 à 19:25
Le mot "Apte" perd tout son sens ici bas...
:)
@+
31 août 2006 à 18:53
Comme toute portion de code, elle doit être utilisée par des personnes aptes à le faire sinon conseiller le recyclage dans le terrassement ou autre.
31 août 2006 à 18:34
Le mieu serait d'en faire une classe et de liberer le handle dans "Terminate"
@+
31 août 2006 à 18:09
On pourrait aussi checker que le path (+exename) de notre application n'est pas le path (+exename) d'un processus déjà lancé, quoique ce serait plus lourd. Quoique.
@+