Πώς να τερματίσετε μια εφαρμογή Win32 "Καθαρότητα"

Μεταφράσεις άρθρων Μεταφράσεις άρθρων
Αναγν. άρθρου: 178893 - Δείτε τα προϊόντα στα οποία αναφέρεται το συγκεκριμένο άρθρο.
Ανάπτυξη όλων | Σύμπτυξη όλων

Σε αυτήν τη σελίδα

Περίληψη

Σε έναν ιδανικό κόσμο διαδικασία σας θα μπορούσε να ζητήσει άλλη διαδικασία μέσω ορισμένων φόρμα επικοινωνίας στο εσωτερικό των διαδικασιών, για να τερματίσετε τη λειτουργία. Ωστόσο, εάν δεν το κάνετε στοιχείο ελέγχου προέλευσης επίπεδο της εφαρμογής που θέλετε να τερματίσετε, στη συνέχεια, ίσως δεν έχετε αυτήν την επιλογή. Παρόλο που υπάρχει όχι εγγυημένη "καθαρό" τρόπο για να τερματίσετε μια εφαρμογή στο Win32, υπάρχουν βήματα που μπορείτε να ακολουθήσετε Για να εξασφαλίσετε ότι η εφαρμογή χρησιμοποιεί την καλύτερη μέθοδο για την εκκαθάριση πόροι.

Περισσότερες πληροφορίες

Διεργασίες των 32-bit (και διεργασίες των 16-Bit στα Windows 95)

Στην περιοχή Win32, το λειτουργικό σύστημα υπόσχεται να εκκαθαρίσετε πόρους που ανήκουν σε διαδικασία όταν τερματιστεί. Αυτό, ωστόσο, συνεπάγεται τη διαδικασία ίδιο είχε την ευκαιρία να κάνετε οποιαδήποτε τελική Εκκαθαρίσεις πληροφοριών δίσκος, οποιαδήποτε τελική επικοινωνία μέσω απομακρυσμένης σύνδεσης, ούτε σημαίνει που η διαδικασία του DLL θα έχετε την ευκαιρία να εκτελέσει τους Κωδικός PROCESS_DETACH. Αυτός είναι ο λόγος είναι συνήθως προτιμότερο να αποφύγετε Τερματισμός αίτησης στα πλαίσια των Windows 95 και Windows NT.

Εάν απολύτως πρέπει να τερματίσετε μια διεργασία, ακολουθήστε τα εξής βήματα:
  1. Καταχώρηση ενός WM_CLOSE ανήκουν στη διαδικασία που θέλετε να τερματίσετε όλα τα παράθυρα ανωτάτου επιπέδου. Πολλές εφαρμογές Windows ανταποκρίνονται σε αυτό το μήνυμα από τον τερματισμό.

    ΣΗΜΕΊΩΣΗ: Απόκριση μια εφαρμογή κονσόλας WM_CLOSE εξαρτάται από ή όχι το έχει εγκαταστήσει ένα πρόγραμμα χειρισμού ελέγχου.

    Χρησιμοποιήστε το EnumWindows() για να βρείτε τις λαβές για να σας windows προορισμού. Σε λειτουργία επιστροφής κλήσης σας, ελέγξτε εάν το windows επεξεργασία ID ταιριάζει στη διεργασία που θέλετε να τερματίσετε. Μπορείτε να το κάνετε με κλήση του GetWindowThreadProcessId(). Αφού έχετε δημιουργήσει μια αντιστοιχία, χρησιμοποιήστε PostMessage() ή SendMessageTimeout() για να καταχωρήσετε το μήνυμα WM_CLOSE στο παράθυρο.
  2. Χρησιμοποιήστε το WaitForSingleObject() να περιμένετε μέχρι ο δείκτης χειρισμού της διαδικασίας. Βεβαιωθείτε ότι περιμένετε με μια τιμή χρονικού ορίου, επειδή υπάρχουν πολλές περιπτώσεις όπου το WM_CLOSE θα Τερματισμός εφαρμογής. Θυμηθείτε να δώσετε το αρκετά μεγάλο χρονικό όριο (είτε με WaitForSingleObject() ή με SendMessageTimeout()), έτσι ώστε ένας χρήστης να ανταποκριθεί σε οποιοδήποτε παράθυρο διαλόγου πλαίσια που έχουν δημιουργηθεί ως απόκριση σε μήνυμα WM_CLOSE.
  3. Εάν η τιμή που επιστρέφεται είναι WAIT_OBJECT_0, στη συνέχεια, η εφαρμογή κλείσει ίδιο καθαρότητα. Εάν η τιμή που επιστρέφεται είναι WAIT_TIMEOUT, πρέπει να χρησιμοποιήσετε TerminateProcess() για τον τερματισμό της εφαρμογής.

    ΣΗΜΕΊΩΣΗ: Εάν είναι getting3 μια επιστροφή τιμής από άλλα WaitForSingleObject() και στη συνέχεια WAIT_OBJECT_0 ή WAIT_TIMEOUT, χρησιμοποιήστε το GetLastError() για να προσδιορίσετε την αιτία.
