[VB] Operovanie s aplikaciou 'before user logon'

C++, C#, Visual Basic, Delphi, Perl a ostatní

Moderátor: Moderátoři Živě.cz

Odeslat příspěvekod DanHen 30. 12. 2018 01:28

Zdravim,
pre firmu, kde pracujem som napisal launcher vo visual basicu. v IT time mame spravenych viac projektov v pythone a potrebujeme ich spustat pri starte systemu. Momentalne je ich cca 10, bude ich daleko viac. Kedze firemne politiky su take, ze pocitace sa obcas restartnu, ci uz kvoli windows updatom, alebo kvoli firemnym updatom, alebo kvoli comukolvek, aj nepredvidanemu (napriklad pri vypadku elektriny), bolo ziaduce, aby sme zachovali nase projekty zive, aj ked sa nebudeme moct o ne fyzicky postarat (napriklad ak sa takato udalost udeje cez vikend, alebo kedykolvek mimo pracovneho casu). Moduly treba spustat so vzajomnym casovym oneskorenim (cize povedzme modul B musi byt spusteny az po module A, dajme tomu 20 sekund). Toto vsetko riesi moj launcher. Aby sa spustal korektne a vzdy, tak som mu vytvoril task v task scheduleri. dal som mu vlastnosti 'Run whether user is logged on or not', a tiez trigger 'On startup', aby som mal zabezpecene, aby sa launcher spustil vzdy, dokonca aj bez toho, aby sa musel nalogovat akykolvek user.
Potialto je to vsetko okay, launcher bezi, spusta moduly, robi backupy a vlastne robi vsetko co ma.
A teraz moj problem:
kedze sa launcher spusti pred lognutim usera, spusta ho systemovy svchost. tento ho vsak spusti tak, ze je nemanipulovatelny, a tiez vsetky moduly, ktore spusti. v praxi to vyzera tak, ze ked sa pozriem do process managera, tak vidim, ze mam spusteny launcher a pod nim spustu child processov, ktore spustil. to je okay. ale so ziadnym procesom nemozem nijak manipulovat: nevidim okno ziadneho procesu, tym padom nevidim konzoly, neviem ho minimalizovat, neviem process korektne zavriet, iba ho zabit cez task manager. to sa tyka jednak launchera, a jednak vsetkych procesov, ktore spusti.
Nakoniec otazka:
akym sposobom by som vedel spustit launcher (a nasledne aj vsetky aplikacie, ktore on sam spusta)? samozrejme tak, aby som vedel s nimi manipulovat, pri zachovani vlastnosti, ktore som definoval vyssie - cize MUSI sa spustit pred lognutim usera, MUSI sa spustit so startom systemu.
launcher ako taky je v podsatte 'mission accomplished' - robi to co ma a vtedy ked ma. avsak manipulacia s nim a s aplikaciami nim spustenymi je - mierne povedane - 'opruz', kedze ak nieco chcem niekde robit, musim launcher jednoducho zabit a spustit nanovo. a to nie je ani profesionalne, ani elegantne, ani pohodlne :(

ma niekto nejaky hint, prosim?
jedine smrt ve svete nespecha,
prichazi pomalu a v klidu
                                (kryptor)
http://danhen.lordcyber.net/
DanHen
Junior
Uživatelský avatar

Odeslat příspěvekod Just_jo 30. 12. 2018 11:06

A je problém v TaskSheduler nastavit vlastníka aplikace - resp. účet pod kterým poběží?
Just_jo
Junior
Uživatelský avatar

Odeslat příspěvekod Nargon 30. 12. 2018 15:13

Ve windows to myslím není možné. (v linuxu netuším, ten moc neznám).
Pokud se uživatel má mít možnost nějak manipulovat s oknem aplikace (i textová konzole je okno) tak aplikaci musíš spustit v rámci jeho přihlášené session. Což tedy lze udělat až po tom co se uživatel přihlásí a jeho session se vytvoří. Nevím o způsobu jak by tohle šlo obejít. Ovšem to je přesně to co chceš. A nějak proces přesunout z LocalSystem session do té uživatelské taky nevím jak by šlo, navíc mám pochybnosti zda by to vůbec fungovalo. Například co třeba práva, tím přesunem by mohlo dojít k tomu, že kam aplikace mohla, tak už nebude moct apod. Tedy důvod proč se o to ani nepokoušet.

V tom případě moc možností nemáš.
1) Asi nejsnadnější řešení je nastavit to, ať se to spouští až po přihlášení uživatele a na tom počítači nastavit automatické přihlášení po spuštění: https://www.lifewire.com/how-do-i-auto- ... ws-2626066
Což ovšem co se týče bezpečnosti je problém. Ovšem pokud to nevadí, tak je to nejrychlejší řešení a jediné bez nutnosti něco doprogramovávat.

