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.

quinta-feira, novembro 02, 2006

Oracle - Tabela temporária

Este artigo explica muito bem como trabalhar com tabelas temporárias no Oracle.

PowerBuilder - Exportando dados de uma DataWindow para o MS Excel

Texto retirado do grupo de discussão de PB

Exportando dados de uma DataWindow para o Excel ultilizando OLE AutomationX

O PowerBuilder tem uma função para exportar dados para MS-Excel, mas ela limitada a dados de DML , com esta rotina podemos exportar toda a DataWindow. É um código simples e pode ser aperfeiçoado para uma aplicação mais complexa.


Passo 1 : Crie um nonvisual object salve ente objeto como nca_excel


Passo 2 : Crie uma função neste objeto com o nome de GetColumns Insira o código abaixo :

// Monta uma lista de todas as colunas da DW para exportação

Long ll_I, ll_Cols

ll_Cols = Long( adw_DW.Describe( 'datawindow.column.count' ) )

FOR ll_I = ll_cols TO 1 STEP -1

as_columns[ ll_I ] = adw_DW.Describe( '#' + String( ll_I ) + '.Name' )

NEXT


Passo 3: Crie uma função neste objeto com o nome de GetData. Esta função retorna um ANY. Propositalmente esta função foi colocada separada porque ela pode ser expandida e tratar ambém um Datasource.Insira o código abaixo :

Long ll_Col

Any la_A

IF al_Row > adw_DW.RowCount() THEN RETURN ""

ll_Col = Long( adw_DW.Describe( as_Column + ".ID" ) )

IF ll_Col > 0 THEN la_A = adw_DW.object.data.primary.current[ al_Row, ll_Col ]

RETURN la_A

Passo 4:Crie uma função neste objeto com o nome de inttocolumn .Esta função retorna um String.

// Converte a posição da coluna para o spreadsheet da coluna no Excel

String ls_Col

Integer li_Min, li_Max

IF ai_col <= 0 THEN RETURN ""

li_Max = ai_col / 26

li_Min = ai_col - ( li_Max * 26 )

IF li_Max > 0 THEN

ls_Col = Char( 64 + li_Max )

END IF

ls_Col += String( Char( 64 + li_Min ) )

RETURN ls_Col


Passo 5: Esta é a rotina principal do Objeto Crie uma função neste objeto com o nome de ExportToExcel .

// Exportando dados para o Excel

OleObject lole_OLE, lole_Sheet

String ls_Columns[]

Long ll_Row, ll_Col, ll_Cols

lole_OLE = CREATE OleObject

SetPointer( HourGlass! )

lole_OLE.ConnectToNewObject( 'excel.application' )

lole_OLE.Workbooks.Add

lole_sheet = lole_OLE.Application.ActiveWorkbook.WorkSheets[1]

this.GetColumns( adw_DW, ls_Columns )

ll_Cols = UpperBound( ls_Columns )

FOR ll_col = 1 TO ll_cols

lole_Sheet.Cells[ 1, ll_Col ] = ls_Columns[ ll_Col ]

NEXT

FOR ll_Row = 2 TO al_rows + 1

FOR ll_Col = 1 TO ll_cols

lole_Sheet.Cells[ ll_Row, ll_Col ] = this.GetData( adw_DW, ll_Row - 1, ls_Columns[ ll_Col ] )

NEXT

NEXT

lole_Sheet.Range( inttocolumn( 1 ) + "1:" + inttocolumn( ll_Cols ) + "1").Select

lole_OLE.Selection.Font.Bold = True

lole_Sheet.Range("A1:A1").Select

lole_Sheet.Columns( inttocolumn( 1 ) + ":" + inttocolumn( ll_cols ) ).EntireColumn.AutoFit

lole_OLE.Application.Visible = TRUE

// Código corrigido por Cristina da ( Multipla )

lole_OLE.Application.Workbooks(1).Saveas("C:\TESTE.XLS")

// lole_OLE.DisconnectObject() DESTROY lole_OLE


Salve o objeto..... Na sua aplicação em um botão ou item de menu escreva a chamada do objeto.

nca_excel lnca_Excel

lnca_Excel.ExportToExcel( dw_1, dw_1.RowCount() )

Onde " dw_1" é a DataWindow que você quer exportar.

Oracle - Gerando Número Sequencial de Registros

Texto escrito por João Carlos S. Ribeiro

Pessoal,

Para quem não conhece, a função analítica do Oracle DENSE_RANK gera um número seqüencial para cada linha pertencente a um determinado grupo de linhas. Vejam o exemplo:

Suponhamos a tabela MUNICIPIO:

SGUF NOMMUN
AP Santana
AP Macapá
MG Belo Horizonte
MG Leopoldina
MG Cataguases
SP São Paulo
SP Campinas
SP Santos
SP Mogi-mirim
SP Jundiaí

Para gerar um seqüencial dos municípios, classificados alfabeticamente, DENTRO dos estados, podemos fazer:

SELECT sguf, DENSE_RANK () OVER (PARTITION BY sguf ORDER BY nommun) AS seq, nommun
FROM municipio
ORDER BY 1, 2;

Resultado:

sguf seq nommun
AP 1 Macapá
AP 2 Santana
MG 1 Belo Horizonte
MG 2 Cataguases
MG 3 Leopoldina
SP 1 Campinas
SP 2 Jundiaí
SP 3 Mogi-mirim
SP 4 Santos
SP 5 São Paulo

Mais detalhes podem ser obtidos na documentação do Oracle.

Diversos – Solução para Problemas com Monitor 15' LCD da Proview

