Forum: Italian Ruby user group Chiamare un processo Win32

Posted by Marco Di antonio (bulletxt)
on 2009-06-22 19:37
Salve,

sto sviluppando un gioco con RPG Maker VX che usa internalmente Ruby
1.8.1.

Sto scrivendo uno script che avvia un processo, ad esempio notepad.exe
in modo da non bloccare il codice di esecuzione.

Il problema principale è che non posso usare "require" perchè non lo
capisce.

Qualcuno ha un'idea di come posso fare?

Qualcosa tipo Win32API.new( 'kernel32', "CreateProcess", ['L'], "n" )

e poi chiamare notepad.exe ma davvero non ho la piu pallida idea di come
si fa.

Spero qualcuno possa aiutarmi!
Posted by Marco Mastrodonato (marcomd)
on 2009-06-25 15:24
Prova con:
system "notepad.exe"
Posted by Marco Di antonio (bulletxt)
on 2009-06-25 17:01
Marco Mastrodonato wrote:
> Prova con:
> system "notepad.exe"

Ciao,

si avevo già provato questo metodo.. il problema è che apre una pop up 
della shell... ho provato con system "start /B notepad.exe" ma /B non 
sembra funzionare come avrei sperato :(
Posted by Marco Mastrodonato (marcomd)
on 2009-06-25 17:54
Marco Di antonio wrote:
> Marco Mastrodonato wrote:
>> Prova con:
>> system "notepad.exe"
> 
> Ciao,
> 
> si avevo già provato questo metodo.. il problema è che apre una pop up 
> della shell... ho provato con system "start /B notepad.exe" ma /B non 
> sembra funzionare come avrei sperato :(

A me non apre nessun popup, sono aggiornate le gemme win32?
Ocio che con start parte un nuovo processo
Posted by Claudio Petasecca Donati (etapeta)
on 2009-06-25 19:21
Prova a guardare in questo blog:

http://rubyonwindows.blogspot.com

ci sono parecchi esempi
Posted by Marco Di antonio (bulletxt)
on 2009-06-25 19:27
Marco Mastrodonato wrote:
> Marco Di antonio wrote:
>> Marco Mastrodonato wrote:
>>> Prova con:
>>> system "notepad.exe"
>> 
>> Ciao,
>> 
>> si avevo già provato questo metodo.. il problema è che apre una pop up 
>> della shell... ho provato con system "start /B notepad.exe" ma /B non 
>> sembra funzionare come avrei sperato :(
> 
> A me non apre nessun popup, sono aggiornate le gemme win32?
> Ocio che con start parte un nuovo processo

Non ti apre niente perchè stai avviando lo script da terminale, avvialo 
fuori da terminale e vedrai :)
Posted by Daniele Alessandri (Guest)
on 2009-06-25 21:47
(Received via mailing list)
2009/6/22 Marco Di antonio <bulletxt@gmail.com>

> sto sviluppando un gioco con RPG Maker VX che usa internalmente Ruby
> 1.8.1.

1.8.1... non è un po' vetusta come versione? :-)

> Sto scrivendo uno script che avvia un processo, ad esempio notepad.exe
> in modo da non bloccare il codice di esecuzione.

Parto dal presupposto che con "non bloccare il codice di esecuzione"
tu intenda che non appena notepad.exe viene lanciato, il controllo
torna allo script ruby in modo da poter proseguire con il normale
flusso dell'applicazione (cosa che di fatto esclude metodi come system
poiché "ascoltano" l'stdout del nuovo processo, bloccando di fatto lo
script ruby fino alla chiusura del processo stesso).

Detto questo, ci sarebbe win32-process che è comodissima come libreria
(richiede come dipendenza windows-pr), ma la compatibilità è data solo
da ruby 1.8.2 in poi e se effettivamente hai a disposizione solo
1.8.1....
Ad ogni modo ecco un esempio:

require 'win32/process'

process_info = Process.create(
    :app_name         => "notepad.exe",
    :creation_flags   => Process::DETACHED_PROCESS,
    :process_inherit  => false
)

> Il problema principale è che non posso usare "require" perchè non lo
> capisce.

Più che altro, require non c'entra con quanto vorresti ottenere.

> Qualcuno ha un'idea di come posso fare?
> Qualcosa tipo Win32API.new( 'kernel32', "CreateProcess", ['L'], "n" )

Più complesso (e molto più noioso) di win32-process, ma almeno non ti
porti dietro dipendenze esterne rispetto alla stdlib di ruby. Ecco un
esempio ridotto all'osso, anche nella valorizzazione dei parametri:

close_handle = Win32API.new('kernel32', 'CloseHandle', 'L', 'L')
create_process = Win32API.new('kernel32', 'CreateProcess', 'PPPPLLLPPP', 
'L')
startup_info   =
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0].pack('LLLLLLLLLLLLSSLLLL')
process_info   = [0,0,0,0].pack('LLLL')

