custom power button action (win (xp))

Tud-e valaki olyan megoldást, amivel Windows alatt egy program (script) futtatását tudnám kiváltani a power button (sleep button) megnyomásakor.

Az Energiagazdálkodási lehetõségek (powercfg.cpl) panelon választható kikapcs/suspend/hibernate/semmi, egyik se indít külön programot - ahogy megfigyeltem -, tehát nem tudom az eseményt úgy elkapni, hogy pl. felülírom a %WINDIR%\halt.exe-t.

Erre egy többfelhasználós gépen van szükségem, ami nem mindig fut, így a kliensek ki-bekapcsolhatják. Nem lenne gond, ha mindenki RDP-rõl jelentkezne be, mert kiveszem a standard kikapcsolás menüt a Startból o'szt jól van. De szoktak Console munkamenetet is kezdeményezni, tehát eléül a gépnek. Nem várom el a Console usertõl, hogy számon tartsa, használja-e még vki a gépet. A script ellenõrizné a session-ök idle time-ját, a console session aktív-e, fut-e olyan, mit nem akarok félbeszakítani, van-e a kikapcsolást felülbíráló control fájl, stb.

Ezen nem akarok változtatni, tehát technikai jellegũ megoldást keresek; a «csapjak a kezére» megoldás nem játszik.

Hozzászólások

megnéztem ezt a Cliassic Shellt, de se az oldalán nem írja, hogy tudna olyat, amit én akarok, se telepíteni nem tudtam (XP-re explicit nem települ).
látszólag ezek a fájlok vannak a telepítõjében:


2013.09.01.  14:07           594 432 ClassicExplorer32.dll 
2013.09.01.  14:07            92 672 ClassicExplorerSettings.exe 
2013.09.01.  14:07           367 616 ClassicIE9DLL_32.dll 
2013.09.01.  14:07            99 328 ClassicIE9_32.exe 
2013.09.01.  14:07         1 366 583 ClassicShell.chm 
2013.09.01.  14:07            99 385 ClassicShellReadme.rtf 
2013.09.01.  14:07            68 608 ClassicShellService.exe 
2013.09.01.  14:07           265 216 ClassicShellUpdate 
2013.09.01.  14:07           108 032 ClassicSkin.skin 
2013.09.01.  14:07           138 752 ClassicStartMenu.exe 
2013.09.01.  14:07         1 514 496 ClassicStartMenuDLL.dll 
2013.09.01.  14:07            41 291 ExplorerL10N.ini 
2013.09.01.  14:07           400 896 FullGlass.skin 
2013.09.01.  14:07            18 152 HISTORY.txt 
2013.09.01.  14:07                 8 inichecksum.bin 
2013.09.01.  14:07            81 408 Metro.skin 
2013.09.01.  14:07           245 248 SmokedGlass.skin 
2013.09.01.  14:07           116 728 StartMenuL10N.ini 
2013.09.01.  14:07           379 392 WindowsAero.skin 
2013.09.01.  14:07           378 880 WindowsBasic.skin 
2013.09.01.  14:07           573 440 WindowsXPLuna.skin 

a linkelt fórumban a kérdezõ igaz, hogy olyan speciális menüt akar, ami egyébként nem elérhetõ a beállítófelületen, de a FAQ-ban nem láttam, hogy tudna ilyet.
Belekukkantok még a forrásába, hátha értem.

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

Szia,
Inkább a testvérét nézd, a Classic Start Menüt (http://www.classicshell.net/faq/#menu), és elég szépen testre szabható :) (Nem tudom, XP kompatibilis-e)
Bár, az XP kompatibilitás, így 2013-ban, kb. 10 évvel az XP kiadása után, már kicsit nehezít a dolgon. De ha más nem, AstonShell-t fel lehet használni erre a célre, de CS és CSM-el ellentétben nem épp ingyenes program...
(Ha esetleg jelzed, hogy XP-hez kell, fel sem vetem ezt a lehetőséget, mivel ez a progi eredetileg direkt Vista/7/8 alá készült :) )
Üdv,
LuiseX
Szerk: esetleg ezzel valamire juthatsz, de az XP képességeit, sem a powercfg lehetőségeit nem ismerem: http://ss64.com/nt/powercfg.html (Csak ez kicsit többet tesz lehetővé, mint a kattintgatós felület :) )

