Página 1 de 4

Executar programa sem janela (invisível)

Enviado: 25 Ago 2012 01:55
por cjp
Pessoal, alguém saberia me dizer se existe algum jeito de executar um programa compilado no xHarbour sem abrir uma janela, de modo que ele fique invisível?

Eu queria rodar algumas funções simples, que não dependem da intervenção do usuário, e daí o ideal é que ele não abrisse nenhuma janela, ficasse invisível. Assim, não atrapalha o usuário em nada, e também não corre o risco de o usuário fechar o programa indevidamente.

É possível?

Executar programa sem janela (invisível)

Enviado: 25 Ago 2012 10:39
por Toledo
Usando o sistema de busca do fórum, encontrei:

https://pctoledo.org/forum/viewto ... =4&t=12185

Abraços,

Executar programa sem janela (invisível)

Enviado: 28 Ago 2012 00:49
por cjp
Verdade, meu caro. Lembrei agora que eu já havia tentado fazer isso antes.

Entretanto, não consegui ajuda para chegar ao objetivo. Será que vc poderia me ajudar?

Eu uso o xharbour, compilando com o xbuild. Não sei usar a Hwgui, e acho que nem a tenho instalada. Entretanto, estou disposto a aprender, até porque, segundo já me falaram neste fórum, ela é muito útil. Só que eu precisaria de ajuda para aprender a usar.

Agradeço qualquer ajuda.

Inacio

Executar programa sem janela (invisível)

Enviado: 28 Ago 2012 19:59
por JoséQuintas
de um jeito tradicional....
start /min seuexe.exe

de outro jeito:
o que cuida da tela é o driver de GT.
GTNUL é sem tela.
Só não sei como vai interromper porque fica sem acesso.

de outro jeito:
uma janela minúscula 1 linha x 5 colunas.
SetMode(1,5)

Executar programa sem janela (invisível)

Enviado: 28 Ago 2012 23:57
por cjp
Meu caro,

Das 3 formas que vc citou, me interessou mais a segunda. Não haverá necessidade de interromper, pois a função roda linearmente por alguns segundos apenas e já se encerra.

Mas eu não sei o que seria esse drive GT. Onde o acho? Como usá-lo?

Por favor, me ajude com isto.

Executar programa sem janela (invisível)

Enviado: 29 Ago 2012 10:18
por JoséQuintas
o que chamei de driver são as GTs do Harbour, que vulgarmente chamam de LIBs gráficas.
Tem a gtwin, gtwvt, gtwvg, hbgui, minigui.... e tem a gtnul que é sem tela.
hbmk2 programa -gtnul.

Outra opção também, se for rodar com o programa aberto, é usar o multithread.

Executar programa sem janela (invisível)

Enviado: 29 Ago 2012 18:04
por cjp
Meu amigo, desculpe, mas eu sou leigo no assunto, vou precisar de sua ajuda mais específica. Não sei o que são essas GTs do Harbour. Já ouvi falar de lib gráfica, mas nunca usei, nem sei usar. Será que vc pode me ajudar neste aspecto?

Eu compilo usando o xbuild. Não sei usar o hbmk2. Será que é a mesma coisa? Seria xbuild programa - gtnul? Testei agora fazer assim, até compilou, mas a tela continua aparecendo, provavelmente porque eu precisaria compilar com essas libs gráficas, né?

Tentei incluir a lib gtwin.lib, que achei na pasta LIB do Xharbour. Compilou, mas ainda assim está aparecendo a tela quando executo o programa. Precisaria saber o que fazer para não aparecer, por favor.

O que seria o multithread? Como assim "rodar com o programa aberto"?

Executar programa sem janela (invisível)

Enviado: 29 Ago 2012 20:24
por JoséQuintas
Confundi. O que falei das LIBs gráficas são no Harbour. - gtnul
e no hbmk2 é só indicar.
Vai no mais simples, define uma janela miniatura 5 x 2.

Executar programa sem janela (invisível)

Enviado: 30 Ago 2012 00:31
por cjp
O problema da janela pequena é que, ainda assim, o usuário poderá fechá-la. Eu preciso de uma forma que impeça ao usuário de fechar a janela. O ideal é que ela fique realmente invisível.