Ακολουθώντας αυτά τα βήματα, δίνετε στην εφαρμογή καλύτερη δυνατή ευκαιρία Τερματισμός καθαρού (εκτός από την IPC ή παρέμβαση του χρήστη).

Το ζήτημα των 16-Bit (στα Windows NT)

Τα προηγούμενα βήματα λειτουργούν για εφαρμογές 16-bit στα Windows 95, ωστόσο, Εφαρμογές των Windows NT 16-bit λειτουργεί πολύ διαφορετικά.

Στα Windows NT, όλες τις εφαρμογές 16-bit εκτελούνται σε εικονική μηχανή DOS (VDM). VDM αυτή εκτελείται ως διαδικασία Win32 (NTVDM) στα Windows NT. Το NTVDM η διαδικασία έχει ένα αναγνωριστικό διαδικασίας. Μπορείτε να αποκτήσετε ένα δείκτη χειρισμού της διαδικασίας μέσω Να OpenProcess(), όπως και με οποιαδήποτε διεργασία Win32. Ωστόσο, καμία εφαρμογές 16-bit εκτελούνται το VDM έχει ένα διαδικασία ID και επομένως δεν μπορείτε να λάβετε μια διαδικασία χειρισμού από OpenProcess(). Κάθε εφαρμογή 16-bit σε ένα VDM έχει λαβή εργασία 16-bit και ένα νήμα εκτέλεσης 32-bit. Αναγνωριστικό δείκτη χειρισμού και νήμα μπορεί να βρεθεί μέσω μιας κλήσης στη συνάρτηση VDMEnumTaskWOWEx(). Για πρόσθετες πληροφορίες, ανατρέξτε στο ακόλουθο άρθρο γνωσιακής Microsoft Βάση:
175030Τρόπος απαρίθμηση εφαρμογών στο Win32
Η πρώτη και πιο απλή, επιλογή σας κατά τον τερματισμό των 16-bit εφαρμογή στα Windows NT είναι να τερματίσετε ολόκληρη τη διαδικασία NTVDM. Μπορείτε να το κάνετε αυτό, ακολουθώντας τα βήματα που περιγράφονται παραπάνω. Πρέπει να γνωρίζετε Αναγνωριστικό διαδικασίας διεργασία NTVDM (ανατρέξτε στο άρθρο KB 175030 αναφέρονται παραπάνω Για να βρείτε το Αναγνωριστικό διαδικασίας NTVDM ένα). Το μειονέκτημα αυτής της προσέγγισης είναι ότι κλείνει όλες τις εφαρμογές 16-bit που εκτελούν το VDM. Εάν αυτή είναι δεν ο στόχος σας, πρέπει να λαμβάνουν μια άλλη προσέγγιση.

Εάν θέλετε να τερματίσετε μια μεμονωμένη εφαρμογή 16-bit σε ένα NTVDM διαδικασία, ακολουθούν τα βήματα που πρέπει να κάνετε:
  1. Καταχώρηση WM_CLOSE για όλα τα ανώτατου επιπέδου windows που ανήκουν τη διαδικασία, και που έχουν το ίδιο Αναγνωριστικό οποίο ανήκει το νήμα ως εργασία 16-bit που θέλετε να Τερματισμός. Ο πιο αποτελεσματικός τρόπος είναι με τη χρήση EnumWindows(). Σε λειτουργία επιστροφής κλήσης σας, ελέγξτε για να δείτε εάν το παράθυρο επεξεργασία ID και Αναγνωριστικό νήματος ταιριάζει εργασία 16-bit που θέλετε να τερματίσετε. Να θυμάστε ότι Αναγνωριστικό διεργασίας πρόκειται να είναι το Αναγνωριστικό της διαδικασίας NTVDM στο όπου εκτελείται η εφαρμογή 16-bit.
  2. Παρόλο που έχει ένα Αναγνωριστικό νήματος, δεν υπάρχει κανένας τρόπος να περιμένετε την περάτωση της διαδικασίας 16-bit. Ως αποτέλεσμα, πρέπει να περιμένετε για ένα αυθαίρετη χρονικό διάστημα (για να επιτρέψετε την καθαρή τερματισμός λειτουργίας προς τα κάτω), και στη συνέχεια προσπαθήστε να ο τερματισμός της εφαρμογής ούτως ή άλλως. Εάν η εφαρμογή έχει ήδη τερματισμός λειτουργίας προς τα κάτω, στη συνέχεια, αυτό θα κάνει τίποτα. Εάν δεν έχει τερματιστεί, στη συνέχεια, θα Τερματισμός εφαρμογής.
  3. Τερματισμός εφαρμογής χρησιμοποιώντας μια συνάρτηση που ονομάζεται VDMTerminateTaskWOW(), που βρίσκονται στο Vdmdbg.dll της. Λαμβάνει το Αναγνωριστικό διαδικασίας της VDM και ο αριθμός εργασιών εργασιών 16-bit.