2) Pokud programovat tak ještě celkem dobré řešení je "korektně" zavřít launcher a aplikace spuštěné bez uživatele a pak spustit aplikace nové, teď už pod přihlášeným uživatelem.
Tady budeš potřebovat 2 věci. Jednak způsob jak korektně ukončit aplikace spuštěné launcherem. A za druhé potřebuješ nějak launcheru přikázat, ať tohle ukončení provede.
Jak korektně ukončit aplikace musíš vědět ty. Ale vzhledem k tomu že je launcher spouští tak má nad nimi kontrolu a může jim například na STDIN poslat slovo STOP a enter.
Příkaz na ukončení už vyžaduje využít nějakou metodu na "meziprocesovou komunikaci" (interprocess communication), co použiješ je na tobě a na tvých možnostech.
V zásadě potřebuješ spustit nový launcher pod korektním uživatelem, detekovat že je již spuštěný jiný launcher a zaslat mu informaci ať ukončí jím spuštěné procesy a i sebe. A ideálně i dostat informaci zpět, že to ukončil a můžeš je znovu spustit, to záleží na tom zda mohou nebo nemohou být aplikace spuštěné vícekrát a zda jim to vadí. Vhodné řešení by byly asi Named Pipes a nebo i TCP Socket. Ovšem můžeš si vystačit i se souborem. A nebo můžeš fungovat i bez meziprocesové komunikace a na hulváta killnout předchozí launcher a jím spuštěné aplikace a nastatrovat je znovu pod tím uživatelským launcherem.

3) Případně nejvíc Hardcore řešení, ale asi nejelegantnější. Ovšem použitelné jen pro konzolové aplikace. Je to takové rozšíření předchozího řešení.
Když máš meziprocesovou komunikaci např pomocí Named Pipes, tak místo posílání tupé zprávy na ukončení můžeš obousměrně posílat přesměrované STDIN a STDOUT aplikací spuštěných launcherem. Pak u toho uživatelského launcheru vytvoříš pseudokonzoli, která bude zobrazovat to co přijmeš z named pipe a zpět do pipe posílat to co napíšeš do konzole.


Pokud je i jiná možnost, tak bych jí sám uvítal. Rád se přiučím něčemu co neznám.
Desktop: Ryzen 7 1800X (3.95GHz, 1.35V), Asus Crosshair VI Hero, 16GB DDR4 Ram (3200MHz), 128GB SSD + 3TB HDD, Nvidia GTX 1080
Notebook: Asus UL50VT 15.6" (SU7300@1.7GHz, 4GB ram, 500GB HDD, Intel GMA 4500MHD + nVidia G210M, dlouha vydrz cca 7+ hod)
Nargon
Moderátor

Odeslat příspěvekod Just_jo 30. 12. 2018 15:32