Se essa lib gtwin funcionou com o xbuild, será que ela não resolveria o meu problema?

Executar programa sem janela (invisível)

Enviado: 30 Ago 2012 10:10
por JoséQuintas
Após ler muitos "mude pro xharbour"... aqui caberia um "mude pro harbour...".... rs

Pra impedir o usuário fechar janela, só não deixar fechar janela.
Não sei se o xharbour tem esta opção:
#include "hbgtinfo.ch"
hb_GtInfo( HB_GTI_CLOSABLE, .f. )

Executar programa sem janela (invisível)

Enviado: 30 Ago 2012 23:50
por cjp
Vc acha que o harbour é melhor que o xharbour? Eu sempre ouvi falar o contrário!!!

Essa opção que vc mencionou seria pra desabilitar o X da janela? Eu tenho isso no xharbour, mas ainda assim o usuário ainda pode fechar de outras maneiras (até com ctrl-alt-del).

Mas também tem um outro problema: o só fato de a janela aparecer na frente da que o usuário está usando (e até na frente do próprio programa) também atrapalha um pouco.

Por favor, dê-me a dica para eu realmente ocultar a janela.

Executar programa sem janela (invisível)

Enviado: 31 Ago 2012 00:55
por alxsts
Olá!

O processamento que o colega cjp precisa fazer seria melhor executado como um serviço do Windows. Aí ficaria independente de usuários. Nem precisaria ter alguém logado.

Verifique se o exemplo (para xHarbour) que existe neste link funciona.

No link citado tem também uma outra alternativa: um programa da Microsoft chamado SrvAny.exe que executa um executável como um serviço. Pelo menos no meu Win 7 64 não achei este programa. Mas deve ter fácil na net.

Antes que o código do exemplo suma da internet, vou postá-lo abaixo:

Código: Selecionar todos

10-31-2008 06:52 PM #8
 Re: Windows service.
On 31 Ott, 09:32, Salvino <salvino.po...@gmail.com> wrote:

Giuseppe Mastrangelo ha scritto:

> How create with xharbour an EXE as windows service.

> That can be install with /INSTALL parameter in windows services.

> Regards Giuseppe.

Try the code that I send in attachment.
In service.ch you must define the informations that will appear in
Windows Services applet.
The entry point of your application becomes the ExecuteService() that
you can put in a separate prg file.
Warning *not* work with the multi threading model.

Sorry, but I can not send the zipped archive

**********************service.ch**********************
#define SZSERVICENAME "FirstxHarbourService"
#define SZVERSION "1.0"
#define SZSERVICEDISPLAYNAME "My first xHarbour Service"
#define SZAPPNAME "service"
#define SZDEPENDENCIES ""

*******Service.prg**************

// A skeleton for writing a NT service for xHarbour compiler
// Author : Salvino Porto
// EMail  : salvino.po...@gmail.com
// This file is derived from service.c by Craig Link - Microsoft Developer Support

//  FUNCTION: Main
//
//  PURPOSE: entrypoint for service
//
//  PARAMETERS:
//    cParameter - command line argument
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:

Function Main(cParameter)

   if cParameter == NIL
     cParameter:=""
   end
   if left(cParameter,1) != "-"
     cParameter:=""
   else
     cParameter:=Upper(Substr(cParameter,2))
   endif
   Do Case
     Case cParameter == "INSTALL"
       CmdInstallService()
     Case cParameter== "REMOVE"
       CmdRemoveService()
     Case cParameter == "HELP"
       CmdHelp()
     Case cParameter == "VERSION"
       CmdVersion()
     OtherWise
       ServiceDispatch()
   End Case

Return NIL

//  FUNCTION: ExecuteService()
//
//  PURPOSE: The main function of service action
//
//  PARAMETERS:
//    none
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:

Function ExecuteService()
   do while IsServiceRunning()
     Tone( 800, 1 )
     SecondsSleep( 4 )
   enddo
Return NIL

#pragma BEGINDUMP

#include <windows.h>
#include <tchar.h>
#include <hbapi.h>
#include <hbvm.h>

#include "service.ch"

