Newsgroup: it.comp.lang.visual-basic
Titolo: Far comunicare 2 applicazioni

Salve a tutti.
Ho scritto 2 programmi in VB6 ed ho la necessità che comunichino tra
di loro.
Attualmente scrivo i dati in un file che dall'altra applicazione
controllo con un timer, ma non mi sembra il massimo.
So che è possibile farlo tramite i moduli di classe e i progetti tipo
ActiveX, ma proprio non riesco a capire come usarli.
Ho fatto così:
1) creo un progetto di tipo EXE ActiveX di nome App1.vbp, lui crea
automaticamente class1
2) in class1 metto una sola riga: Dim pippo as string
3) nella form di App1 metto:
          Private Sub Command1_Click()
          Dim a As Object
          a = CreateObject("App2.class1")
          a.pippo = "Ciao"
          End Sub
4) faccio un altro progetto di tipo EXE ActiveX di nome App2, inserisco
la stessa classe già preparata in App1, e metto in form:
          Private Sub Command1_Click()
          Dim a As Object
          a = CreateObject("App1.class1")
          a.pippo = "Ciao"
          End Sub
A questo punto compilo il tutto, mando in esecuzione sia App1 che App2,
clicco su Command1 e mi dà
Run-time error '429' activeX component can't create object.
Dove sbaglio?
Non è che c'è qualche esempio in giro?
Inoltre ho notato che devo essere loggato come administrator,
altrimenti non mi funziona nemmeno la compilazione e l'esecuzione
dell'exe. E' normale?
Ho visto poi che ci sono anche altri metodi per far comunicare due
processi, come quello di utilizzare il metodo sendMessage
(
http://support.microsoft.com/kb/176058/en-us
).
Forse questo mi riuscirebbe più facilmente, ma secondo voi qual è il
metodo che prende minori risorse in assoluto?
Un'ultima domanda.
E' possibile, oltre che comunicare un dato da App1 a App2, fare in modo
che App1 esegua una certa funzione (con certi argomenti) direttamente
nel contesto di App2?
Grazie a tutti.

 ha scritto nel messaggio 
news:1164121646.8...@j44g2000cwa.googlegroups.com...


 Ho fatto così:
Il tuo problema in particolare è tutto da valutare anche perchè sono secoli 
che non gioco con gli AxExe e potrei sbagliarmi, ma se non ricordo male devi 
prima di tutto complilare gli exe, e poi metterti in debug con la 
compatibilità binaria su questi.
Comunque il tuo sistema non è il massimo poichè ti crei dei riferimenti 
circolari e fai comunicare tra loro sue oggetti "server".
Dovresti fare un AxExe che fa da bridge tra le tue due App, nelle app ci 
aggiungi il riferimento all'ax così hai pure l'intellisense.
E' un po' lungo da spiegare in un post, ma è più complicato a dirlo che a 
farlo.
Ciao

 
Questa non l'ho capita!
Ciao
Daniele.

 aggiungi il riferimento all'ax così hai pure l'intellisense.
Beh, questo per me sarebbe ancora meglio. Il problema è che non riesco
a fare nemmeno un'applicazione di base che comunichi tramite Activex.

 Questa non l'ho capita!