Szia,
Igen, pontosabban cseréli (XP alatt még mindig nem tudom, megy-e, tesztelni kellene), de tudsz egyedi powergombot adni nekik. Amit már csak meg kell tanítani, hogy használjanak... Vagy, cserélheted a meglévőt erre... A default templatek pedig egész jól mintázzák az adott verzió menüjét...
Ellenben, közben a google leidézése mellett találtam egy neked jobban tetsző vonalat: http://stackoverflow.com/questions/4782944/run-a-batch-file-on-windows-…
Csak olvasni kell a sorok közt, hogy milyen mellékes infók bukkannak ki ;)
Remélem, sikerült segítenem,
Üdv,
LuiseX
U.i: Vagy a fizikai gombot akarod újra konfigurálni? Csak, mert az egészen más műfaj :)

a fizikai gombot akarod újra konfigurálni

nem egészen, tehát nem hardveres beavatkozást akarok, de közelebb áll a tervem a fizikai gombhoz, mint a start menühöz.
a power button megnyomása, ha jól gondolom, windózéknál is ACPI eventet generál, ezt lekezeli egy megfelelõ dll vagy service vagy winlogon.exe - nem tudom.
ennek a funkciónak a befolyásolására, kiterjesztésére törekszem.

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

fejlemények:

1. powercfg-ban a kikapcsoló gomb viselkedését (mily' meglepõ) kikapcsolásra állítom
2. ez a Group Policy beállítás ki van kapcsolva:
Felhasználó konf. / Felügy. sabl. / Start Menü / A Leállítás parancs eltávolítása és megakadályozása
tehát akinek van SeShutdownPrivilege joga, az fizikai gombbal, start menübõl tud leállítást kezdeményezni.

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

Véletlenül nincs olyan beépített funkciója a Windowsnak, ami leállítás előtt lefuttatja az általad kívánt parancsokat, beleértve akár egy leállítás sztornózását kiváltó parancsot is, és ha van, ez megfelelő-e számodra?

:)

ez a verzió mindkét kapcsolójelet egyaránt megérti,
de kétlem, hogy ezzel a módszerrel mũködne, mert ha shutdown parancs után hívok "shutdown /a"-t, akkor se abortálja. csak az idõzített (/t 10) leállítások megszakítására való.

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

Nem tudom, működhet-e: kijelentkezéskori futtatásra beteszel egy scriptet, ami figyeli, amit akarsz. Ennek az lehet az alapja, hogy amíg a kijelentkezéskori futtatással elindított folyamat (azaz az elindított scripted) be nem fejezte a futást, addig a leállítás nem történik meg (bár lehet, hogy van valamilyen időlimit).

:)

az ötlet ugyan nem vált be, de lényeges felfedezéseket tettem a kísérlet során.
tettem egy sleep 1000-et leállítási parancsfájlba és így észre tudtam venni, mikor is hajtja végre.
szinte közvetlen az "elsötétedés" elõtt. miután leállítja a session-öket, mindenkit kidob.

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

A kijelentkezési parancsfájlok közé tetted? Ez a felhasználó konfigurációja ágban van.

Ha csak simán a calc.exe-t teszed be a kijelentkezési parancsfájlok közé (ezek nyilván a felhasználó kijelentkeztetése előtt futnak le, ami ugye mindenképpen szükséges még a leállítás bármiféle megkezdése előtt), akkor a Windows addig nem állítja le a gépet, amíg a calc.exe fut, és értelemszerűen a felhasználót sem jelentkezteti ki. Ha az explorer.exe-t teszed be, visszakapod az asztalt, és első látásra semmi nem utal rá, hogy épp leállítás alatt lenne a rendszer; amikor az explorer.exe-t lelövöd pl. a Feladatkezelővel, utána kezdődik meg a leállítás.

