sábado, dezembro 16, 2006

PowerBuilder - Documentando o código fonte

Recentemente, fui questionado por várias pessoas sobre a necessidade de se documentar o seu código fonte.

Por isso, resolvi publicar dois sites que possuí ferramentas com este objetivo.

http://www.pbdr.com/
http://www.novalys.net/

quarta-feira, dezembro 13, 2006

PowerBuilder - Utilizando FTP

Abaixo vai um código interessante para lista arquivos e diretório no FTP utilizanod a dll do Windows WINInet.dll.

/***Declaração de Estrutura
type win32_find_dataa from structure
unsignedlong dwfileattributes
filetime ftcreationtime
filetime ftlastaccesstime
filetime ftlastwritetime
unsignedlong nfilesizehigh
unsignedlong nfilesizelow
unsignedlong dwreserved0
unsignedlong dwreserved1
character cfilename[260]
character calternatefilename[14]
end type


/*** Declaração de Funções externas
function long InternetOpenA(string lpszAgent, long dwAccessType, string lpszProxyName, string lpszProxyBypass, long dwFlags )&
library "wininet.dll"
function long InternetConnectA(long hInternet, string lpszServerName, int nServerPort, string lpszUsername, &
string lpszPassword, long dwService, long dwFlags, long dwContext) library "wininet.dll"
Function Boolean FtpSetCurrentDirectoryA (long hFtpSession, string lpszDirectory) library "wininet.dll"
Function boolean FtpCreateDirectoryA(Long hConnect, string lpszDirectory) library 'wininet.dll';
Function boolean FtpPutFileA(long hConnect, string lpszLocalFile, string lpszNewRemoteFile, long dwFlags, &
long dwContext) library "wininet.dll"
Function boolean FtpGetFileA(long hConnect, string lpszRemoteFile, string lpszNewFile, boolean fFailIfExists, &
long dwFlagsAndAttributes, long dwFlags, long dwContext) library 'wininet.dll'
Function boolean FtpRenameFileA(Long hConnect, string lpszExisting, string lpszNew) library 'wininet.dll';
Function boolean FtpDeleteFileA(Long hConnect, string lpszFileName) library 'wininet.dll';
Function long InternetCloseHandle(long hInet) library "wininet.dll"
Function long FtpFindFirstFileA (Long hFtpSession , string lpszSearchFile, ref WIN32_FIND_DATAA lpFindFileData , long dwFlags, long dwContent) library "wininet.dll"
Function boolean InternetFindNextFileA (Long hFind, ref WIN32_FIND_DATAA lpvFindData) library "wininet.dll"

/*** Variáveis de instáncia
Constant Public long INTERNET_DEFAULT_FTP_PORT = 21, &
INTERNET_SERVICE_FTP = 1, &
FTP_TRANSFER_TYPE_ASCII = 1, &
FTP_TRANSFER_TYPE_BINARY = 2

Public ProtectedWrite long uol_Hnd_open, uol_Hnd_Conexao
Public ProtectedWrite string uos_servidor, uos_dir_atual, uos_usuario, uos_aplicacao, uos_ftp_dir
Private string uos_senha

/**** Função para conectar no FTP
public function long of_conecta_ftp (string p_aplicacao, string p_servername, string p_usuario, string p_senha);
/*----------------------------------------------------------------------------------*/
/* FAZ A CONEXÃO COM O SERVIDOR PARA TRANSFERÊNCIA VIA FTP */
/* PARÂMETROS: p_aplicacao: Nome da aplicação
p_servername: 'ftp.zzzzz.com.br' ou endereço IP Ex.: '255.255.255.255'
p_usuario e p_senha*/

string vlsnulo

setnull(vlsnulo)
uos_servidor = p_servername
uos_usuario= p_usuario
uos_senha = p_senha
uos_aplicacao = p_aplicacao
uos_ftp_dir = ''

uol_hnd_open = internetopena(uos_aplicacao , 1, vlsnulo, vlsnulo, 0)
if uol_hnd_open = 0 or isnull(uol_hnd_open) then
vismsg = 'Erro ao abrir a conexão. Função API InternetOpen'
return - 1
end if

uol_hnd_conexao= internetconnecta( uol_hnd_open, uos_servidor, &
0,uos_usuario, uos_senha, 1, 0, 0)