Entrei em contato com uma autorizada que me informou que este erro ocorreu em um lote especifico de monitores LCD da Proview.
Para resolvê-lo, é necessário um equipamento especifico que reinstala o FirmWare do equipamento.
O grande problema é que existe apenas um equipamento destes para todo o Brasil. Estou aguardando que este equipamento chegue a Belo Horizonte para realizar o conserto do meu monitor.

terça-feira, setembro 05, 2006

Palm - Tipos de Reset

Um amigo meu, Ricardo Contin, me passou a lista de Reset abaixo:


Vire e mexe aparece novos usuários pedindo que se explique como fazer Resets e Hard Resets, pois bem aí vai tudo explicadinho:

1 - Soft Reset (reset suave)
Descrição:
Um soft reset diz a nosso PDA que deixe de fazer o que estava fazendo e comece de novo. Toda a informação que nele temos se conserva. Quando fazemos um soft reset uma tela de boas-vindas aparece e posteriormente nos leva a Preferências.
Procedimento:
Para fazer um soft reset é necessário introduzir pelo orifício atrás do PDA uma ponta de um clipes ou a ponta de algumas stylus apropriadas para isto (como a stylus das séries Tungstens), solte e pronto. É importante lembrar que é um toque leve e suave . JAMAIS USE PONTAS EXTREMAMENTE FINAS: EX.ALFINETES E AGULHAS.

2 - Duplo Soft Reset (duplo reset suave)
Descrição:
Se depois de fazer um soft reset no PDA o mesmo não se acende e está comprovado que tudo está bem (tem carga na bateria, o contraste (Brilho) está bem, etc) pode provar o duplo soft reset.
Procedimento:
Para fazer o duplo soft reset faz o mesmo que fez para o soft reset mas duas vezes seguidas (apertar 2 vezes o botão de reset atrás do palm em menos de 1 segundo)

3 - Warm Reset (reset medio)
Descrição:
Quando fazemos um warm reset em nosso PDA, ele se reinicia, mas ao fazer o carregamento das extensões (os hacks, os programas gestores de hacks, os patches do sistema, as preferências de alarmes, etc) pode ser esta a fonte do problema. Se for este o caso, o PDA te dará error cada vez que carregue, detendo o processo de carregamento dos programas ao tentar carregar a aplicação danificada. Como com o warm reset estas aplicações não se carregam, te dará a oportunidade de descobrir aquilo que está dando conflito com o sistema (normalmente apagando a fonte do problema) e reiniciando normalmente.
Procedimento:
Para fazer o warm reset aperta o botão de rolamento para cima (Direcional para cima) e simultaneamente aperte o botão de reset (atrás do palm), solta o botão de reset e quando aparecer a tela de boas-vindas solta o botão de rolamento (scroll). Deste modo não se perde a informação de PDA.
Se não estiver seguro de que programa está causando o "error", pode usar um programa como ResetEmu depois do warm reset para detectá-lo.http://www.79bmedia.com/resetemu/d_index.html