Az általad megadott kötegelt fájlt (vagy ha csak a cmd.exe-t akarod indítani, azt is) kijelentkezéskor láthatatlanul futtatja, de pl. egy kötegelt fájlból a

start "" /wait "c:\ez_latszani_fog.bat"

paranccsal lehet láthatóan futtatni egy másikat, ha valamiért fontos tudni, mi történik (szépséghiba, hogy a végén

exit

paranccsal ki kell lépni vagy másképp le kell lőni a parancssort, különben ott maradsz a fekete képernyővel, illetve ha több elem szerepel a kijelentkezési parancsfájlok között, nem indul el a következő – de teszteléshez így is megfelel).

:)

gondolkodok még a ACPI (vagy PowerManagement vagy nem tudom, mi a helyes megnevezés) eventek WMI-n keresztüli pollozásán.

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

úú már az is mũvészet volt, hogy megértessem velük, ha elvégezték a dolgukat a gépen, ne féljenek megnyomni a kikapcsoló gombot - az nem olyan mintha a fõkapcsolót húznák le - a rendszer elvégzi, amit kell és lelövi magát. az ATX-es lapok korában már nem kell érte aggódni.

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

fejlemények:

A power button funkcióját kikapcsolásra állítottam.

luisex által citált oldalon talált AutoHotKey scriptet felhasználva csináltam egy progit, ami a leállításkor az ablakoknak küldött WM_QUERYENDSESSION szignált figyeli, megtagadja a leállítást és meghív egy batch scriptet. A condhalt nevet adtam neki.

Ha nem abban a logon session-ben kezdeményezik a leállítást, amelyikben a condhalt fut, nem funkcionál (valószínũleg nem kapja meg a szignált, vagy másikat kap?).
Ezért úgy gondoltam, hogy beállítom startup scriptnek. Így viszont privilégizált user nevében kéne futnia azért, hogy ne tudja a user kilõni (nem feltételezem, hogy készakarva tennének ilyet, de végezzek már legalább logikailag biztos munkát) és hogy megfelelõ jogokkal tudja futtatni a leállíthatóság vizsgálatát.

Ismertek olyan Startup script helyet, amit bejelentkezéskor még a System nevében futtat?

legjobb az lenne, ha csak egy condhalt instansznak kéne futnia és mindegyik session-tõl megkapná a szignált.

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

tényleg bejelentkezési parancsfájl! kösz! kipróbálom.

a szolgáltatáson én is gondolkodtam, de kétlem, hogy megkapná azokat a szignálokat, mert ahogy a fórumokból (ahonnan összeóllóztam az ahk scriptet) kivettem, ezek ablakoknak szóló szignálok.

befordítottam az ahk-t exébe, nemtudom így milyen esélye van nem meghalni.

a végén akartam közzétenni a scriptet. jelenleg így áll:

=== condhalt.ahk ===


#NoEnv
#Persistent
#NoTrayIcon
#SingleInstance, Force
SendMode Input
SetTimer, RunBeforeShutdown, Off

Gui,+LastFound
hwnd:=WinExist()
DllCall("ShutdownBlockReasonCreate", "Uint", hwnd, "Str", "")
;increase the chances of trapping the message first
DllCall("kernel32.dll\SetProcessShutdownParameters", UInt, 0x4FF, UInt, 0)

OnMessage(0x11, "WM_QUERYENDSESSION")
OnMessage(0x0218, "OnPBMsg")
Return

WM_QUERYENDSESSION(wParam, lParam)
{
	ENDSESSION_LOGOFF = 0x80000000
	if (lParam & ENDSESSION_LOGOFF)
	{
		Return true
	}
	Else
	{
		global n
		n:=%lParam%
		;no way to distinguish between shutdown and restart here
		SetTimer, RunBeforeShutdown, On
		Return false
	}
}

