Newsgroup: it.comp.programmare.win32
Titolo: Installare un thread su un altro processo e comunicare (lungo, scusatemi)

Ho qualche domandina "assurda", perdonate la mia ignoranza se qualcosa può
essere banale.
Prima di lanciarmi nella programmazione ad occhi chiusi, vorrei farmi
un'idea di cosa mi aspetta, per cui espongo il mio problema:
supponiamo che la programmazione sotto Win sia per me cosa banale, in C/C++,
nello specifico con VC++ 5.0, e mettiamo che io riesca a fare partire un
thread ed a affibbiarlo ad un altro processo in esecuzione scelto a caso,
diciamo Explorer.
Per fare questo, con o senza MFC, mi pare che esista una bella API, del tipo
SetThreadToProcess o simili (dovrei rintracciarla facilmente nell'help) e
supponiamo che che riesca a farlo impostando correttamente tutti i vari
parametri che essa vuole, poniamo sotto NT.
Ora, terminando il processo "padre", tutti i suoi thread dovrebbero
scomparire tranne quello affibbiato all'altro processo, sempre che non sia
l'altro processo a terminare prima, giusto?
Poniamo di si. In che stato si trova il mio thread rimasto orfano? Può
sperare in un poco di attenzione da parte della CPU o devo settare prima
qualche cosa io, tipo un timer che ogni tanto lo risvegli? La mia idea è che
non ci dovrebbe essere bisogno di altro (scheduler di sistema escuso), sto
andando bene?
Ammettendo che il thread sia bell'e sveglio, sempre pronto a fare quello che
deve, multithreading permettendo, come faccio ad addormentarlo? Ovvero, non
vorrei che questo thread occupasse tutta la CPU (sempre relativamente al
multi-ecc), e vorrei invece fargli fare delle azioni solo alla bisogna.
L'idea in fondo è quella di un mini-server semper in attesa, ma senza
polling.
Se l'idea che ho non è tanto errata, potrei semplicemente metterlo in attesa
di un certo evento, e dargli l'evento solo quando devo effettivamente
svegliarlo.
Il punto è: in Windows gli eventi sono messaggi, e i messaggi hanno bisogno
di un destinatario. Io quindi dovrei, all'occorrenza, fare partire un
programma client che mandi un messaggio al thread interessato. Problemi:
- devo trovare in quale processo è situato il thread (oppure potrei
agganciarlo sempre all'explorer)
- devo usare messaggi non standard, e vorrei sapere quali "numeri" posso
usare.
- devo fare in modo che sia il mio thread a ricevere il messaggio e non il
processo "ospite", poichè il processo non saprebbe che farsene e, nella
migliore delle ipotesi, lo ignorerebbe. Ne consegue che:
- in qualche modo devo poter identificare il mio thread tra quelli del
processo ospite.
I problemi credo ci sarebbero anche se dovessi usare un timer, dato che
anche il timer non fa altro che mandare un messaggio, ma sarebbe più
semplice in quanto il thread attiva il timer e sa "chi è" e "dove si trova",
almeno credo.
Ma un thread può gestire una cosa di messaggi senza che il processo ospite
(uffa, diciamo il "main") ne conosca l'esistenza?
Grazie a chi ha avuto la pazienza di leggere questi deliri personali, e se
poi sapesse darmi delle delucidazioni...
Aggiungo solo che se mi date le linee guida poi posso darmi da fare io a
smazzarmi l'help per cercare tutti i dettagli.
Ciao
--
Alessandro Monti
P.S.
Dimenticavo un particolare: ho tutti i diritti di Administrator, niente
problemi di sicurezza.

Ok, grazie per le dritte, ora dovrò trovare io il tempo di assimilare il
tutto.
Ma sai tutto tu? Mi pare che sei quasi sempre il primo a dare risposte!
Ciao
--
Alessandro Monti

 (uffa, diciamo il "main") ne conosca l'esistenza?
Si`.  Le msg queues sono per-thread, non per-process.
Alex

 Ma sai tutto tu? Mi pare che sei quasi sempre il primo a dare risposte!
Sapere tutto...? *shudder* sarebbe l'inferno, non avere piu`
nulla da imparare...:-(.  Per fortuna, e` un'ipotesi del tutto
ipotetica!-)
Alex

 di un destinatario.
No: gli eventi sono system-wide e sono identificati per nome.
--
Bye! Lorenzo Lutti
http://www.geocities.com/SiliconValley/Peaks/6258/

Grazie anche a te. Magari ti chiederò qualche delucidazione perchè qualcosa
faccio fatica a capirlo, ma magari ci arrivo da solo.
Ne approfitto invece per chiedere:
se sono in attesa di un evento e chiudo windows, l'evento fallisce e il mio
thread si chiude comunque, o devo fare qualcosa in modo da evitare che mi
dica "sto chiudendo la sessione" in eterno? O piuttosto evitare di fare
qualcosa del tipo
while (1){
    ...
    errore = WaitEvent(...)
    if (errore)
        (ignora errore e riprova);
}
Ciao
--
Alessandro Monti

 funziona solo sotto a NT e da 98 in poi).
No, non sono proprio riuscito a capire cosa intendi per "tecnica degli
hooks". In efetti dovrei testare il programma su win95, anche se poi sarà
eseguito su NT, per cui farebbe comodo.
Ho trovato qualchosa che riguarda le funzioni di debug, ma non sono riuscito
a venirne a capo. Anche perchè alcune sezioni del mio help dicono: "Questa
sezione tratta di..." ma poi non continua!
Riusciresti in 2 parole a spiegarmi come funziona? Se ho intuito
giustamente, dovrei far finta di essere un debugger, ma non capisco a cosa
posso agganciarmi, e come far partire un thread dal processo ospite.
Porta pazienza ancora un po', per favore...
Ciao
--
Alessandro Monti

 thread si chiude comunque, o devo fare qualcosa in modo da evitare
Se il tuo thread ha una finestra top-level, gli giungera` un
messaggio WM_QUERYENDSESSION, e se a fronte di questo
torna TRUE (su NT; su 95, se tutte le applicazioni attive
tornano TRUE), un WM_ENDSESSION -- quando tutte le
applicazioni tornano dall'elaborazione di quest'ultimo
messaggio, "il mondo finisce".
Se la tua applicazione ha una finestra top-level, ma non
serve il loop dei messaggi, avrai dal sistema le tipiche
indicazioni di "application not responding", ecc.
Attento che puoi avere una finestra top-level senza
saperlo!  Ad esempio, il Service Control Manager te
ne crea una se servi un oggetto COM del tipo che una
volta si chiamava "apartment-threaded" (e oggi, di
solito, si chiama "single-threaded").
In questo senso, piuttosto che WaitForSingleObject
o WaitForMultipleObjects, puo` essere piu` prudente
usare MsgWaitForMultipleObjects -- se arrivano infatti
messaggi Windows, la MsgWait... si sveglia (puoi anche
farlo in modo selettivo), e con un breve ciclo ad es. di
PeekMessage (con PM_REMOVE) e DispatchMessage,
puoi servirli (ed eventualmente intercettare, se ti serve,
il WM_QUERYENDSESSION ecc ecc).
Comunque, se sei sicuro di non avere finestre top
level, puo` non essere necessaria questa cautela.
Alex

 hooks". In efetti dovrei testare il programma su win95, anche se poi
L'API SetWindowsHookEx ti permette di agganciare una tua
DLL a livello globale, cioe` a tutti i thread del sistema, in
determinate condizioni (puoi anche essere piu` selettivo,
ma mi pare che a te serva invece proprio la globalita`).
Quando la tua DLL entra in esecuzione nel contesto di un
altro thread (avendone cosi` "invaso" lo spazio di indirizzi
virtuale), puoi fare partire il thread supplementare che
desideri (presumibilmente una sola volta per processo
che 'invadi').
Possono esserci dei problemi ad agganciarsi a processi
(o thread) che non servono un loop di messaggi; gli hook
tendono ad essere agganciati appunto ai loop dei
messaggi.
Richter ("Programmazione avanzata in Windows", ed.
italiana di Mondadori Informatica) tratta assai bene
questi temi, secondo me.
Alex

 posso agganciarmi, e come far partire un thread dal processo ospite.
Non proprio. Tempo fa ho scritto un msg piuttosto lungo sui perche` di questa
scelta della M$, comunque se ci pensi il principio e` piuttosto semplice: gli
hooks sono funzioni callback che devono essere chiamate da altri processi,
quindi (dato che ogni processo ha il suo spazio di indirizzamento separato)
come fare per farle funzionare? A meno di non usare strane tecniche
interprocesso, dobbiamo necessariamente spostare il codice nel processo remoto.
Ma spostare una singola procedura avrebbe comportato diversi problemi per il
loader, quindi per semplificare alla M$ hanno deciso di caricare tutta la DLL.


 dica "sto chiudendo la sessione" in eterno?
Dipende da quale programma viene chiuso prima da Windows (quando chiudi la
sessione Windows comincia a chiudere tutte le varie applicazioni, non so se
esista un "ordine" particolare).
Se viene chiuso prima quello che ha creato l'evento, Windows distruggera`
automaticamente anche l'oggetto evento e il tuo programma potrebbe fare in
tempo ad accorgersene; se viene chiuso prima quello che "aspetta" l'evento, non
se ne accorgera`. In generale in casi come questi e` bene intercettare il
messaggio WM_QUERYENDSESSION che Windows spedisce a tutte le applicazioni prima
di iniziare il logoff...


Ok, di nuovo grazie a tutti.
Ora, purtroppo, temo che mi dovrò dare da fare io... :-(
--
Alessandro Monti