4 - Hard Reset (reset duro)
Descrição:
Com um hard reset você apagará tudo que estiver armazenado na memória do PDA, exceto as aplicações e preferências de fábrica (veja extendendo hard reset). Uma vez resetado o PDA será necessário restaurar tudo que tinha com um Hotsync (Se usas Palm OS 3.1 ou anterior e não tiver nenhum programa de Backup, como BackupBuddy ou BackupMan, é muito possivel que terá que reinstalar tudo outra vez.
Por isso, é aconselhavel só fazer o hard reset se todos os métodos anteriores não funcionaram ou se quiser eliminar toda a informação de seu PDA (Por exemplo: na hora de vender o seu PDA, ou se quiser fazer uma limpeza geral).
Procedimento:
Para fazer um hard reset siga os passos seguintes:
Mantenha apertado o botão de Liga-Desliga do PDA.
Ao mesmo tempo em que mantém apertado o botão Liga-Desliga, dê um reset por trás (no furinho).
Solta o botão de reset.
Quando o "logo" da Palm aparecer no visor, pode soltar o botão de Liga-Desliga.
Se tiver feito o procedimento corretamente, aparecerá uma mensagem no visor anunciando que você vai apagar toda a informação do seu PDA, permitindo confirmar a ação ao pressionar o botão direcional para cima. Se não quiser confirmar, é só apertar qualquer outro botão, que o mesmo só dará um soft reset.

5 - Extended Hard Reset (reset duro extendido)
Descrição:
O extended hard reset fará exatamente o mesmo que o hard reset, só com uma diferença: impede a criação de algumas bases de dados que o fabricante pôs (números de telefones do suporte nos contatos, alguma nota de texto no Notepad, as conexões em Preferências, sons de alarme MIDI, a mensagem de boa vinda no Correo, alguns exemplos de fotos, etc). Atente que apagará todas estas informações do seu PDA.
Se fizer o extended hard reset e logo instalar alguma aplicação, te dará um "error"; por isso é recomendável depois de um extended hard reset, entrar em cada uma das aplicações do palm (Agenda, contatos, notas, Correio, Tarefas, etc) para assegurar que foi criado a base de dados. Depois de um extended hard reset não terá mais sons de alarmes adicionais.
Procedimento:
Para fazer um extended hard reset:
Aperta e mantém apertado o botão de Liga-Desliga do seu PDA.
Enquanto o mantém apertado, dê um reset por trás.
Solte o botão de reset.
Quando o "logo" da Palm aparecer no visor, pode soltar o botão de Liga-Desliga.
Quando te perguntar se realmente deseja fazê-lo, aperte e MANTENHA APERTADO o botão direcional (scroll) para cima.
Lembre-se em mantê-lo apertado, ao mantê-lo apertado,aperte em qualquer ordem, o botão de AGENDA, CONTATOS, TAREFAS, e NOTAS.
Solte o botão direcional (scroll) e o processo do extended hard reset terminará.
Tenha em mente que se não chegar a apertar os 04 BOTÕES enquanto mantém o botão direcional para cima apertado, só ocorrerá um soft reset.

6 - FlashPro Reset
Descrição:
Nos PDAs que usam FlashPro (aplicação que permite acessar a memória Flash sobrando) é possivel que uma aplicação que estiver corrompida (danificada) na memória Flash impeça o PDA de responder aos RESETS.
Só deve usar o Flash Pro reset se seu PDA não reage frente à um Hard reset!
Procedimento:
Para fazê-lo:
Aperte e mantenha apertado o botão de Notas de seu PDA.
Enquanto o mantem apertado, dê um reset por trás.
Solte o botão de reset.
Quando o "logo" da Palm aparecer no visor, solte o botão de Notas.
Quando aparecer esta mensagem: "hit the ToDo button to reformat flash" no visor, aperta o botão de tarefas para completar o reset.
Todas as aplicações ou dados que estiverem armazenados na memória Flash se apagará e será necessário reinstalar-las.

7 - JackFlash Reset
Descrição:
Nos PDAS que usam Jack Flash (aplicação que permite acessar a memória Flash sobrando) é possivel haver movido uma aplicação danificada, corrompida ou que não pode ser instalada na memória Flash, impedindo que o PDA responda aos resets.
Procedimento:
Para fazer um JackFlash reset:
Aperte o botão de reset na parte de trás de seu PDA.
Solte o botão de reset.
Imediatamente depois do passo anterior, aperta e mantém apertado o botão de Notas. Se foi feito corretamente, soará um apito do alarme.
Uma vez que haja apitado o alarme, solte o botão de Notas.
Uma vez completado, use o JackFlash para mover as aplicações danificadas ou que não podem ser instaladas na memória Flash para a memória RAM.
O conteúdo da memória Flash não será visivel até que execute o JackFlash ou faça um hard reset. Este método não apaga nada da Flash, com o qual poderá iniciar bem seu PDA e usar o JackFlash para acessar as informações ali guardadas.

8 - Debug Reset
Descrição:
Algumas vezes, quando se tenta atualizar o Palm OS, pode haver uma interrupção no processo que pode ocasionar em seu PDA, uma falha no sistema, na qual ele acusa que seu PDA não tem sistema operativo.
Este reset abrirá O Nº de SERIE do seu PDA para permitir gravar diretamente na memória Flash o sistema operativo.
Este reset só deve ser feito quando na utilização de atualização do sistema nos for necessário.
Procedimento:
Para fazê-lo:
Aperta e mantém apertado o botão de rolagem(direcional) para baixo.
Aperta o botão de reset atrás.
Quando o "logo" da Palm aparecer no visor, solta o botão direcional.
Em alguns modelos de PDA aparecerá um pequeno quadro piscando em um canto do visor.


Aí estão todos os RESETS possíveis....(até o momento)

terça-feira, agosto 22, 2006

Oracle – Diferença no Group By no 10G

Nas versões 8.x e 9 do Oracle, ao se fazer o Group by o resultado já vinha ordenado na ordem das colunas do Group By, como se houvesse um Order By implícito. Este procedimento ocorria, mas não era documentado pela Oracle.

A partir do Oracle 10G, o Order By não ocorre mais, sendo necessário realizar a ordenação manual. Este procedimento está documentado no manual do Oracle 10G.

A partir desta mudança vai uma dica. Nunca confie no que o SGBD faz implicitamente. Se você quer o resultado do Group By ordenado, utilize o Order By para garantir isso.

Oracle - Trabalhando com duas transações

Artigo enviado por Wellington Fernandes do CarmoAnalista de Sistemas
Pessoal, na semana passada precisei usar mais um recurso interessante do oracle que novamente compartilho com vocês.

Eu tinha um bloco pl/sql que, apesar de ter alguns delete, insert e update no seu conteúdo, deveria fazer um commit apenas no final da execução, geralmente o processamento é feito em segundos. Acontece que o update, sem um motivo aparente, começou a demorar mais que o normal. Com isso logo veio a pergunta, porque não fazer um commit a cada comando? Considerando o contexto da rotina, o commit a cada comando não seria possível, exceto em um update. Mas como fazer um commit isolado no meio da transação? A resposta é pragma autonomous_transaction;

Funciona apenas dentro de uma procedure, você cria uma procedure e coloca a declaração pragma autonomous_transaction; pronto essa procedure será considerada uma transação a parte, execute o seu comando e execute o commit.

PS: Funciona desde o Oracle 8i

Exemplo

Begin

Insert ......
Delete ......

Chamada da procedure com a transação autônima.......esse pedaço terá um commit a parte

Etc.......

Commit;
End;

sexta-feira, julho 07, 2006

VisualStudio 2005 - Trabalhando com GridLayout no ASP.Net

Como estou sendo questionado constantemente sobre como mudar de FlowLayout para GridLoyout nas páginas ASP.NET no VisualStudio 2005, abaixo vai um link de como fazer esta mudança.
 

Oracle - Performance X uso de funções

É comum encontrarmos queries com a utilização de funções (to_date, to_char, etc...) em colunas na clausura Where, como o exemplo abaixo:
 
( to_date(to_char(ac1.dataacid,'dd/mm/yyyy'),'dd/mm/yyyy')  >= :VIDDataInicial_AnoI )
 
O problema dessa implementação é que ao utilizarmos uma função na coluna, o Oracle deixa de utilizar algum índice que exista nessa coluna.
 
Por isso, SEMPRE devemos utilizar as funções nos parâmetros. Dessa forma, a comparação acima ficaria:
 
ac1.dataacid >= to_date(to_char(:VIDDataInicial_AnoI,'dd/mm/yyyy' ) || ' 00:00:00', ,'dd/mm/yyyy hh24:mi:ss') AND
 

sexta-feira, junho 23, 2006

PowerBuilder - Bugs no Build 8716 da versão 9

Abaixo vai a lista de Bugs que eu encontrei na Build 8716 do PowerBuilder 9:
 
Duplicação de valores na DataWindow
    Em todas as DataWindows onde você pode inserir várias linhas (Múltiplos registros), quando você insere a primeira linha, funciona perfeito. Quando você tentar inserir a segunda linha, o PowerBuilder está mostrando o valor da primeira linha em tela, como se estivesse duplicando os valores anteriores, mas o campo continua vazio. a explicação técnica é que o valor e duplicado indevidamente em tela mas não no Buffer.

quinta-feira, junho 22, 2006

PowerBuilder - Conectando ao Oracle 10G utilizando Cliente do Oracle 8i

PowerBuilder 9.0.3 Build 8716
 
Recentemente, fizemos a migração do nossos servidores Oracle 8i para Oracle 10G. Para reduzir os impactos resolvemos fazer a migração em partes, primeiro migrando o Servidor e posteriormente migrando o Cliente nas estações.
 
Fizemos a homologação e não encontramos problemas. Após a migração, notamos que em algumas funções o tempo piorou muito. Fizemos uma analise do problemas e descobrimos que as queries utilizadas pelo PowerBuilder 9 , API do Oracle 804, para acessar o Catalogo do Oracle funciona muito bem no Oracle 8 e Oracle 9, mas possui uma performance horrível no Oracle 10.
 
Só para comparação, para listar as tabelas do Oracle 8 no DBProfile demorava 1 segundo. Após a migração para Oracle 10, começou a demorar 22 segundos.
 
Para resolver o problema, fizemos a migração do cliente para Oracle 9 (também funciona com Cliente do Oracle 10) e passamos a utilizar a API do Oracle 9 para conectar utilizando o PowerBuilder.

terça-feira, junho 06, 2006

PowerBuilder - Usando DataWindow para manipular XML

Apenas uma dica para quem quer trabalhar com manipulação de XML em uma DataWindow.
 
O primeiro passo é desenvolver o template que você deseja e associa-lo a DataWindow. A associação pode ser feita no próprio DWPainter ou dinamicamente, como no exemplo abaixo:
 
dw_1.Object.DataWindow.Export.XML.UseTemplate=<Nome do Template XML>
 
Após definir o template, pode ser extrair ou importar os dados diretamente de um arquivo ou variável string, da seguinte forma:
 
- Importação
    - dw_1.importstring(XML!, <variável contendo o XML>) 
    - dw_1.importfile(<Nome do arquivo>) 
 
- Exportação
    - dw_1.Object.DataWindow.Data.XML
    - dw_1.SaveAs(<Nome do arquivo>,XML!,false)

segunda-feira, junho 05, 2006

PowerBuilder - Utilizando HTTP Post

Recentemente tive a necessidade de utilizar o HTTP Post, chamando uma URL passando um XML e recebendo um XML de resposta.
 
No final das contas, o processo é simples, mas não achei nada "pronto" na Web de como utiliza-lo.
 
Abaixo vão os passos necessários para criação de um objeto que chama o método HTTP Post:
 
1 - Objeto com resultado Web
    - Crie um User Object do tipo Standart/InternetResult
    - Declare uma variável de instancia onde será armazenada o retorno (No nosso exemplo, criamos a variável VISRetornoWeb )
    - Na função InternetData(), atribua o parâmetro da função para a variável criada no passo acima
        VISRetornoWeb = string(data)
 
        return 1
 
2 - Criando objeto para disparar metodo HTTP Post
    - Cria um objeto do tipo Custom
    - Crie uma instancia do objeto criado na etapa 1 (No nosso caso, a instancia chama UOI_internet_resultado)
    - Crie uma função para chamar o método HTTP Post com os seguintes argumentos
        * Value String p_URL
        * Value String p_ParametroWeb (Parâmetros que serão passados para Web)
        * Reference String p_RetornoWeb (Parâmetros que serão retornados da Web)
    - Coloque o seguinte código na função
Blob Vlblb_args
String Vls_headers
Long Vll_ret
 
p_retornoWeb = ''
 
Vlblb_args = blob(p_parametroWeb)
 
vll_ret = UOI_Inet.PostURL(p_url, Vlblb_args, vls_headers,  UOI_internet_resultado)
 
if vll_ret = 1 then
 VISMSG = ""
elseif vll_ret = -1 then
 VISMSG = "Erro ao chamar o objeto de acesso a internet."
 Return -1
elseif vll_ret = -2 then
 VISMSG = "A URL informada é inválida."
 Return -1
elseif vll_ret = -4 then
 VISMSG = "Não foi possível conectar a Internet."
 Return -1
elseif vll_ret = -5 then
 VISMSG = "Não foi possível conectar a Internet utilizando protocolo seguro (HTTPS)."
 Return -1
elseif vll_ret = -5 then
 VISMSG = "Ocorreu um erro na requisão a Internet."
 Return -1
else
 VISMSG = "Ocorreu um erro não documentado no acesso a Internet. - Codigo :" + string(vll_ret)
 return -1
end if
 
p_retornoWeb = uoi_internet_resultado.visretornoweb
 
return 1

PowerBuilder - Abrindo um documento

Em algumas situações, o comando RUN não consegui abrir o documento que desejamos ou abre o documento utilizando uma aplicação diferente da configurada como "padrão" para aquele tipo de documento.
 
Para resolver este problema, pode-se utilizar o comando abaixo:
 
String VLSArquivo
long ret
 
ret = run('rundll32 SHELL32.DLL,ShellExec_RunDLL ' + '"'+VLSArquivo+'"')
if ret = -1 then
    vismsg = 'Não foi possível executar '+VLSArquivo+'!'
    return 0
end if
return 1

quarta-feira, maio 17, 2006

PowerBuilder - Bloqueando o Teclado

Recentemente precisei bloquear o entrada de dados via teclado de uma aplicação e encontrei a seguinte função:
 
Function long blockinput(BOOLEAN fBlockIt) LIBRARY "user32.dll"
 
onde True bloqueia o teclado e False libera o teclado.

terça-feira, maio 16, 2006

PDA - Sites interessantes

Abaixo estão relacionando alguns sites interessantes para serem acessados nos PDAs:
Abaixo estão relacionados Sites que fornecem informações sobre PDAs e celulares:

Palm – Problemas com o Treo 650

Estamos avaliando a utilização de alguns aparelhos Treo na empresa. Em todos os aparelhos que testamos, a primeira impressão que fica é que o som do telefone é muito ruim.

Este problema ocorre porque existe um Bug no Treo. Para resolvê-lo, você tem que fazer a atualização da ROM do aparelho, que pode ser baixada direto no site da PALM USA (http://www.palm.com/us/support/downloads/treo650updater/).

Após o update, a qualidade do som melhorou muito, mas ainda perde para muitos telefones celulares disponíveis. A solução adotada por vários usuários é a utilização de fones de ouvido bluetooth.

PowerBuilder – Problemas ao retornar valores por output no Oracle

PowerBuilder : 9.0.3 Build 8004
Oracle : 8.1.7.4
Forma de conexão : API O84 Oracle8/8i (8.x.4+)

Recentemente estava tendo erro ao retornar valores VARCHAR2 como OutPut de uma procedure. A definição da minha procedure era :

create or replace PROCEDURE SP_GERA_XML_POS
(p_numcdc cconta.numcdc_cad%type,
p_CodAgente varchar2,
p_CodEmpresa Number,
p_retorno_xml out varchar2) As ...........


No PowerBuilder, criei um UserObject do tipo Transaction e criei uma External Function apontando para o procedure, da seguinte forma:

subroutine SP_GERA_XML_POS(double P_NUMCDC,string P_CODAGENTE,long P_CODEMPRESA,ref string P_RETORNO_XML) RPCFUNC ALIAS FOR "SP_GERA_XML_POS"

Chamei a procedure utilizando seguinte código :

sqlca.sp_gera_xml_pos( 444, 'zzz', 10, xmlretorno)

if sqlca.sqlcode <> 0 then
xmlretorno = sqlca.sqlerrtext
end if

messagebox('teste',xmlretorno)

Este código me retornava a mensagem :
ORA-06502: PL/SQL: numeric or value error: character string buffer too small

Para resolver o problema, descobri que tenho que inicializar a variável que será utilizada para receber o retorno. Como o Oracle possui um limite de 4000 caracteres, alterei o meu código para ficar da seguinte forma:

xmlretorno = space(4000)

sqlca.sp_gera_xml_pos( 444, 'zzz', 10, xmlretorno)

if sqlca.sqlcode <> 0 then
xmlretorno = sqlca.sqlerrtext
end if

messagebox('teste',xmlretorno)

Desta forma, o problema foi solucionado.

quinta-feira, maio 04, 2006

VisualStudio 2005 – Problemas com o Help

Recentemente instalei o VisualStudio 2005 completo com o MSDN completo. Quando tentei abril o MSDN Library for VisualStudio 2005 obtive o seguinte erro:

Microsoft Document Explorer cannot be shown because the specified help collection 'ms-help://MS.MSDNQTR.v80.en' is invalid

Analisei vários sites e fóruns e descobria a origem e como resolver o problema:

Origem
A minha instalação foi feito a partir de uma imagem de DVD (Arquivo .BIN). Para abrir o arquivo .BIN, utilizei o WINRAR e extrai os arquivos para o meu drive local.
Instalei o VisualStudio e nenhum erro foi informado.
De acordo com artigos que li, o problema está na utilização do WINRAR para extrair arquivo do .BIN. Por algum motivo, o WINRAR modifica alguns arquivos, corrompendo-os e causando o erro acima.

Solução.
Instalei a última versão do Software DAEMON TOOLS, que cria um drive virtual para o arquivo BIN, simulando um drive de DVD.
Apenas pedi para corrigir a instalação do MSDN e o mesmo passou a funcionar.

terça-feira, maio 02, 2006

Oracle – Dica de Performance

Recentemente fiz um trabalho em conjunto com um excelente DBA Oracle para analisarmos alguns pontos de baixa performance.

Um dos pontos que mais causou problemas foi o tratamento dado ao desenvolvedores para os parâmetros opcionais.

Por exemplo, vamos dizer que em uma consulta você tem três parâmetros e todos eles são opcionais. Abaixo estou listando as soluções adotadas e o que podemos concluir das mesmas:

1) Passar Nulo no parâmetro não informado
Where ( Campo1 = :Parametro1 or :Parametro1 is null)
And ( Campo2 = :Parametro2 or :Parametro2 is null)
And ( Campo3 = :Parametro3 or :Parametro3 is null)


Nesta solução, se o parâmetro for informado ele é passado para a query, ao contrário passa-se nulo.
Essa é a pior solução que pode ser adotada. O otimizador do Oracle identifica o OR e verifica que a mesma coluna não é utilizada nas duas comparações e por isso não utiliza índice, degradando em muito o tempo de resposta da query.

2) Passar o valor por limite
Where ( Campo1 Between :Parametro1_ini and :Parametro1_fim)
And (Campo2 Between :Parametro2_ini and :Parametro2_fim)
And (Campo3 Between :Parametro3_ini and :Parametro3_fim)


