INSTANCE UNIQUE DE VOTRE APPLICATION

violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 - 31 août 2006 à 18:09
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 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.

https://codes-sources.commentcamarche.net/source/39361-instance-unique-de-votre-application

Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
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és 308 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 15 juin 2015 1
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és 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
11 mai 2011 à 08:25
j'ai pas compris ce post scriptum...
Philippe734 Messages postés 308 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 15 juin 2015 1
10 mai 2011 à 21:02
J'ai oublié de préciser que mon hFrm est le hPid de la source originale
Philippe734 Messages postés 308 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 15 juin 2015 1
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és 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
12 mars 2010 à 06:55
exact^^
Philippe734 Messages postés 308 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 15 juin 2015 1
12 mars 2010 à 00:20
manque la déclaration : Private mbHasBeenQueriedOnce As Boolean

Merci pour la source
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
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

<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



@+
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
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és 2 Date d'inscription jeudi 9 février 2006 Statut Membre Dernière intervention 11 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és 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
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és 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 9
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és 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
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és 1079 Date d'inscription jeudi 14 novembre 2002 Statut Membre Dernière intervention 1 janvier 2012
5 sept. 2006 à 14:04
Merci pour ces précisions.

++
Moustachu
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 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és 1079 Date d'inscription jeudi 14 novembre 2002 Statut Membre Derniè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és 362 Date d'inscription mardi 18 décembre 2001 Statut Membre Dernière intervention 24 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és 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 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és 362 Date d'inscription mardi 18 décembre 2001 Statut Membre Dernière intervention 24 août 2012
3 sept. 2006 à 12:21
si mes souvenirs sont bons on peut aussi utiliser l'API CreateMutexA...
cs_EBArtSoft Messages postés 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 9
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és 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
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és 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
1 sept. 2006 à 11:25
Non (dans le cas ou tu as copié l'exécutable dans un autre dossier).
@+
cuq Messages postés 345 Date d'inscription mardi 3 juin 2003 Statut Membre Dernière intervention 21 mars 2008 2
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és 1079 Date d'inscription jeudi 14 novembre 2002 Statut Membre Derniè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és 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 9
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és 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 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és 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 9
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és 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
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.

@+
Rejoignez-nous