DetailPage-MSS-KB

Knowledge Base

Artikel-ID: 178893 - Geändert am: Dienstag, 13. Juli 2004 - Version: 2.4

 

Auf dieser Seite

Zusammenfassung

In einer perfekten Welt konnte bitten Sie Ihren Prozess einen anderen Prozess über eine Form der Prozesskommunikation zum Herunterfahren. Jedoch, wenn Sie nicht Quellebene Steuerung der Anwendung, die Sie herunterfahren möchten haben, Sie nicht diese Option möglicherweise. Es gibt zwar keine garantierte "sauberen" Möglichkeit zum Herunterfahren einer Anwendung in Win32, sind die Schritte, die Sie ergreifen können, um sicherzustellen, dass die Anwendung die beste Methode zum Bereinigen von Ressourcen verwendet.

Weitere Informationen

32-Bit-Prozesse (und 16-Bit-Prozesse unter Windows 95)

Unter Win32 verspricht das Betriebssystem zum Bereinigen von Ressourcen, die im Besitz von einem Prozess, wenn er heruntergefahren. Dies nicht, jedoch bedeutet, dass der Prozess selbst hat die Möglichkeit alle endgültigen Leerungen Informationen zum endgültigen Kommunikation über eine Remoteverbindung Datenträger noch es, des Prozess bedeutet der DLL wird haben die Möglichkeit, Ihre PROCESS_DETACH Code auszuführen. Deshalb ist es generell vorzuziehen, damit eine Anwendung unter Windows 95 und Windows NT beenden.

Wenn ein Prozess ist absolut Herunterfahren müssen, gehen Sie folgendermaßen vor:
  1. Buchen Sie, eine WM_CLOSE alle auf oberster Ebene Fenster im Besitz des Prozess, den heruntergefahren werden soll. Viele Windows-Anwendungen reagieren auf diese Nachricht durch Herunterfahren.

    Hinweis : eine Konsolenanwendung als Antwort auf WM_CLOSE hängt davon unabhängig davon, ob es einen Steuerelement-Handler installiert hat.

    Verwenden Sie EnumWindows(), um die Ziehpunkte an Ihr Ziel zu suchen. In der Rückruffunktion entspricht überprüfen Sie, wenn die Windows-ID verarbeiten den Prozess, der heruntergefahren werden soll. Hierzu können Sie GetWindowThreadProcessId() aufrufen. Nachdem Sie eine Übereinstimmung eingerichtet haben, verwenden Sie PostMessage() oder SendMessageTimeout(), um WM_CLOSE-Meldung in das Fenster zu buchen.
  2. Verwenden Sie WaitForSingleObject(), um das Handle des Prozesses warten. Sicher, dass Sie mit einem Timeoutwert, warten, da es gibt viele Situationen, in denen die WM_CLOSE nicht die Anwendung heruntergefahren wird. Denken Sie daran, das Zeitlimit lange genug gestalten (entweder mit WaitForSingleObject() oder mit SendMessageTimeout()) so dass ein Benutzer auf alle Antworten kann Textfelder, in der WM_CLOSE-Meldung erstellt wurden.
  3. Wenn der Rückgabewert WAIT_OBJECT_0 ist, geschlossen dann die Anwendung selbst nach unten ordnungsgemäß. Wenn der Rückgabewert WAIT_TIMEOUT ist, müssen Sie TerminateProcess() zum Herunterfahren der Anwendung verwenden.

    Hinweis : Wenn Sie ein Rückgabewert von WaitForSingleObject() andere dann WAIT_OBJECT_0 oder WAIT_TIMEOUT getting3 sind, verwenden Sie GetLastError(), um die Ursache zu ermitteln.
Anhand dieser Schritte können Sie der Anwendung mögliche Chancen auf Herunterfahren ordnungsgemäß (abgesehen von IPC oder Eingreifen des Benutzers).

Das 16-Bit-Problem (unter Windows NT)

Die obige Schritte arbeiten für 16-Bit-Anwendungen unter Windows 95, Windows NT 16-Bit-Anwendungen arbeiten jedoch sehr unterschiedlich.

