Quoi, tu ne connais pas PB ? Va falloir parcourir tout le forum alors !

Le forum (ô combien francophone) des utilisateurs de Powerbuilder.

Recherche rapide

Annonce

Certaines rubriques, dont des cours, sont uniquement visibles par les membres du forum ^^.
Dans la rubrique Liens & Références, vous avez accès à un sommaire de téléchargement, profitez-en !
Il existe maintenant un nouveau TOPIC "Votre CV en Ligne" accessible uniquement par demande.

#1 19-06-2012 09:44:13

newbee  
Membre
Date d'inscription: 19-06-2012
Messages: 12
Pépites: 71
Banque: 0

[RESOLU] Unique instance d'une application

Bonjour,

Dans le cadre de mon travail, je dois à partir d'une appli web ouvrir une appli développée en PB.
J'ai réussi à le faire en développant un plugin pour le navigateur cible qui embarque un dll appelée depuis du javascript.
Cependant, si une instance est déjà ouverte, une seconde s'ouvre, et ainsi de suite, ce qui devient gênant.

Ce que je souhaiterai faire, c'est que la nouvelle instance qui s'ouvre envoie un message à l'instance ouverte afin qu'elle se ferme.
Pour savoir si une instance est ouverte, je pense lire un fichier dans lequel sera renseigné le PID de l'instance ouverte ou -1 s'il n'y en a pas. S'il n'y en a pas (ie -1) alors j'écris le PID de l'instance en cours d'ouverture et je continue l'ouverture. Si j'ai un numéro de processus différent de -1 alors j'envoie un message à ce processus, j'écris mon PID et je continue l'ouverture de l'appli.

Est-ce que selon vous cela est facilement réalisable et si oui comment puis-je procéder (fonction d'envoie de message, mise en place d'un listener pour la réception d'un messsage, récupération du PID...) ?

Merci.

--
newbee

Dernière modification par newbee (20-06-2012 08:48:14)

Hors ligne

 

#2 19-06-2012 10:11:14

xlat  
0xc0000005
Award: bf
Lieu: Tanger (طنج)
Date d'inscription: 04-12-2010
Messages: 720
Pépites: 11,343
Banque: 100,221,387,868,884,300
Site web

Re: [RESOLU] Unique instance d'une application

Bonjour,

Si tu parles bien d'une application PB en client lourd dont tu voudrais contrôler le nombre d'instances,
alors tu pourrais utiliser l'API windows pour rechercher le processus par son nom d'image (.exe) et forcer un kill dessus (TerminateProcess)

comme çà pas besoin de fichier temporaire, par contre, c'est assez violent comme fermeture...


https://lut.im/eJINqa9o/vAtyxD0h "Don't believe everything you read on the Internet"
    -- Abraham Lincoln

www.ngs.ma

Hors ligne

 

#3 19-06-2012 11:51:27

newbee  
Membre
Date d'inscription: 19-06-2012
Messages: 12
Pépites: 71
Banque: 0

Re: [RESOLU] Unique instance d'une application

Il s'agit bien d'une application PB de type client lourd. En revanche, je trouve effectivement que ce système de fermeture est un peu brutal.
Je viens de fouiller un peu et peut-être que la meilleure solution serait de mettre un thread en écoute sur un port dès l'ouverture de la première instance, de renseigner le numéro de port d'écoute dans un fichier et dès qu'une nouvelle instance se lance elle cherche à écrire dans une socket à destination du thread en écoute et hop c'est bon.

Qu'en pensez-vous? cela est théorique et je ne sais absolument pas comment utiliser des sockets et si c'est possible. Des suggestions ou des exemples de code ?

Merci

Hors ligne

 

#4 19-06-2012 12:36:44

seki  
0x73656B69
Award: bf
Lieu: Laquenexy & Luxembourg
Date d'inscription: 20-11-2008
Messages: 1118
Pépites: 4,296,080,204
Banque: 9,223,372,036,854,776,000
Site web

Re: [RESOLU] Unique instance d'une application

newbee a écrit:

Qu'en pensez-vous?

Que ça ressemble à la description d'une usine à gaz ?

Ça ne serait pas plus simple de rechercher si l'application est démarrée (en recherchant par le nom de la fenêtre ou par sa classe avec FindWindow) et si on la trouve de la remettre au premier plan (avec ShowWindow) ?


The best programs are the ones written when the programmer is supposed to be working on something else. - Melinda Varian

Mes réponses PB sur StackOverflow
http://stackoverflow.com/users/flair/317266.png

Hors ligne

 

#5 19-06-2012 12:41:49

newbee  
Membre
Date d'inscription: 19-06-2012
Messages: 12
Pépites: 71
Banque: 0

Re: [RESOLU] Unique instance d'une application

En fait c'est juste de la communication TCP/IP mais si cela n'est pas possible, regardons ce que tu me propose.
Admettons que la recherche via FindWindow soit fructueuse, est-il possible de lui transmettre un message pour la fermer ? je ne cherche pas à la mettre en premier plan, car la nouvelle instance n'a pas forcément les mêmes paramètres de lancement.

Merci.

Dernière modification par newbee (19-06-2012 12:42:05)

Hors ligne

 

#6 19-06-2012 14:04:09

newbee  
Membre
Date d'inscription: 19-06-2012
Messages: 12
Pépites: 71
Banque: 0

Re: [RESOLU] Unique instance d'une application

xlat a écrit:

tu pourrais utiliser l'API windows pour rechercher le processus par son nom d'image (.exe) et forcer un kill dessus (TerminateProcess)

Est-ce qu'à tout hazard tu pourrais m'expliquer comment appeler des fonctions de l'API Windows ou me mettre un extrait de code?

Merci

Hors ligne

 

#7 20-06-2012 08:18:00

seki  
0x73656B69
Award: bf
Lieu: Laquenexy & Luxembourg
Date d'inscription: 20-11-2008
Messages: 1118
Pépites: 4,296,080,204
Banque: 9,223,372,036,854,776,000
Site web

Re: [RESOLU] Unique instance d'une application

Alors, quand on recherche une fonctionnalité qui n'est pas proposée par PB et qu'on a repéré sur le site MSDN une fonction fournie par Windows (ou un ensemble de fonctions) qui permet d'avoir cette fonctionnalité au niveau système, il faut déclarer le prototype de cette fonction à PB au moyen des Local external functions (pour un userobject ou une fonction globale) ou des global external functions (au niveau de l'appli entière).

Dans PB, une fois qu'on a ouvert un objet en édition, il faut aller dans l'onglet "declare instance variables" et changer dans la combo du haut "instance variables" par "global external functions" ou "local external functions" suivant l'objet et la visibilité qu'on souhaite avoir.

Pour cela il faut regarder le prototype C de la fonction donné sur MSDN et le convertir en syntaxe PB. Exemple avec FindWindow() : on a

HWND WINAPI FindWindow(__in_opt  LPCTSTR lpClassName, __in_opt  LPCTSTR lpWindowName);

- Le HWND nous indique que c'est une fonction qui retourne un DWORD (= en PB un unsigned long)
- WINAPI ne sert que si on utilise la fonction avec Visual C++, ici on peut l'ignorer
- FindWindow c'est le nom de la fonction
- LPCTSTR indique que lpClassName est un pointeur vers une string, __in_opt nous indique que c'est un paramètre d'entrée - c'est une notation supplémentaire récente et parfois on ne l'a pas dans les protoypes
- idem pour lpWindowName

Il faut également repérer dans la page de la doc
- quelle est la dll qui fournit cette fonction (ici User32.dll)
- pour les fonctions manipulant les chaines, il faut voir si la fonction prend du texte ansi, unicode, ou les 2. Ici on voit que sous le nom FindWindow on a 2 versions FindWindowW (Unicode) et FindWindowA (ANSI)
- si la fonction ne retourne rien (void) pour PB ce sera une Subroutine et non une Function