Nargon: kdyby tam ta možnost nebyla, tak to nezmiňuji.
Na Win10 i Win7 je možnost spustit úlohu jako jiný uživatel.
Už jsem tohle řešil pro pár rodičů, kde se spouštěla aplikace pod uživatelem RODIČ při přihlášení účtu DĚTI. To aby to neshodil přes správce úloh
Just_jo
Junior
Uživatelský avatar

Odeslat příspěvekod DanHen 30. 12. 2018 19:16

dakujem za odpovede. operacny system je windows 10 (neuviedol som to vyssie)
Just_jo: ono to samozrejme nie je problem. pri vkladani tasku do task schedulera som aj tak musel nastavit usera, ktory ma opravnenie zapisat tento task, kedze to vyzaduje admin rights. mne je v podstate jedno, pod akym userom to bude spustene, ci pod mojim, kolegovym, alebo sefovym. podstatne je to, aby sa to spustilo. ono sa to aj spusti, ale manipulovat s tym nemozem nijak, kedze je to spustene tak, ako je to spustene. a to ani vtedy, ak je task zalozeny pod mojim uctom a potom sa prihlasim tiez pod mojim uctom. launcher a aplikacie nadalej zostavaju nemanipulovatelne.
Nargon: dik za hinty.
- hint 1 je bohuzial nepouzitelny. sice som sa nikoho na to nepytal, ale autologin usera mi na 99 percent neprejde. pretoze company policies, security a vsetky tie kecy dookola, tak silne pochybujem o tom, ze mi bude dovolene spustat server s autologon usera. mozno by bola malicka sanca spravit to tak, ze spravi autologon, spusti vsetko co ma a potom spravi log off usera, ale ani v to moc neverim. to by mi bolo dovolene mozno vtedy, keby k serveru nemal nikto fyzicky pristup okrem mna, resp. povolanych. ale kedze server je kdesi v serverovni (ja ani vlastne neviem, kde sa ten pocitac fyzicky nachadza), tak toto nepojde. uznavam, ze by to bolo najbezbolestnejsie.
- hint 3 je vskutku hardcore. bolo by to aj celkom elegantne, ale obavam sa, ze to nebudem vediet spravit k vsestrannej spokojnosti.
- hint2 by celkom siel. moduly, ktore spustam cez launcher su pythonovske moduly. takmer kazdy je serverovy modul - postaveny na FLASKu. pokusmi som zistil, ze flasku nijako nevadi, ked je niektora instancia spustena viac krat (dobre, skusal som len dve spustenia rovnakej instancie, ale dve mi stacia). a nevadi to ani klientovi, cize klient nespozna, ze jeho server, na ktory sa odkazuje, bezi 'dvojmo'. pokial bezi prva instancia, vykonava sa prva instancia, ked zabijiem prvu instanciu, plynule pokracuje v druhej. nevykonavaju sa obidve (to by bolo znacne neziaduce, kedze server zapisuje do db, atd ... a keby vsetko vykonaval dvakrat, to by bol dost bordel).
vedel by som si to predstavit tak, ze by som do launchera dorobil kontrolu dvojitosti instancii. zaroven by kontroloval bud parent process, alebo ID procesu. pokial by boli dve instancie, tak by vedel korektne ukoncit instanciu, ktora bola spustena aktualnou instanciou launcheru. takto by pokracoval az dovtedy, kym by neukoncil vsetky instancie, ktore spustil. po ukonceni poslednej by ukoncil sam seba. toto by vyzadovalo mat v launcheri timer, ktory by to periodicky kontroloval.
moznost so suborom je sice 'lamerska', ale asi to bude to prave riesenie. kedze .NET ma event na file creation ( a tiez file delete, file changed, atd ...), tak by bolo mozno vhodne vytvorit si subor, pri nejakej udalosti (spustenie launchera, spustenie jednotlivych modulov...) a tieto subory potom 'catchovat' v event pre file creation / modify. tymto by som sa vyhol timeru, ktory by sice nemusel mat velky interval, stacila by povedzme minuta, ale z principu, ak sa da, vyhybam sa timerovym sluckam, a radsej siahnem po metode cez event.
budem to musiet overit v praxi, ale toto by slo. dik za hint, Nargone. ak niekoho napadne nieco menej bolestive a menej lamerske, rad si dam poradit :)
jedine smrt ve svete nespecha,
prichazi pomalu a v klidu
                                (kryptor)
