WM_ENDSESSION für bestimmten Prozess



  • Ja die eigentliche Nachrichtenschleife ist doch in der WinMain, die eben versteckt ist ( also hab ich doch darauf gar keinen Zugriff, oder doch ? ). Zumindest hab ich das auf zig verschiedenen Seiten so gelesen...

    Ok wenn du Konstruktion unten nicht funktioniert, dann weiss ich es auch nicht wie es gehen soll. Sry , für mich ist das ein logischer Aufbau...wird mir wohl nix anderes übrig bleiben als weiterzusuchen... 😞



  • Ja, die Nachrichtenschleife ist irgendwo in der WinMain() - wenn du mit MFC arbeitest, kannst du dir irgendwo einen Handler für die Nachricht anlegen und mit ON_MESSAGE() in die Message-Map einfügen (lassen). Dann sieht das System ungefähr so aus:

    //Event zur Benachrichtigung des Arbeitsthreads (in der Hauptklasse App oder View)
    CEvent m_evt;
    
    //Bei Start des Programms
    AfxBeginThread(thrdFunc,this);
    
    //Thread-Funktion
    static UINT thrdFunc(LPVOID pParam)
    {
      CMyView* pMain = (CMyView*)pParam; //evt auch CMyApp - je nachdem wer AfxBeginThread() aufgerufen hat
      PROCESS_INFORMATION pi;
      ...
      CreateProcess(&pi);
      HANDLE objects[2]={pi.hProcess,pMain->m_evt};
      switch(WaitForMultipleObjects(2,objects,FALSE,INFINITE))
      {
      case WAIT_OBJECT_0:
        //Zielprogramm beendet
      case WAIT_OBJECT_0+1:
        //Abbruch aus Hauptprogramm
      default:
        //hier ist was schiefgegangen
      }
      return 0;
    }
    
    //Behandlung WM_ENDSESSION
    LRESULT OnEnsSession(WPARAM w,LPARAM l)
    {
      m_evt.SetEvent();//Abbruchsignal für Thread
    }
    


  • Hmmm die Sache ist mit Threads kenn ich mich wieder gar nicht aus...aber trotzdem Danke für die Mühe.
    Du meinst praktisch einen Thread erstellen ( also ne neue Klasse usw. ) wäre die einfachste Lösung ?


  • Mod

    Sicher ist die MessageLoop in der WinMain irgendwo, bzw. in der MFC vergraben. Also was macht man:

    1. Man disabled das eigene Main Window um weitere Input-Events zu verhindern.
    2. Man startet das fremde Programm per CreateProcess/SehlleExcuteEx und merkt sich das Prozess Handle.
    3a. Nach dem Start returniert man. Man überschreibt z.B. CWinApp::OnIdle um dort mit MsgWaitForMultipleObjects zu warten, bzw. weiter zu arbeiten.
    3.b. Baut seine eigene MessageLoop, die nach dem Start mit PumpMessage Nachrichten zieht und verabeitet und zwischendrin mal mit MsgWaitForMultipleObjects darauf wartet, dass der Prozess fertig wird...



  • Beim Versuch den Thread zu erstellen bekomme ich lauter Errors, also meine ganzen Variablen innerhalb des Threads werden nicht mehr erkannt...

    ...und wo muss ich das Event "CEvent m_evt" eintragen ? Ich krieg da irgendwie überall Fehler ( egal wo ichs eintrag ) : 'CEvent': nichtdeklarierter Bezeichner .



  • Zeig doch mal ein Beispiel, wie du das gemacht hast. Der Event sollte ein Member deiner App-Klasse sein, die Thread-Funktion eine statische Methode der App-Klasse (und weil du in einer statischen Methode keinen this-Zeiger hast, mußt du über "CMyApp* pThis=(CMyApp*)pParam;" auf deine Member zugreifen).



  • Also das soll der Thread sein :

    UINT CTimerDlg::thrdFunc(LPVOID pParam)
    {
    
    STARTUPINFO si = {sizeof(si)};
    	PROCESS_INFORMATION pi = {0};
    
    	si.wShowWindow = SW_NORMAL;
    
    	ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );
    
    	if(!CreateProcess( NULL,   
            CmdLineLPSTR,
    		NULL,          
            NULL,           
            FALSE,          
            0,            
            NULL,          
            NULL,         
            &si,           
            &pi )  
    
    		)
    
    	{
            MessageBox("Fehler");
            return 0;
        }
    
      ShowWindow(SW_HIDE);
    
    HANDLE hEvents[1];
    hEvents[0] = pi.hProcess;
    
    dwWaitResult = MsgWaitForMultipleObjects(1,hEvents,TRUE,INFINITE,QS_ALLINPUT);
    
    switch (dwWaitResult)
        {
            case WAIT_OBJECT_0:
    
                            strUhr = m_sTime;
                strDate = m_sDate;
    
                ShowWindow(SW_RESTORE);
    
                SetTimer(ID_COUNT_TIMER2, 1,NULL);
                           break;
    
            default:
                AfxMessageBox("FEHLER!!!!");
                ExitProcess(0);
                break;
       }
    
    	return 0;
    }
    

    Und so sieht die Funktion aus wo vorher der CreateProcess() drin stand :

    void CTimerDlg::OnBnClickedButton1()
    {
    
    	m_Start.EnableWindow(FALSE);
    	m_Ende.EnableWindow(TRUE);
    	m_Verz.EnableWindow(FALSE);
    
    	CString strVerzeichnis, strProc, strSpeicher;
    
    	GetDlgItemText(IDC_EDIT1, strVerzeichnis);
    	GetDlgItemText(IDC_EDIT2, strProc);
    	GetDlgItemText(IDC_EDIT3, strSpeicher);
    
    	if(GetDlgItemText(IDC_EDIT1, m_Verzedit) == NULL)
    	{
    
    		CmdLineLPSTR = T2A(m_openpath.GetBuffer(m_openpath.GetLength()));
    	}
    
    	else
    	{
    
    		m_SpeicherOrt = strSpeicher;
    		m_proc2 = strProc;
    		m_Verzedit = strVerzeichnis;
    
    		CmdLineLPSTR = T2A(strVerzeichnis.GetBuffer(strVerzeichnis.GetLength()));
    
    	}
    
    	AfxBeginThread(thrdFunc ,this); 
    
    }
    

    Und in der .h steht : EDIT : sry header nict .cpp

    ...
    protected:
    	HICON m_hIcon;
    	CEvent m_evt;
    
    ...
    

    Bekomme 19 Fehler 🙄



  • Wo (und wie) hast du eigentlich "CmdLineLPTSTR" definiert? Wenn das ein Member der App-Klasse ist, hast du zwei Probleme: Erstens mußt du dem Compiler sagen, wessen Member du benötigst (siehe oben: pThis->CmdLineLPTSTR) und zweitens könnte T2A dort ein paar Probleme verursachen (das holt sich seinen Speicher im Ernstfall per alloca(), da werden die Daten ungültig, bevor du etwas damit anfangen kannst.

    PS: Und MsgWaitForMultipleObjects() wacht auf bei der ersten WM_... Nachricht, die dein Programm übergeben bekommt. Wenn du das nutzt, brauchst du (vermutlich) keinen Thread - mußt aber wieder zurückkehren zum Warte-Modus, wenn dort die falsche Nachricht gekommen ist. Besser ist's, du überlässt dem Hauptthread die Nachrichtenverarbeitung und lässt dich über einen Event (und die "klassische" WaitForMultipleObjects()) informieren, wenn Windows sich beenden will.



  • Ja es ist eine Membervariable in der .cpp *heul*

    Also meinst du ich sollte das so lassen wie ichs hatte ( hab ja ne Sicherung ) und dann mit WaitForMultipleObjects() ?

    Aber hab ich dann nicht wieder dasselbe Problem wie vorher, das bei WM_ENDSESSION nur der Hauptprozess reagiert ?



  • Dann nochmal langsam zum Mitschreiben - du übergibst der Funktion dein App-Objekt als pParam - darüber kannst du auch auf dessen Member zugreifen (ich glaub', ich hab' ne Schallplatte verschluckt).

    (und wieso verwendest du überhaupt "T2A()"? CreateProcess verlangt doch genauso wie der Rest der WinAPI-Funktionen einen TCHAR*)

    Aber hab ich dann nicht wieder dasselbe Problem wie vorher, das bei WM_ENDSESSION nur der Hauptprozess reagiert ?

    Es reicht doch, wenn der Hauptprozess (bzw. dessen Hauptthread) darauf reagiert - dieser setzt einen Event, um den Überwachungs-Thread abzubrechen.
    (und der überwachte Prozess wird schon selber auf WM_ENDSESSION reagieren, wenn er an der Reihe ist)



  • Ja ok ok ich versuchs mal, tut mir Leid wenn ich dich so Stresse aber bin kurz vorm Kollaps



  • Habs endlich hinbekommen, aber ohne deine Hilfe wahrscheinlich nicht, danke Mr.Stoll und danke auch für die Geduld


Anmelden zum Antworten