Le type de chaine est important parce que PB en interne gère des chaines "unicode" (pour être exact, encodées en utf-16-le) soit avec 2 octets par caractère et soit on peut appeler la fonction directement, soit PB doit convertir en ansi (= encodage windows cp-1252 - si le windows est en réglages occidentaux - avec 1 octet par caractère)

Ici on va parler des PB post-10.x qui sont unicode en interne (alors que PB 9 et avant étaient en ansi) Soit on déclare la fonction directment sous son nom final et ça donne

Code: pb

Function ULONG FindWindowW(string lpClassName, string lpWindowName) Library "User32.dll"


soit on veut l'utiliser dans PB avec son nom plus simple FindWindow et on utilise un alias

Code: pb

Function ULONG FindWindow(string lpClassName, string lpWindowName) Library "User32.dll" alias for "FindWindowW"


Enfin pour info, si on voulait utiliser la version ansi de la fonction (ou si on veut accéder à une fonction d'une dll qui ne connaît que les chaines ansi) on aurait dit (attention au A de FindWindowA et au ";ansi" qui indique qu'il y a conversion de texte)

Code: pb

Function ULONG FindWindow(string lpClassName, string lpWindowName) Library "User32.dll" alias for "FindWindowA;ansi"


PS: dans les cas où les fonctions utilisent des structures à la place de types simples (string, long, ...) il faut aussi déclarer des structures PB compatibles avec les structs C.

PS2: et dans les cas où la fonction doit écrire dans un buffer, il faut allouer le buffer dans PB. Habituellement on déclare une string et on la remplit avec la bonne taille avec la fonction space() avant d'appeler la dll.

Dernière modification par seki (20-06-2012 08:42:15)


The best programs are the ones written when the programmer is supposed to be working on something else. - Melinda Varian

Mes réponses PB sur StackOverflow
http://stackoverflow.com/users/flair/317266.png

Hors ligne

 

#8 20-06-2012 08:46:43

newbee  
Membre
Date d'inscription: 19-06-2012
Messages: 12
Pépites: 71
Banque: 0

Re: [RESOLU] Unique instance d'une application

Parfait. Merci Seki, une explication claire et nette que je vais utiliser.

Merci pour toutes ces informations et votre aide.

Hors ligne

 

#9 20-06-2012 09:08:10

seki  
0x73656B69
Award: bf
Lieu: Laquenexy & Luxembourg
Date d'inscription: 20-11-2008
Messages: 1118
Pépites: 4,296,080,204
Banque: 9,223,372,036,854,776,000
Site web

Re: [RESOLU] Unique instance d'une application

Histoire de montrer un peu plus de détails concrets, voici le code d'un userobject unvo_process_mgt que j'ai repris de Roland Smith et dans lequel j'avais ajouté la recherche de process.

Il suffit de créer un nouvel userobject unvo_process_mgt, de le fermer puis de rouvrir directement le code source pour y coller ce qui suit. Il y a
- la déclaration de fonctions permettant de démarrer, rechercher, arrêter des process windows
- la déclaration des structs nécessaires directement dans l'objet

Code: pb

forward
global type unvo_process_mgt from nonvisualobject
end type
type processentry from structure within unvo_process_mgt
end type
type moduleentry from structure within unvo_process_mgt
end type
type process_memory_counters from structure within unvo_process_mgt
end type
type startupinfo from structure within unvo_process_mgt
end type
type shellexecuteinfo from structure within unvo_process_mgt
end type
type process_information from structure within unvo_process_mgt
end type
end forward

type processentry from structure
        unsignedlong            lpidprocess[500]
end type

type moduleentry from structure
        unsignedlong            lpidmodule[100]
end type

type process_memory_counters from structure
        unsignedlong            cb
        unsignedlong            pagefaultcount
        unsignedlong            peakworkingsetsize
        unsignedlong            workingsetsize
        unsignedlong            quotapeakpagedpoolusage
        unsignedlong            quotapagedpoolusage
        unsignedlong            QuotaPeakNonPagedPoolUsage
        unsignedlong            QuotaNonPagedPoolUsage
        unsignedlong            PagefileUsage
        unsignedlong            PeakPagefileUsage
end type

type startupinfo from structure
    long        cb
    string        lpreserved
    string        lpdesktop
    string        lptitle
    long        dwx
    long        dwy
    long        dwxsize
    long        dwysize
    long        dwxcountchars
    long        dwycountchars
    long        dwfillattribute
    long        dwflags
    long        wshowwindow
    long        cbreserved2
    long        lpreserved2
    ulong        hstdinput
    ulong        hstdoutput
    ulong        hstderror
end type

type shellexecuteinfo from structure
  long    cbsize
  long    fmask
  long    hwnd
  string    lpverb
  string    lpfile
  string    lpparameters
  string    lpdirectory
  long    nshow
  long    hinstapp
  long    lpidlist
  string    lpclass
  ulong    hkeyclass
  ulong    hicon
  ulong    hmonitor
  ulong    hprocess
end type

global type process_information from structure
    ulong        hprocess
    ulong        hthread
    long        dwprocessid
    long        dwthreadid
end type

global type unvo_process_mgt from nonvisualobject
end type
global unvo_process_mgt unvo_process_mgt

type prototypes
Function boolean CloseHandle (ref ulong hObject) Library "KERNEL32.DLL"
Function Boolean EnumProcesses(REF processEntry Process, long cb, REF long cbNeeded ) Library "PSAPI.DLL"
Function long OpenProcess( long dwDesiredAccess, boolean bInheritHandle,ulong dwProcessId) LIBRARY "KERNEL32.DLL"
Function boolean EnumProcessModules( ulong hProcess, REF ModuleEntry Module, long cb, REF long lpcbNeeded ) LIBRARY "PSAPI.DLL"
Function long GetModuleBaseNameW(ulong hProcess, ulong hModule, REF string lpBaseName,long nSize) LIBRARY "PSAPI.DLL"
Function long GetModuleFileNameExW(ulong hProcess, ulong hModule, REF string lpBaseName,long nSize) LIBRARY "PSAPI.DLL"
Function boolean GetProcessMemoryInfo(ulong hProcess, REF PROCESS_MEMORY_COUNTERS ppsmemCounters,long nSize) LIBRARY "PSAPI.DLL" 
FUNCTION boolean CreateProcess(string AppName, string CommLine, long l1, long l2, boolean binh, long creationflags, long l3, string dir, startupinfo startupinfo, ref process_information pi ) library 'kernel32.dll' alias for "CreateProcessW"
FUNCTION long WaitForSingleObject ( ulong ul_Notification, long lmillisecs ) library "kernel32.dll"
FUNCTION long GetExitCodeProcess(ulong hProcess,ref ulong lpExitCode) LIBRARY "kernel32.dll"
Function boolean ShellExecuteEx (ref SHELLEXECUTEINFO lpExecInfo) Library "shell32.dll" Alias For "ShellExecuteExW"
Function long ShellExecute ( long hWnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, long nShowCmd) library 'shell32' alias for 'ShellExecuteW' 
Function Boolean TerminateProcess (long hProcess,long uExitCode) Library "kernel32.dll"

end prototypes

type variables
private:
Boolean ib_terminate
long il_millsecs

ulong HandleP[] // Handle of the process
constant ulong  PROCESS_ALL_ACCESS = 2035711

ProcessEntry Process       // Window structure (array of 500 ulong)...arbitrary value !
ModuleEntry Module         // Window structure (array of 100 long)... idem  
PROCESS_MEMORY_COUNTERS pmc