http://danhen.lordcyber.net/
DanHen
Junior
Uživatelský avatar

Odeslat příspěvekod Nargon 30. 12. 2018 19:49

Just_jo:
Vím, že v plánovači úloh můžeš zadat "uživatelský účet" pod kterým to bude spuštěno, ale to neřeší tenhle problém.
Pokud nastavíš, že se úloha má "Spustit pouze pokud je uživatel přihlášen", tak to funguje celkem OK. Pro názornost řekněme že jsi nastavil ať se spustí Total Commander (nebo cokoliv jiného, internetový prohlížeč, kalkulačka, hudební přehrávač, webový server atd...) Zapneš počítač, přihlásíš se a vidíš okno spuštěné aplikace total commanderu. Má to jediný problém, že se to spustí až když se uživatel přihlásí. Tedy po restartu stroje se to nezapne dokud se uživatel nepřihlásí.
Pokud nastavíš, že se úloha má "Spustit nezávisle na přihlášení uživatele", tak tím vyřešíš problém přihlášení. Aplikace se spustí ihned po nastartování PC, tj ještě před tím než se tam někdo přihlásí. Jen to není spuštěné v session (možná říkejme na ploše) toho uživatele, ale někde na ploše systémového účtu. To znamená, že když se následně přihlásí ten uživatel, pod kterým to je spuštěné, tak okno Total commanderu nevidí. Když se podívá do správce úloh, tak tam je vidět že total commander je spuštěný, dokonce že je spuštěný pod zadaným uživatelským účtem, ale ten uživatel okno total commanderu nevidí, protože je spuštěné na ploše systému, nikoliv na ploše přihlášeného uživatele. Ale aplikace jako taková funguje. Když je to hudební přehrávač s automatickým přehráváním hudby, tak slyšíš hudbu, ale nevidíš okno toho přehrávače. Když je to webovy server, tak se na něj můžeš internetovým prohlížečem připojit a vidíš internetovou stránku...

Ono je to podobné jako když máš na PC účet administrátora a uživatele. Když si v účtu uživatele klidneš pravým myšítkem na total commander a dáš spustit jako správce, zadáš jméno a heslo administrátora tak se ti na uživatelské ploše spustí total commander. Když se podíváš na správce úloh tak tam je vidět že total commander běží pod účtem administrátora. Ale když se přihlásíš na administrátorský účet tak okno total commanderu nikde nevidíš, ikdyž je spuštěný pod administrátorským účtem. Je to správně, protože to okno je spuštěné na ploše uživatele, nikoliv na ploše administrátora.


Když já osobně programuji něco takovéhoto, tak to programuji jako dvojaplikaci (klient-server). Kde ta serverová část (tj ta část co něco dělá, má potřebná práva a je spuštěna trvale) je u mě většinou windows služba. A ta klientská část je "ovládací aplikace" s tlačítky, progress bary, hejblátky a nastavovátky. A to celé spolu komunikuje, takže ta nastavovací aplikace jen říká té serverové co má dělat. Případně si předávají i data ke zpracování, protože každá ta část můžeš běžet na jiném počítači a ten "server" nemusí mít síťový přístup k souboru, který uživatel u své ovládací aplikace vybral. Je tedy nezbytné aby klientská stanice soubor načetla, poslala ho na server, tam se zpracoval a uživateli se vrátil výsledek. Když je výkonný server tak je to často rychlejší než když ty data chroupá klientský PC.
Desktop: Ryzen 7 1800X (3.95GHz, 1.35V), Asus Crosshair VI Hero, 16GB DDR4 Ram (3200MHz), 128GB SSD + 3TB HDD, Nvidia GTX 1080
Notebook: Asus UL50VT 15.6" (SU7300@1.7GHz, 4GB ram, 500GB HDD, Intel GMA 4500MHD + nVidia G210M, dlouha vydrz cca 7+ hod)
Nargon
Moderátor