// internal variables
SERVICE_STATUS          ssStatus;       // current statusof the service
SERVICE_STATUS_HANDLE   sshStatusHandle;
DWORD                   dwErr = 0;
TCHAR                   szErr[256];

HANDLE  hServerStopEvent = NULL;
static PHB_DYNS s_pDynExecuteService;

// internal function prototypes
VOID WINAPI service_ctrl(DWORD dwCtrlCode);
VOID WINAPI service_main(void);
void ServiceStop(void);
void ServiceStart(void);
void ServiceExecutionThread(void);
BOOL ReportStatusToSCMgr(DWORD , DWORD , DWORD );
VOID AddToMessageLog(LPTSTR);
LPTSTR GetLastErrorText( LPTSTR , DWORD );

//  FUNCTION: IsServiceRunning
//
//  PURPOSE: Notify to xHarbour code if service is running
//
//  PARAMETERS:
//    none
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:
HB_FUNC ( ISSERVICERUNNING )
{
   hb_retl(ssStatus.dwCurrentState == SERVICE_RUNNING);

}

//  FUNCTION: ServiceDispatch
//
//  PURPOSE: entrypoint for C code
//
//  PARAMETERS:
//    none
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:
HB_FUNC_STATIC ( SERVICEDISPATCH )
{

     SERVICE_TABLE_ENTRY dispatchTable[] =
     {
         { TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main },
         { NULL, NULL }
     };
     if (!StartServiceCtrlDispatcher(dispatchTable))
         AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed."));

}

//  FUNCTION: service_main
//
//  PURPOSE: To perform actual initialization of the service
//
//  PARAMETERS:
//    dwArgc   - number of command line arguments
//    lpszArgv - array of command line arguments
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:
//    This routine performs the service initialization and then calls
//    the user defined ServiceStart() routine to perform majority
//    of the work.

void WINAPI service_main(void)
{
     // register our service control handler:
     sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME),
service_ctrl);

     if (!sshStatusHandle)
       return;

     // SERVICE_STATUS members that don't change in example
     ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
     ssStatus.dwServiceSpecificExitCode = 0;

     // report the status to the service control manager.
     if (ReportStatusToSCMgr(
         (DWORD)SERVICE_START_PENDING, // service state
         NO_ERROR,              // exit code
         (DWORD)3000))                 // wait hint

       // Start up the service
         ServiceStart();

     // try to report the stopped status to the service control manager.
     if (sshStatusHandle)
         ReportStatusToSCMgr((DWORD)SERVICE_STOPPED, dwErr, (DWORD)0);

     return;

}  // service_main

//  FUNCTION: service_ctrl
//
//  PURPOSE: This function is called by the SCM whenever
//           ControlService() is called on this service.
//
//  PARAMETERS:
//    dwCtrlCode - type of control requested
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:

VOID WINAPI service_ctrl(DWORD dwCtrlCode)
{
     // Handle the requested control code.
     switch(dwCtrlCode)
     {
         // Stop the service.
         case SERVICE_CONTROL_STOP:
             ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
             ServiceStop();
             break;

         // Update the service status.
         case SERVICE_CONTROL_INTERROGATE:
             break;

         // invalid control code
         default:
             break;
     }
     ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, (DWORD)0);

}  // service_ctrl

//  FUNCTION: ServiceStart
//
//  PURPOSE: Actual code of the service that does the work.
//
//  PARAMETERS:
//    dwArgc   - number of command line arguments
//    lpszArgv - array of command line arguments
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:
//    The service stops when hServerStopEvent is signalled
void ServiceStart (void)
{
    DWORD idThread;

    // Service initialization

    // report the status to the service control manager.
    if (!ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 3000))
        return;

    // create the event object. The control handler function signals
    // this event when it receives the "stop" control code.
    if((hServerStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
        return;

    // report the status to the service control manager.
    if (!ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 3000))
        goto cleanup;

    // report the status to the service control manager.
    if (!ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 3000))
        goto cleanup;

    // create the working thread
    if ( CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)ServiceExecutionThread, 0, 0, &idThread)==NULL)
        goto cleanup;
    // report the status to the service control manager.
    if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 3000))
        goto cleanup;

    // End of initialization

    _tprintf(TEXT("Init %s ok.\n"), TEXT(SZSERVICEDISPLAYNAME));

    // Service is now running, perform work until shutdown
    WaitForSingleObject(hServerStopEvent,INFINITE);
    CloseHandle(hServerStopEvent);

  cleanup:

    if (hServerStopEvent)
        CloseHandle(hServerStopEvent);

}