CONSTANT long INFINITE      = -1
CONSTANT long WAIT_ABANDONED  = 128
CONSTANT long WAIT_COMPLETE  = 0
CONSTANT long WAIT_OBJECT_0  = 0
CONSTANT long WAIT_TIMEOUT  = 258

CONSTANT long SW_HIDE      = 0
CONSTANT long SW_SHOWNORMAL  = 1
CONSTANT long SW_NORMAL    = 1
CONSTANT long SW_SHOWMINIMIZED  = 2
CONSTANT long SW_SHOWMAXIMIZED  = 3
CONSTANT long SW_MAXIMIZE    = 3
CONSTANT long SW_SHOWNOACTIVATE  = 4
CONSTANT long SW_SHOW    = 5
CONSTANT long SW_MINIMIZE    = 6
CONSTANT long SW_SHOWMINNOACTIVE  = 7
CONSTANT long SW_SHOWNA    = 8
CONSTANT long SW_RESTORE    = 9
CONSTANT long SW_SHOWDEFAULT  = 10
CONSTANT long SW_FORCEMINIMIZE  = 11
CONSTANT long SW_MAX      = 11

CONSTANT long SW_SCROLLCHILDREN = 17
CONSTANT long SW_INVALIDATE = 18
CONSTANT long SW_ERASE = 20
//SW_MAX = 10
//SW_OTHERUNZOOM = 4
//SW_OTHERZOOM = 2
//SW_PARENTCLOSING = 1
//SW_PARENTOPENING = 3


CONSTANT long STARTF_USESHOWWINDOW  = 1
CONSTANT long STARTF_USESIZE      = 2
CONSTANT long STARTF_USEPOSITION    = 4
CONSTANT long STARTF_USECOUNTCHARS    = 8
CONSTANT long STARTF_USEFILLATTRIBUTE  = 16
CONSTANT long STARTF_RUNFULLSCREEN    = 32
CONSTANT long STARTF_FORCEONFEEDBACK  = 64
CONSTANT long STARTF_FORCEOFFFEEDBACK  = 128
CONSTANT long STARTF_USESTDHANDLES    = 256
CONSTANT long STARTF_USEHOTKEY    = 512

CONSTANT long CREATE_DEFAULT_ERROR_MODE  = 67108864
CONSTANT long CREATE_FORCEDOS    = 8192
CONSTANT long CREATE_NEW_CONSOLE    = 16
CONSTANT long CREATE_NEW_PROCESS_GROUP  = 512
CONSTANT long CREATE_NO_WINDOW    = 134217728
CONSTANT long CREATE_SEPARATE_WOW_VDM  = 2048
CONSTANT long CREATE_SHARED_WOW_VDM  = 4096
CONSTANT long CREATE_SUSPENDED    = 4
CONSTANT long CREATE_UNICODE_ENVIRONMENT  = 1024
CONSTANT long DEBUG_PROCESS      = 1
CONSTANT long DEBUG_ONLY_THIS_PROCESS  = 2
CONSTANT long DETACHED_PROCESS    = 8

CONSTANT long HIGH_PRIORITY_CLASS    = 128
CONSTANT long IDLE_PRIORITY_CLASS    = 64
CONSTANT long NORMAL_PRIORITY_CLASS    = 32
CONSTANT long REALTIME_PRIORITY_CLASS  = 256

end variables

forward prototypes
public function boolean of_findprocess (string as_procname)
public function unsignedlong of_runandwait (string as_command, boolean ab_visible)
public function integer of_shellexec (string as_command)
public subroutine of_set_options (boolean ab_terminate, decimal adec_seconds)
public function long of_shellrun (string as_filename, string as_shellverb, long al_showwindow)
public function long of_shellrun (string as_filename, string as_shellverb, trigevent a_windowstate)
public function long of_shellrun (string as_filename, string as_shellverb, windowstate a_windowstate)
private function long of_run (string as_exefullpath, long al_showwindow, string as_initialdir)
public function long of_run (string as_exefullpath, trigevent a_windowstate, string as_initialdir)
public function long of_run (string as_exefullpath, windowstate a_windowstate, string as_initialdir)
end prototypes

public function boolean of_findprocess (string as_procname);
long tailleP=2000 // Size of Process
long TailleM=400 // Size of Module
long NeededP // returned size of Process
long NeededM // returned size of Module
long resName // size of returned name of the module
long ifx, ii // for looping through processes
boolean resultP, resultM // return codes for EnumProcesses and EnumProcessModules
string name // Name of the module
boolean lb_found = false

resultP=EnumProcesses(Process,TailleP,NeededP)
if resultP=true then
 for ifx=1 to integer(NeededP / 4)
  HandleP[ifx] = OpenProcess(PROCESS_ALL_ACCESS,false,Process.lpIdProcess[iFX])
  resultM = EnumProcessModules(HandleP[ifx], Module, TailleM, NeededM)
  if NeededM >= 4 then
        if GetProcessMemoryInfo( HandleP[ifx], pmc, 40 ) then
  /*    
      ls_message = ''
      ls_message = "PageFaultCount: " + string(pmc.PageFaultCount) + '~r~n' + &
                    + "PeakWorkingSetSize: " + string(pmc.PeakWorkingSetSize ) + '~r~n' &
          + "WorkingSetSize: " + string(pmc.WorkingSetSize ) + '~r~n' &
          + "QuotaPeakPagedPoolUsage: " + string(pmc.QuotaPeakPagedPoolUsage ) + '~r~n' &
          + "QuotaPagedPoolUsage: " + string(pmc.QuotaPagedPoolUsage ) + '~r~n' &
          + "QuotaPeakNonPagedPoolUsage: " + string(pmc.QuotaPeakNonPagedPoolUsage ) + '~r~n' &
          + "QuotaNonPagedPoolUsage: " + string(pmc.QuotaNonPagedPoolUsage) + '~r~n' &
          + "PagefileUsage: " + string(pmc.PagefileUsage ) + '~r~n' &
          + "PeakPagefileUsage: " + string(pmc.PeakPagefileUsage )
  */
      Name=space(254)
      resName=GetModuleBaseNameW(handleP[ifx], Module.lpidmodule[1], name ,254)
      //MessageBox( "Memory Info for : " + Name,ls_message)
                ii ++
                //mle_1.text += "~r~nMemory Info for : " + Name + ls_un + ls_message + ls_un
           
    if name = as_procname then 
      lb_found = true
    exit //for
    end if
    end if
  end if
  CloseHandle(HandleP[ifx])
 next
 /*
 IF ii > 0 THEN
        mle_1.text = "Retrieved ProcessMemoryInfo for " + string(ii) + " processes~r~n" + mle_1.text

 END IF
else
 MessageBox ("Memory Info","Fail calling EnumProcesses")
 */
end if

return lb_found

end function

public function unsignedlong of_runandwait (string as_command, boolean ab_visible);
 
boolean lb_Return
long ll_Null, ll_CreationFlags, ll_Return
ulong lul_ProcessReturn
string ls_CurDir, ls_Null
StartupInfo lstr_Start
Process_information lstr_PI

SetNull(ll_Null)
SetNull(ls_Null)
SetNull(ls_CurDir)

lstr_Start.cb                            = 72
lstr_Start.dwFlags               = STARTF_USESHOWWINDOW
IF ab_Visible THEN
        lstr_Start.wShowWindow   = 1
ELSE
        lstr_Start.wShowWindow   = 0
END IF

ll_CreationFlags = CREATE_NEW_CONSOLE + NORMAL_PRIORITY_CLASS