Nesta solução, se o parâmetro for informado, o valor é passado para o parâmetro inicial e final, por exemplo Campo1 between 45 and 45. Ao contrário, é passado um valor de forma a não filtrar os dados, por exemplo Campo1 between 0 and 9999.
Essa solução, apensar de funcionar, deve ser evitada, pois em algumas situações o Oracle armazena o plano de execução para utilizá-lo futuramente, com a intenção de melhorar a performance da query, evitando a analise necessária para identificar o melhor plano. Como os valores passados por limite podem vária, este tipo de query pode prejudicar o trabalho do otimizador.
Além disso, se você passa apenas um parâmetro, você está gerando trabalho extra para o Oracle, que tem que avaliar se os dois outros parâmetros devem ou não ser utilizados pelo filtro.

3) Montar a Query Dinamicamente
Essa é a melhor solução, onde alteramos a query em tempo de execução passando apenas os valores necessários. Dessa forma, o otimizador pode trabalhar com uma query mais simples e montar o plano de execução com mais precisão.

Devo lembrar que em algumas situações, como a utilização de Composites complexas, essa solução não poderá ser adotada. Neste caso, recomendo utilizar a solução B.

Oracle - Query com Recursividade

De vez enquanto recebo um e-mail de como desenvolver uma query com recursividade (Peças de um automóvel, etapas de um projeto, hierarquia de funcionários, etc...). O Oracle possui um comando interessante que recupera o dado recursivamente, independente da quantidade de níveis.