//
//  FUNCTION: ServiceStop
//
//  PURPOSE: Stops the service
//
//  PARAMETERS:
//    none
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:
//    If a ServiceStop procedure is going to
//    take longer than 3 seconds to execute,
//    it should spawn a thread to execute the
//    stop code, and return.  Otherwise, the
//    ServiceControlManager will believe that
//    the service has stopped responding.
//
void ServiceStop()
{
    if ( hServerStopEvent )
        SetEvent(hServerStopEvent);

}

//  FUNCTION: ServiceExecutionThread
//
//  PURPOSE: Invoke the xHarbour ExecuteService procedure
//
//  PARAMETERS:
//    none
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:

void ServiceExecutionThread(void)
{
   s_pDynExecuteService = hb_dynsymGet( "ExecuteService" );

      if( s_pDynExecuteService != NULL )
      {
         hb_vmPushSymbol( s_pDynExecuteService->pSymbol );
         hb_vmPushNil();
         hb_vmDo( 0 );
      }
   return;

}

//  FUNCTION: ReportStatusToSCMgr()
//
//  PURPOSE: Sets the current status of the service and
//           reports it to the Service Control Manager
//
//  PARAMETERS:
//    dwCurrentState - the state of the service
//    dwWin32ExitCode - error code to report
//    dwWaitHint - worst case estimate to next checkpoint
//
//  RETURN VALUE:
//    TRUE  - success
//    FALSE - failure
//
//  COMMENTS:

BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
                          DWORD dwWin32ExitCode,
                          DWORD dwWaitHint)
{
     static DWORD dwCheckPoint = 1;
     BOOL fResult;

     if (dwCurrentState == SERVICE_START_PENDING)
         ssStatus.dwControlsAccepted = 0;
     else
         ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

     ssStatus.dwCurrentState = dwCurrentState;
     ssStatus.dwWin32ExitCode = dwWin32ExitCode;
     ssStatus.dwWaitHint = dwWaitHint;

     if ( ( dwCurrentState == SERVICE_RUNNING ) ||
          ( dwCurrentState == SERVICE_STOPPED ) )
         ssStatus.dwCheckPoint = 0;
     else
         ssStatus.dwCheckPoint = dwCheckPoint++;

     // Report the status of the service to the service control manager.
     //
     fResult = SetServiceStatus( sshStatusHandle, &ssStatus);
     if (!fResult)
       AddToMessageLog(TEXT("SetServiceStatus"));

     return fResult;

}  // ReportStatusToSCMg

//  FUNCTION: AddToMessageLog(LPTSTR lpszMsg)
//
//  PURPOSE: Allows any thread to log an error message
//
//  PARAMETERS:
//    lpszMsg - text for message
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:

