RpcSetEnv x PREPARE ENVIRONMENT

Há possibilidade de abrir um ambiente de dois modos, por:

  1. Método :: PREPARE ENVIRONMENT EMPRESA "99" FILIAL "01" MODULO "COM"
    1. Função :: RpcSetEnv("99","01",,,"COM")

Pergunto:

  • Qual a diferença entre eles?
    • Como conferir que o ambiente já está inicializado e não a executar
    • Melhor modo para execução desta customização como Rotina Automática?

PS: Gostaria de saber como construir uma função híbrida. Que abra o ambiente não preparado (fora do Remote), e, não seja executada quando ambiente já está preparado (Smartclient em execução com usuário autenticado).

Prefiro RpcSetEnv pelo retorno lógico e facilitar para tratar a falha ao abrir ambiente (gerar LOG).

Denis,

PREPARE ENVIRONMENT e RpcSetEnv são a mesma coisa! :)


Diferença entre eles:

Um você chama a função RpcSetEnv de forma explícita e o outro você utiliza de uma diretiva que após a pré-compilação acaba também se transformando na função RpcSetEnv.


Como posso conferir se o ambiente está aberto:

Não existe uma forma simples de fazer isso, o ambiente pode ter sido aberto sem conectar no banco de dados, sem abrir os dicionários, sem abrir a SM0 etc...

Normalmente são verificados alguns fatores, exemplo:


if Type("cFilAnt") == "C" .and. TCIsConnected()
     ConOut("Ambiente Protheus aberto e pronto para uso")
else
     RpcSetEnv("99", "01") //Abro o ambiente, pois o mesmo não encontrava-se aberto
endif

Esse exemplo está bem simples, verificando apenas se a variável pública cFilAnt existe (legado) e se você tem uma conexão com o banco de dados, fica a seu critério criar mais verificações, mudar etc.

Obs.: Cuidado com a variável cFilAnt, ela é uma variável pública, logo "imortal" (Highlander), com isso, mesmo que o ambiente Protheus seja encerrado, as tabelas fechadas e a conexão com o banco de dados encerrada, a variável cFilAnt continua a existir, por isso verifiquei a conexão com o banco além da sua existência.


Então imagina que você tem uma rotina de menu que também é executada via job, quando uma rotina é chamada no menu o ambiente SEMPRE está aberto, além disso você tem uma interface, podemos então fazer algo assim:


if GetRemoteType() == -1
    //Não tenho interface
    if Type("cFilAnt") == "C" .and. TCIsConnected()
         ConOut("Ambiente Protheus aberto e pronto para uso")
    else
         RpcSetEnv("99", "01") //Abro o ambiente, pois o mesmo não encontrava-se aberto
    endif
else
    //Tenho interface
    //Se for uma rotina de menu, sempre terá ambiente aberto, então aqui, não deveríamos ter qualquer complicação ou verificação de ambiente
endif

Caso queira fechar o ambiente após ter aberto, utilize da função RpcClearEnv, mas nunca feche o ambiente caso não tenha sido você o responsável por abrir, isso com certeza vai gerar inconsistências e/ou exceções.

  • Ambiente inicializado: verificava se as variáveis cFilAnt e cEmpAnt não eram indefinidas com isso considerava inicializado;
  • Modo JOB: Para detectar verificava se variável lMsHelpAuto estava definida e a função IsBlind() == .F..

SOLUÇÃO: Mas, com GetRemoteType() e TCIsConnected() fica mais simples, claro e já compreensível o código.

Muito bom! Muito obrigado!

Incrível, estava precisando muito disto para melhorar meus fontes que são executados via schedule, job e menu. Eu fiz usando !IsBlind() .or. !__lSchedule.