Odeslat příspěvekod DanHen 30. 12. 2018 20:31

presne tak, ako pise nargon. sprava sa to uplne presne tak, ako si popisal. launcher nastartuje flask server, a on funguje. viem sa do neho pripojit, a pracovat s nim a vsetko funguje okay. snad by som len doplnil, ze pokial by sa jednalo len o launcher ako taky, tak slak ho traf, nech ho neni vidno, je mi to jedno, atiez by som to riesil na baze, ako pises - jedna instancia by bezala ako 'sluzba', a druha by bola klientska - s hejblatky a buttonmi. ale s modulmi, ktore spusta z casu na cas potrebujem operovat a tam uz to, ze sa s nimi neda manipulovat je dost neprijemny jav, odhliadnuc od toho, ze su to pythonove moduly, a kazdy jeden bezi len ako konzola, bez GUI.
jedine smrt ve svete nespecha,
prichazi pomalu a v klidu
                                (kryptor)
http://danhen.lordcyber.net/
DanHen
Junior
Uživatelský avatar

Odeslat příspěvekod Nargon 30. 12. 2018 20:45

Jen s těmi soubory opatrně, protože když aplikace spadne (nebo je například při restartu serveru killnuta), tak soubor na disku zůstane a při nastartování to může být chybně interpretováno jako že už to běží.

Právě proto jsem psal například o TCP Socketech. Tam lze elegantně využít toho, že na jednom portu můžeš spustit jen jeden listener. Tedy například si vybereš port 5555, po startu launcheru se pokusíš vytvořit listener na portu 5555. Pokud se povede, tak je to první spuštěný launcher. Pokud ne, tak už běží jiný launcher. Pak například připojením (connect) na port 5555 můžeš říci prvnímu launcheru ať spustí ukončovací sekvenci. Až doběhne a původní launcher opustí port 5555, tak nový launcher obsadí port 5555 a nastartuje moduly. Tohle má výhodu v tom že po restartu je jistě port 5555 volný a nedojde tam k chybné interpretaci zda to běží. Stejně tak když aplikaci killneš tak systém uklidí a uvolní port.
Jen pro reálné nasazení to asi chce něco víc než jen "connect" na port 5555 pro spuštění ukončovací sekvence. Protože takhle by ti to mohl "vypnout" každý skener portů :)
Desktop: Ryzen 7 1800X (3.95GHz, 1.35V), Asus Crosshair VI Hero, 16GB DDR4 Ram (3200MHz), 128GB SSD + 3TB HDD, Nvidia GTX 1080
Notebook: Asus UL50VT 15.6" (SU7300@1.7GHz, 4GB ram, 500GB HDD, Intel GMA 4500MHD + nVidia G210M, dlouha vydrz cca 7+ hod)
Nargon
Moderátor

Odeslat příspěvekod Just_jo 30. 12. 2018 23:53

Nargon: OK beru zpět. To co jsi popsal mělo být naprogramované jako služba a jiná app jako ovládání. To mě ale nenapadlo.

Asi si něco zítra zkusím naťukat
Just_jo
Junior
Uživatelský avatar

Odeslat příspěvekod Just_jo 1. 1. 2019 10:36

Tak asi nejlepší řešení by bylo toto:
Kód: Vybrat vše
1. doprogramovat do launcheru CMD parametr ( příklad spuštění "launcher.exe -service" )
   ten pak volat v plánovači
   Při parametru by se : 1. smazaly PID soubory
                      2. vytvořili nové PID soubory tak, jak se budou postupně spouštět
                      3. nakonec sám sebe ukončit