VOID AddToMessageLog(LPTSTR lpszMsg)
{
     TCHAR   szMsg[256];
     HANDLE  hEventSource;
     LPTSTR  lpszStrings[2];

     dwErr = GetLastError();

Executar programa sem janela (invisível)

Enviado: 03 Set 2012 18:24
por cjp
Meu caro, eu fiz como vc disse, usando o exemplo do link que vc passou. Aparentemente deu certo, ele diz que o serviço está instalado, e realmente não aparece qualquer janela. Inclusive, se tento instalar de novo, ele diz que já está instalado. Abrindo o gerenciador de tarefas do Windows, vejo-o na lista de serviços ativos.

Mas, aparentemente, ele também não executa a função que está no programa. Não sei se entendi bem o conceito de executar o programa como serviço, mas fiz vários testes, e em nenhum deles funcionou. Minha função é simples: ela deveria fazer algumas alterações em algumas bases de dados, enviar um e-mail (usando o sendmail) e logo fecha. Leva só alguns segundos, no máximo uns 2 minutos rodando. Mas nada disso está sendo feito. Ele simplesmente não roda nada do que está na função.

Será que estou fazendo algo errado?

Executar programa sem janela (invisível)

Enviado: 04 Set 2012 11:46
por alxsts
Olá!
cjp escreveu:...fiz vários testes, e em nenhum deles funcionou...
Não sabemos quais testes você fez. Como estou sem ambiente [x]Harbour em minha máquina, não poderei testar.

Fiz algumas alterações no código. Por favor, substitua no teu código as duas funções que seguem alteradas abaixo e informe os resultados. Caso não funcione, poste o teu código.

Nunca usei essa técnica também. Talvez outro colega possa ajudar a encontrar a solução. Creio que o caminho a seguir para a tua necessidade seja este.

Código: Selecionar todos

// A skeleton for writing a NT service for xHarbour compiler
// Author : Salvino Porto
// EMail : salvino.po...@gmail.com
// This file is derived from service.c by Craig Link - Microsoft Developer Support

// FUNCTION: Main
//
// PURPOSE: entrypoint for service
//
// PARAMETERS:
//  cParameter - command line argument
//
// RETURN VALUE:
//  none
//
// COMMENTS:

Function Main(cParameter)

   if cParameter == NIL
    cParameter:=""
   end

   if left(cParameter,1) != "-"
    cParameter:=""
   else
    cParameter:=Upper(Substr(cParameter,2))
   endif
   
   Do Case
    Case cParameter == "INSTALL"
     CmdInstallService()
    Case cParameter== "REMOVE"
     CmdRemoveService()
    Case cParameter == "HELP"
     CmdHelp()
    Case cParameter == "VERSION"
     CmdVersion()
    OtherWise
     ServiceDispatch()
   End Case

   ExecuteService()
   
   // parar o serviço em algum ponto
   
   Return NIL

//--------------------------------------------------------------------------------------------------

// FUNCTION: ExecuteService()
//
// PURPOSE: The main function of service action
//
// PARAMETERS:
//  none
//
// RETURN VALUE:
//  none
//
// COMMENTS:

#include "fileio.ch"

Function ExecuteService()

 LOCAL nHandle, cString, nTimes := 0
 
 do while IsServiceRunning() .And. nTimes <= 5
    cString := Dtos(Date()) + '-' Time()
    //
    nHandle := FOPEN( StrTran( cString, ":","" ) + ".Txt", FO_READWRITE + FO_SHARED )
    
    IF FERROR() == 0
       FWrite( nHandle, "Data e hora atual do sistema: " + cString )
       FClose( nHandle )
       nTimes++
    ENDIF
  
    SecondsSleep( 60 )  // Aguarda um minuto e volta
 enddo
 
Return NIL

//--------------------------------------------------------------------------------------------------

Executar programa sem janela (invisível)

Enviado: 04 Set 2012 18:41
por cjp
Eu estava usando a função que peguei do link que vc passou, que estava compilando e até executando normalmente (abria o serviço, mas não executava a minha função), como te escrevi antes.

Entretanto, ao tentar substituir pela função que vc postou aqui, ela não compila. Dá os seguintes erros:

Error E2206 tar2p.prg 125: Illegal character '#' (0x23)
Error E2141 tar2p.prg 125: Declaration syntax error
Error E2451 tar2p.prg 159: Undefined symbol 'ssStatus' in function HB_FUN_ISSERVICERUNNING
Error E2451 tar2p.prg 179: Undefined symbol 'SZSERVICENAME' in function HB_FUN_SERVICEDISPATCH
Error E2141 tar2p.prg 179: Declaration syntax error in function HB_FUN_SERVICEDISPATCH
Error E2139 tar2p.prg 179: Declaration missing ; in function HB_FUN_SERVICEDISPATCH
Warning W8004 tar2p.prg 179: 'dispatchTable' is assigned a value that is never used in function HB_FUN_SERVICEDISPATCH
Error E2190 tar2p.prg 179: Unexpected }
Error E2040 tar2p.prg 179: Declaration terminated incorrectly
Error E2190 tar2p.prg 181: Unexpected }
Error E2190 tar2p.prg 181: Unexpected }
Error E2040 tar2p.prg 182: Declaration terminated incorrectly
Error E2190 tar2p.prg 185: Unexpected }
Error E2451 tar2p.prg 206: Undefined symbol 'SZSERVICENAME' in function service_main
Error E2451 tar2p.prg 213: Undefined symbol 'ssStatus' in function service_main
Error E2451 tar2p.prg 253: Undefined symbol 'ssStatus' in function service_ctrl
Error E2451 tar2p.prg 315: Undefined symbol 'SZSERVICEDISPLAYNAME' in function ServiceStart
Error E2451 tar2p.prg 404: Undefined symbol 'ssStatus' in function ReportStatusToSCMgr
Warning W8004 tar2p.prg 426: 'dwCheckPoint' is assigned a value that is never used in function ReportStatusToSCMgr
Warning W8057 tar2p.prg 426: Parameter 'dwWin32ExitCode' is never used in function ReportStatusToSCMgr
Warning W8057 tar2p.prg 426: Parameter 'dwWaitHint' is never used in function ReportStatusToSCMgr
Error E2451 tar2p.prg 453: Undefined symbol 'function' in function AddToMessageLog
Error E2379 tar2p.prg 453: Statement missing ; in function AddToMessageLog
Error E2206 tar2p.prg 478: Illegal character '@' (0x40) in function AddToMessageLog
Error E2206 tar2p.prg 505: Illegal character '@' (0x40) in function AddToMessageLog
Error E2206 tar2p.prg 506: Illegal character '@' (0x40) in function AddToMessageLog
Error E2206 tar2p.prg 507: Illegal character '@' (0x40) in function AddToMessageLog
Error E2206 tar2p.prg 508: Illegal character '@' (0x40) in function AddToMessageLog
Error E2206 tar2p.prg 509: Illegal character '@' (0x40) in function AddToMessageLog
Error E2228 tar2p.prg 509: Too many error or warning messages in function AddToMessageLog
*** 26 errors in Compile ***
Type: C >>>Couldn't build: tar2p.obj<<<


