Buenos días pupo!
Te comparto esto que alguna vez encontré en la red:
***apagar pc
Parameter tlOptions, tlInteractiveShutdown
* Por defecto - Cierra todas las aplicaciones y reinicia Windows sin preguntar.
* Obtenida de UniversalThread
* Parámetros:
* tlOptions - (0 Cierra sesión windows, 1 Apaga windows, 2 Reinicia windows).
* tlInteractiveShutdown - .T. Muestra el cuadro de diálogo para preguntar si cerramos Windows, .F. (default) No pregunta nada y cierra Windows
* Esta función permite cerrar o reiniciar Windows desde VFP; hace las llamadas necesarias
* a funciones API de Windows para ajustar los privilegios necesarios en las plataformas Windows NT 4.0 o Windows 2000
* si se puede. La función devuelve .F. si no puede hacer los ajustes necesarios para garantizar que el privilegio
* llamado SE_SHUTDOWN_NAME sea establecido. En Windows 9x no es necesario establecer este privilegio.
* Probado en las plataformas WinNT 4.0 SP6, Win2K Pro, Win98 y WinME.
* Probado en VFP 5.0, VFP 6.0 y VFP 7.0 SP1.
*
* Definición de constantes
#DEFINE SE_SHUTDOWN_NAME "SeShutdownPrivilege" && Nombre del privilegio de Windows NT y 2000
#DEFINE SE_PRIVILEGE_ENABLED 2 && Flag para activar privilegios
#DEFINE TOKEN_QUERY 2 && Token para consultar el estado
#DEFINE TOKEN_ADJUST_PRIVILEGE 0x20 && Token para ajustar privilegios
#DEFINE EWX_CLOSE_SESSION 0 && Cerrar Sesión Windows.
#DEFINE EWX_SHUTDOWN 1 && Apagar Windows
#DEFINE EWX_REBOOT 2 && Reiniciar Windows
#DEFINE EWX_FORCE 4 && Forzar el cierre de las aplicaciones ó
&& cierra sesión.
#DEFINE SIZEOFTOKENPRIVILEGE 16
* API de Windows para ejecutar ShutDown - Todas las versiones
DECLARE ExitWindowsEx IN WIN32API INTEGER uFlags, INTEGER dwReserved && API call to shut down Windows
* Comprobamos la versión de Windows para saber si hay que establecer privilegios
IF ('4.0' $ OS() OR '5.0' $ OS() OR 'NT' $ OS())
* APIs necesarias para manipular los permisos de los procesos
* Devuelve el LUID privilegio específico - changes each time Windows restarts
DECLARE SHORT LookupPrivilegeValue IN ADVAPI32 ;
INTEGER lpSystemName, ;
STRING @ lpPrivilegeName, ;
STRING @ pluid
* Obtiene el hToken con los permisos de un proceso
DECLARE SHORT OpenProcessToken IN Win32API ;
INTEGER hProcess, ;
INTEGER dwDesiredAccess, ;
INTEGER @ TokenHandle
* Ajusta otros privilegios de un proceso vía un hToken específico
DECLARE INTEGER AdjustTokenPrivileges IN ADVAPI32 ;
INTEGER hToken, ;
INTEGER bDisableAllPrivileges, ;
STRING @ NewState, ;
INTEGER dwBufferLen, ;
INTEGER PreviousState, ;
INTEGER @ pReturnLength
* Obtiene el Handle de un proceso
DECLARE INTEGER GetCurrentProcess IN WIN32API
LOCAL cLUID, nhToken, cTokenPrivs, nFlag
cLUID = REPL(CHR(0),8) && Identificador Unico Local de 64 bits de un privilegio
IF LookupPrivilegeValue(0, SE_SHUTDOWN_NAME, @cLUID) = 0
RETURN .F. && Privilegio No definido en el proceso
ENDIF
nhToken = 0 && Token de un proceso usado para manipular los privilegios del mismo
IF OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY + TOKEN_ADJUST_PRIVILEGE , @nhToken) = 0
RETURN .F. && El sistema operativo no puede garantizar los privilegios necesarios
ENDIF
* Se crea la estructura TOKEN_PRIVILEGES , los 4 primeros bytes DWORD indican permisos,
* seguidos de un array(arreglo) de 8 bytes con los LUIDs y los últimos 4 bytes son los atributos
* de los permisos.
cTokenPrivs = CHR(1) + REPL(CHR(0),3) + cLUID + CHR(SE_PRIVILEGE_ENABLED) + REPL(CHR(0), 3)
IF AdjustTokenPrivileges(nhToken, 0, @cTokenPrivs, SIZEOFTOKENPRIVILEGE, 0, 0) = 0
RETURN .F. && Privilegio denegado o no permitido
ENDIF
ENDIF
CLOSE ALL && Cierra todas las tablas de VFP
FLUSH && Fuerza la escritura en disco de los Buffers
CLEAR EVENTS && Cancela eventos pendientes
ON SHUTDOWN && Reestablece el proceso SHUTDOWN
* Se comprueban los parámetros pasados
DO CASE
CASE tlOptions = 0
nFlag = IIF(tlInteractiveShutdown, EWX_CLOSE_SESSION + EWX_FORCE, EWX_CLOSE_SESSION)
CASE tlOptions = 1
nFlag = IIF(tlInteractiveShutdown, EWX_SHUTDOWN + EWX_FORCE, EWX_SHUTDOWN)
CASE tlOptions = 2 && Si quieres colocas OTHERWISE
nFlag = IIF(tlInteractiveShutdown, EWX_REBOOT + EWX_FORCE, EWX_REBOOT)
ENDCASE
=ExitWindowsEx(nFlag, 0)
CLEAR DLLS && para quitar de memoria ExitWindowsEx.
QUIT && Sale de VFP
****************
El código anterior es un prg llamado "apagarPC.prg"
Lo tengo implementado en un formulario de respaldo programado y lo llamo con la siguiente línea:
Do apagarPC With 1,.T.
Sería cuestión que condiciones el llamado a la fecha y hora que requieras
Suerte
zarlu
Chetumal, Quintana Roo, México