Miten voisin tarkkailla minkänimisiä prosesseja on päällä?
Tehtävienhallinta --> prosessit
Tarkoituksena olisi saada selvitettyä onko internet exploreria käynnistetty eli jos joku tietää toisenlaisenkin tavan niin se käy myös.
No eikö Ctrl+Alt+Del avaa prosessi-ikkunan ainakin XP:ssä. Minulle taas tuli sellainen ongelma, etten pääse enää siitä prosessi-ikkunasta takaisin siihen ikkunaan, mistä näkee samat ohjelmat kuin taskbarissa.
Kyllä minä tuon tiesin..
Tarkoitus olisi että jos joku avaa internet explorerin niin vb:llä tekemäni ohjelma saa tiedon siitä.
Miten tarkistan löytyykö iexplore nimistä prosessia tuolta tehtävienhallinta --> prosessit listasta (vb:tä käyttäen).
Entä miten saisin sitten suljettua sen internet explorerin jos sellainen löytyy?
Ensimmäinen idea oli leikkiä SendKeysillä ja lähettää Exploderille yksi kappale Alt+F4:ää. Hienostuneempi tapa saattaisi olla WM_CLOSE:n (vaiko onko se tuo WM_QUIT? Joku API:sta enemmän tietävä kertokoot) lähettäminen SendMessage -API:lla.
Kai se on tuo WM_CLOSE, mutta se nyt on yksi ja sama, kun kerran sen itse määrittelee vakioksi. Tarkoitus kuitenkin on lähettää viesti &H10 tai 16 kohdeikkunalle.
SendMessage(KohdeIkkunanKahva, 16, 0, 0&) 'tai hienostuneemmin Const WM_CLOSE = &H10 SendMessage(KohdeIkkunanKahva, WM_CLOSE, 0, 0&)
Onko jokaisen ohjelman ikkunalla kahva vakiona vai muuttuko se (tarkoitan kahvan arvoa)?
Entä miten selvitän esim. ie:n kahvan?
Selailin hieman tuota mentaliksen sivua ja huomasin että on olemassa myös PostMessage niminen api-funktio.
Eroaako miten tuosta sendmessagesta?
SendMessage vs. PostMessage
AllAPI.net kirjoitti:
The SendMessage function sends the specified message to a window or windows. The function calls the window procedure for the specified window and does not return until the window procedure has processed the message. The PostMessage function, in contrast, posts a message to a thread’s message queue and returns immediately.
Kahvoilla erotetaan ikkunat toisistaan ja kahva pysyy samana niin kauan kuin ikkuna on auki. Ohjelman käynnistyessä se saa vapaana olevan kahvan, eli se vaihtuu joka kerta kun ohjelma käynnistetään. Käynnissä olevan ohjelman kahvan saa selville FindWindow:lla.
RetVal = Shell("Notepad.exe", vbNormalNoFocus) NoteHwnd = FindWindow(vbNullString, "Untitled - Notepad") RetVal = SendMessage(NoteHwnd, WM_CLOSE, 0, 0&)
Ei lähde oikein toimimaan..
Löytäisittekö te vikaa?
For i = 0 To prosessit.ListCount - 1 If InStr(1, prosessit.List(i), "Internet Explorer") Then IEHwnd = FindWindow(vbNullString, "Internet Explorer") RetVal = SendMessage(IEHwnd, WM_CLOSE, 0, 0&) End If Next i
FindWindowlle pitää olla ikkunan nimi kokonaisena, eli tuo nimi mikä näkyy TaskBarilla. Koitan katsoa millä tuon kiertää...
Vastaus ongelmaan on EnumWindows-functio.
AllApi.net kirjoitti:
The EnumWindows function enumerates all top-level windows on the screen by passing the handle of each window, in turn, to an application-defined callback function. EnumWindows continues until the last top-level window is enumerated or the callback function returns FALSE.
Seuraava koodi laskee kaikki avoimet IE:t.
'Moduuliin Option Explicit Declare Function EnumWindows Lib "user32" _ (ByVal lpEnumFunc As Any, ByVal lParam As Long) As Long Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _ (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long Public montako As Long Public Function EnumProc(ByVal app_hwnd As Long, ByVal lParam As Long) As Boolean Dim buf As String * 1024 Dim title As String Dim length As Long ' Otetaan ylös ikkunan otsikko length = GetWindowText(app_hwnd, buf, Len(buf)) title = Left$(buf, length) If Right$(title, 30) = " - Microsoft Internet Explorer" Then 'löytyi, joten lisätään summaan 'korvaa SendMessagella, jos haluat sulkea montako = montako + 1 End If EnumProc = 1 End Function
'Formille nappula cmIE Option Explicit Private Sub cmdIE_Click() montako = 0 EnumWindows AddressOf EnumProc, 0 If montako Then MsgBox montako End Sub
Korvaan siis tuon kohdan sendmessagella näin:
Mutta mistän tiedän hwnd:n?
If Right$(title, 30) = " - Microsoft Internet Explorer" Then retval = SendMessage(Hwnd,WM_CLOSE, 0, O&) End If
Badsource?
Pakko tehdä töitäkin välillä...;) Vaihdat Hwnd:n tilalle app_hwnd.
Kun leikkaa/liimaa/soveltaa, niin muuttujat vaihtuvat matkan varrella...
Tuon palauttama hwnd on aina sama minulla vaikka välillä ikkunoita on enemmän päällä ja välillä vähemmän päällä.
Joka kerta kun ajan tuon ohjelma pyytää sammuttamaan windowsin.
Huomasin juuri että jos tuon määrän laskijan jättää koodin niin se palauttaa vääriä arvoja.
Saamani arvot vaihtelevat 100 - 200 välillä.
En sisäistänyt vielä koodinkaan toimintaa täysin..
Tässä siis ei kutsuta itse funktiota vaan tuota apia jolle syötetään funktion antama arvo? Olenko väärässä?
EnumWindows AddressOf EnumProc, 0
Entä tuo arvo nolla joka välittyy tuolle lparam:lle?
Miten vaikuttaa?
Jos sait tuon itse toimimaan niin voitko lähettää projektina? Itse olen yrittänyt tässä jo tunti tolkulla kikkailla..
Mitä tuo byval muuten merkitsee?
Jokin hämärä muistikuva minulla olisi että se välittää arvon suoraan muuttujalle ja byref toisin päin...
Enpäs ole hirveenä jaksanut lueskella tätä mutta vastataan nyt pariin...
tuomas kirjoitti:
En sisäistänyt vielä koodinkaan toimintaa täysin..
Tässä siis ei kutsuta itse funktiota vaan tuota apia jolle syötetään funktion antama arvo? Olenko väärässä?EnumWindows AddressOf EnumProc, 0
Puoliksi oikein: sille syötetään EnumProc:in osoite muistissa, eikä kutsuta EnumProcia.
tuomas kirjoitti:
Entä tuo arvo nolla joka välittyy tuolle lparam:lle?
Miten vaikuttaa?
Noh:
MSDN kirjoitti:
The EnumWindows function enumerates all top-level windows on the screen by passing the handle to each window, in turn, to an application-defined callback function. EnumWindows continues until the last top-level window is enumerated or the callback function returns FALSE.
Syntax
BOOL EnumWindows( WNDENUMPROC lpEnumFunc,
LPARAM lParam
);
ParameterslpEnumFunc
[in] Pointer to an application-defined callback function. For more information, see EnumWindowsProc.
lParam
[in] Specifies an application-defined value to be passed to the callback function.
Elikkäs lparam on parametri joka menee callback functioniin eli tässä tapauksessa EnumProciin. Sillä ei nyt ole väliä tässä.
tuomas kirjoitti:
Mitä tuo byval muuten merkitsee?
Jokin hämärä muistikuva minulla olisi että se välittää arvon suoraan muuttujalle ja byref toisin päin...
oikea muistikuva... byval on by value, se passaa vaan sen arvon ja jos variaapelia muutetaan aliohjelmassa niin se ei muutu sitten... njoh esimerki:
sub moi(byval teksti) msgbox teksti teksti="" 'ei vaikutusta end sub sub moi2(teksti) 'oletuksena byref elikäs sub moi2(teksti) on sama kuin sub moi2(byref teksti) msgbox teksti teksti="" end sub sub form_load() ilmo="paiväee!" moi ilmo 'msgboxaa "paiväee!" moi2 ilmo 'msgboxaa "paiväee!" 'ny paiväee on ei mitään moi ilmo 'msgboxaa tyhjän end sub
hatusta... :P
Ceen syntaksista tuo on helpompi tajuta. Byref ymmärtääkseni passaa aliohjelmalle suoraan variaapelin muistiosoitteen joten jos sitä variaapelia muokataan niin kutsuttavasta ohjelmasta se muuttuu kanssa, byvalilla se vaan kopsitaan sinne ja sillä on vaikutusta vain aliohjelmassa.
Toivottavasti tajusit :)
Kyllä ymmärsin tuon byvalin nyt kun selitit mutta en silti osaa löytää tuosta koodista mitään virhettä tai yms.
Eli minulla on tuo moduulissa tuo funktio, muuten samanlainen mutta korvasin sen laskemisen sendmessagella:
RetVal = SendMessage(app_Hwnd, WM_CLOSE, 0, 0&)
Sieltä löytyy myös vakio WM_CLOSE = &H10,sekä api shelliä varten..
sitten formilla on timerissa seuraava:
EnumWindows AddressOf EnumProc, 0
eli muuten sama kuin tuossa esimerkissä, se laskenta vain puuttuu (se laskenta muuten palauttaa vääriä arvoja).
Eli missä on vika?
EDIT: hwnd palauttaa aina saman arvon ja yrittää sammuttaa windowsin.
hAAh! Kannattaa tonkia vanhoja ohjelmia. Kaksi vikaa:
SendMessage app_Hwnd, WM_CLOSE, 0, 0&
Viimeisen pitää olla vbNullString ja sendmessage ei toimi tässä(älä kysy miksi :P): käytä postmessaakia.
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As Any) As Long
Ja tämän pitäis toimia:
PostMessage app_hwnd, WM_CLOSE, 0, vbNullString
Sooda, saitko tuota itse toimimaan?
Itse en ole päässyt vielä testaamaan tälläisen takia:
"- Microsoft Internet Explorer - Toimittaja Elisa Internet...."
Hyvä että löysin tuollaisen jo nyt, olisi saattanut tulla myöhemmin virheitä joita en olisi välttämättä osannut korjata..
Pitää varmaankin käyttää tuon leftin tilalle instr:ää.
EDIT: Nyt se lähti toimimaan! Kiitos paljon kaikille jotka auttoivat!
Ja minä kun luulin että kun osaan tuon niin loppu sujuisi hyvin :(
Eli kun avoin ie löydetään se suljetaan ja avataan uusi:
'Moduuliin Option Explicit Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As Any) As Long Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Any, ByVal lParam As Long) As Long Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long Public Paalla2 As Boolean Public hw Public Maara As Integer Const WM_CLOSE = &H10 Public Function EnumPro(ByVal app_hwnd As Long, ByVal lParam As Long) As Boolean Dim buf As String * 1024 Dim title As String Dim length As Long Dim Etsittävä As String Dim i As Integer 'Etsittävä = "Microsoft Internet Explorer" Etsittävä = "Microsoft Internet Explorer" ' Otetaan ylös ikkunan otsikko length = GetWindowText(app_hwnd, buf, Len(buf)) title = Left$(buf, length) If InStr(title, Etsittävä) Then If app_hwnd = hw Then Exit Function End If Paalla2 = True PostMessage app_hwnd, WM_CLOSE, 0, vbNullString End If EnumPro = 1 End Function
Ja tässä on timerin koodi joka tarkistaa onko ie avoinna:
Private Sub Timer10_Timer() EnumWindows AddressOf EnumPro, 0 If Paalla2 = True Then AvaaUusiIE Timer9.Enabled = True Paalla2 = False End If End Sub
ja näin avaan uuden selaimen.
Private Sub AvaaUusiIE() On Error Resume Next If Maara = 0 Then 'luodaan uusi ie Set IExplore = New InternetExplorer 'kahva hw = IExplore.hwnd 'navigoidaan aloitus sivulle IExplore.GoHome 'jotta selain on varmasti näkyvissä IExplore.Visible = True Maara = Maara + 1 Else Exit Sub End If End Sub
Kun selain suljetaan
maara = maara - 1
Siis tuon kuuluisi toimia näin:
kun löytyy avoinna oleva ie ohjelma sulkee sen ja avaa uuden koodista käsin.
Ohjelma ottaa talteen avatun ie:n hwnd:n ja tarkistaa ettei sulje sitä.
Kun koodista avattu ie suljetaan suoritus alkaa alusta.
Eli kun taas avataan uusi ie niin se suljetaan jne.
Itse en ole tuota saanut toimimaan joten tarvitsisin apua.
Tähän mennessä ohjelma toimii näin:
ensimmäinen selain suljetaan ja avataan uusi.
Tähän mennessä toimii hyvin.
Sitten jossain vaiheessa käyttäjä sulkee selaimen.
Kun hän on avaamassa selainta uudestaan selain ei suostu enää aukeamaan.
olisiko kellään ratkaisua tähän?
Ette usko miten kauan olen rämpyttänyt tuota...
Oletko tarkistanut, että tuo Maara todella vähenee poistuttaessa? Jos se ei ole nolla, niin uusi ei avaudu...
Miksi siinä tuollainen muuten on? Tuo rajaa sen, että AvaaUusiIE tekee jotain vain silloin, kun selainta ei ole auki (parhaassa tapauksessa)... Eikö tuo Paalla2 riitä tarkistamaan, että jotain olisi syytä tehdä...
Aihe on jo aika vanha, joten et voi enää vastata siihen.