2010-06-21 1 views
6

Para detectar y evitar el apagado de la computadora utilizo un programa muy simple. Tiene una sola forma y un procedimiento privado, como a continuación:Prevención del cierre de Windows

TForm3 = class(TForm) 
private 
    procedure WMQueryEndSession(var Msg : TWMQueryEndSession) ; 
     message WM_QueryEndSession; 
end; 

y la implementación

procedure TForm3.WMQueryEndSession(var Msg: TWMQueryEndSession); 
begin 
    Msg.Result := 0; //so I don't want to shutdown while my program is running 
end; 

que lo recopiló Delphi 5 y Delphi 2010. Ambos detectar el apagado. Pero cuando compilé en Delphi 2010; después de prevenir el cierre, mi programa se cierra. (PC no se apaga)

¿Cómo obtengo el mismo resultado de ambos?

+3

¿Puedo preguntarte por qué estás haciendo esto? por lo general, es grosero e injustificado interferir con el apagado. Además, este tipo de código tiende a ser frágil y rompe con los parches de seguridad ... – MJB

+0

@MJB: Escribí ese programa una vez: otro programa grosero (Windows Update, IIRC) pensó que estaba bien reiniciar la computadora, cada vez que me dio la espalda por un minuto. Probablemente fue una mala configuración de WU, pero como no podía arreglarlo o desactivarlo (privilegios y todo), al menos pude evitar que engulliera mi trabajo.(Por cierto, este es un comportamiento documentado y legítimo desde WinXP, y el propósito principal del mensaje: 'WM_QUERYENDSESSION' se envía a todas las aplicaciones para ver si alguno de ellos tiene una objeción al cierre; si es así, se cancela el apagado) – Piskvor

Respuesta

0

Parece un error en Delphi. Te sugiero que publiques esto en Quality Central.

+5

Ya informé esto al control de calidad el mes pasado: http://qc.codegear.com/wc/qcmain.aspx?d=84886 –

+0

No pude encontrar la respuesta correcta a mi pregunta. Pero el comentario de Remy me mostró el camino. Entonces, ¿qué debo hacer para aceptar una respuesta? – SimaWB

+0

Para aceptar la respuesta, necesita: 1. seleccione una respuesta para aceptar. 2. haga clic en blanco \/"check" justo debajo de los votos para la respuesta. "Verificar" debería ponerse verde: esto significará que se aceptó esta respuesta (por lo que la pregunta se resolvió). – Alex

0

Editar: Aquí hay un enfoque que no funciona. Gracias

Procedure TMyForm.FormClose(Sender: TObject; Var Action: TCloseAction); 
Begin 
    Action := caNone; //The form is not allowed to close, so nothing happens. 
End;     // Note: the OP says he tried this, doesn't help. See the comments. 
+0

Wouldn ' t que impiden cerrar la aplicación de todos modos? –

+0

desafortunadamente. También probé el evento OnCloseQuery. Pero mi programa se cierra de inmediato. No activa OnClose ni OnCloseQuery. – SimaWB

+8

@Uwe, SimbaWB, gracias por confirmar que esto no funciona. Pensé en eliminarlo, pero a veces es útil ver lo que no funciona. Este es uno de esos ejemplos. No invites por favor. Siéntase libre de downvote. –

0

¿Estás probando en el mismo sistema operativo? Hay algunos cambios en el apagado de la aplicación en Vista. Lea esto: Application Shutdown Changes in Windows Vista

Si está probando en el mismo sistema operativo, tal vez Delphi 2010 maneje los mensajes WM_ENDSESSION de una manera diferente. En Delphi 7, el mensaje WM_ENDSESSION se maneja en Application.WndProc.

+0

Probé los mismos sistemas operativos (XP y Windows 7) – SimaWB

+0

@SimaWB: intente averiguar si existen diferencias en el manejo del mensaje WM_ENDSESSION entre Delphi 5 y 2010 –

1

EDITAR: se ha cambiado para interceptar WM_ENDSESSION en lugar de WM_QUERYENDSESSION.

Como no puede cambiar directamente el comportamiento de TApplication, puede instalar un enganche de mensaje de TApplication que neutralice el mensaje WM_ENDSESSION.

La instalación de un gancho de este tipo es bastante simple, solo tiene que agregar un método similar al siguiente a su forma principal y registrar el gancho en FormCreate.

function TForm25.HookEndSession(var Message: TMessage): Boolean; 
begin 
    result := false; 
    if Message.Msg = WM_ENDSESSION then begin 
    Message.Result := 0; 
    result := true; 
    end; 
end; 

procedure TForm25.FormCreate(Sender: TObject); 
begin 
    Application.HookMainWindow(HookEndSession); 
end; 
+1

El cartel dijo ambos programas impidieron el apagado, por lo que su solución funciona y no se necesita un enlace. Creo que el problema radica en la WM_ENDSESSION que el sistema operativo envía a continuación. –

+0

Al mirar la respuesta de Alexander y el comentario de Remy Lebeau, es en realidad el mensaje WM_ENDSESSION que está causando problemas. –

+0

Tiene razón, la WM_QUERYENDSESSION no llega a TApplication cuando se manejó anteriormente. He actualizado mi respuesta para interceptar WM_ENDSESSION con un gancho. –

0

En todas las versiones, ¿no debería usar el evento FormCloseQuery?

procedure TForm3.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
begin 
    Canclose := Not StillDoingImportantStuff; 
end; 

Vaya - acaba de leer los comentarios de "esto no funciona" :(Es ganar 7 diferentes

En todas mis aplicaciones esto se llama si Windows está tratando de apagar ...

1
?

normalmente corro comando "shutdown -a". Usted puede hacer lo mismo a partir de su código para interrumpir Windows desde la parada.

Saludos

0

ShutdownGuard es construido con Delphi y es de código abierto, puedes descargarlo modificarlo para tus necesidades

+0

Gracias por el enlace Mohammed. Pero usa el mismo método que he escrito anteriormente. Entonces el problema continúa ... – SimaWB

Cuestiones relacionadas