lb_Return = CreateProcess (ls_Null, as_Command, ll_Null, ll_Null, FALSE,ll_CreationFlags, ll_Null, ls_CurDir, lstr_Start, lstr_PI)
ll_Return = WaitForSingleObject (lstr_PI.hProcess, INFINITE)
ll_Return = GetExitCodeProcess (lstr_PI.hProcess, lul_ProcessReturn)
CloseHandle(lstr_PI.hProcess)
CloseHandle(lstr_PI.hThread)

RETURN lul_ProcessReturn

end function

public function integer of_shellexec (string as_command);
//ShellExecute( 0, ls_Oper, ls_File, ls_Param, ls_Dir, ll_Show) 

return 0
end function

public subroutine of_set_options (boolean ab_terminate, decimal adec_seconds);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_set_options
//
// PURPOSE:    This function sets a timeout period so that it can stop
//             waiting after so many seconds.  It also sets an option
//          to terminate the process if it is still running after
//          the timeout period expires.
//
// ARGUMENTS:  ab_terminate  - Terminate if still running
//             adec_seconds  - Timeout period in seconds
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------

ib_terminate = ab_terminate
il_millsecs = adec_seconds * 1000

end subroutine

public function long of_shellrun (string as_filename, string as_shellverb, long al_showwindow);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_ShellRun
//
// PURPOSE:    This function starts the program that is defined to perform
//          the action on the file. It then waits for it to finish.
//          If a timeout period has been set, it optionally can terminate
//          the process.
//
// ARGUMENTS:  as_exefullpath  - Path of program to execute
//          as_shellverb  - Shell action verb (blank for default)
//             ai_showwindow  - Show window option
//
// RETURN:    Return code of the program or:
//          -1  = Create Process failed
//          258 = Process terminated after timeout
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------

CONSTANT Long SEE_MASK_NOCLOSEPROCESS = 64
SHELLEXECUTEINFO lstr_sei
uLong ll_ExitCode

// initialize structure values
lstr_sei.cbSize = 60
lstr_sei.fMask  = SEE_MASK_NOCLOSEPROCESS
lstr_sei.hWnd   = Handle(this)
lstr_sei.lpVerb = as_shellverb
lstr_sei.lpFile = as_filename
lstr_sei.nShow  = al_showwindow

If ShellExecuteEx(lstr_sei) Then
  // wait for the process to complete
  If il_millsecs > 0 Then
    // wait until process ends or timeout period expires
    ll_ExitCode = WaitForSingleObject(lstr_sei.hProcess, il_millsecs)
    // terminate process if not finished
    If ib_terminate And ll_ExitCode = WAIT_TIMEOUT Then
      TerminateProcess(lstr_sei.hProcess, -1)
      ll_ExitCode = WAIT_TIMEOUT
    Else
      // check for exit code
      GetExitCodeProcess(lstr_sei.hProcess, ll_ExitCode)
    End If
  Else
    // wait until process ends
    WaitForSingleObject(lstr_sei.hProcess, INFINITE)
    // check for exit code
    GetExitCodeProcess(lstr_sei.hProcess, ll_ExitCode)
  End If
  // close process and thread handles
  CloseHandle(lstr_sei.hProcess)
Else
  // return failure
  ll_ExitCode = -1
End If

Return ll_ExitCode

end function

public function long of_shellrun (string as_filename, string as_shellverb, trigevent a_windowstate);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_ShellRun
//
// PURPOSE:    This function takes the Hide! enumerated value and
//             passes SW_HIDE to the form of the function that
//          actually does the processing.
//
// ARGUMENTS:  as_exefullpath  - Path of program to execute
//          as_shellverb  - Shell action verb (blank for default)
//             a_windowstate  - Show window option
//
// RETURN:    Return code from processing
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------

long ll_rtn

CHOOSE CASE a_windowstate
  CASE Hide!
    // run the passed file
    ll_rtn = this.of_ShellRun(as_filename, as_shellverb, SW_HIDE)
  CASE ELSE
    // valid trigevent but invalid windowstate
    SetNull(ll_rtn)
END CHOOSE

Return ll_rtn

end function

public function long of_shellrun (string as_filename, string as_shellverb, windowstate a_windowstate);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_ShellRun
//
// PURPOSE:    This function takes the Normal!, Maximized and
//          Minimized! enumerated values and passes the
//             corresponding value to the form of the function
//          that actually does the processing.
//
// ARGUMENTS:  as_exefullpath  - Path of program to execute
//          as_shellverb  - Shell action verb (blank for default)
//             a_windowstate  - Show window option
//
// RETURN:    Return code from processing
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------

long ll_rtn

CHOOSE CASE a_windowstate
  CASE Normal!
    ll_rtn = this.of_ShellRun(as_filename, as_shellverb, SW_SHOWNORMAL)
  CASE Maximized!
    ll_rtn = this.of_ShellRun(as_filename, as_shellverb, SW_SHOWMAXIMIZED)
  CASE Minimized!
    ll_rtn = this.of_ShellRun(as_filename, as_shellverb, SW_SHOWMINIMIZED)
END CHOOSE

Return ll_rtn

end function

private function long of_run (string as_exefullpath, long al_showwindow, string as_initialdir);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_Run
//
// PURPOSE:    This function starts the process and waits (or not) for it to
//             finish.  If a timeout period has been set, it
//          optionally can terminate the process.
//
// ARGUMENTS:  as_exefullpath  - Path of program to execute
//             ai_showwindow  - Show window option
//          as_initialdir  - initial directory for run
//
// RETURN:    Return code of the program or:
//          -1  = Create Process failed
//          258 = Process terminated after timeout
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------
// 31/01/2008  SeKi      If il_millsecs < 0 then don't wait 

STARTUPINFO lstr_si
PROCESS_INFORMATION lstr_pi
long ll_null, ll_CreationFlags, ll_msecs
ulong ll_ExitCode
String ls_null
string ls_inidir

// initialize arguments
SetNull(ll_null)
SetNull(ls_null)
lstr_si.cb = 72
lstr_si.dwFlags = STARTF_USESHOWWINDOW
lstr_si.wShowWindow = al_showwindow
ll_CreationFlags = CREATE_NEW_CONSOLE + NORMAL_PRIORITY_CLASS
if trim(as_initialdir) <> "" then 
  ls_inidir = as_initialdir
else
  ls_inidir = ls_null
end if

// create process/thread and execute the passed program
If CreateProcess(ls_null, as_exefullpath, ll_null, &
      ll_null, False, ll_CreationFlags, ll_null, &
      ls_inidir, lstr_si, lstr_pi) Then
  // wait for the process to complete
  If il_millsecs > 0 Then
    // wait until process ends or timeout period expires
    ll_ExitCode = WaitForSingleObject(lstr_pi.hProcess, il_millsecs)
    // terminate process if not finished
    If ib_terminate And ll_ExitCode = WAIT_TIMEOUT Then
      TerminateProcess(lstr_pi.hProcess, -1)
      ll_ExitCode = WAIT_TIMEOUT
    Else
      // check for exit code
      GetExitCodeProcess(lstr_pi.hProcess, ll_ExitCode)
    End If
  Elseif il_millsecs = 0 then
    // wait until process ends
    WaitForSingleObject(lstr_pi.hProcess, INFINITE)
    // check for exit code
    GetExitCodeProcess(lstr_pi.hProcess, ll_ExitCode)
  else
    // check for exit code
    GetExitCodeProcess(lstr_pi.hProcess, ll_ExitCode)
  End If
  // close process and thread handles
  CloseHandle(lstr_pi.hProcess)
  CloseHandle(lstr_pi.hThread)
Else
  // return failure
  ll_ExitCode = -1
End If

Return ll_ExitCode

end function

