Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Bonjour,
Je travaille sur une application en PB12.5 utilisée jusqu'à présent sur Windows XP et Office 2003.
Elle vient d'être mise dans un environnement Windows Seven et Office 2010.
Après des recherches, j'ai trouvé une explication à un plantage lors d'un traitement utilisant WorD :
Outlook 2010 (et sans doute 2007) est classé dans "opusApp" lors de l'utilisation de la fonction FindWindow(), ce qui ne permet plus de vérifier la présence de Word comme le faisait le code de mon application.
http://www.office-forums.com/windows-7- … 88190.html
Du coup je cherche une solution pour tester la présence de Word ou du processus WinWord sur le poste et en récupérer le cas échéant, l'id.
Hors ligne
Si je comprends bien, le problème c'est de détecter que Word est démarré, et le problème ne vient probablement pas du fait que outlook est confondu avec word (je viens de vérifier que la classe d'outlook 2010 c'était autre chose "rtcrl_renwnd32") mais qu'il est configuré pour utiliser word comme éditeur de message. Du coup on trouve même plusieurs occurrences de la classe "OpusApp" dans la hiérarchie des fenêtres et sous-fenêtres d'Outlook 2010. Le problème ne se posait pas précédemment ?
J'ai eu le même genre de problème pour détecter si un outil satellite d'une application ici avait besoin d'être démarré ou si il tournait déjà. Pour cela je ne cherche pas par fenêtre mais par processus.
J'ai étendu un code publié par Roland Smith de Topwiz Software (compatibilité : pb10+) et pour savoir si mon processus tourne déjà, je fais
unvo_process_mgt process_mgt process_mgt = create unvo_process_mgt if process_mgt.of_findprocess("nom_de_l_executable_sans_le_path.exe") then //c'est démarré else //il faut le démarrer end if destroy process_mgt
l'objet permet aussi d'autres action comme démarrer un processus avec ou sans attente, tuer un processus (attention c'est comme un "kill -9" sous unix : mort violente du processus), ...
Code de l'objet unvo_process_mgt
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
Hors ligne