Αυτή η προσέγγιση σάς επιτρέπει να τερματίσετε μια μεμονωμένη εφαρμογή 16-bit σε ένα VDM στα Windows NT. Ωστόσο, δεν είναι πολύ καλή σε καθαρισμό Windows 16-bit πόροι εργασίας τερμάτισε και ούτε είναι WOWExec σε VDM. Εάν αναζητάτε την καθαρότερη προσέγγιση για Τερματισμός μιας εφαρμογής 16 bit στα Windows NT, θα πρέπει να Τερματισμός ολόκληρο διεργασία VDM. ΣΗΜΕΊΩΣΗ: Εάν ξεκινάτε 16-bit εφαρμογή που μπορεί να τερματίσει αργότερα, τότε χρησιμοποιήστε το CREATE_SEPARATE_WOW_VDM με CreateProcess().

Δείγμα κώδικα

Το δείγμα κώδικα υλοποιεί τις τεχνικές που περιγράφονται παραπάνω για 16-bit και 32- bit εφαρμογές χρησιμοποιώντας τις παρακάτω δύο λειτουργίες: TerminateApp() και Terminate16App(). TerminateApp() λαμβάνει ένα Αναγνωριστικό διεργασίας 32-bit και ένα χρονικό όριο (σε miliseconds). Terminate16App(). Και οι δύο συναρτήσεις χρησιμοποιούν ρητή σύνδεση DLL λειτουργεί έτσι ώστε θα είναι συμβατή με το δυαδικό μέσω των Windows NT και Τα Windows 95.
   //******************
   //Header
   //******************

   #include <windows.h>

   #define TA_FAILED 0
   #define TA_SUCCESS_CLEAN 1
   #define TA_SUCCESS_KILL 2
   #define TA_SUCCESS_16 3

   DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout ) ;
   DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
                        WORD w16Task, DWORD dwTimeout );

   //******************
   //Source
   //******************

   #include "TermApp.h"
   #include <vdmdbg.h>

   typedef struct
   {
      DWORD   dwID ;
      DWORD   dwThread ;
   } TERMINFO ;

   // Declare Callback Enum Functions.
   BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) ;

   BOOL CALLBACK Terminate16AppEnum( HWND hwnd, LPARAM lParam ) ;

   /*----------------------------------------------------------------
   DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )

   Purpose:
      Shut down a 32-Bit Process (or 16-bit process under Windows 95)

   Parameters:
      dwPID
         Process ID of the process to shut down.

      dwTimeout
         Wait time in milliseconds before shutting down the process.

   Return Value:
      TA_FAILED - If the shutdown failed.
      TA_SUCCESS_CLEAN - If the process was shutdown using WM_CLOSE.
      TA_SUCCESS_KILL - if the process was shut down with
         TerminateProcess().
      NOTE:  See header for these defines.
   ----------------------------------------------------------------*/ 
   DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )
   {
      HANDLE   hProc ;
      DWORD   dwRet ;

      // If we can't open the process with PROCESS_TERMINATE rights,
      // then we give up immediately.
      hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE,
         dwPID);

      if(hProc == NULL)
      {
         return TA_FAILED ;
      }

      // TerminateAppEnum() posts WM_CLOSE to all windows whose PID
      // matches your process's.
      EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID) ;

      // Wait on the handle. If it signals, great. If it times out,
      // then you kill it.
      if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0)
         dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED);
      else
         dwRet = TA_SUCCESS_CLEAN ;

      CloseHandle(hProc) ;

      return dwRet ;
   }

   /*----------------------------------------------------------------
   DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
                        WORD w16Task, DWORD dwTimeout )

   Purpose:
      Shut down a Win16 APP.

   Parameters:
      dwPID
         Process ID of the NTVDM in which the 16-bit application is
         running.

      dwThread
         Thread ID of the thread of execution for the 16-bit
         application.

      w16Task
         16-bit task handle for the application.

      dwTimeout
         Wait time in milliseconds before shutting down the task.

   Return Value:
      If successful, returns TA_SUCCESS_16
      If unsuccessful, returns TA_FAILED.
      NOTE:  These values are defined in the header for this
      function.

   NOTE:
      You can get the Win16 task and thread ID through the
      VDMEnumTaskWOW() or the VDMEnumTaskWOWEx() functions.
   ----------------------------------------------------------------*/ 
   DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
                        WORD w16Task, DWORD dwTimeout )
   {
      HINSTANCE      hInstLib ;
      TERMINFO      info ;

      // You will be calling the functions through explicit linking
      // so that this code will be binary compatible across
      // Win32 platforms.
      BOOL (WINAPI *lpfVDMTerminateTaskWOW)(DWORD dwProcessId,
         WORD htask) ;

      hInstLib = LoadLibraryA( "VDMDBG.DLL" ) ;
      if( hInstLib == NULL )
         return TA_FAILED ;

      // Get procedure addresses.
      lpfVDMTerminateTaskWOW = (BOOL (WINAPI *)(DWORD, WORD ))
         GetProcAddress( hInstLib, "VDMTerminateTaskWOW" ) ;

      if( lpfVDMTerminateTaskWOW == NULL )
      {
         FreeLibrary( hInstLib ) ;
         return TA_FAILED ;
      }

      // Post a WM_CLOSE to all windows that match the ID and the
      // thread.
      info.dwID = dwPID ;
      info.dwThread = dwThread ;
      EnumWindows((WNDENUMPROC)Terminate16AppEnum, (LPARAM) &info) ;

      // Wait.
      Sleep( dwTimeout ) ;

      // Then terminate.
      lpfVDMTerminateTaskWOW(dwPID, w16Task) ;

      FreeLibrary( hInstLib ) ;
      return TA_SUCCESS_16 ;
   }

   BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam )
   {
      DWORD dwID ;

      GetWindowThreadProcessId(hwnd, &dwID) ;

      if(dwID == (DWORD)lParam)
      {
         PostMessage(hwnd, WM_CLOSE, 0, 0) ;
      }

      return TRUE ;
   }

   BOOL CALLBACK Terminate16AppEnum( HWND hwnd, LPARAM lParam )
   {
      DWORD      dwID ;
      DWORD      dwThread ;
      TERMINFO   *termInfo ;

      termInfo = (TERMINFO *)lParam ;

      dwThread = GetWindowThreadProcessId(hwnd, &dwID) ;

      if(dwID == termInfo->dwID && termInfo->dwThread == dwThread )
      {
         PostMessage(hwnd, WM_CLOSE, 0, 0) ;
      }

      return TRUE ;
   }
				