Unter Windows NT werden alle 16-Bit-Anwendungen in eine virtual DOS Machine (VDM) ausgeführt. Diese VDM wird als ein Win32-Prozess (NTVDM) unter Windows NT ausgeführt. Der NTVDM-Prozess hat eine Prozess-ID. Sie können ein Handle für den Prozess über OpenProcess(), abrufen, wie mit anderen Win32-Prozess. Dennoch keine der 16-Bit-Anwendungen, die in der VDM ausgeführt haben eine Prozess-ID, und daher erhalten Sie keine Prozess-Handle vom OpenProcess(). Jeder 16-Bit-Anwendung in einer VDM hat eine 16-Bit-Aufgaben behandeln und eine 32-Bit-Ausführungsthread. Der Handle und Thread-ID kann durch einen Aufruf der Funktion VDMEnumTaskWOWEx() gefunden werden. Weitere Informationen finden Sie in der folgenden Artikel der Microsoft Knowledge Base:
175030  (http://support.microsoft.com/kb/175030/EN-US/ ) Gewusst wie: Auflisten von Anwendungen in Win32
Die erste und einfachste, Option wird eine 16-Bit-Anwendung unter Windows NT Herunterfahren um den gesamten NTVDM-Prozess zu beenden. Hierzu können Sie die oben beschriebenen Schritte. Sie müssen nur die Prozess-ID des NTVDM-Prozess kennen (Siehe die KB-Artikel 175030  (http://support.microsoft.com/kb/175030/EN-US/ ) nach die Prozess-ID ein NTVDM oben genannten). Der Nachteil dieses Ansatzes ist, dass alle 16-Bit-Anwendungen geschlossen wird, die das VDM ausgeführt werden. Wenn dies nicht Ihr Ziel ist, müssen Sie einen anderen Ansatz.

Wenn Sie eine einzelne 16-Bit-Anwendung in einem NTVDM-Prozess beenden möchten, sind es sich bei folgenden um die Schritte, die Sie durchführen müssen:
  1. Alle auf oberster Ebene Windows, deren Besitzer des Prozess und, haben die gleichen besitzende Thread-ID als die 16-Bit-Aufgabe, die Sie herunterfahren möchten, buchen Sie eine WM_CLOSE. Die effektivste Möglichkeit dazu ist die Verwendung EnumWindows(). Überprüfen Sie in der Rückruffunktion, wenn das Fenster, Prozess-ID und Thread-ID entspricht die 16-Bit-Aufgabe heruntergefahren werden soll. Denken Sie daran, dass die Prozess-ID wechselt die PROZESSKENNUNG des NTVDM-Prozess werden in der 16-Bit-Anwendung ausgeführt wird.
  2. Obwohl eine Thread-ID haben, müssen Sie keine Möglichkeit, auf die Beendigung des 16-Bit-Prozesses warten. Folglich müssen Sie warten auf eine beliebige Zeitdauer (um eine saubere Herunterfahren zu ermöglichen) und wiederholen Sie die Anwendung trotzdem beendet. Wenn die Anwendung bereits heruntergefahren wurde, wird dies nichts tun. Wenn er heruntergefahren noch nicht, wird es die Anwendung beendet.
  3. Beendet die Anwendung eine Funktion namens VDMTerminateTaskWOW(), die in der vdmdbg.dll. Die PROZESSKENNUNG der VDM und der Vorgang Anzahl der 16-Bit-Vorgang dauert.
Dieser Ansatz ermöglicht Ihnen, eine einzelne 16-Bit-Anwendung innerhalb einer VDM unter Windows NT Herunterfahren. Allerdings 16-Bit-Windows ist nicht sehr gut zur Bereinigung von Ressourcen für einen beendeten Vorgang, und weder die WOWExec in der VDM ausgeführt wird. Wenn Sie nach der cleanest mögliche Ansatz für das Beenden einer 16-Bit-Anwendung unter Windows NT suchen, sollten Sie den gesamten VDM-Prozess beendet. Hinweis: Wenn Sie eine 16-Bit-Anwendung starten, die Sie später beenden können, Verwenden der CREATE_SEPARATE_WOW_VDM mit CreateProcess().

Beispielcode

Der Beispielcode implementiert die für 16-Bit- und 32-Bit-Anwendungen, die Verwendung der folgenden zwei Funktionen oben beschriebenen Verfahren: TerminateApp() und Terminate16App(). TerminateApp() wird eine 32-Bit-Prozess-ID und ein Zeitlimit (in Millisekunden). Terminate16App(). Beide Funktionen verwenden die explizite Verknüpfung DLL-Funktionen, so dass Sie binärkompatibel über Windows NT und Windows 95 werden.
   //******************
   //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 ;
   }
				

Die Informationen in diesem Artikel beziehen sich auf:
  • Microsoft Win32 Application Programming Interface, wenn verwendet mit:
    • Microsoft Windows 95
    • Microsoft Windows NT 4.0
    • the operating system: Microsoft Windows 2000
    • the operating system: Microsoft Windows XP
Keywords: 
kbmt kbhowto kbkernbase kbthread KB178893 KbMtde
Maschinell übersetzter ArtikelMaschinell übersetzter Artikel
Wichtig: Dieser Artikel wurde maschinell und nicht von einem Menschen übersetzt. Die Microsoft Knowledge Base ist sehr umfangreich und ihre Inhalte werden ständig ergänzt beziehungsweise überarbeitet. Um Ihnen dennoch alle Inhalte auf Deutsch anbieten zu können, werden viele Artikel nicht von Menschen, sondern von Übersetzungsprogrammen übersetzt, die kontinuierlich optimiert werden. Doch noch sind maschinell übersetzte Texte in der Regel nicht perfekt, insbesondere hinsichtlich Grammatik und des Einsatzes von Fremdwörtern sowie Fachbegriffen. Microsoft übernimmt keine Gewähr für die sprachliche Qualität oder die technische Richtigkeit der Übersetzungen und ist nicht für Probleme haftbar, die direkt oder indirekt durch Übersetzungsfehler oder die Verwendung der übersetzten Inhalte durch Kunden entstehen könnten.
Den englischen Originalartikel können Sie über folgenden Link abrufen: 178893  (http://support.microsoft.com/kb/178893/en-us/ )
Microsoft stellt Ihnen die in der Knowledge Base angebotenen Artikel und Informationen als Service-Leistung zur Verfügung. Microsoft übernimmt keinerlei Gewährleistung dafür, dass die angebotenen Artikel und Informationen auch in Ihrer Einsatzumgebung die erwünschten Ergebnisse erzielen. Die Entscheidung darüber, ob und in welcher Form Sie die angebotenen Artikel und Informationen nutzen, liegt daher allein bei Ihnen. Mit Ausnahme der gesetzlichen Haftung für Vorsatz ist jede Haftung von Microsoft im Zusammenhang mit Ihrer Nutzung dieser Artikel oder Informationen ausgeschlossen.
Freigeben
Weitere Supportoptionen
Microsoft Community-Supportforen
Kontaktieren Sie uns direkt
Zertifizierten Partner finden
Microsoft Store