O nome deste comando é CONNECT BY PRIOR

Abaixo estou enviando o trecho do e-mail que um amigo meu enviou sobre este comando:

Pessoal, hoje eu aprendi um recurso interessante do oracle utilizado para trazer um result set com recursividade.
Talvez seja útil para vocês.


SELECT lpad(' ', 2*level) ID ID, NOME, REC_ID FROM RECURSIVIDADE start with id = 3 CONNECT BY PRIOR ID = REC_ID

Escrito por : Wellington Fernandes do Carmo

domingo, abril 30, 2006

CodeWarrior - Memory is getting low

Estou tentnado utilizar o Constructor do CodeWarrior em uma máquina com 1GB de memória RAM e a ferramenta me retorna o erro abaixo.

"Memory is getting low. Try closing some windows, or give Constructor a largermemory partition."

Procurei em vários sites e não obtive sucesso na solução do problema.

No site da Metrowerks, proprietária od CodeWarrior, achei o seguinte artigo:

Each time I run Constructor on my system, I receive an error window that reads,
"Memory is getting low. Try closing some windows, or give Constructor a larger
memory partition."
This error message is a bug within Constructor. It reports a low memory error on any
system that contains 512 MB or more of RAM. Usually, the error is triggered if you have a
multiple of 512 MB on your system, so 1024 MB would cause the error, but 768 MB may
not.
Therefore, the solution would be to try increasing or decreasing the amount of RAM the
system is currently using. However, various users have had this problem go away by
changing the amount of virtual memory the system uses in the System settings, so this is
another option to try. Palm is aware of this problem and should be working on a fix for
future releases of Constructor. Since Constructor is maintained and distributed by Palm as
part of the Palm OS SDK, any bug fixes or feature requests for Constructor can be
implemented only by Palm.

