Synkronisoimaton SHELL-käsky Visual Basicille. VB:n SHELL käsky on synkronisoitu, eli kun suoritat sillä ohjelman, ei VB odota ajetun ohjelman terminointia vaan jatkaa VB-ohjelman suoritusta heti seuraavalta riviltä. Ongelmaan löytyy toki ratkaisu. Alla oleva koodi esittelee NShell -funktion joka suorittaa ohjelman ja palaa funktiosta vasta kun se on lopetettu.
Huomaa että funktion WindowStyle parametri on valinnainen, oletus on tässä tapauksessa vbMinimizedFocus.
edit 9.6.2004: Hmm, mitä helkkaria. Miksi tuo esimerkki ei näkynyt oikein? Ts. miksi kenoviiva pitää eskeipata?
edit 2.10.2004: Ei näköjään toiminut XP:llä; muutin PROCESS_DUP_HANDLE:n SYNCHRONIZE:ksi (typerä virhe ;-)
General-osioon
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long Private Const INFINITE = &HFFFF Private Const SYNCHRONIZE = &H100000 Private Sub NShell(PathName As String, Optional WindowStyle As VbAppWinStyle = vbMinimizedFocus) Dim e As Long ' e = dword-muuttuja e = Shell(PathName, WindowStyle) ' suoritetaan tiedosto e = OpenProcess(SYNCHRONIZE, False, e) ' avataan prosessi (saadaan kahva) WaitForSingleObject e, INFINITE ' odotellaan signaalia :) End Sub
Esimerkki
NShell "c:\paska\notepad.exe", vbNormalFocus
Äh, ja jo löytyi ensimmäinen "kirjoitusvirhe" :>
"d = dword-muuttuja" pitäisi toki olla
"e = dword-muuttuja".
sblao.
No, onneksi virhe on vain kommentissa...
Tuo on hyvä ja lainaan sitä heti. Tein näet opetellakseni (tökerösti koodatun...) ohjelmaan, joka pakkaa valitut tiedostot Winzip Commandlinen avulla (ja lähettää sitten paketin sähköpostilla mapin avulla).
Paketit voivat olla isojakin, joten koko pitäisi tietää. Mutta koska wb jatkaa odottamatta (shellin kautta ajettavan) ohjelman sulkemista, seuraa tietenkin virheilmoitus, koska nimetylle mutta kesken olevalle paketille ei ole vielä tiedostopituutta. Tuo nähdäkseni ratkaisee pulman vieläpä sivistyneesti. :)
Voisi tuon vielä sivistyneemminkin ratkaista. Eli niin, että käyttäisi INFINITE:n sijasta jotain lyhyempää odotusaikaa ja ajaisia DoEventsiä aina siinä välissä. Nyt tuo jää odottamaan vaikka maailman tappiin asti ja siihen asti VB ohjelma on "jumissa".
Aihe on jo aika vanha, joten et voi enää vastata siihen.