E' sempre perchè mi preoccupo di occupare meno risorse possibile.
Infatti se invece di usare un file uso le DDE (come anche ho fatto)
posso per esempio fare in modo che quando cambia un controllo TextBox
in App1 cambia anche un altro controllo TextBox in App2. Pero' a questo
punto in app2 sono costretto comunque a tenere un timer che veda se è
cambiato il contenuto di textbox per poter lanciare una determinata
funzione. questo timer, anche se non legge un file su disco, occupa
risorse anche quando non serve per gli stessi motivi di cui sopra.
Invece io vorrei poter lanciare la funzione di App2 direttamente da
App1.
Questo si puo'fare in parte con i messaggi nel senso che mandi, magari,
il messaggio KeyUp da App1 a App2 e associ una funzione particolare
all'evento KeyUp in App2. Ma ho subodorato che si possa fare in modo
più efficiente con i controlli ActiveX, anche se non capisco come.
Forse mi spiego meglio con un esempio.
Ho App1 con una textbox1. poi ho App2 con una funzione "quadrato
(numero as double) as double" che calcola un numero elevato al quadrato
e scrive il risultato in textbox2.
Ora App1 e App2 girano insieme. Quando l'utente preme invio sulla
textbox1 (di App1) l'evento KeyPress anzichè lanciarmi una funzione
che si trova in App1 mi lancia la funzione quadrato(textbox1) che si
trova in App2, e in textbox2 (di App2) esce numero elevato al quadrato.
Ora per fare questo, ad esempio con le DDE, sono costretto a tenere un
controllo nascosto textbox3 in App2 linkato a textbox1 di App1. Inoltre
devo tenere anche un timer che vada periodicamente a controllare il
contenuto di textbox3 il quale, se vede che il contenuto è cambiato,
lancia la funzione quadrato.
Se poi faccio un file o scrivo un valore nel registry il discorso non
cambia, devo sempre fare un controllo periodico dall'altra parte.
Ecco, quello che voglio fare è togliere questo controllo periodico,
che il 99% delle volte gira a vuoto, e far scaturire da un'applicazione
un'evento che si trova in un'altra applicazione.
Ora, *penso* che questo si possa fare con gli ActiveX, ache se no ho
capito come. Mentre si puo' fare sicuramente con i messaggi, dove pero'
ci sono altre problematiche, ad esempio App1 deve conoscere l'handle di
App2 e viceversa, e questo mi incasina un po' nel momento in cui sono n
applicazoni che comunicano con n altre.
Grazie di a tutti!

 - Winsock
^^^^^^^^^^^^^^^
Stai scherzando vero? Perchè winsock per comunicare tra due 
applicazioni che stanno sullo stesso pc è tutto tranne che scevro da 
problemi e complessità...
-- 
IBM: Invented By Murphy
News 2002 [v 2.07] / StopDialer / PopDuster - 
http://www.socket2000.com
Akapulce portal: 
http://www.akapulce.net

 problemi e complessità...
Mah!
Da problemi...poteri anche capire....ma da complessità!!
Poi, come sempre, dipende uno COSA e COME deve fare! ;-)
Ciao,
Daniele.

 in cui sono n applicazoni che comunicano con n altre.
Cerca "Interprocess communication VB6" con google, ne troverai a iosa di
tecniche.
Bye
Raf
-----------------------------------------------------
Funk: cooler than the other side of the pillow.

vabbè fatto sta che per far comunicare 2 applicazioni ne serve sempre una di 
appoggio!
ma il problema secondo me è che anche con un AX le 2 applicazioni creano un 
collegamento
nuovo nel senso che è come se l' AX si copy vuoto ogni volta che un 
apllicazione si linka lui!
di conseguenza le variabili o dati che devono essere passati di fatto non si 
psassano!
Forse sbaglio io, ma l'esperienza che ho avuto a riguardo è stata negativa 
su questo fronte.
ma ho postato un argomento simile nei giorni passati.
Trattava di passaggio dati (o variabili) da un EXE a un DLL.
l'ho risolto in questo modo:
ho creato:
    Progetto EXE (Prg)
    Progetto DLL per variabili (Var)
    Progetto DLL per il resto del Programma (Rst)
il Prg si lilnka alla Var mediante createobject()
il Prg si linka anche alla Rst mediante createobject()
il Prg richiama una funzione dichiarata come publica nella Rst passando come 
parametro
la variabile settata come Createobject("var")
nel codice EXE:
set DllVar=createobject("Var.Class1")
set DllRst=createobject("Rst.Class1")
DllRst.Imposta ( DllVar )
nel codice Rst:
public VarDll as object    'variabile delle variabile tra Prg e Rst
public property set Imposta ( byRef V as object)
    set VarDll =imposta
end property
è un modo scomodo ma efficace posso garantire! :-) 