created = create_process.call(
    0,                  # lpApplicationName
    "notepad.exe",      # lpCommandLine
    0,                  # lpProcessAttributes
    0,                  # lpThreadAttributes
    0,                  # bInheritHandles
    0x08,               # dwCreationFlags
    0,                  # lpEnvironment
    "C:/Temp/",         # lpCurrentDirectory
    startup_info,       # lpStartupInfo
    process_info        # lpProcessInformation
)

close_handle.call(process_info[0,4].unpack('L').first)
close_handle.call(process_info[4,4].unpack('L').first)

Nota bene: process_info è una struttura al cui interno vengono
memorizzati gli handle del processo appena creato e del thread
principale di quest'ultimo. Essi vanno *necessariamente* chiusi
(certo, a meno che non ti servano in giro per la tua
applicazione/script ruby, ma dubito), pena il rimanere allocati in
memoria anche alla chiusura del processo esterno: questo ti porterebbe
inesorabilmente a leak di memoria se la tua applicazione principale
dovesse rimanere aperta per tanto tempo lanciando spesso processi
esterni. Uomo avvisato... :-)

Comunque per la valorizzazione dei parametri di CreateProcess e altre
info c'è http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx

PS: dato che non so che diavolo verrà fuori come impaginazione, i due
snippet sono anche qui http://gist.github.com/136104

Ciao,
Daniele


--
Daniele Alessandri
http://www.clorophilla.net/blog/
http://twitter.com/JoL1hAHN
Posted by Marco Di antonio (bulletxt)
on 2009-06-26 15:50
grazie appena torno dal lavoro(stanotte) lo provo!
Posted by Marco Di antonio (bulletxt)
on 2009-06-30 02:57
Sembra funzionare alla grande....... grazie!!!!!!!
Posted by Marco Mastrodonato (marcomd)
on 2009-07-01 12:53
Daniele Alessandri wrote:
>> Sto scrivendo uno script che avvia un processo, ad esempio notepad.exe
>> in modo da non bloccare il codice di esecuzione.
> 
> Parto dal presupposto che con "non bloccare il codice di esecuzione"
> tu intenda che non appena notepad.exe viene lanciato, il controllo
> torna allo script ruby in modo da poter proseguire con il normale
> flusso dell'applicazione (cosa che di fatto esclude metodi come system
> poich� "ascoltano" l'stdout del nuovo processo, bloccando di fatto lo
> script ruby fino alla chiusura del processo stesso).
> 

Con system "start notepad" puoi iniziare un nuovo processo in modo da 
non attenderne il termine, ma aveva già provato e gli compariva una 
shell, la cosa strana è che a me non compare se non quella 
dell'interprete ma è normale che ci sia e comunque c'è anche con i 
metodi più complessi che hai illustrato tu.
Posted by Marco Mastrodonato (marcomd)
on 2009-07-01 12:55
Marco Di antonio wrote:
> Sembra funzionare alla grande....... grazie!!!!!!!

Adesso però ce lo fai vedere questo rpg scritto in ruby???
Posted by Daniele Alessandri (Guest)
on 2009-07-01 15:49
(Received via mailing list)
2009/7/1 Marco Mastrodonato <m.mastrodonato@gmail.com>:

> Con system "start notepad" puoi iniziare un nuovo processo in modo da
> non attenderne il termine, ma aveva già provato e gli compariva una
> shell, la cosa strana è che a me non compare se non quella
> dell'interprete ma è normale che ci sia e comunque c'è anche con i
> metodi più complessi che hai illustrato tu.

A te non compare perché esegui lo script da un interprete che gira in
una shell (istanza di cmd.exe) con una sua finestra di console. Il
comando START crea una nuova shell ereditando l'handle di una
eventuale finestra di console già esistente, lancia il processo
secondario e poi termina la shell da lui creata restituendo il
controllo. Se, come nel suo caso, il comando START viene eseguito da
un processo che non ha associato alcuna istanza di shell, allora
l'esecuzione di START comporterà la creazione di una nuova shell il
che comporta anche, tuttavia, la creazione di una nuova finestra di
console la quale si chiuderà non appena START avrà terminato di
lanciare il processo secondario.

Per la cronaca non è assolutamente detto che ruby giri per forza in
una finestra di console (es. rubyw.exe non crea un'istanza di shell
quando viene eseguito, oppure come nel caso di Marco l'engine di ruby
può essere embeddato in un'altra applicazione GUI... ed ecco perché 
gli compare per un attimo una finestra di console usando START).

--
Daniele Alessandri
http://www.clorophilla.net/blog/
http://twitter.com/JoL1hAHN
Posted by Marco Di antonio (bulletxt)
on 2009-07-01 22:12
Marco Mastrodonato wrote:
> Marco Di antonio wrote:
>> Sembra funzionare alla grande....... grazie!!!!!!!
> 
> Adesso però ce lo fai vedere questo rpg scritto in ruby???

Uscirà il primo capitolo del gioco (circa 4 ore) tra qualche giorno... 
metterò il link qui ;)
Posted by Marco Di antonio (bulletxt)
on 2009-07-02 20:07
Come promesso, ecco il Capitolo del gioco :)

http://lodestone2d.sourceforge.net
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.