public function long of_run (string as_exefullpath, trigevent a_windowstate, string as_initialdir);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_Run
//
// PURPOSE:    This function takes the Hide! enumerated value and
//             passes SW_HIDE to the form of the function that
//          actually does the processing.
//
// ARGUMENTS:  as_exefullpath  - Path of program to execute
//             a_windowstate  - Show window option
//          as_initialdir  - initial directory for run
//
// RETURN:    Return code from processing
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------

long ll_rtn

CHOOSE CASE a_windowstate
  CASE Hide!
    // run the passed program
    ll_rtn = this.of_Run(as_exefullpath, SW_HIDE,as_initialdir)
  CASE ELSE
    // valid trigevent but invalid windowstate
    SetNull(ll_rtn)
END CHOOSE

Return ll_rtn

end function

public function long of_run (string as_exefullpath, windowstate a_windowstate, string as_initialdir);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_Run
//
// PURPOSE:    This function takes the Normal!, Maximized and
//          Minimized! enumerated values and passes the
//             corresponding value to the form of the function
//          that actually does the processing.
//
// ARGUMENTS:  as_exepath    - Path of program to execute
//             a_windowstate  - Show window option
//          as_initialdir  - initial directory for run
//
// RETURN:    Return code from processing
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------

long ll_rtn

CHOOSE CASE a_windowstate
  CASE Normal!
    ll_rtn = this.of_Run(as_exefullpath, SW_SHOWNORMAL,as_initialdir)
  CASE Maximized!
    ll_rtn = this.of_Run(as_exefullpath, SW_SHOWMAXIMIZED,as_initialdir)
  CASE Minimized!
    ll_rtn = this.of_Run(as_exefullpath, SW_SHOWMINIMIZED,as_initialdir)
END CHOOSE

Return ll_rtn

end function

on unvo_process_mgt.create
call super::create
TriggerEvent( this, "constructor" )
end on

on unvo_process_mgt.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on

The best programs are the ones written when the programmer is supposed to be working on something else. - Melinda Varian

Mes réponses PB sur StackOverflow
http://stackoverflow.com/users/flair/317266.png

Hors ligne

 

#10 13-09-2012 08:14:30

erasorz  
Admin
Lieu: Babylone
Date d'inscription: 23-11-2006
Messages: 5121
Pépites: 97,197
Banque: 2,147,483,647

Re: [RESOLU] Unique instance d'une application

seki a écrit:

Histoire de montrer un peu plus de détails concrets, voici le code d'un userobject unvo_process_mgt que j'ai repris de Roland Smith et dans lequel j'avais ajouté la recherche de process.

Il suffit de créer un nouvel userobject unvo_process_mgt, de le fermer puis de rouvrir directement le code source pour y coller ce qui suit. Il y a
- la déclaration de fonctions permettant de démarrer, rechercher, arrêter des process windows
- la déclaration des structs nécessaires directement dans l'objet

J'ai regardé cet objet, mais il n'y a pas la fonction pour arrêter des process windows... (bien que TerminateProcess soit déclaré en external function)
Tu aurais le bout de code correspondant ?


N'envoyez jamais un humain faire le travail d'un programme.

Hors ligne

 

#11 14-09-2012 08:43:26

seki  
0x73656B69
Award: bf
Lieu: Laquenexy & Luxembourg
Date d'inscription: 20-11-2008
Messages: 1118
Pépites: 4,296,080,204
Banque: 9,223,372,036,854,776,000
Site web

Re: [RESOLU] Unique instance d'une application

EDIT: en recompilant l'objet pendant que je jouais avec je suis tombé sur un problème bizarre de surcharge de variable. J'ai modifié le nom de 2 variables d'instance pour pallier au problème.

erasorz a écrit:

J'ai regardé cet objet, mais il n'y a pas la fonction pour arrêter des process windows... (bien que TerminateProcess soit déclaré en external function)
Tu aurais le bout de code correspondant ?

En fait une fois qu'une fonction externe est déclarée dans un objet, ça devient une méthode de l'objet que tu peux appeler directement sans passer par une méthode "proxy".

Edit: je viens de jouer un peu avec ça et il est possible de spécifier dans les déclaration des external Private ou Protected pour limiter l'usage des fonctions externes.

Je n'avais plus regardé ce code depuis longtemps, c'est un bout qui a été mis en place et puis "oublié". En relisant je me dis qu'il mériterait d'être un peu remanié.

TerminateProcess() a besoin d'un handle de process mais si l'objet fournit de quoi énumérer les processus, il n'y avait pas de méthode simple pour rechercher un processus et retourner son handle. J'ai modifié of_FindProcess() pour retourner un handle quand on trouve une correspondance et ajouté of_ProcessExists() comme simple helper par dessus pour reprendre l'ancienne fonctionnalité de of_FindProcess à savoir retourner un booléen si on a trouvé.

Voici un exemple simple de démarrage de programme externe

Code: pb

unvo_process_mgt l_pm
l_pm = create unvo_process_mgt

//les 2 lignes suivantes équivalentes à run("notepad.exe", normal!)
l_pm.of_set_options( false, -1)
l_pm.of_run( "notepad.exe", normal!, "" /*possible aussi : "c:\temp"*/)

destroy l_pm


Pour stopper on peut faire

Code: pb

unvo_process_mgt l_pm
l_pm = create unvo_process_mgt

ulong ul_hdl
ul_hdl = l_pm.of_findprocess( "notepad.exe")
//attention recherche simpliste : ce n'est peut-être pas la bonne instance... ;^)
//il faudrait une version de of_run() qui retourne le pid ou handle créé
if ul_hdl <> 0 then l_pm.terminateprocess( ul_hdl, 42 /*code de fin retourné au parent du process*/)

destroy l_pm


Et une version un peu améliorée de l'objet. Enjoy !

Code: pb

forward
global type unvo_process_mgt from nonvisualobject
end type
type processentry from structure within unvo_process_mgt
end type
type moduleentry from structure within unvo_process_mgt
end type
type process_memory_counters from structure within unvo_process_mgt
end type
type startupinfo from structure within unvo_process_mgt
end type
type shellexecuteinfo from structure within unvo_process_mgt
end type
type process_information from structure within unvo_process_mgt
end type
type stru_test from structure within unvo_process_mgt
end type
end forward

type processentry from structure
        unsignedlong            lpidprocess[500]
end type

type moduleentry from structure
        unsignedlong            lpidmodule[100]
end type

type process_memory_counters from structure
        unsignedlong            cb
        unsignedlong            pagefaultcount
        unsignedlong            peakworkingsetsize
        unsignedlong            workingsetsize
        unsignedlong            quotapeakpagedpoolusage
        unsignedlong            quotapagedpoolusage
        unsignedlong            QuotaPeakNonPagedPoolUsage
        unsignedlong            QuotaNonPagedPoolUsage
        unsignedlong            PagefileUsage
        unsignedlong            PeakPagefileUsage
end type

type startupinfo from structure
    long        cb
    string        lpreserved
    string        lpdesktop
    string        lptitle
    long        dwx
    long        dwy
    long        dwxsize
    long        dwysize
    long        dwxcountchars
    long        dwycountchars
    long        dwfillattribute
    long        dwflags
    long        wshowwindow
    long        cbreserved2
    long        lpreserved2
    ulong        hstdinput
    ulong        hstdoutput
    ulong        hstderror
end type

type shellexecuteinfo from structure
  long    cbsize
  long    fmask
  long    hwnd
  string    lpverb
  string    lpfile
  string    lpparameters
  string    lpdirectory
  long    nshow
  long    hinstapp
  long    lpidlist
  string    lpclass
  ulong    hkeyclass
  ulong    hicon
  ulong    hmonitor
  ulong    hprocess
end type

global type process_information from structure
    ulong        hprocess
    ulong        hthread
    long        dwprocessid
    long        dwthreadid