Ciao
avevo un problema analogo: una applicazione doveva mandare alcuni
comandi ad un'altra, e viceversa.
ho fatto in questa maniera: ho inserito in entrame le applicazioni (che
chiamo AppsA e AppsB) due textbox nascoste, che ho chiamato
"txtComandoA" e "txtComandoB"
Appena Appsa e AppsB vengono caricate, scrivono nel registro due chiavi,
rispettivamente "HandleTxtComandoA" e "HandleTxtComandoB", e come valore
impostano l'handle per l'appunto delle due TextBox
Quando una applicazione deve inviare un comando all'altra, va a leggere
l'handle della textbox ricevente dal registro, e mediante una semplice
SendMessage vi scrive il comando che deve far eseguire.
ciascuna Apps ha ovviamente l'evento txtComandoA_Change che viene
lanciato appena la SendMessage vi scrive qualcosa, e con una lista di
"Case", interpreta ed esegue il comando corretto.
Codice:
[Form_Load di AppsA]
[...]
'Nel caso l'applicazione B debba mandare informazioni alla applicazione
A, la AppsA salva l'handle della textbox ricevente
SaveSetting "MecVision", "Esecuzione", "HandleTxtComandoA",
txtComandoA.Handle
[...]
[Subrutine di invio informazione/comando da AppsA a AppsB (funzione di
AppsA)]
[...]
Dim strComando as string
Dim HandleTextBoxRicevente as long
'Cerco l'handle delle textbox ricevente dell'altra applicazione
HandleTextBoxRicevente=val(GetSetting("MecVision", "Esecuzione",
"HandleTxtComandoB")
If HandleTextBoxRicevente<>0 then
	strComando="UNLOAD"
	SendMessageA HandleTextBoxRicevente, WM_SETTEXT, 0&, ByVal StringaComando)
End If
[...]
Evento di AppsB:
[txtComandoB_Change]
[...]
if txtComandoB.text="UNLOAD" then Unload Me
[...]
Nota1: importante in questo caso il ByVal quando si passa la stringa
alla SendMessage
Nota2: ricordo che il WM_SETTTEXT = 12 (o &Hc, come preferite)

 Da problemi...poteri anche capire....ma da complessit=E0!!
Complessità riferita ad un DDE beninsteso...
-- 
A bad random number generator:  1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1


 è un modo scomodo ma efficace posso garantire! :-)
Con questo sistema oltre a passare le variabili da un'App a un'altra,
è possibile anche scatenare un evento a cavallo di 2 applicazioni
(come descritto sopra)?
Altrimenti, se ho capito bene, sono costretto a fare un timer che
faccia ogni tanto DllRst.Imposta ( DllVar ) per vedere se è cambiata
la variabile.
Grazie a tutti!


secondo me ti sei solo complicato la vita! esiste l'ape che manda messaggi 
da una app a un altra
in pratica invece del Hwnd del text gli dai quella dell'applicazione!!!
l'ape si chiama sendmessage o qualcosa del genere! 

la variabile.
non cè bisogno, una volta che imposti la Rst passandogli come valore ByRef 
la VarDLL
ogni volta che le variabili all'interno di VarDLL cambiano valore sono 
tranquillamente "aggiornate"
autromaticamente anche da Rst!!!
prova e vedi!!
Grazie a tutti!

 genere!
Eh... e Marco cosa ha usato invece?!
L'API (non APe... non ho capito se ci fai o ci sei...) SendMessage invia
messaggi ad una *window*.
Una qualunque, quindi quella di un Textbox, della finestra principale di
un'applicazione (se ce l'ha) etc...
La tecnica usata da Marco non è tanto complicata, ma si poteva anche fare a meno
dei textbox e utilizzare altre window, anche create appositamente con l'API
CreateWindow, come spiegato qui:
http://www.codeproject.com/vbscript/vb6ipc.asp
Altra tecnica simile:
http://support.microsoft.com/kb/639464
Bye
Raf
P.S.
<ramanzina mode on>
Non me ne volere, ma se vuoi aiutare efficacemente i membri del NG non puoi
permetterti di essere vago e/o impreciso e/o fornire informazioni non del tutto
corrette, vedi anche gli altri tuoi post che IMHO non brillano certo per
chiarezza (...omonimia del nickname a parte).
<ramanzina mode off>


 autromaticamente anche da Rst!!!