2. Při normálním spuštění po přihlášení by pak launcher zkusil načíst PID soubory a vyhledat procesy podle PID
Just_jo
Junior
Uživatelský avatar

Odeslat příspěvekod DanHen 12. 1. 2019 21:17

trochu dlhsie mi trvala odpoved, ospravedlnujem sa, bolo vela roboty :)

just_jo:
nieco podobne ma samozrejme napadlo.
1. launcher ma moznost spustenia s paratrom, uz od zaciatku. ten parameter je 'startup'. ked je psusteny s parametrom, tak spusta jednotlive procesy pri svojom samotnom starte.
2. odchytit PID nie je problem. dokonca nie je problem ani odchytit HWND (handle) samotneho procesu, kedze python sa spusti s jednym oknom a je to konzola aplikacia (napriklad taky chrome, alebo vivaldi maju desiatky okien, tam by mohol byt problem s hladanim spravneho okna. tu ten problem nie je.)
stale vsak pretrvava problem, ze sa neda s onom / aplikaciou manipulovat. ja sice viem PID daneho procesu, a viem aj jeho hwnd (ked nijak inak, tak ho viem vysypat do suboru pri samotnom starte procesu), ale je mi to uplne k nicomu, lebo sa s tym manipulovat neda. to znamena, ze ak napriklad spravim ShowWindow(my_hwnd,1), tak by sa mi malo zobrazit okno s danym hwnd. ale ono sa mi nezobrazi. preco? pretoze je startovane scvhostom 'nad systemom' a nemam pravo s nim manipulovat.
skusal som presvedcit python, aby mi vystup posielal do suboru, a nie do konzoly. tu som uspech bohuzial nezaznamenal, resp. len ciastocny. niekedy mi zapisoval do konzoly, niekedy nie (stdout). neviem, od coho to zavisi, ale pokial to nie je stopercentne, tak to pouzit nemozem, nakolko do konzoly priebezne pocas behu programu vypisujem niektore uzitocne informacie, ktore potom pouzivam dalej, povedzme pri debugu, alebo pri feedbacku od userov.
3. manipulacia s danymi procesmi je proste VELMI obtiazna, pokial su spustene tak, ako ich spustam ja. priznam sa, ze neviem, ako 'preniest' premennu, resp. objekt procesu inde. ja ich totiz spustam tak, ze ich hidnem hned pri spusteni, resp. rovno ich spustam ako hidden ( zprocess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden ). a potom drzim v pamati jednotlive zprocess premenne (objekty). na poziadanie ich viem ukazat (ShowWindow), killnut, atd ... priamo z launchera. ide totiz oto, ze ich je velmi vela, a nechcem mat milion konzolovych okien na screene, odhliadnuc od toho, ze python sa spusti tak, ze v title konzoly je len c:\programdata\anaconda3\python.exe, a nic viac, cize ani neviem, ku ktoremu procesu dana konzola patri. ked zavrem launcher, tak pri opatovnom spusteni uz neviem narabat s tymito procesmi, pretoze neviem, ako preniest ten objekt zprocess. nie je to strong, alebo int, kde by pomohlo jednoduche zapisanie do suboru a nasledne precitanie pri opatovnom spusteni.
prenasat objekty process by som v podstate nemusel, keby som vedel prinutit python, aby mi stopercentne zapisoval vystup do suboru, namiesto do konzoly. potom by som vedel vlastne spustit jednotlive moduly, a launcher by sa mohol sam ukoncit. pri opatovnom spusteni by som vedel citat jednotlive subory s jednotlivymi konzolami ... lenze to mi nejde stopercentne. mozno robim niekde chybu.
jedine smrt ve svete nespecha,
prichazi pomalu a v klidu
                                (kryptor)
http://danhen.lordcyber.net/
DanHen
Junior
Uživatelský avatar


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 0 návštevníků