Ιδιότητες

Αναγν. άρθρου: 178893 - Τελευταία αναθεώρηση: Παρασκευή, 23 Σεπτεμβρίου 2011 - Αναθεώρηση: 6.0
Οι πληροφορίες σε αυτό το άρθρο ισχύουν για:
  • Microsoft Win32 Application Programming Interface
Λέξεις-κλειδιά: 
kbhowto kbkernbase kbthread kbmt KB178893 KbMtel
Μηχανικά μεταφρασμένο
ΣΗΜΑΝΤΙΚΟ: Αυτό το άρθρο είναι προϊόν λογισμικού μηχανικής μετάφρασης της Microsoft και όχι ανθρώπινης μετάφρασης. Η Microsoft σάς προσφέρει άρθρα που είναι προϊόντα ανθρώπινης αλλά και μηχανικής μετάφρασης έτσι ώστε να έχετε πρόσβαση σε όλα τα άρθρα της Γνωσιακής Βάσης μας στη δική σας γλώσσα. Ωστόσο, ένα άρθρο που έχει προκύψει από μηχανική μετάφραση δεν είναι πάντα άριστης ποιότητας. Ενδέχεται να περιέχει λεξιλογικά, συντακτικά ή γραμματικά λάθη, όπως ακριβώς τα λάθη που θα έκανε ένας μη φυσικός ομιλητής επιχειρώντας να μιλήσει τη γλώσσα σας. Η Microsoft δεν φέρει καμία ευθύνη για τυχόν ανακρίβειες, σφάλματα ή ζημίες που προκύψουν λόγω τυχόν παρερμηνειών στη μετάφραση του περιεχομένου ή χρήσης του από τους πελάτες της. Επίσης, η Microsoft πραγματοποιεί συχνά ενημερώσεις στο λογισμικό μηχανικής μετάφρασης.
Η αγγλική έκδοση αυτού του άρθρου είναι η ακόλουθη:178893

Αποστολή σχολίων

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com