Após N dias e muita pesquisa tentando resolver este problema, consegui a solução que é instalar o Constructor for Palm OS 1.9. Então começou outra luta, onde encontrar a atualização!!!

Foram gastos mais N dias para achar essa atualização, que se encontra no SDK R3 para PALM OS 5. Aproveitei e já baixeis a versão 1.9.1, que é a mais recente.

Mas, o melhor de tudo, que após este trabalho todo, o problema agora está resolvido.

Fico muito feliz em poder publicar este problema aqui e puder ajudar outras pessoas. Afinal, foram um mês e meio de pesquisa para resolver este problema.

segunda-feira, abril 24, 2006

PowerBuilder 11 - Versão de Avaliação

Recentemente a Sybase divulgou uma amostra do que será o PowerBuilder 11. A grande novidade dessa versão é a geração de WebForms utilizando DotNet.

Apesar dessa versão possuir muito bugs, vale apena entrar no Link e dar uma olhada.

Além do DotNet, houve mudanças no visual da ferramenta e inclusão de recursos para desenvolvimento Mobile.

Diversos - Problemas com Monitor 15' LCD da Proview

Recentemente adquiri um monitor de 15’ LCD da Proview. Para a minha surpresa, após o primeiro boot, a tela do monitor ficou preta e apresentou a mensagem de No Signal.

Após vários testes, identifiquei que se eu reiniciasse o computador com o cabo do monitor ligado, o mesmo apresentava o problema. Mas se eu desligasse o cabo do monitor, aguardasse o tempo suficiente para aparecer a tela de Login e ligasse o cabo novamente, funcionava 100%.

Fiz o teste com o monitor em outro computador e o mesmo funcionou 100%. Então, comecei a desconfiar da minha placa de vídeo. Como ela funcionava com outros monitores, percebi que poderia ser alguma incompatibilidade.

Possuo uma placa de vídeo NVIDIA GeForce4 MX 4000. Essa placa possui um recurso de desabilitar a aceleração gráfica. Utilizei este recurso, e o monitor funcionou 100%.

Explicando o problema. No momento que o Windows e inicializado, a minha placa de vídeo tenta identificar qual a melhor configuração do monitor. Por algum problema, ela configura a taxa de atualização para um valor muito alto e o monitor perde o sinal.

Entrei em contato com a Proview e após vários dias e muitos e-mails/telefonemas. Eles me passaram a seguinte resposta:

Boa tarde
Thiago para resolvermos este problema , voce tem que levar sua cpu e o monitor ao um posto autorizado proview, pois teremos que atualizar a bios do monitor para este tipo de placa.