Si, ho capito.
Solo che io devo scatenare un evento a seguito dell'aggiornamento di
questa variabile.
Ora per fare in modo che quando questa variabile venga aggiornata si
esegua una data funzione, l'unica cosa che mi viene a mente è di fare
un timer che controlla la variabile per vedere se è cambiata e, se è
cambiata, esegue una determinata funzione passandogli come argomento
quella variabile.
Ora per evitare di mettere questo timer, volevo sapere se è possibile
far eseguire questa determinata funzione direttamente dall'activeX.
Mi spiego meglio.
---------------------------------------------------------------
    Progetto EXE (Prg)
    Progetto DLL per variabili (Var)
    Progetto DLL per il resto del Programma (Rst)
nel codice EXE:
set DllVar=createobject("Var.Class1")
set DllRst=createobject("Rst.Class1")
DllRst.Imposta ( DllVar )
nel codice Rst:
public VarDll as object    'variabile delle variabile tra Prg e Rst
public property set Imposta ( byRef V as object)
    set VarDll =imposta
end property
---------------------------------------------------------------------
Ora se ho capito bene la logica che tu tìdici dovrebbe essere
1) modifico il valore di DllVar dall'exe (Prg)
2) automaticamente poichè ho impostato DllRst.Imposta ( DllVar )
viene modificato anche il valore di VarDll
3) a questo punto il resto del programma che gira nella DLL (Rst) puo'
utilizzare il nuovo  valore di VarDll.
La mia domanda è: come fa Rst ad accorgersi che VarDll è cambiata? Fa
un cotrollo routinante su VarDll oppure gestisce un evento tipo:
sub VarDll_change()
'Sono arrivati nuovi dati!
'fai questo e quello
end sub
?
In sostanza è possibile gestire gli eventi in VarDll che si trova in
Rst?
Cioè voglio dire in rst invece di:
public VarDll as object
dichiarare:
public WithEvents VarDll as object
Spero di essermi spiegato.
Grazie.

 
http://www.codeguru.com/vb/gen/vb_general/idelanguage/article.php/c11549/
Grazie!
Quindi, vediamo se ho capito bene.
1) In app1 ho textbox1 e in app2 ho textbox2
2) voglio fare in modo che quando l'utente scriva "pippo" e prema invio
in textbox1 si scateni sia l'evento Keypress di textbox1 in app1 che
l'evento keypress di textbox2 in app2
3) quindi dopo aver linkato dovutamente textbox1 e textbox2 tramite
linktopic, faccio un evento keypress di textbox1 in app1 del tipo:
sub textbox1_keyPress()
if keyascii = 13 then
    call textbox1_Linkexecute
    '.... Fai il resto di quello che devi fare in app1
end if
end sub
4) quando faccio call linkexecute questo scatena l'evento linknotify in
textbox2 di app2, quindi in app2 il codice sarà:
sub TextBox2_linkNotify()
call textbox_keypress(13)
end sub
in questo modo ho ottenuto lo stesso effetto dun utente che scrive
"pippo" [invio] in textbox1 e poi scrive "pippo" [invio] in textbox2.
Se funziona così, lo vedo molto più semplice da implementare rispetto
al sendmessage e all'activeX.
Ma perchè il DDE è stato, per così dire, "abbandonato" ? Ha qualche
problematica che mi sfugge, ad esempio in termini di spreco di risorse
o altro?
grazie di nuovo!

