kath Δημοσ. 19 Μαΐου 2006 Δημοσ. 19 Μαΐου 2006 Γεια και παλι . Για ακομα μια φορα χρειαζομαι τις γνωσεις σας για την επιλυση ενος προβληματος. Συγκεκριμενα , θελω να τερματισω μια διεργασια που τρεχει στο background. Αυτο που ζητω , ειναι με καποιο τροπο να τερματισω την εφαρμογη χρησιμοποιωντας το proccess name και οχι με τον τιτλο παραθυρου , γιατι αλλαζει συνεχως. Καμια προταση ; Ευχαριστω
Directx Δημοσ. 19 Μαΐου 2006 Δημοσ. 19 Μαΐου 2006 Για να διακόψεις την εκτέλεση μιας διεργασίας (process) πρέπει να καλέσεις την ομώνυμη εντολή TerminateProcess μαζί με το ανάλογο process Handle που την προσδιορίζει. Τα Windows προσφέρουν ένα σύνολο εντολών (CreateToolhelp32Snapshot) με το οποίο μπορείς να εξετάσεις τις εκτελούμενες διεργασίες (Process32First & Process32Next) αναζητώντας αυτό που χρειάζεσαι. Η παρακάτω ρουτίνα (Borland C/C++ Builder 2006) υλοποιεί την αναζήτηση της διεργασίας που μας ενδιαφέρει με βάση την ονομασία του αρχείου της και ύστερα ζητά από το σύστημα (δια της OpenProcess) να λάβει ένα Handle στην διεργασία που να επιτραπεί την «αίτηση διακοπής» (PROCESS_TERMINATE). Μετά απλά περνά το συγκεκριμένο Handle στην εντολή TerminateProcess η οποία διακόπτει την εκτέλεση της διεργασίας με βίαιο τρόπο. > // _KillProcess by DIRECTX (Borland C/C++ Builder 2006) #include <stdio.h> #include <conio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> //--------------------------------------------------------------------------- BOOL _KillProcess(char *pszProcName) { // Take a snapshot of the running processes (use 9x - XP compatible API) HANDLE hProcSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0), hProcHandle; PROCESSENTRY32 procEntry; BOOL bTerminated = FALSE; char szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szFName[_MAX_FNAME], szExt[_MAX_EXT]; if(hProcSnapshot!=INVALID_HANDLE_VALUE) { ZeroMemory(&procEntry,sizeof(procEntry)); procEntry.dwSize = sizeof(procEntry); // Start running processes list traverse if(Process32First(hProcSnapshot,&procEntry)) { do{ // Windows 9x & Me. return full path+filename info, 2000 & XP not! _splitpath(procEntry.szExeFile,szDrive,szDir,szFName,szExt); // Did we found the expected process (file) name? if(!lstrcmpi(lstrcat(szFName,szExt),pszProcName)) { // Attempt to open process for TERMINATION if((hProcHandle=OpenProcess(PROCESS_TERMINATE,FALSE, procEntry.th32ProcessID))!=NULL) { // Ask system to terminate it! bTerminated = TerminateProcess(hProcHandle,0); CloseHandle(hProcHandle); // We stop process list traverse on first found process instance break; } } }while(Process32Next(hProcSnapshot,&procEntry)); } CloseHandle(hProcSnapshot); } return bTerminated; } int main(int argc, char* argv[]) { printf("%d\n",_KillProcess("NOTEPAD.EXE")); getch(); return 0; } Υ.Γ. Η παραπάνω ρουτίνα είναι συμβατή με όλες τις εκδόσεις των Windows αφού χρησιμοποιεί το Tool-Help32 API το οποίο είναι μερικός βέβαια συμβατό με τα MS-Windows 2000 & XP αλλά για την παρούσα ανάγκη επαρκές. Ο κώδικας: > _splitpath(procEntry.szExeFile,szDrive,szDir,szFName,szExt); Εξασφαλίζει την σωστή λειτουργεία της εντολής τόσο στα 9x & Me. όπου η Process32First & Process32Next επιστρέφουν πλήρες διαδρομής (πχ. C:\Windows\NOTEPAD.EXE) προς την εκτελούμενη διεργασία , σε αντίθεση με τα XP & 2000 που επιστρέφουν μόνο την ονομασία της (πχ. NOTEPAD.EXE) Επίσης εάν υπάρχουν πολλαπλές διεργασίες με την ίδια ονομασία (multi instances) τότε κρίνεται ανεπαρκείς αφού δεν μπορεί να ξεχωρίσει το ζητούμενο ενώ την έχω ρυθμίσει ώστε να διακόπτει (εντολή break) την περαιτέρω αναζήτηση του process list με το κλείσιμο της πρώτης διεργασίας που ικανοποιεί τα κριτήρια μας. Το παράδειγμα απλά κλείνει την πρώτη διεργασία με την ονομασία NOTEPAD.EXE
kath Δημοσ. 19 Μαΐου 2006 Μέλος Δημοσ. 19 Μαΐου 2006 Μου εμφανιζει σφαλμα σε αυτο το κομματι κωδικα : > _splitpath(procEntry.szExeFile,&szDrive,&szDir,&szFName,&szExt); 30 C:\prj00sock\main.cpp cannot convert `char (*)[3]' to `char*' for argument `2' to `void _splitpath(const char*, char*, char*, char*, char*)'
kath Δημοσ. 19 Μαΐου 2006 Μέλος Δημοσ. 19 Μαΐου 2006 Ακυρο , το διορθωσα : > _splitpath(procEntry.szExeFile,szDrive,szDir,szFName,szExt); ..Για αλλη μια φορα σ'ευχαριστω
Directx Δημοσ. 19 Μαΐου 2006 Δημοσ. 19 Μαΐου 2006 Ooops! Αβλεψία μου διότι το ανέπτυξα σε C - Άλλαξα και το source. Καλή συνέχεια!
kath Δημοσ. 20 Μαΐου 2006 Μέλος Δημοσ. 20 Μαΐου 2006 Να ρωτησω κατι σχετικο - ασχετο ; (ελπιζω να μην "κουραζω" ... αλλα αν δεν ρωτησεις δεν μαθαινεις ποτε!) Με βαση τον παραπανω κωδικα , μπορω να αλλαξω την προτεραιοτητα μιας διεργασιας ; η οχι ;
Directx Δημοσ. 21 Μαΐου 2006 Δημοσ. 21 Μαΐου 2006 Μπορείς με τις παρακάτω αλλαγές: 1ον) Αλλάζεις το αιτούμενο δικαίωμα της OpenProcess από PROCESS_TERMINATE σε PROCESS_SET_INFORMATION. 2ον) Αντικαθιστάς την εντολή TerminateProcess με την SetPriorityClass η οποία αλλάζει την προτεραιότητα εκτέλεσης της διεργασίας. 3ον) Ορίζεις την νέα επιθυμητή προτεραιότητα ως (από το Windows API SDK): HIGH_PRIORITY_CLASS = υψηλή προτεραιότητα, IDLE_PRIORITY_CLASS = χαμηλή προτεραιότητα, NORMAL_PRIORITY_CLASS = κανονική προτεραιότητα, REALTIME_PRIORITY_CLASS = υπερ-υψηλή προτεραιότητα (προσοχή γιατί το σύστημα μπορεί να σταματήσει να ανταποκρίνεται στα αιτήματα άλλων διεργασιών). Ακολουθεί ο μετατρεμμένος κώδικας σε μορφή εντολής _SetProcPriority: > [size="4"] // _SetProcPriority by DIRECTX (Borland C/C++ Builder 2006) #include <stdio.h> #include <conio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> //--------------------------------------------------------------------------- BOOL _SetProcPriority(char *pszProcName,DWORD dwNewPriority) { // Take a snapshot of the running processes (use 9x - XP compatible API) HANDLE hProcSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0), hProcHandle; PROCESSENTRY32 procEntry; BOOL bNewPriority = FALSE; char szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szFName[_MAX_FNAME], szExt[_MAX_EXT]; if(hProcSnapshot!=INVALID_HANDLE_VALUE) { ZeroMemory(&procEntry,sizeof(procEntry)); procEntry.dwSize = sizeof(procEntry); // Start running processes list traverse if(Process32First(hProcSnapshot,&procEntry)) { do{ // Windows 9x & Me. return full path+filename info, 2000 & XP not! _splitpath(procEntry.szExeFile,szDrive,szDir,szFName,szExt); // Did we found the expected process (file) name? if(!lstrcmpi(lstrcat(szFName,szExt),pszProcName)) { // Attempt to open process for TERMINATION // 1.1+ if((hProcHandle=OpenProcess(PROCESS_SET_INFORMATION, FALSE,procEntry.th32ProcessID))!=NULL) { // Set process priority class bNewPriority = SetPriorityClass(hProcHandle,dwNewPriority); CloseHandle(hProcHandle); // We stop process list traverse on first found process instance break; } } }while(Process32Next(hProcSnapshot,&procEntry)); } CloseHandle(hProcSnapshot); } return bNewPriority; } int main(int argc, char* argv[]) { printf("%d\n",_SetProcPriority("NOTEPAD.EXE",IDLE_PRIORITY_CLASS)); getch(); return 0; } [/size] Υ.Γ. 1ον) Η τιμή dwNewPriority της _SetProcPriority ακολουθεί τις προαναφερθείσες προτεραιότητες. 2ον) Το παράδειγμα αλλάζει το priority class ενός NOTEPAD instance σε “χαμηλή προτεραιότητα”. 3ον) Επειδή έχω ρυθμίσει διαφορετικά τα tabs στο IDE του C/C++ Builder η δομή του κώδικα χάνεται κατά την επικόλληση στο forum..
kath Δημοσ. 21 Μαΐου 2006 Μέλος Δημοσ. 21 Μαΐου 2006 Τι να πω ; ! εισαι φοβερος Θα το δοκιμασω αργοτερα
kath Δημοσ. 21 Μαΐου 2006 Μέλος Δημοσ. 21 Μαΐου 2006 Δουλευει αψογα! κατι μαθαμε και σημερα! Να'σαι καλα .... να βοηθας τον κοσμο !
Directx Δημοσ. 21 Μαΐου 2006 Δημοσ. 21 Μαΐου 2006 3 tab stops σε Courier New των 10 στιγμών στα 1152x864 με Large Fonts
kath Δημοσ. 22 Μαΐου 2006 Μέλος Δημοσ. 22 Μαΐου 2006 Μια ακομα ερωτηση ( )... Για να αποκρυψω ενα παραθυρο , του οποιου δεν γνωριζω τον τιτλο. Πως μπορω να το αποκρυψω ? ( ξερω το ονομα της διεργασιας). Δοκιμασα αυτο: HWND con; con = FindWindow("hproc00", NULL); ShowWindow(con, SW_HIDE); Αλλα δεν δουλευει
Directx Δημοσ. 23 Μαΐου 2006 Δημοσ. 23 Μαΐου 2006 Εάν δεν γνωρίζεις τον τίτλο του παραθύρου (Window Caption) τότε μπορείς να δοκιμάσεις τον εντοπισμό του με βάση το Class του, με την βοήθεια της FindWindow ή FindWindowEx. Όμως οι συγκεκριμένες ρουτίνες όπως έχω εξηγήσει σε παλαιότερο θέμα, δεν λειτουργούν σωστά σε περιπτώσεις πολλαπλών instances όπου υπάρχουν δηλαδή πολλά παράθυρα με τα ίδια κριτήρια αναζήτησης ή με ιδιόρρυθμα window visibility flags τα οποία αφορούν το Z-Order (πχ. παράθυρα on-top). Τώρα όσον αφορά την περίπτωση σου, από την στιγμή που δεν γνωρίζεις τον τίτλο του παραθύρου της εφαρμογής, έγραψα μια νέα ρουτίνα (_ProcShowWindow) που απλά αλλάζει το visibility state όλων των top-level (parent αν θες) παραθύρων της συγκεκριμένης διεργασίας αφού δεν γνωρίζω κανένα άλλο κριτήριο για αυτά. Ο εντοπισμός του process id που μας ενδιαφέρει γίνεται με βάση τις προηγηθείσες ρουτίνες (_SetProcPriority & _KillProcess) κατάλληλα προσαρμοσμένες (_GetProcID) ώστε να επιστρέφουν μόνο το process id (dwPID) με βάση το όνομα της διεργασίας. Ο εντοπισμός όλων των top-level παραθύρων γίνεται με την βοήθεια της ρουτίνας _ProcShowWindow η οποία είναι συμβατή με τις παραμέτρους της ShowWindow και στηρίζεται στην Windows API function EnumWindows η οποία ορίζει ένα CALLBACK (EWProc) το οποίο διασχίζει την λίστα των διαθέσιμων παραθύρων. Όταν το CALLBACK function EWProc εντοπίσει πως το process id του παράθυρου (GetWindowThreadID) ταιριάζει με αυτό που μας ενδιαφέρει (το περνάμε δια της lParam) τότε αλλάζει το visibility state του με κλήση στην ShowWindowAsync η οποία προτιμάται από την ShowWindow διότι αφορά διαφορετική διεργασία και δεν μπλοκάρει την εκτέλεση της εφαρμογής μας. Τέλος η _bSomethingFound τίθεται σε TRUE με την πρώτη κλήση για αλλαγή του visibility state κάποιου παραθύρου που ταιριάζει με το process id που μας ενδιαφέρει. > //-_ProcShowWindow (C) BY DIRECTX--------------------------------------------- #include <stdio.h> #include <conio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #pragma hdrstop //--------------------------------------------------------------------------- int _nCmdShow; BOOL _bSomethingFound; //--------------------------------------------------------------------------- DWORD _GetProcID(char *pszProcName) { // Take a snapshot of the running processes (use 9x - XP compatible API) HANDLE hProcSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0), hProcHandle; PROCESSENTRY32 procEntry; char szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szFName[_MAX_FNAME], szExt[_MAX_EXT]; if(hProcSnapshot!=INVALID_HANDLE_VALUE) { ZeroMemory(&procEntry,sizeof(procEntry)); procEntry.dwSize = sizeof(procEntry); // Start running processes list traverse if(Process32First(hProcSnapshot,&procEntry)) { do{ // Windows 9x & Me. return full path+filename info, 2000 & XP not! _splitpath(procEntry.szExeFile,szDrive,szDir,szFName,szExt); // Did we found the expected process (file) name? if(!lstrcmpi(lstrcat(szFName,szExt),pszProcName)) return procEntry.th32ProcessID; // Return Process ID }while(Process32Next(hProcSnapshot,&procEntry)); } CloseHandle(hProcSnapshot); } return 0; } //--------------------------------------------------------------------------- BOOL CALLBACK EWProc(HWND hWnd,LPARAM lParam) { // Traverse all top-level windows DWORD dwPID; GetWindowThreadProcessId(hWnd,&dwPID); if(dwPID==lParam) { // Process IDs match - apply _nCmdShow to window! ShowWindowAsync(hWnd,_nCmdShow); _bSomethingFound = TRUE; } // Continue list traverse return TRUE; } //--------------------------------------------------------------------------- BOOL _ProcShowWindow(char *pszProcName,int nCmdShow) { // Find pszProcName ID _bSomethingFound = FALSE; DWORD dwPID = _GetProcID(pszProcName); _nCmdShow = nCmdShow; // Did _GetProcID succeeded? if(dwPID) EnumWindows((WNDENUMPROC)EWProc,(LPARAM)dwPID); // Did we found anything? return _bSomethingFound; } #pragma argsused int main(int argc, char* argv[]) { printf("%d\n",_ProcShowWindow("NOTEPAD.EXE",SW_HIDE)); getch(); return 0; } //--------------------------------------------------------------------------- Υ.Γ. 1ον)Ο εντοπισμός του process id με βάση το όνομα της διεργασίας επιστρέφει το πρώτο instance οπότε κρίνεται ανεπαρκείς για πολλαπλές διεργασίες με την ίδια ονομασία (multi instances) παρʼ όλα αυτά με ορισμένες αλλαγές στην δομή του κώδικα αυτό διορθώνεται. 2ον)Το παράδειγμα κρύβει το παράθυρο ενός NOTEPAD instance.
kath Δημοσ. 23 Μαΐου 2006 Μέλος Δημοσ. 23 Μαΐου 2006 Υπαρχει ενα μικρο προβλημα ομως, οταν κανω εμφανιση ενος παραθυρου , εμφανιζονται και καποιες "κρυφες" φορμες.Γιατι ;
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.