end type

type stru_test from structure
  string    toto
end type

global type unvo_process_mgt from nonvisualobject
end type
global unvo_process_mgt unvo_process_mgt

type prototypes
Function boolean CloseHandle (ref ulong hObject) Library "KERNEL32.DLL"
Function Boolean EnumProcesses(REF processEntry Process, long cb, REF long cbNeeded ) Library "PSAPI.DLL"
Function long OpenProcess( long dwDesiredAccess, boolean bInheritHandle,ulong dwProcessId) LIBRARY "KERNEL32.DLL"
Function boolean EnumProcessModules( ulong hProcess, REF ModuleEntry Module, long cb, REF long lpcbNeeded ) LIBRARY "PSAPI.DLL"
Function long GetModuleBaseNameW(ulong hProcess, ulong hModule, REF string lpBaseName,long nSize) LIBRARY "PSAPI.DLL"
Function long GetModuleFileNameExW(ulong hProcess, ulong hModule, REF string lpBaseName,long nSize) LIBRARY "PSAPI.DLL"
Function boolean GetProcessMemoryInfo(ulong hProcess, REF PROCESS_MEMORY_COUNTERS ppsmemCounters,long nSize) LIBRARY "PSAPI.DLL" 
FUNCTION boolean CreateProcess(string AppName, string CommLine, long l1, long l2, boolean binh, long creationflags, long l3, string dir, startupinfo startupinfo, ref process_information pi ) library 'kernel32.dll' alias for "CreateProcessW"
FUNCTION long WaitForSingleObject ( ulong ul_Notification, long lmillisecs ) library "kernel32.dll"
FUNCTION long GetExitCodeProcess(ulong hProcess,ref ulong lpExitCode) LIBRARY "kernel32.dll"
Function boolean ShellExecuteEx (ref SHELLEXECUTEINFO lpExecInfo) Library "shell32.dll" Alias For "ShellExecuteExW"
Function long ShellExecute ( long hWnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, long nShowCmd) library 'shell32' alias for 'ShellExecuteW' 
Function Boolean TerminateProcess (long hProcess,long uExitCode) Library "kernel32.dll"

end prototypes
type variables
private:
Boolean ib_terminate
long il_millsecs

ulong HandleP[] // Handle of the process
constant ulong  PROCESS_ALL_ACCESS = 2035711

ProcessEntry i_Process       // Window structure (array of 500 ulong)...arbitrary value !
ModuleEntry i_Module         // Window structure (array of 100 long)... idem  
PROCESS_MEMORY_COUNTERS pmc


CONSTANT long INFINITE      = -1
CONSTANT long WAIT_ABANDONED  = 128
CONSTANT long WAIT_COMPLETE  = 0
CONSTANT long WAIT_OBJECT_0  = 0
CONSTANT long WAIT_TIMEOUT  = 258

CONSTANT long SW_HIDE      = 0
CONSTANT long SW_SHOWNORMAL  = 1
CONSTANT long SW_NORMAL    = 1
CONSTANT long SW_SHOWMINIMIZED  = 2
CONSTANT long SW_SHOWMAXIMIZED  = 3
CONSTANT long SW_MAXIMIZE    = 3
CONSTANT long SW_SHOWNOACTIVATE  = 4
CONSTANT long SW_SHOW    = 5
CONSTANT long SW_MINIMIZE    = 6
CONSTANT long SW_SHOWMINNOACTIVE  = 7
CONSTANT long SW_SHOWNA    = 8
CONSTANT long SW_RESTORE    = 9
CONSTANT long SW_SHOWDEFAULT  = 10
CONSTANT long SW_FORCEMINIMIZE  = 11
CONSTANT long SW_MAX      = 11

CONSTANT long SW_SCROLLCHILDREN = 17
CONSTANT long SW_INVALIDATE = 18
CONSTANT long SW_ERASE = 20
//SW_MAX = 10
//SW_OTHERUNZOOM = 4
//SW_OTHERZOOM = 2
//SW_PARENTCLOSING = 1
//SW_PARENTOPENING = 3


CONSTANT long STARTF_USESHOWWINDOW  = 1
CONSTANT long STARTF_USESIZE      = 2
CONSTANT long STARTF_USEPOSITION    = 4
CONSTANT long STARTF_USECOUNTCHARS    = 8
CONSTANT long STARTF_USEFILLATTRIBUTE  = 16
CONSTANT long STARTF_RUNFULLSCREEN    = 32
CONSTANT long STARTF_FORCEONFEEDBACK  = 64
CONSTANT long STARTF_FORCEOFFFEEDBACK  = 128
CONSTANT long STARTF_USESTDHANDLES    = 256
CONSTANT long STARTF_USEHOTKEY    = 512

CONSTANT long CREATE_DEFAULT_ERROR_MODE  = 67108864
CONSTANT long CREATE_FORCEDOS    = 8192
CONSTANT long CREATE_NEW_CONSOLE    = 16
CONSTANT long CREATE_NEW_PROCESS_GROUP  = 512
CONSTANT long CREATE_NO_WINDOW    = 134217728
CONSTANT long CREATE_SEPARATE_WOW_VDM  = 2048
CONSTANT long CREATE_SHARED_WOW_VDM  = 4096
CONSTANT long CREATE_SUSPENDED    = 4
CONSTANT long CREATE_UNICODE_ENVIRONMENT  = 1024
CONSTANT long DEBUG_PROCESS      = 1
CONSTANT long DEBUG_ONLY_THIS_PROCESS  = 2
CONSTANT long DETACHED_PROCESS    = 8

CONSTANT long HIGH_PRIORITY_CLASS    = 128
CONSTANT long IDLE_PRIORITY_CLASS    = 64
CONSTANT long NORMAL_PRIORITY_CLASS    = 32
CONSTANT long REALTIME_PRIORITY_CLASS  = 256

end variables
forward prototypes
public function unsignedlong of_runandwait (string as_command, boolean ab_visible)
public function integer of_shellexec (string as_command)
public subroutine of_set_options (boolean ab_terminate, decimal adec_seconds)
public function long of_shellrun (string as_filename, string as_shellverb, long al_showwindow)
public function long of_shellrun (string as_filename, string as_shellverb, trigevent a_windowstate)
public function long of_shellrun (string as_filename, string as_shellverb, windowstate a_windowstate)
private function long of_run (string as_exefullpath, long al_showwindow, string as_initialdir)
public function long of_run (string as_exefullpath, trigevent a_windowstate, string as_initialdir)
public function long of_run (string as_exefullpath, windowstate a_windowstate, string as_initialdir)
public function boolean of_processexists (string as_procname)
public function unsignedlong of_findprocess (string as_procname)
end prototypes

public function unsignedlong of_runandwait (string as_command, boolean ab_visible);
 
boolean lb_Return
long ll_Null, ll_CreationFlags, ll_Return
ulong lul_ProcessReturn
string ls_CurDir, ls_Null
StartupInfo lstr_Start
Process_information lstr_PI

SetNull(ll_Null)
SetNull(ls_Null)
SetNull(ls_CurDir)

lstr_Start.cb                            = 72
lstr_Start.dwFlags               = STARTF_USESHOWWINDOW
IF ab_Visible THEN
        lstr_Start.wShowWindow   = 1
ELSE
        lstr_Start.wShowWindow   = 0
END IF

ll_CreationFlags = CREATE_NEW_CONSOLE + NORMAL_PRIORITY_CLASS

