none
Bloccare un processo per Sempre RRS feed

  • Domanda

  • Salve a tutti,
    il problema riguarda sempre il mio programma (C#) per la domotica. Avendo necessità di leggere le mail, ho usato la libreria ImapClient di Limilabs, che è gratutita. La questione è che dopo circa 10 minuti che il mio programma è in esecuzione appare una finestra che mi dice di acquistare la licenza di Limilabs e di conseguenza il mio programma si blocca fin quando l'utente non chiude quell'odiosa finestra che si riapre ogni 7 minuti circa.

    Allora vi chiedo, è possibile bloccare l'avvio di quella finestra? O in qualche maniera farla chiudere appena si avvii?

    lunedì 8 dicembre 2014 07:55

Risposte

  • Diciamo che dovresti comprare la licenza, ma questo è ovvio :)

    Ci sono altri prodotti open-source che potrebbero fare al caso tuo:

    MailKit

    aenetmail

    S22.Imap

    Detto questo puoi approfondire il tuo problema con del codice unmanaged, e cercare di individuare la finestra creata, per poi chiuderla, oppure se il messaggio di apertura parte da dentro allo stesso dominio applicativo, probabilmente puoi aggiungere un filtro sulla pompa dei messaggi di windows, ed evitare proprio che la creazione della window venga fatta, sopprimendo il messaggio che parte dalla tua applicazione e tenta di comunicare con il sistema operativo.

    Per fare tutto questo dovrai avere un po' di fantasia e tanta buona volontà, e se sei fortunato qualche volta qualcosa di manage lo trovi, ma il più delle volte a così basso livello, sarai costretto a giocare con le unmanaged API di windows le così dette PInvoke*.

    Io prima proverei con un approccio managed, prova a registrare un IMessageFilter sull'Application, e prova a vedere se Control.FromHandle ti trova quel controllo che appare, e vedi se riesci ad individuarlo o per via del suo tipo dato o anche per il Name o Text associato, una volta individuato, puoi vedere se riesci a bloccare il messaggio di creazione window, cosa che non credo però purtroppo passi da questo IMessageFilter, ad ogni modo può essere un punto di inizio per giochicchiare un po', ma probabilmente dovrai cimentarti in chiamate puramente unmanaged.

    Controllando Msg, LParam e WParam, puoi scoprire di che messaggio si tratta, ad esempio Msg=51x mi sembrano operazioni mouse (512 mouse move, 513 left mouse down, 514 left mouse up, 516 right mouse down, 517 right mouse up), ma la creazione delle window non passa di qui, ma una volta individuato il control, puoi sempre lanciargli un bel .Dispose() per chiuderlo e dismettere le risorse:

    using System;
    using System.Diagnostics;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication2
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.AddMessageFilter(new MyMessageFilter());
    
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
    
            public class MyMessageFilter : IMessageFilter
            {
                public bool PreFilterMessage(ref Message m)
                {
                    var control = Control.FromHandle(m.HWnd);
                    if (control != null)
                    {
                        Trace.WriteLine(string.Format("[{0}] {1} '{2}' Msg={3} LParam={4} WParam={5} Result={6}", control.GetType().FullName, control.Name, control.Text, m.Msg, m.LParam, m.WParam, m.Result));
    
                        // questo però non blocca l'apertura della form, 
                        // però hai in mano la form, e potresti fargli una semplice close
                        // anche se non è il posto forse migliore dove fare questa cosa
                        // sarebbe forse più corretto un hook su WH_SHELL e aspettare l'evento
                        // HSHELL_WINDOWCREATED e sopprimere il messaggio, oppure lanciare
                        // subito dopo la form close, sempre con il semplice Control.FromHandle(hwnd).Visible = false
                        if (control.Text == "Form2")
                        {
                            control.Dispose();
                            GC.Collect();
                            GC.WaitForFullGCComplete();
                            return true;
                        }
                    }
                    return false;
                }
            }
        }
    }

    Forse quello non è il punto più adatto a fare questa cosa, e probabilmente puoi proprio riuscire a sopprimere la creazione della window, con SetWindowsHookEx e registrando un hook su WH_SHELL, e aspettando l'evento HSHELL_WINDOWCREATED, esiste anche una libreria molto completa dove ti aiuta a capire come chiamare le varie istruzione delle winapi, pinvoke.net dove trovi ad esempio come richiamare SetWindowsHookEx.

    Ti lascio anche il mio esempio completo da scaricare, anche se ti consiglio l'approccio descritto nel link qua sotto. Ah "GC.Collect();" e "GC.WaitForFullGCComplete();" vanno tolti, li ho solo messi per vedere che la memoria venisse gestita correttamente, perchè con la sola "Visible = false", che avevo provato in precedenza, il tutto andava in memory leak.

    Prova a vedere anche in questo articolo "Intercept and Manage Windows Originated by Third-party Components Hosted in C# Application", che tratta proprio di questo argomento.


    Michael Denny
    Microsoft MVP - Visual C#
    About Me

    • Proposto come risposta Paolo Pranzo martedì 9 dicembre 2014 13:16
    • Contrassegnato come risposta Francesco Bruno martedì 9 dicembre 2014 18:42
    lunedì 8 dicembre 2014 12:18