Fico pensando em um usuário leigo, que não tem experiência e que acha que fez um excelente negocio comprando uma placa top de linha e um monitor bacana e que descobre que tem uma dor de cabeça ao invés de alegria.

Como a assistência técnica mais próxima de mim fica a 300 KM (RJ). Vou ficar um bom tempo sem solução para o meu monitor. A minha sorte é que raramente faço um boot no meu computador.

terça-feira, março 14, 2006

CodeWarrior – O que é?

CodeWarrior é uma ferramenta utilizada para desenvolvimento de aplicativos para PalmOs (Sistema operacional utilizados em handhelds Palm).

É uma excelente ferramenta, se não for a melhor. O próprio sistema PalmOS é desenvolvido utilizando essa ferramenta, por isso ela permite acessar todos os recursos do sistema operacional

O desenvolvimento é feito utilizando linguagens como o C, C++ e Java.

A algumas semanas atrás, foram requisitados o desenvolvimento de alguns módulos do nosso ERP que funcionassem em Palms e fiquei responsável por estes aplicativos, iniciando o meu relacionamento com o desenvolvimento para Palm.

A partir de vários estudos, elegemos o CodeWarrior como ferramenta de desenvolvimento.

A partir deste momento, estarei incluindo no meu blog algumas dicas sobre o CodeWarrior, bem como publicar informações interessantes sobre a ferramenta.

quarta-feira, março 01, 2006

quinta-feira, fevereiro 16, 2006

PowerBuilder – GPF ao Fazer GLV / RefreshStatus

Recentemente tive um problema onde a aplicação de um dos desenvolvedores fechava quando se fazia GetLatestVersion (GLV) ou RefreshStatus em um PBL no PowerBuilder 9.

Após várias tentativas e erro, descobri que o desenvolvedor tinha editado o PBG manualmente e cometido um erro. O nome do objeto estava da seguinte forma:
"dw_cad_impressora.srd.srw" "sigsa_cad.pbl";

Este erro causava o cancelamento da aplicação sem nenhuma informação para o desenvolvedor.

Para resolvê-lo, apenas corrigi o nome do objeto no PBG.

terça-feira, janeiro 31, 2006

PowerBuilder – Recuperando valor de uma coluna em um Report

Um Report é uma DataWindow que é inserida dentro de outra DataWindow.

Existem duas formas de trabalhar com Report, utilizando uma DataWindow comum e acrescentar um objeto Report, denominada de DataWindow Nested. A segunda opção é criar uma DataWindow Composite e adicionar os Reports.

No Primeiro caso, a DataWindow principal possui dados e para cada registro existente, ele executára as Reports.

No Segundo caso, a DataWindow principal não possui dados, recuperando os reports apenas uma vez.

A dúvida que existe entre muitos desenvolvedores é como devemos proceder para buscar valores (GetItem) em uma coluna que está dentro de um Report.

Abaixo está a solução para os dois casos:

1) Report em DataWindow Composite
Este é o caso mais simples e possui duas soluções.

A primeira solução é realizar um GetChild do Report e fazer um comando GetItem ou Object tradicional, por exemplo:

datawindowchild vldwc_aux
dw_1.getchild('dw_1',vldwc_aux)
messagebox('teste',vldwc_aux.getitemstring( 1, 'sistema'))
messagebox('teste',vldwc_aux.getitemstring( 2, 'sistema'))


A segunda solução é baseado na estrutura de objetos do PowerBuilder, ou seja, você pode utilizar o OBJECT para buscar o valor, como no exemplo abaixo:
string vlsteste
//Syntax : .object.[].object..[]
vlsteste = string(dw_1.object.dw_1[1].object.sistema.primary[1])
messagebox('teste2',vlsteste)


Existem alguns variações do comando acima, que também funcionam no PowerBuilder.

2) Report em DataWindow Nested
Neste caso, a única solução é usar o OBJECT para busca o valor, como no exemplo abaixo:

//Syntax : .object.[].object..[]
vlsteste = string(dw_1.object.dw_1[1].object.sistema.primary[1])
messagebox('teste2',vlsteste)

sexta-feira, janeiro 27, 2006

PowerBuilder - Retirando o X do menu das janelas

Achei interessante este artigo do site do Celso Cortes de como remover o X (Opção de fechar a janela). É interessante para algumas situação, principalmente para janelas Response.

http://www.celso.cortes.nom.br/seleciona/c_2.php?opc=7&it=2&gr=3&item=61&tit=Anulando%20o%20%22X%22%20na%20Window&cc=34

PowerBuilder – Salvando uma DataWindow como PDF

Obs: Solução existente para PowerBuilder 9 ou superior

Recentemente tive a necessidade de implementar um processo batch para gerar arquivos PDF e enviá-los por e-mail.

A funcionalidade de envio de arquivos por e-mail já tinha sido implementada através do blat ( http://thiagocpereira.blogspot.com/2005/01/powerbuilder-enviar-e-mail-via-smtp.html )

O grande problema era como gerar arquivo PDF. Procurei na Internet e vi vários artigos de como gerar o PDF, mas nenhum deles satisfez por completo as necessidades da minha aplicação.

Depois de muito trabalho de pesquisa e juntando informações de N sites, consegui definir uma forma de trabalho que funciona 100%.

Abaixo vai as informações sobre a solução e como consegui chegar até ela.

1) Problema
a) Processo Batch de geração de arquivos PDF em lote e envio por e-mail, sem nenhuma interação do usuário.
b) Permitir salvar os relatórios existentes em todos os sistemas em PDF, envolvendo uma média de 7000 estações de trabalho, incluindo sistemas operacionais Windows 98, 2000 e XP.