lb_Return = CreateProcess (ls_Null, as_Command, ll_Null, ll_Null, FALSE,ll_CreationFlags, ll_Null, ls_CurDir, lstr_Start, lstr_PI)
ll_Return = WaitForSingleObject (lstr_PI.hProcess, INFINITE)
ll_Return = GetExitCodeProcess (lstr_PI.hProcess, lul_ProcessReturn)
CloseHandle(lstr_PI.hProcess)
CloseHandle(lstr_PI.hThread)

RETURN lul_ProcessReturn

end function

public function integer of_shellexec (string as_command);
//ShellExecute( 0, ls_Oper, ls_File, ls_Param, ls_Dir, ll_Show) 

return 0
end function

public subroutine of_set_options (boolean ab_terminate, decimal adec_seconds);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_set_options
//
// PURPOSE:    This function sets a timeout period so that it can stop
//             waiting after so many seconds.  It also sets an option
//          to terminate the process if it is still running after
//          the timeout period expires.
//
// ARGUMENTS:  ab_terminate  - Terminate if still running
//             adec_seconds  - Timeout period in seconds
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------

ib_terminate = ab_terminate
il_millsecs = adec_seconds * 1000

end subroutine

public function long of_shellrun (string as_filename, string as_shellverb, long al_showwindow);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_ShellRun
//
// PURPOSE:    This function starts the program that is defined to perform
//          the action on the file. It then waits for it to finish.
//          If a timeout period has been set, it optionally can terminate
//          the process.
//
// ARGUMENTS:  as_exefullpath  - Path of program to execute
//          as_shellverb  - Shell action verb (blank for default)
//             ai_showwindow  - Show window option
//
// RETURN:    Return code of the program or:
//          -1  = Create Process failed
//          258 = Process terminated after timeout
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------

CONSTANT Long SEE_MASK_NOCLOSEPROCESS = 64
SHELLEXECUTEINFO lstr_sei
uLong ll_ExitCode

// initialize structure values
lstr_sei.cbSize = 60
lstr_sei.fMask  = SEE_MASK_NOCLOSEPROCESS
lstr_sei.hWnd   = Handle(this)
lstr_sei.lpVerb = as_shellverb
lstr_sei.lpFile = as_filename
lstr_sei.nShow  = al_showwindow

If ShellExecuteEx(lstr_sei) Then
  // wait for the process to complete
  If il_millsecs > 0 Then
    // wait until process ends or timeout period expires
    ll_ExitCode = WaitForSingleObject(lstr_sei.hProcess, il_millsecs)
    // terminate process if not finished
    If ib_terminate And ll_ExitCode = WAIT_TIMEOUT Then
      TerminateProcess(lstr_sei.hProcess, -1)
      ll_ExitCode = WAIT_TIMEOUT
    Else
      // check for exit code
      GetExitCodeProcess(lstr_sei.hProcess, ll_ExitCode)
    End If
  Else
    // wait until process ends
    WaitForSingleObject(lstr_sei.hProcess, INFINITE)
    // check for exit code
    GetExitCodeProcess(lstr_sei.hProcess, ll_ExitCode)
  End If
  // close process and thread handles
  CloseHandle(lstr_sei.hProcess)
Else
  // return failure
  ll_ExitCode = -1
End If

Return ll_ExitCode

end function

public function long of_shellrun (string as_filename, string as_shellverb, trigevent a_windowstate);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_ShellRun
//
// PURPOSE:    This function takes the Hide! enumerated value and
//             passes SW_HIDE to the form of the function that
//          actually does the processing.
//
// ARGUMENTS:  as_exefullpath  - Path of program to execute
//          as_shellverb  - Shell action verb (blank for default)
//             a_windowstate  - Show window option
//
// RETURN:    Return code from processing
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------

long ll_rtn

CHOOSE CASE a_windowstate
  CASE Hide!
    // run the passed file
    ll_rtn = this.of_ShellRun(as_filename, as_shellverb, SW_HIDE)
  CASE ELSE
    // valid trigevent but invalid windowstate
    SetNull(ll_rtn)
END CHOOSE

Return ll_rtn

end function

public function long of_shellrun (string as_filename, string as_shellverb, windowstate a_windowstate);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_ShellRun
//
// PURPOSE:    This function takes the Normal!, Maximized and
//          Minimized! enumerated values and passes the
//             corresponding value to the form of the function
//          that actually does the processing.
//
// ARGUMENTS:  as_exefullpath  - Path of program to execute
//          as_shellverb  - Shell action verb (blank for default)
//             a_windowstate  - Show window option
//
// RETURN:    Return code from processing
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------

long ll_rtn

CHOOSE CASE a_windowstate
  CASE Normal!
    ll_rtn = this.of_ShellRun(as_filename, as_shellverb, SW_SHOWNORMAL)
  CASE Maximized!
    ll_rtn = this.of_ShellRun(as_filename, as_shellverb, SW_SHOWMAXIMIZED)
  CASE Minimized!
    ll_rtn = this.of_ShellRun(as_filename, as_shellverb, SW_SHOWMINIMIZED)
END CHOOSE

Return ll_rtn

end function

private function long of_run (string as_exefullpath, long al_showwindow, string as_initialdir);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_Run
//
// PURPOSE:    This function starts the process and waits (or not) for it to
//             finish.  If a timeout period has been set, it
//          optionally can terminate the process.
//
// ARGUMENTS:  as_exefullpath  - Path of program to execute
//             ai_showwindow  - Show window option
//          as_initialdir  - initial directory for run
//
// RETURN:    Return code of the program or:
//          -1  = Create Process failed
//          258 = Process terminated after timeout
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------
// 31/01/2008  SeKi      If il_millsecs < 0 then don't wait 

STARTUPINFO lstr_si
PROCESS_INFORMATION lstr_pi
long ll_null, ll_CreationFlags, ll_msecs
ulong ll_ExitCode
String ls_null
string ls_inidir

// initialize arguments
SetNull(ll_null)
SetNull(ls_null)
lstr_si.cb = 72
lstr_si.dwFlags = STARTF_USESHOWWINDOW
lstr_si.wShowWindow = al_showwindow
ll_CreationFlags = CREATE_NEW_CONSOLE + NORMAL_PRIORITY_CLASS
if trim(as_initialdir) <> "" then 
  ls_inidir = as_initialdir
else
  ls_inidir = ls_null
end if

// create process/thread and execute the passed program
If CreateProcess(ls_null, as_exefullpath, ll_null, &
      ll_null, False, ll_CreationFlags, ll_null, &
      ls_inidir, lstr_si, lstr_pi) Then
  // wait for the process to complete
  If il_millsecs > 0 Then
    // wait until process ends or timeout period expires
    ll_ExitCode = WaitForSingleObject(lstr_pi.hProcess, il_millsecs)
    // terminate process if not finished
    If ib_terminate And ll_ExitCode = WAIT_TIMEOUT Then
      TerminateProcess(lstr_pi.hProcess, -1)
      ll_ExitCode = WAIT_TIMEOUT
    Else
      // check for exit code
      GetExitCodeProcess(lstr_pi.hProcess, ll_ExitCode)
    End If
  Elseif il_millsecs = 0 then
    // wait until process ends
    WaitForSingleObject(lstr_pi.hProcess, INFINITE)
    // check for exit code
    GetExitCodeProcess(lstr_pi.hProcess, ll_ExitCode)
  else
    // check for exit code
    GetExitCodeProcess(lstr_pi.hProcess, ll_ExitCode)
  End If
  // close process and thread handles
  CloseHandle(lstr_pi.hProcess)
  CloseHandle(lstr_pi.hThread)
Else
  // return failure
  ll_ExitCode = -1
End If

Return ll_ExitCode

end function

