Duvida Pegar o PID do Progress para abrir apenas uma vez

Discussão em 'Progress 4GL' iniciado por ueluis, Junho 11, 2015.

  1. ueluis

    ueluis Membro Participativo

    Galera,

    alguém já precisou implementar uma rotina para abrir um programa progress apenas uma vez?

    Em outras linguagens já utilizei esta lógica:
    pesquiso se existe algum PID com o nome do programa a ser verificado, caso encontrar derruba a aplicação que está subindo e mantém a que está ativa.

    No progress nunca fiz isto, existe algum comando nativo do progress para obter ou consultar o PID de um programa ou tem que ser via prompt mesmo?
  2. rafael.andrade

    rafael.andrade Membro Master Moderador Equipe de Suporte

    Existe algumas DLLs do Windows que podem ser "invocadas" pelo progress retornando um valor...infelizmente estou mesmo sem tempo para pesquisar.

    Porque vc precisa desse tipo de tratativa?

    Abraço

    Rafael
  3. rafael.andrade

    rafael.andrade Membro Master Moderador Equipe de Suporte

    Achei mais rápido do que imaginava:
    http://knowledgebase.progress.com/articles/Article/P6250
    Código:
    DEFINE VARIABLE intProcessHandle AS INTEGER NO-UNDO.
    
    PROCEDURE GetCurrentProcessId EXTERNAL "KERNEL32.DLL":
    DEFINE RETURN PARAMETER intProcessHandle AS LONG.
    END PROCEDURE.
    
    RUN GetCurrentProcessId (OUTPUT intProcessHandle).
    
    MESSAGE "Process ID = " intProcessHandle VIEW-AS ALERT-BOX.
    
    Abraço

    Rafael
  4. rafael.andrade

    rafael.andrade Membro Master Moderador Equipe de Suporte

    Com o código anterior somado ao do link abaixo, obtive uma forma de mostrar o processo progress que existe com PID diferente do que está sendo iniciado
    http://www.oehive.org/node/508

    Código:
    &GLOB PROCESS_QUERY_INFORMATION 1024
    &GLOB PROCESS_VM_READ 16
    &GLOB MAX_PATH 260
    
    PROCEDURE EnumProcesses EXTERNAL "psapi.dll" :
      DEFINE INPUT  PARAMETER lpIdProcess AS LONG.
      DEFINE INPUT  PARAMETER cb          AS LONG.
      DEFINE OUTPUT PARAMETER cbNeeded    AS LONG.
      DEFINE RETURN PARAMETER ReturnValue AS LONG.
    END PROCEDURE.
    
    PROCEDURE EnumProcessModules EXTERNAL "psapi.dll" :
      DEFINE INPUT  PARAMETER hProcess    AS LONG.
      DEFINE INPUT  PARAMETER lphModule   AS LONG.  /* lp to array of module handles */
      DEFINE INPUT  PARAMETER cb          AS LONG.
      DEFINE OUTPUT PARAMETER cbNeeded    AS LONG.
      DEFINE RETURN PARAMETER ReturnValue AS LONG.
    END PROCEDURE.
    
    PROCEDURE GetModuleBaseNameA EXTERNAL "psapi.dll" :
      DEFINE INPUT  PARAMETER hProcess      AS LONG.
      DEFINE INPUT  PARAMETER hModule       AS LONG.
      DEFINE OUTPUT PARAMETER lpBaseName    AS CHARACTER.
      DEFINE INPUT  PARAMETER nSize         AS LONG.
      DEFINE RETURN PARAMETER nReturnedSize AS LONG.
    END PROCEDURE.
    
    PROCEDURE OpenProcess EXTERNAL "kernel32.dll" :
      DEFINE INPUT  PARAMETER dwDesiredAccess AS LONG.
      DEFINE INPUT  PARAMETER bInheritHandle  AS LONG.
      DEFINE INPUT  PARAMETER dwProcessId     AS LONG.
      DEFINE RETURN PARAMETER hProcess        AS LONG.
    END PROCEDURE.
    
    PROCEDURE CloseHandle EXTERNAL "kernel32.dll" :
      DEFINE INPUT  PARAMETER hObject     AS LONG.
      DEFINE RETURN PARAMETER ReturnValue AS LONG.
    END PROCEDURE.
    
    FUNCTION GetProcessName RETURNS CHARACTER (INPUT PID AS INTEGER) :
    
      DEFINE VARIABLE hProcess      AS INTEGER NO-UNDO.
      DEFINE VARIABLE cbNeeded      AS INTEGER NO-UNDO.
      DEFINE VARIABLE lphMod        AS MEMPTR  NO-UNDO.
      DEFINE VARIABLE szProcessName AS CHARACTER    NO-UNDO.
      DEFINE VARIABLE ReturnValue   AS INTEGER NO-UNDO.
    
      /* OpenProcess returns a handle (hProcess),
         needed for querying info about the process */
      RUN OpenProcess ( {&PROCESS_QUERY_INFORMATION} + {&PROCESS_VM_READ},
                        0,
                        PID,
                        OUTPUT hProcess).
    
      /* some system processes can not be queried, 
         like "System" and "System Idle Process" and "csrss.exe".
         ProcessName will be initialized to [unknown] for these processes: */
      szProcessName = "[unknown]" + FILL(" ", {&MAX_PATH}).
      IF hProcess NE 0 THEN DO:
    
         /* EnumProcessModules fills an array of module handles */
         /* The first module handle is a handle to the main module, and that's the 
            only handle you need  */
         SET-SIZE (lphMod) = 4. /* need only one hMod  */
         RUN EnumProcessModules ( hProcess,
                                  GET-POINTER-VALUE(lphMod),
                                  GET-SIZE(lphMod),
                                  OUTPUT cbNeeded,
                                  OUTPUT ReturnValue).
         IF ReturnValue NE 0 THEN DO:
            /* GetModuleBaseNameA returns the name of a module.
               Because this module is the main module, it's also considered to 
               be the name of the process */
            RUN GetModuleBaseNameA (hProcess,
                                    GET-LONG(lphMod,1),
                                    OUTPUT szProcessName,
                                    LENGTH(szProcessName),
                                    OUTPUT ReturnValue).
            /* ReturnValue is the number of returned bytes (chars): */
            szProcessName = SUBSTRING(szProcessName,1,ReturnValue).
            SET-SIZE (lphMod) = 0.
         END.
         RUN CloseHandle ( hProcess, OUTPUT ReturnValue).
      END.
      RETURN TRIM(szProcessName).
    
    END FUNCTION.
    
    /* =============== TEST ================ */
    
    DEFINE VARIABLE lpId          AS MEMPTR  NO-UNDO.
    DEFINE VARIABLE PID           AS INTEGER NO-UNDO.
    DEFINE VARIABLE cbNeeded      AS INTEGER NO-UNDO.
    DEFINE VARIABLE i             AS INTEGER NO-UNDO.
    DEFINE VARIABLE ReturnValue   AS INTEGER NO-UNDO.
    
    
    /* lpID is an array of PID's (Process Identifiers) */
    SET-SIZE(lpId) = 1000. /* assume room for 250 pid's */
    
    /* EnumProcesses fills an array of PID's */
    RUN EnumProcesses (INPUT GET-POINTER-VALUE(lpId),
                       INPUT GET-SIZE(lpID),
                       OUTPUT cbNeeded,
                       OUTPUT ReturnValue).
    
    DEFINE VARIABLE intProcessHandle AS INTEGER NO-UNDO.
    
    PROCEDURE GetCurrentProcessId EXTERNAL "KERNEL32.DLL":
    DEFINE RETURN PARAMETER intProcessHandle AS LONG.
    END PROCEDURE.
    
    RUN GetCurrentProcessId (OUTPUT intProcessHandle).
    
    DO i = 1 TO cbNeeded / 4 :
      PID = GET-LONG(lpID, 4 * (i - 1) + 1).
    
      /* display what you have found (for testing purposes) */
      IF GetProcessName(PID) BEGINS "prowin" AND PID <> intProcessHandle THEN
      MESSAGE 'PID='  PID 
              SKIP
              'Name=' GetProcessName(PID)
               VIEW-AS ALERT-BOX.
    END.
    
    SET-SIZE(lpId) = 0.
    
    Abraço

    Rafael
    ueluis curtiu isso.
  5. rlfritz

    rlfritz Membro Ativo

    Tem uma alternativa mais simples....
    no .pf de inicialização do client Progress, acrescenta isto:
    -wss

    Isso vai limitar o Progress a abrir apenas uma vez o cliente.
    Detalhe: se tiver mais ícones de acesso ao sistema apontando para .pf diferentes, todos devem ter o -wss ... caso contrário pode conseguir abrir dois clients.
  6. bootstrapmaster

    bootstrapmaster Moderator Moderador Equipe de Suporte

    e ainda, se ativar o timeout, ele não permite que vc se log 2 vezes no sistema com o mesmo usuario.

Compartilhe esta Página