OnPBMsg(wParam, lParam, msg, hwnd)
{
	MsgBox, %wParam% %lParam%
	; TCUP: em_set_poweroffhibernate: 0 1
	; procexp: 18 0
	If (wParam = 0 or wParam=4) 
	{						;PBT_APMQUERYSUSPEND
		If (lParam & 1)		;Check action flag
		{
			SetTimer, RunBeforeShutdown, On
			; Allow
			;Return 4
			; Deny: BROADCAST_QUERY_DENY
			Return 1112363332
		}
	}
	Return True
} 


runBeforeShutdown:
	SetTimer, RunBeforeShutdown, Off
	
	DllCall("ShutdownBlockReasonDestroy", "Uint", hwnd)
	; **** Your commands go here ****
	RunWait hidec.exe condhalt.bat %n%, %A_ScriptDir%, UseErrorLevel
	; ********
	
	e:=ErrorLevel
	If (e == 0 or e == "ERROR")
	{
		;MsgBox, %e%
		;noop
	}
	Else If (e < 16)
	{
		Shutdown, e
	}
	Else If (e == 16)
	{
		DllCall("PowrProf\SetSuspendState", "int", 1, "int", 1, "int", 0)
	}
	Reload
Return


;Logoff	0
;Shutdown	1
;Reboot	2
;Force	4
;Power down	8
; Parameter #1: Pass 1 instead of 0 to hibernate rather than suspend.
; Parameter #2: Pass 1 instead of 0 to suspend immediately rather than asking each application for permission.
; Parameter #3: Pass 1 instead of 0 to disable all wake events.
;DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)

=== condhalt.bat ===


@echo off

PATH C:\fenestra\bin;C:\WINDOWS\system32;C:\WINDOWS


IF EXIST C:\nohalt.ctl GOTO prevent

FOR /F %%n IN ('TSListUsers ^| awk "BEGIN{n=0}{if(/^Active Conn/){a=1}if(a>0&&/^\s*$/){exit}if(a==2){n++}if(a==1&&/^-/){a=2}}END{print n}"') DO SET n=%%n

echo %DATE% %TIME% [%*] users: %n% >> shutdown.log
IF "%n%" == "" GOTO hibernate
IF %n% GTR 1 GOTO prevent

GOTO hibernate



:prevent
rem msgbox Leállítás "A munkaállomás még használatban van.\nA leállítás később történik meg.\n" 7
msgbox Shutdown "The workstation is still in use.\nShutdown will be executed later.\n" 7
IF ERRORLEVEL 1 GOTO noop
logoff

:noop
exit 0

:hibernate
exit 16


REM --- None		 0
REM --- Shutdown	 1
REM --- Reboot		 2
REM --- Force		 4
REM --- Power down	 8
REM --- Hibernate	16

=== msgbox.ahk ===


#NoEnv
#NoTrayIcon

sec=%3%
If (sec == "")
{
	sec=10
}

msg=%2%
msg:=RegExReplace(msg, "\\n", Chr(13))

msg:=msg . Chr(13) . "[Continue in " . sec . " sec...]"
MsgBox, 4417, %1%, %msg%, %sec%
IfMsgBox Cancel
	Exit 1
Exit 0

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

nem indul el mindegyik user bejelentkezésekor, ha indítási parancsfájlban van. igaz, az eredeti igényeimhez elég lenne ha csak a Console user sessionjében indul el, de mostmár univerzálisabb megoldást akarok belõle kihozni.

illetve így is a user nevében indul el és ki tudja killelni.
proxess explorerben találtam olyat, hogy a processre (sõt egy threadre is) tudok NTFS ACL-szerũ jogokat adni-venni, amik köz van Termination jog. az is hasznos lehet, ha indításkor leveti magáról a Termination jogot a processz.
viszont elég érdekesen mũködik: ha leveszem róla a Change Permissions jogot, vissza is tudom tenni!?

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

Az indítási egyszer elindul a bejelentkezés előtt, és leállításig fut (SYSTEM). A bejelentkezési pedig minden bejelentkezéskor lefut (adott felhasználó).