Tutte le risposte

  • Diciamo che dovresti comprare la licenza, ma questo è ovvio :)

    Ci sono altri prodotti open-source che potrebbero fare al caso tuo:

    MailKit

    aenetmail

    S22.Imap

    Detto questo puoi approfondire il tuo problema con del codice unmanaged, e cercare di individuare la finestra creata, per poi chiuderla, oppure se il messaggio di apertura parte da dentro allo stesso dominio applicativo, probabilmente puoi aggiungere un filtro sulla pompa dei messaggi di windows, ed evitare proprio che la creazione della window venga fatta, sopprimendo il messaggio che parte dalla tua applicazione e tenta di comunicare con il sistema operativo.

    Per fare tutto questo dovrai avere un po' di fantasia e tanta buona volontà, e se sei fortunato qualche volta qualcosa di manage lo trovi, ma il più delle volte a così basso livello, sarai costretto a giocare con le unmanaged API di windows le così dette PInvoke*.

    Io prima proverei con un approccio managed, prova a registrare un IMessageFilter sull'Application, e prova a vedere se Control.FromHandle ti trova quel controllo che appare, e vedi se riesci ad individuarlo o per via del suo tipo dato o anche per il Name o Text associato, una volta individuato, puoi vedere se riesci a bloccare il messaggio di creazione window, cosa che non credo però purtroppo passi da questo IMessageFilter, ad ogni modo può essere un punto di inizio per giochicchiare un po', ma probabilmente dovrai cimentarti in chiamate puramente unmanaged.

    Controllando Msg, LParam e WParam, puoi scoprire di che messaggio si tratta, ad esempio Msg=51x mi sembrano operazioni mouse (512 mouse move, 513 left mouse down, 514 left mouse up, 516 right mouse down, 517 right mouse up), ma la creazione delle window non passa di qui, ma una volta individuato il control, puoi sempre lanciargli un bel .Dispose() per chiuderlo e dismettere le risorse:

    using System;
    using System.Diagnostics;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication2
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.AddMessageFilter(new MyMessageFilter());
    
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
    
            public class MyMessageFilter : IMessageFilter
            {
                public bool PreFilterMessage(ref Message m)
                {
                    var control = Control.FromHandle(m.HWnd);
                    if (control != null)
                    {
                        Trace.WriteLine(string.Format("[{0}] {1} '{2}' Msg={3} LParam={4} WParam={5} Result={6}", control.GetType().FullName, control.Name, control.Text, m.Msg, m.LParam, m.WParam, m.Result));
    
                        // questo però non blocca l'apertura della form, 
                        // però hai in mano la form, e potresti fargli una semplice close
                        // anche se non è il posto forse migliore dove fare questa cosa
                        // sarebbe forse più corretto un hook su WH_SHELL e aspettare l'evento
                        // HSHELL_WINDOWCREATED e sopprimere il messaggio, oppure lanciare
                        // subito dopo la form close, sempre con il semplice Control.FromHandle(hwnd).Visible = false
                        if (control.Text == "Form2")
                        {
                            control.Dispose();
                            GC.Collect();
                            GC.WaitForFullGCComplete();
                            return true;
                        }
                    }
                    return false;
                }
            }
        }
    }

    Forse quello non è il punto più adatto a fare questa cosa, e probabilmente puoi proprio riuscire a sopprimere la creazione della window, con SetWindowsHookEx e registrando un hook su WH_SHELL, e aspettando l'evento HSHELL_WINDOWCREATED, esiste anche una libreria molto completa dove ti aiuta a capire come chiamare le varie istruzione delle winapi, pinvoke.net dove trovi ad esempio come richiamare SetWindowsHookEx.

    Ti lascio anche il mio esempio completo da scaricare, anche se ti consiglio l'approccio descritto nel link qua sotto. Ah "GC.Collect();" e "GC.WaitForFullGCComplete();" vanno tolti, li ho solo messi per vedere che la memoria venisse gestita correttamente, perchè con la sola "Visible = false", che avevo provato in precedenza, il tutto andava in memory leak.

    Prova a vedere anche in questo articolo "Intercept and Manage Windows Originated by Third-party Components Hosted in C# Application", che tratta proprio di questo argomento.


    Michael Denny
    Microsoft MVP - Visual C#
    About Me

    • Proposto come risposta Paolo Pranzo martedì 9 dicembre 2014 13:16
    • Contrassegnato come risposta Francesco Bruno martedì 9 dicembre 2014 18:42
    lunedì 8 dicembre 2014 12:18
  • Provando con quelle librerie IO non sono riuscito a leggere le mail dal form.
    Ho provato a scaricare un'altra libreria --> Libreria Imap ma nemmeno con quella sono riuscito.

    Il mio obiettivo è leggere solamente il corpo della mail. Forse chiedo troppo, qualcuno può gentilmente scrivermi il codice? O almeno darmi una mano, visto che sto Impazzendo XD?

    giovedì 11 dicembre 2014 18:48
  • Provando con quelle librerie IO non sono riuscito a leggere le mail dal form.
    Ho provato a scaricare un'altra libreria --> Libreria Imap ma nemmeno con quella sono riuscito.

    Il mio obiettivo è leggere solamente il corpo della mail. Forse chiedo troppo, qualcuno può gentilmente scrivermi il codice? O almeno darmi una mano, visto che sto Impazzendo XD?

    Ciao Francesco,
    questo messaggio riguarda un'altra problematica, differente da questo thread.
    Eventualmente apri un nuovo thread riguardante il nuovo problema.

    Comunque ti segnalo un tutorial, spero possa aiutarti:
    Retrieve Email and Parse Email in C#

    Ciao

    Paolo Pranzo

    giovedì 11 dicembre 2014 19:01