2) Pesquisa
Pesquisei vários SITES, NewsGroup e lista de discursão. Após um filtro nas opções existentes, resolvi estudar as seguintes ferramentas:
* PDF995
* PDF Reditector
* SaveAs PDF da DataWindow

PDF995
A primeira opção e a que me pareceu mais simples foi a utilização do PDF995 (www.pdf995.com). Como ele é FreeWare, não teria problema com licenças.
Os problemas surgiram na automação do processo e Deploy do Software. Teria que instalar o software em todas as máquinas o que não agrada muito a nossa equipe, devido a quantidade de estações e a localização das mesmas.
A geração automática do arquivo não teria problema, pois descobri que apenas teria que alterar uma chave no arquivo INI do PDF995.
Mas, o problema que a principio tornou inviável a solução foi a propaganda que é exibida no momento que você salva os arquivo como PDF. Para retirar essas propagandas você tem que comprar uma licença de uso. Baixei uma licença utilizando o e-mule é funcionou perfeitamente. O problema é que a empresa não permite nenhum tipo de pirataria. A solução de comprar a licença se tornou inviável. A licença para cada máquina custa 10$. Fazendo as contas, teríamos que gastar R$161.000,00 para licenciarmos todas as nossas estações o que tornou a relação custo / beneficio um empecilho para a implementação da funcionalidade.

PDF Redirector
A segunda opção seria a utilização do PDF Redirector. Como ele não exibe nenhuma propaganda e é FreeWare, não teríamos os problemas o PDF995.
Mas, continuamos tendo o empecilho de ter que instalar o Software em todas máquinas.
Além desse problema, a automatização do processo de geração de PDF é um pouco complexa, aumentando o tempo necessário para a implementação e gerando novos pontos de risco.

SaveAs PDF da DataWindow
Como é um recurso nativo do PowerBuilder, seria a solução melhor a ser adotado.
O problema inicial encontrado foi a falta de informações sobre o processo.
Também tivemos problema na versão do GNU GhostScript (FreeWare), adotando a versão 7.05 como a melhor que se adequar as nossas necessidades.
Após levantar informações de vários sites, conseguimos fazer a solução funcionar em uma máquina com todos os softwares instalados (PowerBuilder e GNU GhostScript).
Então esbarramos em outro problema, como fazer o Deploy dos softwares na rede. Após algumas pesquisas, descobri que seria necessário apenas adicionar duas novas chaves no registry, o que pode ser automatizado utilizando o Script de Login dos usuários.

Assim, resolvemos o problema utilizando a solução existente no próprio PowerBuilder 9 ou superior.

3) Solução
Todos os nossos sistemas e DLLs do PowerBuilder encontra-se na rede, por isso, a solução abaixo foi feita baseado nesse ambiente
Abaixo estão os passos necessários para a implementação da solução
a. Coloque os sistemas e DLLs do PowerBuilder na rede. No nosso exemplo vamos adotar que estes arquivos se encontram no Drive X:
b. Copie a pasta C:\......\Sybase\Shared\PowerBuilder\Drivers para o drive X: . Na verdade o diretório Drivers tem que estar na mesma pasta da dll PBDWEXX.DLL.
c. Baixe a versão 7.05 do GNU GhostScript (http://prdownloads.sourceforge.net/ghostscript/gs705w32.exe?download) e instale em um máquina usando o diretório padrão.
d. No Drive X:, crie uma pasta chamada GS e copie as pastas BIN, LIB e FONTS da pasta c:\GS\ para a pasta na rede.
e. Cria as seguintes chaves no Registry das máquinas (Essa etapa pode ser automatizada utilizando o Login Script)
[HKEY_LOCAL_MACHINE\Software\GNU GhostScript]

[HKEY_LOCAL_MACHINE\Software\GNU GhostScript\7.05]

"GS_DLL"="X:\gs\bin\gsdll32.dll"
"GS_LIB"="X:\gs\lib;X:\gs\fonts"

f. Para Salvar a DataWindow, você tem que observar se as seguintes propriedades estão configuradas
//Se o GhostScript tiver instalado, configura a DataWidnow para utiliza-lo
dw_dados.Object.DataWindow.Export.PDF.Distill.CustomPostScript='No'
dw_dados.Object.DataWindow.Export.PDF.Method = Distill!
dw_dados.Object.DataWindow.Export.PDF.XSLFOP.Print='No'

O próximo passo é salvar a DataWindow como PDF

//Salva a DataWindow como PDF
dw_dados.saveas(p_path,PDF!,True)


4) Conclusão
O objetivo deste artigo é esclarecer o procedimento de Salvar como PDF e compartilhá-lo com outros desenvolvedores.

Quem tiver dúvida ou sugestões, pode incluir um comentário para que possamos enriquecer o conteúdo deste artigo.



Boa sorte!

segunda-feira, janeiro 23, 2006

Microsoft Outlook - Como configurar o Outlook XP para abrir arquivos EXE em anexo

Essa informação é muito importante, principalmente se você recebe anexos dos seus clientes e precisa abri-los de qualquer forma.
Só tomem cuidado com vírus ou outros BAD PROGRAMS.

quarta-feira, janeiro 18, 2006

PowerBuider – Problema ao Formatar Valor em gráfico

No PowerBuilder 9, existe um Bug ao formatar o campo de Valor quando utilizamos uma DataWindow Gráfica.

Quando você informa o formata de exibição do campo, ele exibe o formato correto no Preview, mas após fechar e reabrir a DW, o formata é perdido.

O problema ocorre porque o PowerBuilder grava a informação de formata em um local errado, o que pode ser visto quando você visualiza o source da DW.

Para resolver o problema no source da DW (Edit Source), altera a propriedade values.dispattr.format="".