Vissza. De ha te vissza tudod tenni, akkor a felhasználó is, ha elindítja a Process Explorert... Vagy, ha ki is találsz valamit, hogyan tudnád a felhasználó által futtatott folyamatból úgy kivitelezni, hogy ne lehessen visszacsinálni, de jól működjön? Megváltoztatod a tulajdonost?

Amúgy miért akarnád visszatenni, hiszen a nem túlbuzgó felhasználótól megvédted a folyamatot, de nem tiltottál olyasmit, ami szükséges a feladat ellátásához. A Feladatkezelőből való processz-kilövés megakadályozása elégnek tűnik, nem?

Ha annyira be akarod biztosítani, talán olyat is lehetne, hogy alapból egy SYSTEM által futtatott folyamatod van, ami figyeli a bejelentkezéseket, és amikor valaki bejelentkezik, elindítja a nevében a programod, ami első lépésként megtagadja magára a Terminate és a Change Permissions jogot a felhasználótól. A SYSTEM által futtatott folyamat figyeli, hogy a felhasználó által futtatott program be lett-e zárva (logolja is neked, hogy tudjál róla), és ha igen, újra elindítja.

A leállítás figyeléséhez megnézhetnéd a WMI-t, ahogy eredetileg gondoltad, és a leállítás megtagadása talán menne a SYSTEM-nek is, így nem lenne szükséged felhasználó nevében futó megoldásra.

:)

Az indítási egyszer elindul

ez számomra is így világos. aszittem, azt javaslod, hogy indítási parancsfájlként futtassam a cuccomat SYSTEM nevében, erre mondtam, hogy nem lenne kapcsolata a user session-jével így nem kapna WM_QUERYENDSESSION plusz egyéb szignálokat.

leveszem róla a Change Permissions jogot, vissza is tudom tenni!?

De ha te vissza tudod tenni, akkor a felhasználó is

a halmozott írásjelekkel az értetlenségemet akartam kifejezni, nem kérdést :D
nem is gondoltam rá, hogy admin jogú userrel próbálgattam a mũveletet, de privilégizálatlan user esetében is useless a Change Permission ACL process objektumon, még ha Deny-ra állítom, akkor is (nem igazan értek az nt acl-ekhez, lehet hogy valami nincs implementálva ebben a win kiadásban, ezért nincs is rá hivatalos felület - csak a procexplorernek).

szó ami szó, normálisabb lenne ha eleve a SYSTEM user nevében futna, úgy nem tudja killelni, ha meg egyéb módon állítana le egy "testtel" nem rendelkezõ alkalmazást, akkor elismerem tiszteletbeli rendszergazdának :)

a bejelentkezések figyelését is megkíséreltem (igazából a session indításokat kéne, telnet/ssh bejelentkezésekre nem is mertem gondolni :D ), de még ha meg is tudnám figyelni, hogyan indítok alkalmazást _úgy_, hogy azon a Desktopon fusson?

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

Ezt amúgy nem teljesen értem. Ha valaki olyan botor, hogy egy calc.exe-t indít el SYSTEM nevében (mondjuk felveszi az indítási parancsfájlok közé), az a calc.exe nem kapja meg a leállítási szignált? Hanem? Valamikor valamit kell, hogy kapjon, mert egy komolyabb kaliberű program is lehetne a helyén, amit nem illendő csak úgy lelőni, meg nem is elegáns bármit is egyszerűen lelőni, szóval biztosan kap valami infót a leállításról az összes folyamat.
Számodra az a lényeg, hogy SYSTEM is tud ablakos folyamatot futtatni, csak ellenőrizned kell, hogy elkaphatsz-e valamilyen szignált. Vagy pedig azt kell megvizsgálnod, a WMI pontosan mikor tájékoztat a leállításról, van-e még lehetőség a megszakításra.

Szerintem a tulajdonosra nem érvényes, vagyis arra jó, hogy egy másik felhasználótól megtagadd a jogot.