Si, ho capito.
Solo che io devo scatenare un evento a seguito dell'aggiornamento di
questa variabile.
Ora per fare in modo che quando questa variabile venga aggiornata si
esegua una data funzione, l'unica cosa che mi viene a mente è di fare
un timer che controlla la variabile per vedere se è cambiata e, se è
cambiata, esegue una determinata funzione passandogli come argomento
quella variabile.
Ora per evitare di mettere questo timer, volevo sapere se è possibile
far eseguire questa determinata funzione direttamente dall'activeX.
La mia domanda è: come fa Rst ad accorgersi che VarDll è cambiata? Fa
un cotrollo routinante su VarDll oppure gestisce un evento tipo:
sub VarDll_change()
'Sono arrivati nuovi dati!
'fai questo e quello
end sub
?
In sostanza è possibile gestire gli eventi in VarDll che si trova in
Rst?
Cioè voglio dire in rst invece di:
public VarDll as object
dichiarare:
public WithEvents VarDll as object
Spero di essermi spiegato.
Grazie.
___________________________________________________
si ottima idea.... mi piace sta "sfida" e la accetto :-)
allora...
potremmo:
1) exe.cambiavalore (newvalore)
    exe.comunicaRst()
    a questo punto la funzione in Rst esegue quello che deve eseguire!
    e viceversa anche da Rst a Exe
2) exe.cambiavalore( newvalore)
    VarDLL:
        public cambiavalore(byval val)
        ' cambia il valore
        ed esegue le operazioni richieste
        end
3) nel VarDLL creare una classe che contenga metodi, proprietà ed eventi.
    ma su questo argomento sono un po' impreparato....
    ma ci sono e mi sprono...
    ci risentiamo tra un po'..
    scriviamo un po' di codice e vediamo chi riesce prima ok????
:-) 

 o altro?
Che sia stata abbandonata č tutto da vedere, che esistano (da mo') tecnologie
migliori invece č un altro par de maniche.
http://en.wikipedia.org/wiki/Dynamic_Data_Exchange
Come vedi, č tuttora usata per consentire ad esempio di aprire i file DOC con
Word facendovi doppio clic...
Per obiettivi semplici come il tuo non vedo problemi né limitazioni al suo
utilizzo.


 utilizzo.
Ok, sono riuscito a fare un VB di esempio grazie al link che mi ha
postato prima, ed ho capito il funzionamento.
Ora pero' ho un altro problema.
Fintanto che app1 deve comunicare qualcosa a App2 va tutto bene.
Ma in determinate circostanze io ho una istanza di App1 che deve
comunicare un dato a 3 istanze di App2.
Attualmente mi funziona perchè lo scrivo in un file che è lo stesso
controllato da tutte e tre le istanze di App2.
Ma se uso il DDE e carico tre istanze di App2, solo la prima è quella
che riceve il dato.
Come faccio a mandarlo anche alle altre due isanze?
Infatti se ho ben capito in LinkTopic ci devo mettere il nome del .exe,
che in questo caso è uguale per tutte e 3 le istanze che girano in
contemporanea. Oppure è possibile metterci qualche altra cosa, come ad
esempio il pid restituito da shell()?
Grazie!

>(...omonimia del nickname a parte).
non credo sia errore di omonimia perchè sono cosciente delle cose che posto 
e di conseguenza so
anche che la "romanzina" è rivolta a me!!
tranquillo non te ne volgio... :-)
dal salento è tutto... Grazie magari ha fatto bene!! 


In questo caso App1 funge da DDE Source, ogni istanza di App2 funge da DDE
destination: probabilmente conviene usare una label (o una textbox) linkata tra
App1 e App2.
Scaricati questo esempio
http://www.angelfire.com/biz/rhaminisys/binaries/vbdde.zip
 e lancia più istanze
del client, impostando per ciascuna LinkMode = Automatic o Notify: vedrai che
quando premi "Start fast send" dal server, tutte le istanze client ricevono la
modifica.
Nello stesso sito trovi anche altre informazioni molto utili sul DDE:
http://www.angelfire.com/biz/rhaminisys/ddeinfo.html


Che figata che un mio post finalmente può essere utile e comunque un mio
codice è stato oggetto di un piccolo thread :-)
Marco che gioca con mdb