public function long of_run (string as_exefullpath, trigevent a_windowstate, string as_initialdir);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_Run
//
// PURPOSE:    This function takes the Hide! enumerated value and
//             passes SW_HIDE to the form of the function that
//          actually does the processing.
//
// ARGUMENTS:  as_exefullpath  - Path of program to execute
//             a_windowstate  - Show window option
//          as_initialdir  - initial directory for run
//
// RETURN:    Return code from processing
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------

long ll_rtn

CHOOSE CASE a_windowstate
  CASE Hide!
    // run the passed program
    ll_rtn = this.of_Run(as_exefullpath, SW_HIDE,as_initialdir)
  CASE ELSE
    // valid trigevent but invalid windowstate
    SetNull(ll_rtn)
END CHOOSE

Return ll_rtn

end function

public function long of_run (string as_exefullpath, windowstate a_windowstate, string as_initialdir);// -----------------------------------------------------------------------------
// SCRIPT:     n_runandwait.of_Run
//
// PURPOSE:    This function takes the Normal!, Maximized and
//          Minimized! enumerated values and passes the
//             corresponding value to the form of the function
//          that actually does the processing.
//
// ARGUMENTS:  as_exepath    - Path of program to execute
//             a_windowstate  - Show window option
//          as_initialdir  - initial directory for run
//
// RETURN:    Return code from processing
//
// DATE        PROG/ID    DESCRIPTION OF CHANGE / REASON
// ----------  --------    -----------------------------------------------------
// 07/16/2003  RolandS    Initial Coding
// -----------------------------------------------------------------------------

long ll_rtn

CHOOSE CASE a_windowstate
  CASE Normal!
    ll_rtn = this.of_Run(as_exefullpath, SW_SHOWNORMAL,as_initialdir)
  CASE Maximized!
    ll_rtn = this.of_Run(as_exefullpath, SW_SHOWMAXIMIZED,as_initialdir)
  CASE Minimized!
    ll_rtn = this.of_Run(as_exefullpath, SW_SHOWMINIMIZED,as_initialdir)
END CHOOSE

Return ll_rtn

end function

public function boolean of_processexists (string as_procname);
//Test the existence of a process
// -----------------------------------------------------------------------------
// 14/09/2012  SeKi

ulong ul_hdl

ul_hdl = of_findprocess(as_procname)

return ul_hdl <> 0

end function

public function unsignedlong of_findprocess (string as_procname);//Returns the handle of a process after searching by its name
// -----------------------------------------------------------------------------
// 14/09/2012  SeKi

long tailleP=2000 // Size of Process
long TailleM=400 // Size of Module
long NeededP // returned size of Process
long NeededM // returned size of Module
long resName // size of returned name of the module
long ifx, ii // for looping through processes
boolean resultP, resultM // return codes for EnumProcesses and EnumProcessModules
string name // Name of the module
ulong ul_hfound = 0 //handle of the process

resultP=EnumProcesses(i_Process,TailleP,NeededP)
if resultP=true then
 for ifx=1 to integer(NeededP / 4)
  HandleP[ifx] = OpenProcess(PROCESS_ALL_ACCESS,false,i_Process.lpIdProcess[iFX])
  resultM = EnumProcessModules(HandleP[ifx], i_Module, TailleM, NeededM)
  if NeededM >= 4 then
        if GetProcessMemoryInfo( HandleP[ifx], pmc, 40 ) then
  /*    
      ls_message = ''
      ls_message = "PageFaultCount: " + string(pmc.PageFaultCount) + '~r~n' + &
                    + "PeakWorkingSetSize: " + string(pmc.PeakWorkingSetSize ) + '~r~n' &
          + "WorkingSetSize: " + string(pmc.WorkingSetSize ) + '~r~n' &
          + "QuotaPeakPagedPoolUsage: " + string(pmc.QuotaPeakPagedPoolUsage ) + '~r~n' &
          + "QuotaPagedPoolUsage: " + string(pmc.QuotaPagedPoolUsage ) + '~r~n' &
          + "QuotaPeakNonPagedPoolUsage: " + string(pmc.QuotaPeakNonPagedPoolUsage ) + '~r~n' &
          + "QuotaNonPagedPoolUsage: " + string(pmc.QuotaNonPagedPoolUsage) + '~r~n' &
          + "PagefileUsage: " + string(pmc.PagefileUsage ) + '~r~n' &
          + "PeakPagefileUsage: " + string(pmc.PeakPagefileUsage )
  */
      Name=space(254)
      resName=GetModuleBaseNameW(handleP[ifx], i_Module.lpidmodule[1], name ,254)
      //MessageBox( "Memory Info for : " + Name,ls_message)
                ii ++
                //mle_1.text += "~r~nMemory Info for : " + Name + ls_un + ls_message + ls_un
           
    if name = as_procname then 
      ul_hfound = handleP[ifx]
    exit //for
    end if
    end if
  end if
  CloseHandle(HandleP[ifx])
 next
 /*
 IF ii > 0 THEN
        mle_1.text = "Retrieved ProcessMemoryInfo for " + string(ii) + " processes~r~n" + mle_1.text

 END IF
else
 MessageBox ("Memory Info","Fail calling EnumProcesses")
 */
end if

return ul_hfound

end function

on unvo_process_mgt.create
call super::create
TriggerEvent( this, "constructor" )
end on

on unvo_process_mgt.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on

Dernière modification par seki (14-09-2012 09:27:47)


The best programs are the ones written when the programmer is supposed to be working on something else. - Melinda Varian

Mes réponses PB sur StackOverflow
http://stackoverflow.com/users/flair/317266.png

Hors ligne

 

#12 14-09-2012 15:18:46

erasorz  
Admin
Lieu: Babylone
Date d'inscription: 23-11-2006
Messages: 5121
Pépites: 97,197
Banque: 2,147,483,647

Re: [RESOLU] Unique instance d'une application

ok

le kill marche bien, mais quand je fais un simple of_run( exe, normal!, "" ), PB se vautre lamentablement


N'envoyez jamais un humain faire le travail d'un programme.

Hors ligne

 

#13 14-09-2012 15:34:11

seki  
0x73656B69
Award: bf
Lieu: Laquenexy & Luxembourg
Date d'inscription: 20-11-2008
Messages: 1118
Pépites: 4,296,080,204
Banque: 9,223,372,036,854,776,000
Site web

Re: [RESOLU] Unique instance d'une application

erasorz a écrit:

PB se vautre lamentablement

Gni? Tu peux montrer le bout de code ?


The best programs are the ones written when the programmer is supposed to be working on something else. - Melinda Varian

Mes réponses PB sur StackOverflow
http://stackoverflow.com/users/flair/317266.png

Hors ligne

 

#14 14-09-2012 16:24:27

erasorz  
Admin
Lieu: Babylone
Date d'inscription: 23-11-2006
Messages: 5121
Pépites: 97,197
Banque: 2,147,483,647

Re: [RESOLU] Unique instance d'une application

c'est ce que j'ai mis en remplaçant exe par le chemin et nom complet d'un exécutable...


N'envoyez jamais un humain faire le travail d'un programme.

Hors ligne

 

#15 17-09-2012 07:12:24

seki  
0x73656B69
Award: bf
Lieu: Laquenexy & Luxembourg
Date d'inscription: 20-11-2008
Messages: 1118
Pépites: 4,296,080,204
Banque: 9,223,372,036,854,776,000
Site web

Re: [RESOLU] Unique instance d'une application

Bizarre.

Je en reproduis pas de plantage en appelant un exe avec son path complet, ni avec un path incorrect (PB 11.5.1.4843 Win7 64b).


The best programs are the ones written when the programmer is supposed to be working on something else. - Melinda Varian

Mes réponses PB sur StackOverflow
http://stackoverflow.com/users/flair/317266.png

Hors ligne

 

Pied de page des forums

Propulsé par FluxBB 1.2.22