Az aktív kapcsolatokat tuti lehet valahogy nézni, mert alapvető.

Mármint melyik desktopon és miért? A konzoloson?
Ha azért szeretnéd, mert csak ablakos megoldásod van a leállítás elkaszálására, az talán a SYSTEM folyamatból is menni fog, ki kellene próbálnod. Attól, hogy nem látszik, még létezik.
Ha azért szeretnéd, hogy üzenetet írj ki a felhasználónak, utána kell nézned, hogyan érheted el őt: runas illetve ennek API-alternatívája, vagy pedig mégis kellhet egy felhasználó oldali folyamat (megtagadott Terminate és Change Permissions joggal). Előbbi esetén valamiképpen elérhetővé kell tenned a hitelesítő adatokat a scripted számára, utóbbinál pedig a felhasználó által futtatott rész csak az üzenet megjelenítését végezné, így ha a felhasználó valahogy kilövi, nem kap üzenetet arról, hogy a gép még bekapcsolva marad, szépen kijelentkezteted, és ennyi. Célszerű beállítani, hogy bejelentkezés nélkül ne lehessen kikapcsolni a gépet.

Eszembe jutott még egy megközelítés. A felhasználóknak csak kijelentkezni lehetne (kikapcsolás helyett), a SYSTEM által futtatott cuccod pedig a kijelentkezést figyelné, és ezután vizsgálná, mikor lehet kikapcsolni a gépet. Így a többi bejelentkezettről nem kell semmilyen üzenet a felhasználóknak, majd megszokják az új helyzetet. Egy időre beállítasz nekik egy bejelentkezési üzenetet, hogy mától leállítás helyett csak kijelentkezés van. Ennek az az előnye, hogy nem kell megszakítani a leállítást, nem kell szignálokat elkapni, csak figyelni a kijelentkezést.

Mi van, ha a felhasználó újra akarja indítani a gépet?

:)

biztosan kap valami infót a leállításról az összes folyamat

teljesen egyet értek. csak sajnos töredékes ebben a témában az ismeretem. az ebben a topikban hivatkozott fórumokból arra következtetek, hogy ez a két megtagadható leállítás-féle szignál van (OnMessage 0x11 és 0x0218), mert csak ezeket emlegetik.

Mármint melyik desktopon és miért? A konzoloson?

azon a Desktopon, amelyikrõl éppen event érkezik, hogy megszületett. tehát amikor figyelem a "user_a bejelentkezett és session ID-ja 5" tipusú eventeket, akkor az 5-ös logon session-ön kéne elindítani a szignál figyelõ programot.

Ha azért szeretnéd, mert csak ablakos megoldásod van

azért gondoltam, hogy minden logon session-ben futnia kell egy példánynak, mert amikor csak egy session-ben futott, mintha nem kapta volna meg a szignálokat, amikor egy másik session-ben kezdeményeztem a leállítást [vide].
már látom, hogy ez az ablakos szignálfigyelõ gondolat zsákutca, mert mivan, ha a login screennél nyom kikapcsoló gombot? :D akkor erre is külön kéne figyelni, hogy ott is fusson (a winlogon.exe mellett) ez a figyelõ program! ááááá

Célszerű beállítani, hogy bejelentkezés nélkül ne lehessen kikapcsolni a gépet.

ezzel kezdtem az OS telepítést :D

csak kijelentkezni lehetne

ez tényleg sokkal jobb ötlet! ki is próbálom amint tudom. ebben az esetben logoff-ra kéne állítani a power button mũködését - erre nem emlékszem, lehet-e. mert az is kezdeti feltételem, hogy a power buttont szokják nyomogatni... :)

ez tenyleg egy egyszerũ megoldás lehet!

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

Hogyan tagadod meg a leállítást?

tehát a 0x11-es szignálra, ami kijelentkezéskor/leállításkor/újraindításkor jön, false-szal válaszolok; a 0x0218-esra, ami hibernáláskor/suspendoláskor jön, 0x424d5144 = 1112363332-vel válaszolok.

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7