if uol_hnd_conexao= 0 or isnull(uol_hnd_conexao) then
vismsg= 'Erro ao abrir a conexão. Função API InternetConnect'
internetclosehandle( uol_hnd_open)
return - 1
end if

return 1
end function


/**** Função para desconectar do FTP
public function long of_desconecta_ftp ();
internetclosehandle( uol_hnd_conexao)
internetclosehandle( uol_hnd_open )

uos_usuario = ''
uos_senha = ''
uos_servidor = ''
uos_aplicacao = ''
uos_dir_atual = ''
uol_hnd_conexao = 0
uol_hnd_open = 0
return 1
end function


/**** Troca o diretório do FTP
public function long of_ftp_set_dir (string p_dir);
if not FtpSetCurrentDirectoryA ( uol_hnd_conexao , p_dir ) then
vismsg = 'Não foi possível encontrar a pasta ' + p_dir + '!'
return -1
end if

//Altera a propriedade uos_ftp_dir (Pasta corrente)
long vll_pos
if p_dir = '\' then
uos_ftp_dir = ''
elseif p_dir = '..' and uos_ftp_dir <> '' then
do while pos(uos_ftp_dir, '\', vll_pos + 1) > 0
vll_pos = pos(uos_ftp_dir, '\', vll_pos + 1)
loop
if vll_pos > 0 then
uos_ftp_dir = left(uos_ftp_dir , vll_pos - 1)
else
uos_ftp_dir = ''
end if
else
uos_ftp_dir += '\' + p_dir
end if
////////////////////
return 1
end function

/**** Renomeia arquivo no FTP
public function long of_ftp_renamefile (string p_nome_ant, string p_nome_atu);
if not FtpRenameFileA(uol_hnd_conexao, p_nome_ant, p_nome_atu) then
vismsg = 'Não foi possível renomear o arquivo ' + uos_ftp_dir + '\'+ p_nome_ant + ' para ' + uos_ftp_dir + &
'\'+ p_nome_atu + '!'
return -1
end if

return 1
end function

/**** Envia arquivo para o FTP
public function long of_ftp_putfile (string p_arquivo_local, string p_arquivo_ftp);
if not ftpputfilea( uol_hnd_conexao, p_arquivo_local, p_arquivo_ftp, ftp_transfer_type_ascii, 0) then
vismsg = 'Erro ao transferir arquivo ' + p_arquivo_local + ' via FTP!'
return -1
end if

return 1
end function

/**** Baixa arquivo do FTP
public function long of_ftp_getfile (string p_remoto, string p_local);
if not FtpGetFileA(uol_hnd_conexao, p_remoto , p_local, false, 0, 1, 0) then
vismsg = 'Não foi possível fazer o download do arquivo '+ uos_ftp_dir + '\'+ p_remoto +' via FTP!'
return -1
end if

return 1
end function

/**** Deleta arquivo do FTP
public function long of_ftp_deletefile (string p_arquivo);if not FTPDeleteFileA(uol_hnd_conexao, p_arquivo) then
vismsg = 'Não foi possível excluir o arquivo ' + uos_ftp_dir + '\'+ p_arquivo + '!'
return -1
end if

return 1
end function


/**** Cria Diretório no FTP
public function long of_ftp_cria_dir (string p_dir);if not this.ftpcreatedirectorya( uol_hnd_conexao , p_dir ) then
vismsg = 'Não foi criar a pasta ' + p_dir + '!'
return -1
end if

return 1
end function


/**** Lista arquivo e diretórios do FTP
public function integer of_ftp_lista_arquivos (string p_filter, ref string p_arquivos[]);
// DESCRIÇÃO:
// * Lista os arquivos existentes no FTP
//
// ARGUMENTOS DE ENTRADA:
// * sfilter : Filtro utilizado para diretórios
// * p_arquivos : Lista de arquivos retornados
//
// RETORNO:
// * 1 : Sucesso
// * -1 : Erro
// * 0 : Registro não encontrado
//
// OBSERVAÇÃO:
// * Lista dos atributos retornados para arquivos
// Public Const FILE_ATTRIBUTE_READONLY = &H1
// Public Const FILE_ATTRIBUTE_HIDDEN = &H2
// Public Const FILE_ATTRIBUTE_SYSTEM = &H4
// Public Const FILE_ATTRIBUTE_DIRECTORY = &H10
// Public Const FILE_ATTRIBUTE_ARCHIVE = &H20
// Public Const FILE_ATTRIBUTE_NORMAL = &H80
// Public Const FILE_ATTRIBUTE_TEMPORARY = &H100
// Public Const FILE_ATTRIBUTE_COMPRESSED = &H800
// Public Const FILE_ATTRIBUTE_OFFLINE = &H1000
//
// CRIADO POR :
// 12/12/2006 - Thiago Campos Pereira
// ALTERADO POR :
//
//========================================================================

long VLLhandleFind, VLLRet, VLLItem
string vlsAux
WIN32_FIND_DATAA VLstrData

//Procura primeiro arquivo no FTP
VLLhandleFind = FtpFindFirstFileA(uol_hnd_conexao, p_Filter, VLstrData, 0, 0)

//Se não encontrar arquivos, sai da função
If VLLhandleFind = 0 then return 1

//Se encontrou arquivo, realizar loop preenchendo vetor com diretórios
do
//Verificar se é arquivo e se não é diretorno
if mod(VLstrData.dwfileattributes , 128) = 0 then
//Se for diretório, armazena nome do diretório
vlsAux = ''
for VLLItem = 1 to upperbound(VLstrData.cfilename)
//No momento que encontrar o caracter 0, quer dizer que é o final do nome do diretório
if asc(VLstrData.cfilename[VLLItem]) = 0 then
p_arquivos[upperbound(p_arquivos) + 1] = vlsAux
exit
else
vlsAux = vlsAux + VLstrData.cfilename[VLLItem]
end if
next
end if

//Procura próximo diretório
if not InternetFindNextFileA(VLLhandleFind, VLstrData) then
VLLhandleFind = 0
end if
loop while VLLhandleFind > 0

return 1
end function

segunda-feira, dezembro 11, 2006

PowerBuilder - Listando Arquivos de um diretório

Constantemente eu vejo desenvolvedores que necessitam listar os arquivos em um diretório especifico.Normalmente, adicionam uma ListBox a uma window e chamam o método DIRLIST para preencher a ListBox com os arquivos.O grande problema é quando não possuímos uma janela no nosso programa. Muitas vezes, o desenvolvedor adiciona uma janela apenas para conseguir utilizar o ListBox, o que é uma ótima solução.
Recentemente, juntei algumas informações na Web e criei o código abaixo, que devolve em um vetor a lista de arquivos de arquivos de uma pasta, criando o ListBox e window dinamicamente.


/*INICIO Da FUnção
Salve o Conteúdo abaixo em um arquivo com o nome f_dir_list.SRF e importe para dentro da sua library*/