Quando combino apenas a última parte que vc mandou com a função que baixei do link que vc tinha postado, ela compila normalmente, mas continua não executando as minhas funções.

Minha função está assim:

Código: Selecionar todos

**********************service.ch**********************
#define SZSERVICENAME "FirstxHarbourService"
#define SZVERSION "1.0"
#define SZSERVICEDISPLAYNAME "My first xHarbour Service"
#define SZAPPNAME "service"
#define SZDEPENDENCIES ""

Código: Selecionar todos

*******Service.prg**************
Function Main(cParameter)

 if cParameter == NIL
  cParameter:=""
 end

 if left(cParameter,1) != "-"
  cParameter:=""
 else
  cParameter:=Upper(Substr(cParameter,2))
 endif
 
 Do Case
  Case cParameter == "INSTALL"
  CmdInstallService()
  Case cParameter== "REMOVE"
  CmdRemoveService()
  Case cParameter == "HELP"
  CmdHelp()
  Case cParameter == "VERSION"
  CmdVersion()
  OtherWise
  ServiceDispatch()
 End Case

 ExecuteService()
 
 // parar o serviço em algum ponto
 
 Return NIL

#include "fileio.ch"

Function ExecuteService()

 LOCAL nHandle, cString, nTimes := 0
 
 do while IsServiceRunning() .And. nTimes <= 5
  cString := Dtos(Date()) + '-' + Time()
  //
  nHandle := FOPEN( StrTran( cString, ":","" ) + ".Txt", FO_READWRITE + FO_SHARED )
  

tar2p() //Esta é a minha função


  IF FERROR() == 0
   FWrite( nHandle, "Data e hora atual do sistema: " + cString )
   FClose( nHandle )
   nTimes++
  ENDIF
 
  SecondsSleep( 60 ) // Aguarda um minuto e volta
 enddo
 
Return NIL
//--------------------------------------------------------------------------------------------------


#pragma BEGINDUMP

...


function tar2p		 

...
//Aqui eu fiz vários testes, criando arquivos, testando com o tone, mandando e-mails etc; nada roda