global type f_dir_list from function_object
end type

forward prototypes
global function long f_dir_list (string p_diretorio, string p_filtro, integer p_tipo_arquivo, ref string p_arquivos[])
end prototypes

global function long f_dir_list (string p_diretorio, string p_filtro, integer p_tipo_arquivo, ref string p_arquivos[]);
// DESCRIÇÃO:
// * Busca os arquivos de um diretório//
// ARGUMENTOS DE ENTRADA:
// * p_diretorio : Diretorio onde será feito a pesquisa. Se está variável estiver vazia, pesquisa o diretório corrente
// * p_filtro : Filtro utilizado no diretório. Se está variável estiver vazia, lista todos os arquivos
// * p_tipo_arquivo : Tipo do arquivo, conforme lista abaixo, sendo que o Default é 0 + 2 + 4
// - 0 : Arquivos de Leitura e gravação
// - 1 : Arquivos somente leitura
// - 2 : Arquivos Ocultos
// - 4 : Arquivos do Sistema
// - 16 : Sub-Pastas
// - 32 : Arquivos modificados
// - 16384 : Drivers
// - 32768 : Todos os arquivos, exceto arquivo de leitura e gravção
// - Para recuperar a uniao de um ou mais tipos acima, some os valores.
// Por exemplo, para listar arquivos leitura e gravação, subdiretorios e drivers, use 0+16+16384 ou 16400.
// * p_arquivos : Retorna por referencia a lista de arquivos passados
//
// RETORNO:
// * 1 : Sucesso
// * -1 : Erro
// * 0 : não existe arquivos
//
// OBSERVAÇÃO:
//
// CRIADO POR :
// 29/11/2006 - Thiago Campos Pereira
// ALTERADO POR :
//
//========================================================================
//Variaveis
string vls_arquivos[]
window vlw_temp
listbox vllb_temp
int vli_items, vli_i

//Trata Parametros
If isnull(p_diretorio) then
p_diretorio = ""
else
//Verifica se existe a barra no diretorno
p_diretorio = trim(p_diretorio)
if right(p_diretorio,1) = "\" then
//Retira a barra, para fazer pesquisa de diretório
p_diretorio = mid(p_diretorio,1,len(p_diretorio) - 1)
end if

//Verifica se o diretório existe
IF not DirectoryExists(p_diretorio) then
return -1
end if

//Acrescenta barra
p_diretorio = p_diretorio + "\"
end if

if isnull(p_filtro) then p_filtro = "*.*"

if isnull(p_tipo_arquivo) then p_tipo_arquivo = 0 + 2 + 4

//Instancia Objetos
Open(vlw_temp)
vlw_temp.openUserObject( vllb_temp )

//Lista arquivosv
llb_temp.DirList( p_diretorio + p_filtro , p_tipo_arquivo )

//Passa pelos arquivos, gerando lista no array
vli_items = vllb_temp.TotalItems()
For vli_i = 1 to vli_items
vls_arquivos[ vli_i ] = vllb_temp.Text( vli_i )
Next

//Fecha instancia de objetos
vlw_temp.closeUserObject( vllb_temp )
Close( vlw_temp )
p_arquivos = vls_arquivos

return 1
end function

/*Fim da função*/

PowerBuilder – Build 8784 da Versão 9

Recentemente homologamos o Build 8784 do PowerBuilder 9.

A homologação foi um sucesso, sendo considerado o Build mais estável lançado pela Sybase nos últimos tempos.

Além de não detectarmos nenhum erro, resolveram todos os erros existentes, incluindo o problema quando se exclui um SubMenu do Menu ancestral e compila os descendentes.


******* Observação em 11/12/2006
Apenas para complementar o Post. Foi encontrado um Bug neste Build do PowerBuilder, onde a função dw_1.Object.DataWindow.Data.XML não respeita o “XML Declaration”, sempre gerando UTF-8 e trazendo problemas, principalmente relativos a acentos e caracteres especiais.

Para contornar o problema, utilizei o comando export da DataWindow, gravei um arquivo temporário e recuperei o conteúdo do arquivo através de FileOpen/FileRead.

PowerBuilder – Chamando uma aplicativo e aguardando a finalização

Abaixo vai um código fornecido pelo Ricardo Contin, que chama uma executável a partir do PowerBuilder e fica aguardando a execução do mesmo.

Este código é muito útil, principalmente quando você depende do resultado da outra aplicação, com a compactação de um arquivo, criptografia e etc...

Rodar um executavel e esperar
OleObject wsh
integer li_rc
CONSTANT integer MAXIMIZED = 3
CONSTANT integer MINIMIZED = 2
CONSTANT integer NORMAL = 1
CONSTANT boolean WAIT = TRUE
CONSTANT boolean NOWAIT = FALSE

wsh = CREATE OleObject
li_rc = wsh.ConnectToNewObject( "WScript.Shell" )
li_rc = wsh.Run("Notepad" , NORMAL, WAIT)

a msg abaixo so deve aparecer apos vc fechar o notepad
messagebox("ola", "teste")

se usar WAIT teremos em Run o codigo de retorno da aplicacao chamada
as constantes definidas podem tbm ser:

0 Hides the window and activates another window.
1 Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
2 Activates the window and displays it as a minimized window.
3 Activates the window and displays it as a maximized window.
4 Displays a window in its most recent size and position. The active window remains active.
5 Activates the window and displays it in its current size and position.
6 Minimizes the specified window and activates the next top-level window in the Z order.
7 Displays the window as a minimized window. The active window remains active.
8 Displays the window in its current state. The active window remains active.
9 Activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when restoring a minimized window.
10 Sets the show state based on the state of the program that started the application.