Jump to content

Manimal

Administradores (Adm)
  • Content count

    540
  • Joined

  • Last visited

  • Days Won

    70

Everything posted by Manimal

  1. Desenvolvendo na interface metro

    Parabéns. Realmente muito bom!
  2. Framework Comercial

    Este tópico é para montarmos uma biblioteca básica para utilizarmos o AutoIt de uma forma mais comercial. Todas as funções aqui apresentadas são de uso e acesso livre a qualquer pessoa para qualquer utilização que desejar, independente de cobrança ou não. Traduzindo, se quiser usar o que tiver aqui para fazer um sistema e cobrar por ele, fique a vontade. Nosso intuito é divulgar e difundir o conhecimento, mas por favor, mantenha os créditos! As funções aqui presentes serão adequadas ao padrão internacional de formatação e documentação e portanto serão centralizadas, formatadas e liberadas na última versão disponível aqui neste post. Me comprometo a fazer este trabalho de ajustes e manter a biblioteca atualizada. Por favor, peço auxílio a todos na questão de padronização. Outro detalhe é que as funções, na medida do possível, sejam completamente independentes, ou se necessário acompanhadas de todos os includes e/ou fontes que sejam necessários à sua execução. A intenção é poder incorporar através de #include a Framework e poder utilizar qualquer função nela contida. Exemplo: #include "Framework.au3" OutPut(DT2EXT(_NowCalcDate())) Observar que o #include tem ASPAS (") e não os tradicionais <>. Porque disso? Para procurar o arquivo Framework.au3 na MESMA pasta onde está o nosso script principal. Se usarmos como #include <Framework.au3> Provavelmente vai dar errado porque o AutoIt procura o arquivo na pasta INCLUDE. Se quiser usar assim, lembre de copiar o arquivo para lá mas cuidado para não ficar com 2 cópias! Uma boa dica para obter os parâmetros de cada função, é pressionar CTRL-J com o mouse em cima da função! Versão 1.04 - padronizadas constantes de localização corrigida função TRUNC com resultados 0 (zero) Versão 1.03 colocado mais algumas validações de parâmetros substituídos comandos _ArrayAdd para aumentar a eficiência corrigido retorno de algumas funções (sempre setava @error) incluído as funções StringDifference e Trunc Versão 1.02 - corrigido cálculo da função PADC e incluído algumas funções para números Versão 1.01 - integradas as funções de string Versão 1.0 Funções até então: Name ..........: OUTPUT Description ...: Mostra mensagem usando ConsoleWrite ou MsgBox Example .......: OUTPUT("Isto é uma mensagem") Name ..........: DAY Description ...: Dia do mês de uma data específica Example .......: DAY(_NowCalcDate()) ; retorna o dia da data de hoje Name ..........: DOW Description ...: Dia da semana de uma data específica Example .......: DOW(_NowCalcDate()) ; retorna o dia da semana de hoje Name ..........: DOW2EXT Description ...: Extenso do dia da semana Example .......: DOWEXT(4) ; retorna "Quarta" DOWEXT(4, 3) ; retorna "Qua" DOWEXT(4, Default, Default, True) ; retorna "Quarta-feira" DOWEXT(4, Default, False, True) ; retorna "quarta-feira" Name ..........: EXT2DOW Description ...: Dia da Semana de acordo com o extenso Example .......: EXT2DOW("Quarta") ; retorna 4 EXT2DOW("Dom") ; retorna 1 EXT2DOW("Sexta-feira") ; retorna 6 Name ..........: MONTH Description ...: Mês de uma data específica Example .......: MONTH(_NowCalcDate()) ; retorna o mês da data de hoje Name ..........: MONTH2EXT Description ...: Mês por extenso Example .......: MONTH2EXT(2) ; retorna Fevereiro MONTH2EXT(8) ; retorna Agosto Name ..........: EXT2MONTH Description ...: Mês de acordo com o extenso Example .......: EXT2MONTH("Março") ; retorna 3 EXT2MONTH("Set") ; retorna 9 Name ..........: YEAR Description ...: Ano de uma data específica Example .......: YEAR(_NowCalcDate()) ; retorna o ano da data de hoje Name ..........: DT2EXP Description ...: Expande a data para o formato dd/MMM/yyyy Example .......: DT2EXP(_NowCalcDate()) ; retorna 12/Dez/2017 Name ..........: DT2EXT Description ...: Extenso de uma data Example .......: DT2EXT(_NowCalcDate()) ; retorna Terça, 12 de Dezembro de 2017 DT2EXT(_NowCalcDate(), False) ; retorna 12 de Dezembro de 2017 Name ..........: VIRA_DATA Description ...: Inverte o formato de data de ddmmyyyy para yyymmdd ou vice-versa com ou sem separadores Example .......: VIRA_DATA("25/06/2017") ; retorna 2017/06/25 Name ..........: SPACE Description ...: Retorna string com uma quantidade determinada de espaços Example .......: SPACE(30) ; retorna " " Name ..........: LIMPA_ESPACO_DUPLO Description ...: Elimina os espaços duplos dentro de uma string Example .......: LIMPA_ESPACO_DUPLO(" Este é um exemplo ") ; retorna " Este é um exemplo " Name ..........: LTRIM Description ...: Elimina os espaços ANTES do texto, pode escolher qual caracter será limpo Example .......: LTRIM(" Este é um exemplo ") ; retorna "Este é um exemplo " Name ..........: RTRIM Example .......: RTRIM(" Este é um exemplo ") ; retorna " Este é um exemplo" Name ..........: ALLTRIM Description ...: Elimina os espaços ANTES e DEPOIS do texto, pode escolher qual caracter será limpo Example .......: ALLTRIM(" Este é um exemplo ") ; retorna "Este é um exemplo" Name ..........: PADR Description ...: Completa uma string com espaços NO FINAL até uma determinada quantidade Example .......: PADR("ABCDE", 10) ; retorna "ABCDE " PADR("ABCDE", 3) ; retorna "ABCDE" Name ..........: PADL Description ...: Completa uma string com espaços NO COMEÇO até uma determinada quantidade Example .......: PADL("ABCDE", 10) ; retorna " ABCDE" PADL("ABCDE", 3) ; retorna "ABCDE" Name ..........: PADC Description ...: Completa uma string com espaços NO COMEÇO e NO FINAL até uma determinada quantidade centralizando o texto dentro da string Example .......: PADC("ABCDE", 11) ; retorna " ABCDE " PADC("ABCDE", 3) ; retorna "ABCDE" Name ..........: FATORIAL Description ...: Fatorial de um número Example .......: FATORIAL(5) ; retorna 120 Name ..........: STRZERO Description ...: Completa com zeros à esquerda dos números Example .......: STRZERO(123, 5) ; retorna "00123" STRZERO(123, 7, 2) ; retorna "00123.00" Name ..........: NUMBERFORMAT Description ...: Formata um nro com separador de milhares e decimais Example .......: NUMBERFORMAT(12345, 0) ; retorna "12.345" NUMBERFORMAT(12345, 2) ; retorna "12.345,00" NUMBERFORMAT(-12345, 0) ; retorna "-12.345" NUMBERFORMAT(-12345, 2) ; retorna "-12.345,00" NUMBERFORMAT(12345, 0, 15) ; retorna " 12.345" NUMBERFORMAT(12345, 2, 15) ; retorna " 12.345,00" NUMBERFORMAT(-12345, 0, 15, True) ; retorna " (12.345)" NUMBERFORMAT(-12345, 2, 15, True) ; retorna " (12.345,00)" Name ..........: MONEYFORMAT Description ...: Formata um nro com separador de milhares e decimais e inclue o símbolo da moeda no começo, R$ para Brasil Example .......: MONEYFORMAT(12345, 0) ; retorna "R$ 12.345" MONEYFORMAT(12345, 2) ; retorna "R$ 12.345,00" MONEYFORMAT(-12345, 0) ; retorna "R$ -12.345" MONEYFORMAT(-12345, 2) ; retorna "R$ -12.345,00" MONEYFORMAT(12345, 0, 15) ; retorna "R$ 12.345" MONEYFORMAT(12345, 2, 15) ; retorna "R$ 12.345,00" MONEYFORMAT(-12345, 0, 15, True) ; retorna "R$ (12.345)" MONEYFORMAT(-12345, 2, 15, True) ; retorna "R$ (12.345,00)" Name ..........: STRINGDIFFERENCE Description ...: Mostra a diferença entre duas strings Example .......: STRINGDIFFERENCE("abc", "abcde") ; return "de" STRINGDIFFERENCE("123456", "246") ; return "135" Name ..........: TRUNC Description ...: Trunca números (corta o nro desprezando as decimais) Example .......: TRUNC(1.238, 2) ; returns 1.23 Framework.au3
  3. Receber dados no pc via Bluetooth

    Olá @mutleey. Pois eu acho que isso nós conseguimos trabalhar!!! Muito boa a ideia.
  4. Receber dados no pc via Bluetooth

    Olá. @mutleey nem esquenta. Meu comentário foi no sentido de que o formato Bluetooth foi desenvolvido já pensando nesta questão do pareamento obrigatório por motivos de segurança. E eu estava apenas apresentando uma seqüência cronológica dos modelos de segurança de rede. Do totalmente aberto até o atual padrão. No seu caso, a caixinha xing-ling tbm exige o pareamento. A função senha é quando vc precisa conectar "manualmente" ao dispositivo. A conexão automática (sem senha) é o pareamento por hardware. Vou usar o exemplo da Wi-fi. É a coisa mais normal do mundo vc chegar em um lugar e para conectar na wi-fi, vc pedir a senha e pronto. Mas poucas pessoas percebem que os modens atuais já permitem o pareamento por hardware tbm, que é o protocolo WPS. Se vc procurar no seu modem/roteador, deve ter um botào WPS (Wi-Fi Protected Setup) que é basicamente a mesma coisa do Bluetooth, ou seja, vc aperta ele e o celular se conecta na rede wi-fi sem a necessidade de informar a senha. Este sistema foi desenvolvido om base no conceito do acesso físico, que eu falei no meu outro post). Se, em teoria, a pessoa tem acesso físico ao roteador, por exemplo então ele já estaria "pré-autorizado" a se conectar, visto que este roteador não está na vitrine, por assim dizer. Portanto, em qualquer situação de pareamento é necessário que uma das partes, normalmente a qual vc deseja se conectar e que vc precisa ter acesso físico (apertar o botão na caxinha xing-ling, por exemplo) para permitir o acesso. Considerando que são 2 (duas) partes e que uma sempre está em "espera" (passivo, caixinha de som) e a outra em "pesquisa" (ativo, celular) sempre vai haver uma exigência de pareamento. No nosso caso em termos de software a vantagem é que podemos ativar o pareamento via script do dong no computador, mas acho que vai depender do outro dispositivo tbm ativar o dispositivo para efetivar o pareamento. Depois disso é só curtir! Em termos de tecnologia ou conhecimento necessário para isso, acredito que os hardwares já estão prontos para isso, tanto o pareamento como a comunicação, e nós só precisamos aprender como acessar o outro dispositivo em um nível mais de recurso mesmo. Digo isso, combatendo a minha vontade de de saber como funciona em baixo nível. Na prática, vai ser como copiar um arquivo de um ponto a outro pela rede, concordam? Agora se esta rede é LAN, WAN, IP, Bluetooth, Netbios ou o que for, não nos importa.
  5. Receber dados no pc via Bluetooth

    Olá. O pareamento, como todos já sabem, é uma barreira que existe por questões de segurança, para que nenhum equipamento possa se conectar com outro e ter acesso aos seus recursos sem pelos menos uma autorização. Estamos acostumados a conectar em redes ponto-a-ponto sem muita firula (nossas redes normais do dia-a-dia entre computadores) e achamos estranho que haja necessidade de "confirmação" para poder se juntar a uma rede protegida. Porém este comportamento deve-se a alguns fatores que originalmente (em rede P2P) nós ignorávamos. Por exemplo, até hoje, para poder conectar em uma rede é necessário uma estrutura física (como cabo de rede, acesso ao hub/switch, etc) e eventualmente alguma configuração. Partindo deste princípio, qual o sentido de "impedir" o acesso de quem teve todo este trabalho para conectar? Mas quando gradualmente fomos migrando para redes wi-fi, onde a conexão já não depende mais de cabeamento, ou seja, basta "estar na área" de cobertura daquele wi-fi e já podemos nos conectar. Daí surgiu a necesidade de termos a "senha" do wi-fi (início dos procedimentos de segurança), onde em teoria, há pelo menos alguém que passa a senha, que faz o trabalho (ou deveria) de permissão para se juntar na rede. O que a maioria não percebeu (e ainda não percebe) é que apenas as senhas de wi-fi não bastam para dar segurança à rede. É muito comum atualmente, encontrarmos em trocentas redes abertas, a maioria nos estabelecimentos comerciais ou de serviços (médicos, dentistas, etc) onde a senha é visível (placas, facebook) e estas redes estão permitindo a todos que nela se conectem poderem utilizar quaisquer recursos desta mesma rede, ou seja, qualquer pessoa com um celular pode acessar os documentos, impresoras e quaisquer outros recursos que a rede disponha. Eu pessoalmente utilizo desta artimanha para vender meus serviços em muitos consultórios médicos e lojas, demonstrando a facilidade do vazamento de dados e informaçòes condifenciais. A maioria destes clientes (99%) não tem noção que a rede deles está completamente aberta! Claro que ao mesmo tempo, por outro lado, são pouquíssimas pessoas que detém o conhecimento para fuçar na rede (por exemplo nós aqui do fórum ou qualquer outro programador). A maioria das pessoas que se conectam pela senha do wi-fi nas redes comenricais que existem hoje é para poder utilizar a internet mesmo. Já com o advento das redes "remotas", onde o usuário pode se conectar na rede interna (intranet) através da rede externa (internet), começaram a surgir procedimentos, protocolos e programas para "limitar" esta conexão, como VPNs e autorização de conexão (protocolo de confiança), muito utilzado até mesmo em redes internas através do Active Directory. Ou seja, o procedimento de autorizar um equipamento a ter acesso à rede (ou a outro equipamento) não é novidade. E agora neste mundo completamente w-fi então... Agora imagina a zona que seria se qualquer telefone se conectasse com qualquer outro através do Bluetooth e poderia ter acesso a qualquer informação, foto e vídeo que tiver no telefone alheio. E se alguém estivesse fuçando no seu telefone? Quais segredos e nudes acharia? kkkkk Mas vamos conversar mais, também me interessa essa questão de usar o Bluetooth para conectar e conversar entre dispositivos. Parabéns pela iniciativa, Belini.
  6. Dicas e truques

    Olá pessoal. Aproveitando o feriado de carnaval, que dependendo da região é mais ou menos comemorado, quero abrir um tópico para que todos possam dar sua contribuição em dicas, macetes e truques ao utilizar o AutoIt. Afinal todos nós, de uma maneira ou outra, ao fazermos nosso scripts, utilizamos as vezes sem nem mesmo pensar, alguma dica ou macete. Vou tentar manter compilado aqui no 1o post, essas dicas. Não tem sequência, nem melhor nem pior. Só uma lista! 1) a diretiva #include serve para incorporarmos códigos já prontos referentes a um determinado tópico aos nossos scripts. Ao utilizarmos o #include tem duas maneiras, que passam desapercebidas: #include <> com os sinais de maior e menor, que identifica um arquivo que será procurado e incorporado a partir da subpasta Include da pasta principal do AutoIt #include "" com as aspas, que identiica um arquivo que está na mesma pasta do script, facilitando assim para desdobrar o script em vários outros scripts menores para facilitar a edição ou manutenção Exemplos: #include <Misc.au3> - estamos procurando o arquivo Misc.au3 que está na pasta Include #include "MeuScript.au3" - estamos procurando o arquivo MeuScript.au3 que está na mesma pasta do meu script stual Aqui fica uma segunda dica que eu utilizo. Quando o script passa a ser meio genérico, tipo uma biblioteca de scripts em comum a vários projetos (vide o tópico Framework), eu costumo criar um link simbólico do arquivo na subpasta Include. Dessa forma, tenho o melhor dos dois mundos, pois mantenho o script "à mão" e ao mesmo tempo ele está disponível para qualquer projeto, sem criar uma cópia do mesmo e correndo o risco de ficar com arquivos desatualizados. 2) Já aconteceu a situação de vc testar seu código e as mensagens estarem em português correto (ou com acentos) mas ao compilar o mesmo script, ele aparece com alguns caracteres malucos no lugar dos acentos? Outra situação é quando eu vejo o pessoal reclamando do erro UTF-8 ou UNICODE ao compilar algum script, principalmente do fórum gringo. Isto acontece porque ao escrevermos nosso códigos no SciTe (assumindo que vc use o editor padrão do AutoIt), os códigos são escritos utilizando o código de página Windows 1252, que preserva os acentos e demais caracteres diferenciados da nossa língua portuguesa e similares. Porém, várias ferramentas do AutoIt e outras exigem UNICODE como forma de codificação. Não vou entrar em detalhes aqui (não é local para isto), mas minha recomendação é que vcs modifiquem o SciTe para que todos os seus scripts sejam gravados em UTF-8 with BOM, que é um padrão internacional UNICODE. Assim, vc ganha de várias formas: os acentos que estão no seu código em desenvolvimento serão transferidos adequada e corretamente para a versào compilada pode-se trocar scripts (ou compartilhá-los) nos fóruns estrangeiros sem problemas as ferramentas do AutoIt e outras externas não reclamarão da codificação do arquivo. Mas atenção, ao fazer esta modificação é necessário abrir o script, mudar a codificação e conferir o script para as mudanças que possam surgir, principalmente nas mensagens ao usuário. Ao salvar o script, ele já será salvo nste novo formato. Para fazer isto, com o script aberto no SciTe, vá no menu FILE, opção ENCODING e troque de Code Page Property para UFT-8 with BOM e salve seu script ou feche o editor, salvando o arquivo. Finalmente este procedimento é necessário ser feito em todos os seus scripts, o que dependendo da quantidade, pode ser um processo longo e trabalhoso/tedioso, assim vou colocar em outro tópico um script para fazer este processo de forma automática (a conversão apenas). Mesmo assim é importante que os scripts sejam conferidos. Veja aqui => Conversão de Codificação dos Scripts E vem mais por aí... A comunidade agradece!
  7. Dicas e truques

    Agora vou falar sobre alguns programas externos que eu uso diariamente, que me ajudam um monte ao fazer minhas tarefas. 1) WInMerge = https://winmerge.org/ O WinMerge é um comparador de arquivos. Sua principal função é comparar arquivos estilo TXT (como scripts) e mostrar as diferenças entre eles. Serve também para quaisquer outros tipos de arquivos, mas nos arquivos estilo TXT é que ele mostra sua força. Quer comparar 2 fontes? Quer comparar 2 arqs INI? Quer comparar sei lá o que? WinMerge te ajuda. Ele mostra linha a linha as diferenças e ainda permite que vc copie de um lado para outro se vc quiser. Compara até pastas, informando quais arquivos são iguais e quais são diferentes. E quando vc escolhe um arquivo, ele detalha como expliquei acima. 2) GrepWin = https://tools.stefankueng.com/grepWin.html Para efetuar pesquisas dentro dos arquivos, o GrepWin é fantástico. Eu uso muito para encontrar referências dentro dos scripts da pasta Include por exemplo, mas ele serve para qualquer tipo de pesquisa. É só clicar com o botão direito na pasta que vc quer procurar e informar o que procurar que ele sai vasculhando. Tem pesquisa Regex, mostra os arquivos e trechos onde achou o item pesquisado e até mesmo pode ser usado para REPLACE. 3) Everything = https://www.voidtools.com/ Sabe aquele search de arquivos do Windows que leva uma eternidade para localizar o que vc quer? Mande pro inferno... O Everything é extremamente rápido e encontra tudo que vc quiser em questão de segundos (se não antes). Precisa procurar um arquivo pelo nome? Mesmo parcial? Não sabe qual pasta ele está? Vc sabe quantos arquivos .MP3 vc tem? Ou .JPG? A medida que vc vai digitando os nomes na barra de pesquisa, ele vai filtrando os resultados. Por exemplo: .PDF - mostra todos os PDFs que tem na máquina .PDF jorge - mostra todos os PDFs que tem o nome jorge (em qualquer llugar do nome) .PDF jorge contratos\ - mostra todos os PDFs com o nome jorge na pasta contratos E assim por diante. Com os recursos de AND, OR e NOT, vc tem um poderoso procurador de arquivos instantâneo! Outro ponto positivo, no português brasil, é que ele ignora acentos e cedilha. Assim ao procurar "declaracao" ele acha "declaração" tbm!! Mesmo assim, para procurar DENTRO dos arquivos, ainda recomendo o GrepWin ou o FileSearchy (como 2a opção). 4) Ditto = https://ditto-cp.sourceforge.io/ Um gereciador de clipboard. Não sabe o que é isso? Lembra do copia-e-cola? CTRL-C e CTRL-V que usamos diariamente? Pois é, pense nisso como um turbinador dessa função. Com o Ditto, vc pode guardar até os últimos 500 recortes. Sabe quando vc copiou um trecho de alguma coisa e entre uma coisa e outra ao colar, colou outra coisa que vc copiou nesse meio tempo? Pois é. Com o Ditto, vc pode recuperar o que foi copiado, sem precisar copiar de novo! Nunca pensei que usaria um destes. Até fui muito resistente a instalar este programa. Hoje não vivo mais sem ele! Não muda nada no CTRL-C e CTRL-V normal, mas facilmente vc pode olhar, selecionar e até pesquisar os últimos CTRL-C que foram feitos e o melhor, reaproveitá-los! Hoje eu uso para salvar senhas da repetição, códigos, informações que posso usar depois. É muito prático. E daí O que acharam? Tem outras recomendações? Eu uso mais uma penca de aplicativos aqui... Inclusive vários eu cobro para instalar/configurar para os meus colegas advogados (hehehehe)
  8. Olá. Para o SO (sistema operacional), um arquivo precisa se encaixar nas definições de um programa executável quando: termina com a extensão .COM ou .EXE ou .BAT (arquivo auxiliar) ou .CMD (arquivo auxiliar mais novo) ou qualquer outra reconhecida pelo SO obedece alguns critérios técnicos (como identificação do PE, Data table definida, etc) específico para cada tipo de arquivo existem prerrogativas de segurança para executar o arquivo (usuário, regras, controle de domínio, etc) Finalmente se todas estes pré-requisitos forem observados, o arquivo será executado, ou seja, é carregado na memória e transferido o controle à primeira instrução dele. Portanto, o arquivo executável é exatamente como outro arquivo qualquer dentro do computador, seja ele uma foto, uma música, um vídeo, um documento... A única diferença que existe é que em vez de ser um arquivo tipo secundário (que precisa de um outro programa para utlizar), ele pode ser uma extensão (nativa ou não) do SO. Infelizmente aqui no Brasil, nossos procedimentos de segurança não são lá grande coisa e por uma questão cultural nos acostumamos a ser sempre o proprietário, dono e senhor do computador e seus programas, inclusive o SO. Isto inclusive explica a nossa resistência, enquando sociedade a não pagar pelos programas que utilizamos. Fica difícil se preocupar com se nossos scripts serão ou não copiados ou descompilados, numa clara preocupação com nossos direitos autorais, aprendizado e esforços, porém na maioria dos casos, desrespeitamos os direitos autorais dos outros sem discriminação, ao piratear um Windows, um Office ou qualquer outro software do mercado. Mas, tirando esta questão da frente e nos focando no problema em questão, a trava no executável (se houvesse), deveria ser de responsabilidade que quem o criou e não do SO. O próprio programa, poderia em sua inicialização, deveria fazer um auto-diagnóstico e caso se identifique identificado, se auto-encerra. Porém esta abordagem traz algumas dificuldades técnicas: muitos desenvolvedores não se preocupariam com este auto-diagnóstico (preguiça) a verificação só pode acontecer com um código de segurança, checksum por exemplo, se este mesmo checksum for externo, pois não há como inserir um checksum no meu próprio programa sem alterar o valor do próprio checksum. Se fosse um checksum parcial, abre uma brecha para modificação, daí não serve (impossibildade técnica) finamente, se o programa se auto-diagnosticar como infectado, mesmo que ele auto-encerre, o objetico do vírus já foi alcançado, pois o vírus vem antes do programa, então no momento que o programa se verifica bichado, é porque o vírus já foi para a memória (atraso) A partir daí, para evitar esta situação, seria necessário que o SO fizesse uma verificação antes de carregar o programa, que aliás isto não é tarefa dele (SO), mas do sistema de segurança (AVs). Assim mostramos que mesmo que haja um mecanismo de auto-bloqueio, ele seria inútil por parte do desenvolvedor. E confiar em um software de segurança, por melhor que ele seja, sempre haverá exceções, falhas, janelas de reconhecimento, etc, ou seja, não há como evitar uma virose surja e se instale. Porém podemos e devemos tomar algumas medidas protetivas que não só protegem os programas mas também o ambiente que trabalham (SO): manter nosso SO atualizado, limpo e não corrompido usar programas de segurança confiáveis e comprovadamente eficazes (ou no mínimo que sejam menos furados!!!!) utilizar softwares somente de fontes confiáveis ou verificáveis (quase impossível) utilizar as prerrogativas de segurança do próprio SO, como usuários limitados e restrições de segurança de arquivos bloquear os arquivos executáveis para serem apenas lidos e/ou executados mas nunca gravados ou modificados (com restrições de gravação e não atributo RO) aceitar as restrições De qualquer maneira, depende muito mais do usuário (e das configurações aplicadas no computador) do que propriamente do desenvolvedor. E mesmo assim, existe a possibildade de uma infecção acontecer devido a fatores ainda desconhecidos. Posso citar aqui como exemplos: erro do caminho da DLL: ao fazer a chamada a uma DLL (coisa comum em programas), foi descoberto que havia um erro na chamada do SO e se houvesse uma DLL com o mesmo nome na mesma pasta do programa, esta seria chamada em detrimento à DLL original pretendida modificação do processo de carregamento: muito utilizado pelos vírus envelopadores ou até mesmo os teimosos mesmo, resulta de uma modificação do mecanismo de chamada do executável (por exemplo mudança no registro) de tal forma que quando qualquer executável seja chamado, uma nova cópia do vírus é executada antes do programa original injeção de DLL ou SQL: quando um malware se auto-coloca em uma seção de memória de um programa conhecido, de tal forma que o programa original ao chamar esta porção de código, execute o vírus e tem mais trocentos exemplos... Como disse o @mutleey, as instruções são inseridas em código de máquina e a qualquer momento possível onde haja uma brecha para tal. A última ideia do @Belini é a mais correta de se usar atualmente, porém demanda que o usuário aceite as restrições impostas a ele para sua própria proteção, o que culturalmente nunca vai ocorrer por livre e espontâna vontade. Veja o caso que estamos falando onde o usuário não usa o AV porque não deia ele trabalhar. O problema é tão grande que ele (usuário) não percebe o absurdo da situação e ainda reclama do AV, que está tentando ajudar. Finalmente, tem vários softwares de segurança que ao fazerem a varredura, montam seus próprios checksum (CRC) para identificarem quando houve alterações nos programas e a partir daí, conseguirem bloquear as infecções futuras. Porém o mesmo remédio que ajuda, também atrapalha, pois mudanças legítimas nos progamas (versões novas por exemplo) não são aceitas. E se o software perguntar se houve uma alteração e se o usuário confirma a modificação (até para substituir pelo novo checksum), é o espaço de abertura necessário para um malware se instalar, e por onde passa boi, passa boiada!!!! Mas e o que vc acham? Teríamos como poteger mais nosso sistemas (progs e SO)???
  9. @Belini Em teoria, vc deixar o arquivo sem extensão poderia ser uma solução no seu caso, onde os programas são chamados por você através do Run. Em termos genéricos não resolve o problema dele. Mas isso pode depender de onde o vírus fez seu gatilho, se na chave do registro do arquivo tipo .EXE ou na chamada de execução do SO para eecutáveis. Se for no registro, este método resolve. Mas é inacreditável que um cara esteja tão "sujo" que não percebe a situação ridícula que se colocou, a ponto do AV "não deixar ele trabalhar"! Caramba! @mutleey A ideia é boa, eu mesmo utilizo em alguns clients esta mesma técnica, mas o ideal é desativar o autorun geral, pois caso algun pendrive estranho (ou sem a pasta) apareça, daí recomeça o ciclo de infecção. Uma outra técnica que existe, quando vc não quer ativar o autorun para um determinado dispositivo (pendrive ou HD) é segurar o SHIFT enquanto espeta o dispositivo. Mantendo o SHIFT pressionado diz pro SO não ativar o autorun para aquele dispositivo. Segue um arquivo de registro que eu uso para desativar os autorun de todos os drives. AutoPlay for all drives - Disable.reg
  10. Olá. Exatamente pelo mesmo motivo que vc não consegue sobrepor os arqs que vc quer descompactar, pois estão em uso. Vc até pode mandar um HD limpo para seu cliente, mas avise ele que: Tenha um antivírus atualizado, qualquer um, pode até ser o Avast mesmo (arghhh) Limpe os pendrives Se estiver na rede, tem que desinfectar a rede também Enquanto ele não fizer isto, continuará a ser reinfectado eternamente (e mais 6 meses depois - dizia um colega meu de faculdade kkk) Mas ambos os vírus que vc citou são bem antigos. Qualquer AV de hoje pega e elimina antes de dar problema. O Sality é o mais chato, porque é um envelopador, o outro é apenas um keylogger. Provavelmente o Sality deve estar em algum programa que ele utiliza que não está no HD que vc mandou ou até mesmo em um pendrive infectado, portanto começe desativando o AUTORUN das mídias removíveis. Isto ajuda bastante. Para identificar o arquivo zero, tem que varrer TODOS os HD e mídias removíveis, até mesmo CD's que podem ser sido infectados previamente à gravação. Como esta é a minha linha principal de trabalho, sei que este tipo de vírus é muito chato de remover, pois o cliente sempre tem um arquivo infectado em algum lugar que depois reinfecta tudo novamente! É um saco mesmo. Boa sorte!
  11. Olá Belini. Suponho que vc está fazendo um backup (zipado) dos arquivos executáveis para alguma eventual contaminação por vírus, principalmente dos envelopadores, correto? Não concordo com sua estratégia porque vc estaria resolvendo a consequência e não a causa! E se realmente houver um vírus, mesmo que a cada nova geração de arquivos limpos seja extraída, eles serão novamente reinfectados gerando um loop, ou pior, um dead lock! Mesmo assim, estou recomendando uma biblioteca de compactação para utilizar para decompactar os seus arquivos. Acredito que vc já tenha utilizado (ou conheça) esta, mas foi a melhor que encontrei até agora, com uma taxa de compressão muito boa e bem simples de utilizar. É a que eu uso nos meus projetos. O único problema é que é necessário enviar uma DLL junto para que o processo possa ocorrer. E para contornar este problema, eu utilizo com o FileInstall. Segue o link do fórum americano porque por algum motivo não estou conseguindo anexar a LIB na resposta (https://www.autoitscript.com/forum/topic/85094-7zip/). Voltando ao problema original que vc descreveu, que é a confirmação da sobregravação dos arquivo EM USO, eu diria que é impossível. É exatamente por este motivo que o próprio Windows pede para reiniciar, pois ele não consegue nem sobrepor os próprios arquivos que estão em uso, portanto não teria como fazer isto diretamente. Porém uma alternativa (sem considerar reiniciar a máquina), seria a de utilizar um terceiro programa (ou helper) para efetuar esta tarefa. Este helper pode ser um programa especialmente criado para isto ou uma cópia do próprio programa inicializado especificamente para este fim (minha técnica preferida). De qualquer maneira é preciso um programa externo. Isto SE os arquivos (executáveis ou não) estiverem em uso. E finalmente, caso a mensagem de sobreposição não seja mostrada (ou ignorada) e o arquivo não seja sobreposto (dá erro mas não mostra isso), vc não resolverá o problema, visto que o arquivo infectado não seria sobreposto e continuaria sujo, ou seja, de volta ao início!
  12. Dicas e truques

    2) O outro aquivo a ser modificado, se quiser, é o arquivo das Abreviações. Abreviações, para quem não conhece é uma maneira bem legal de facilitar a codificação, pois reduz bastante a digitação (e obviamente os erros) por aceitar atalhos. Funciona mais ou menos assim, vc está escrevendo o código e vc vai fazer um ConsoleWrite, daí em vez de digitar o comando inteiro, vc digita cw e pressiona Ctrl B E o editor "escreve" o comando inteiro e ainda coloca um @CRLF no final, ou seja, faz o trabalho por vc. Mamão com açúcar. Existem "trocentas" abreviações. Tbm não tem como saber tudo e nem precisa, mas pelo menos algumas são obrigatórias (como o CW, por exemplo). Outra que gosto muito é o incl, depois Ctrl B, e vc sai digitando o nome do arquivo de include que vai sendo preenchido o nome correto e vc encerra com Enter!!! Para conhecer as abreviações olhem o arquivo "C:\Program Files (x86)\AutoIt3\SciTE\au3abbrev.properties", ou entrem no SciTe, menu Options, opção Open Abbreviations File, mas se precisarem editar para criar novas abreviações usem a Menu Options, opção Open au3UserAbbrev.properties, porque se vcs editarem o arquivo principal, ao atualizarem o SciTe, as alterações serão perdidas, então trabalhem sempre nos arquivos tipo USER. Vc pode criar quantas abreviações quiser com quaisquer combinações malucas de letras, desde que não conflitem com as originais, claro. Um detalhe interessante ao criar/editar abreviações é que o I (pipe) é a posição onde o cursor vai ficar após o Ctrl B, ou seja vc mesmo coloca o cursor onde ele deve ficar. Tipo (exemplo meu): cw[=ConsoleWrite("[" & | & "]" & @CRLF) Neste caso, ao digitar cw[ e pressionar Ctrl B, vai escrever todo o comando do ConsoleWrite, e deixar o cursor exatamente no local para inserir uma variável! Isto é muito legal! outro exemplo: ""=" & | & " Aqui, após o Ctrl B, as aspas duplas são subtituídas por abre e fecha string e deixa no local para continuar o código. Depois que vc acostuma com isso, é muito mais rápido de trabalhar e ajuda "paracamba"! Mudando um pouco, acredito que todos utilizem o recurso de hint, até porque ele está ativo por default. O recurso de hint é aquele que ao escrever uma função do AutoIt, ele apresenta os parâmetros que vc deve preencher, inclusive acompanhando a medida que vc os escreve. E para aquele que não conhecem (acho difícil), pressionar F1 em um comando ou função qualquer do AutoIt, abre o Help focalizado nesta função, o que é bem útil em algumas situações! Alguém aí tem mais alguma dica?
  13. Dicas e truques

    Olá. Dando sequência na ideia de customizar o SciTe, para fazê-lo basta editar os arqs de configuração. Isto pode ser feito de dentro do editor, pelo menu Option e selecionando o arquivo a ser modificado, Ou editando estes mesmos arquivos externamente através do bloco de notas (ou similar). Porém se fizer isso, recomendo que o SciTe esteja fechado para evitar que as alterações não sejam gravadas ou sejam sobregravadas quando o SciTe fechar. De qualquer maneira, editando estes arquivos (e quaisquer outros) pode aumentar o seu controle sobre o SciTe e deixar o seu ambiente de trabalho mais amigável. Vamos aos arquivos: 1) Menu Options / Open User Options File, ou externamente edite o arquivo "C:\Program Files (x86)\AutoIt3\SciTE\SciTEUser.properties" Este arquivo controle várias configurações do SciTe, em particular algumas das mais interessantes como: highlight.current.word=1 => para realçar a palavra onde está o cursor e podermos visualmente identificar as iguais no resto do código. Dica: quando fizer isto, normalmente mostra somente na tela as palavras iguais. No momento que vc move o cursor, vai selecionar outra palavra. A dica aqui é usar o botão do meio do mouse para rolar e ver as demais coincidências no resto do script highlight.current.word.minlength=3 => identifica qual o mínimo de letras para realçar uma palavra use.tabs=0 => para escolher entre tabulação ou espaço nas identações. Pessoalmente prefiro espaços, ou seja, quando eu aperto o TAB o SciTe insere x espaços a cada TAB. Para usar o TAB mesmo, coloque use.tabs=1 tabsize=3 => para escolher quantos espaços serão inseridos a cada TAB indent.size=3 => para escolher quantos espaços serão inseridos a cada nova linha para manter a identação highlight.current.word.stoponspace=0 => quando vc seleciona com o Shift uma quantidade maior do que uma palavra, tbm funciona o realce, porém ao chegar no primeiro espaço, para de realçar. Com esta opção, não para. Eu acho ótimo para comparar visualmente 2 linhas de código, pois ao marcar com o Shift, vai mostrando se a outra linha está igual. As vezes, uma pequena diferença como um apóstrofe é ruim de ver, mas no realce é fécil de ver. Tbm para mexer nas cores do editor, mexa nas seguintes configurações #Background -> style.au3.32=style.*.32=$(font.base),back:#F0F4F9 # CaretLineBackground -> caret.line.back= # Brace highlight -> style.au3.34= # Brace incomplete highlight -> style.au3.35= # White space -> style.au3.0= # Comment line -> style.au3.1= # Comment block -> style.au3.2= # Number -> style.au3.3= # Function -> style.au3.4= # Keyword -> style.au3.5= # Macro -> style.au3.6= # String -> style.au3.7= # Operator -> style.au3.8= # Variable -> style.au3.9= # Sent keys -> style.au3.10= # Pre=Processor -> style.au3.11= # Special -> style.au3.12= # Abbrev=Expand -> style.au3.13= # Com Objects -> style.au3.14= # Standard UDF's -> style.au3.15= As minhas cores são basicamente o padrão, porém eu gosto de usar uma cor amarela para realçar a linha atual que estou trabalhando. Então eu mexi na linha caret.line.back=#FFFA2B Se fizer isto por detro do prório editor, ao pressionar Ctrl S para salvar, a mudança aparece na hora. Para ajudar a selecionar cores e os seus códigos eu recomendo 2 sites, onde vc pode selecionar as cores e copiar o código hexa ou informar o código hexa e ver a cor desejada: https://www.colorschemer.com/color-picker/ https://www.rapidtables.com/web/color/RGB_Color.html
  14. Dicas e truques

    Olá. Vc sabia que o SciTe é um baita editor (para AutoIt, pelo menos)? Claro que tem outros como o Sublime ou até mesmo o EditpadLite. Sem falar nos específicos, como o ISN Auto Studio. Mas vamos nos ater ao SciTe, por enquanto. As vezes, usamos só o básico por desconhecimento das funções mais "cabeludas", mas igualmente interessantes. E tbm, com um pouco de ajustes, vc pode personalizar mais ainda o SciTe. Minha sugestão é começar baixando o SciTe atualizado aqui => https://www.autoitscript.com/site/autoit-script-editor/downloads/ O SciTe é uma versão do editor Scintilla, especificamente ajustado para o AutoIt (ambos freeware). O Scintilla/SciTe está na versão 4.3 e o mais atualizado para o AutoIt é a versão 4.2. Sempre tem melhorias e mudanças, por isso recomendo volta e meia, dar uma olhadinha para ver se tem alguma versão mais atualizada. Ao baixar e instalar o SciTe atualizado (v4.2), ainda podemos fazer mais alguns ajustes finos nele. Recursos que eu uso com frequência: Abreviações (excelentes) Duplicar uma linha ou um bloco mais fácil do que usar o Ctrl C e Ctrl V é pressionar Ctrl D Localizador de funções = Alt L Para pular direto para a função = com o cursor na função digite Ctrl J e vai pra função, pode mexer à vontade daí Ctrl Shift J volta pro ponto anterior (muito bom). Serve inclusive para as funções internas do AutoIt (para tirar alguma dúvida ou apenas para estudo mesmo) Bookmarks = marca pontos no script e permite ir e voltar para eles rapidamente. Ctrl F2 para criar um bookmark e apenas F2 para trocar entre eles. Pode criar quantos quiser. Só existe enquanto não fechar o editor. Para abrir um include rapidamente = vá a té a linha do include e pressione Alt I (alt i) Em scripts grandes, clique no menu View e depois em Toogle All Folds, para "encolher" todas as funções. Faça novamente para "abrir" tudo de novo. Muito útil para navegar para cima e para baixo. Se quiser "encolher" manualmente cada bloco de código (pode ser uma função, um IF, um FOR, um WHILE, várias linhas de comentários, etc) pressione o + (sinal de mais) do bloco numérico. Pressionando novamente, "abre" o bloco Para comentar/descomentar linhas de código pressione o - (sinal de menos) do bloco numérico. Serve para a linha atual, não importa onde está o cursor. Se quiser fazer com várias linhas, marque as linhas e pressione a tecla para comentar/descomentar Ao pressionar o TAB ou Shift TAB, vc pode aumentar ou reduzir a identação do seu código. Para várias linhas, marque as linhas e aperte o TAB. Funções não tão comuns, mas tbm úteis: Para criar um cabeçalho de função (para fins de documentação) = Ctrl Alt H. Tem como ajustar os detalhes permanentemente Opção avançada para trabalhar com várias linhas ao mesmo tempo, como se fosse o TAB, mas para escrever, apagar ou editar: vá até a linha que inicia o bloco e deixe o cursor no local correto, agora mantenha pressiona o Shift e o Alt e clique com o mouse no ponto onde vc quer marcar o bloco. Se fizer certo vai aparecer um "cursorzão". Tudo que digitar ou apagar será replicado para as outras linhas. No mesmo estilo, vc pode usar "blocos verticais". O padrão do Scite é usar blocos horizontais, ou seja, ao marcarmos um bloco as "linhas" são marcadas. Porém eventualmente precisamos marcar um bloco "vertical", que seria um bloco no meio das linhas, não sei se fui claro... Neste caso, ponha o cursor no início do bloco a ser marcado e depois segurando os mesmos Shift e Alt, clique aonde (qual coluna) vc quer marcar o fim do bloco. Com o bloco marcado, pode usar quaisquer opções (Ctrl C, Ctrl D, Del, etc). A diferença entre um cursorzão e o bloco vertical é a coluna onde vc está clicando para marcar o fim do bloco. Se clicar numa coluna IGUAL à do cursor, gera um cursorzão, se clicar em uma coluna diferente, gera um bloco vertical. E daí? Vcs tem mais algumas dicas? Vamos lá! Próximo post será sobre como customizar o SciTe (se quiser).
  15. Olá. Para converter seu script basta informar a pasta raiz onde estão armazenados os seus scripts e mandar ver. Eles serão convertidos para o padrão UTF-8 with BOM, com vários benefícios. Não esqueça de fazer uma cópia dos seus arquivos ANTES da conversão pois se der alguma coisa errada, poder fazer novamente (se ainda quiser). #include <File.au3> #include <Array.au3> #include <FileConstants.au3> #include <MsgBoxConstants.au3> If not CONVERSOR_ENCODING("C:\Scripts") Then MsgBox($MB_OK, "Erro", "Problemas ao converter os cripts") EndIf Func CONVERSOR_ENCODING ($sPasta, $nEncoding = $FO_UTF8) If IsKeyword($nEncoding) Then $nEncoding = $FO_UTF8 Local $aArquivos = _FileListToArrayRec($sPasta, "*.au3", $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH) If @error Then Return SetError(1, 0, False) ConsoleWrite($sPasta & @CRLF) Local $sConteudo, $hArquivo, $nOld_Encoding = -1, $nNew_Encoding = -1, $sAtributos = "", $bMudou_Atributo = False For $nArquivo = 1 to $aArquivos[0] $bMudou_Atributo = False $nOld_Encoding = FileGetEncoding($aArquivos[$nArquivo]) $sAtributos = FileGetAttrib($aArquivos[$nArquivo]) If StringInStr($sAtributos, "R") Then $bMudou_Atributo = True FileSetAttrib($aArquivos[$nArquivo], "-R") EndIf If $nOld_Encoding = $nEncoding Then ConsoleWrite("> ") Else ConsoleWrite("! ") $sConteudo = FileRead($aArquivos[$nArquivo]) FileDelete($aArquivos[$nArquivo]) $hArquivo = FileOpen($aArquivos[$nArquivo], $FO_OVERWRITE + $nEncoding) ConsoleWrite(FileWrite($hArquivo, $sConteudo) & " ") FileClose($hArquivo) EndIf If $bMudou_Atributo Then FileSetAttrib($aArquivos[$nArquivo], "+R") $nNew_Encoding = FileGetEncoding($aArquivos[$nArquivo]) ConsoleWrite(StringFormat("%-100s", $aArquivos[$nArquivo]) & " = " & NOME_ENCODING($nOld_Encoding) & " => " & NOME_ENCODING($nNew_Encoding) & @CRLF) Next Return SetError(0, 0, True) EndFunc ;==>CONVERSOR_ENCODING Func NOME_ENCODING ($nCode) Local $aNomes = [ [ $FO_UTF16_LE, "UTF16 Little Endian" ], _ [ $FO_UTF16_BE, "UTF16 Big Endian" ], _ [ $FO_UTF8, "UTF8 (with BOM)" ], _ [ $FO_UTF8_NOBOM, "UTF8 (without BOM)" ], _ [ $FO_ANSI, "ANSI (containing char > 127 and < 255)" ] ] Local $nPosicao = _ArraySearch($aNomes, $nCode) If @error Then Return SetError(1, 0, "NÃO ENCONTRADO") Return SetError(0, 0, StringFormat("%40s", $aNomes[$nPosicao][1])) EndFunc
  16. Humm, então é por isso. Faz sentido. Belini, por questões pessoais, ainda usa uma versão mais antiga do AutoIt. Agora funcionou o exemplo.
  17. Show de bola! Agora deu boa. Parabéns!
  18. Criar e ler um banco de dados SQlite

    Olá. Eu pessoalmente sou muito fã de expressões regulares, mas eu acredito que neste caso, ela ficaria muito lenta. Um LIKE ficaria mais rápido, não?
  19. Como assim, flickers? Flickers são exatamente falha de vídeo, pois a frequencia de exibição está muito alta ou muito baixa. Quando vc fala em controlar a frequencia é exatamente para evitar o flicker. Neste caso, vc setou em 20ms, o que provavelmente na sua máquina não "flicka", mas é interessante testar em outras, para ter certeza do valor. E vc percebeu que o GIF tem o tamanho de 300x300, mas a janela que vc abriu tem 100x100? Quando falamos em redimensionar para caber, um GIF não é uma imagem estática que é facilmente ajustada pelo tamanho, inclusive tem várias técnicas para determinar a menor perda de qualidade no redimensionamento. Um GIF é basicamente um filminho, ou seja, para redimensionar para caber cada frame deve ser extraído, redimensionado e reinserido no GIF, e não vejo nenhuma função fazendo isso. Talvez, como a função é bem detalhada, colocar uma função de redimensionamento no meio dela, poderia funcionar. Especificamente, neste GIF que vc enviou junto são 3 imagens de 300x300. Eu mudei o tamanho para 100x100. Veja se serve.
  20. Está dando erro na variável ghGDIPDll Provavelmente, vc esqueceu de "abrir" a DLL adequada a ser armazenada em ghGDIPDll
  21. Olá Belini. Achei que vc já tivesse alguma. Segue a que eu uso. Só precisa ajustar o tamanho da janela ao tamanho do gif (se necessário). #include <GUIConstants.au3> #include "GIFAnimation.au3" #include <FileConstants.au3> #include <WindowsConstants.au3> Local $sPastaDestino = @ScriptDir, $sArquivoGIF = "\Hello.gif" If @Compiled Then $sPastaDestino = @TempDir FileInstall(@ScriptDir & $sArquivoGIF, $sPastaDestino & $sArquivoGIF, $FC_OVERWRITE) Else If not FileExists($sPastaDestino & $sArquivoGIF) Then ConsoleWrite("GIF não existe" & @CRLF) Exit EndIf EndIf Local $hWnd_Janela = GUICreate("Atualizando multimídia...", 220, 206, -1, -1, $WS_EX_TOOLWINDOW) Local $hGIF = _GUICtrlCreateGIF($sPastaDestino & $sArquivoGIF, "", 0, 0) If not @error Then GUISetState(@SW_SHOW) Sleep(5000) _GIF_DeleteGIF($hGIF) EndIf GUIDelete($hWnd_Janela) If @Compiled Then FileDelete($sPastaDestino & $sArquivoGIF) GIFAnimation.au3
  22. Criar e ler um banco de dados SQlite

    Buenas! Sempre que falamos em clonar um banco em memória, nosso objetivo é melhorar o tempo de resposta para funções de massa, como grandes e complexas consultas por exemplo, que talvez ao serem efetuadas a partir do disco (BD original) possam resultar bem mais lentas para apresentar os resultados. Grandes alterações no banco como inserção em massa de dados, alterações ou exclusões também podem ocorrer. Então, ao clonarmos o BD para a memória, temos que ter em mente que eventuais alterações feitas na memória podem ter 2 (dois) destinos: são ignoradas, ou seja o BD serve apenas para SELECTs e o que vale é o BD em disco; precisam ser salvas, ou seja, em algum momento, precisam ser descarregadas/efetivadas/replicadas em disco. Na opção 1, o problema está resolvido. Ignora-se o BD em memória e tudo bem! Na opção 2 o buraco é bem mais embaixo. Aqui temos novamente 2 (duas) possibilidades: efetivamos as alterações à medida que acontecem! Pessoalmente é a que eu utilizo por algumas razões: mantenho o BD em memória igual ao BD no disco (sincronização); caso ocorra alguma falha no equipamento (reset, falta de luz, travamento, etc) as alterações estão seguras; ao iniciar o script, carrego novamente o BD em memória, sabendo que é a última versão das informações e parto disto; não preciso me preocupar em descarregar as alterações posteriormente (no final do programa ou em algum ponto definido) e neste momento qualquer ganho de tempo que eu tive, foi por água abaixo, pois o tempo de gravação em disco de todas as alterações é enorme. Como fazemos isso? Após a clonagem do BD em memória, qualquer alteração ao ser executada, deve ser feita tanto em memória como em disco. #include <Sqlite.au3> ; incializa SQLite _SQLite_Startup() ; Abre BD em mmória Local $hBD_Mem = _SQLite_Open() ; Abre BD em disco Local $hBD_Disco = _SQLite_Open(@ScriptDir & "\BancoDeDados.db") ; ... ; Faz a clonagem conforme as técnicas explicadas em post anterior ; ... ; faz as eventuais alterações no BD mem e no BD disco _SQLite_Exec($hBD_Mem, "UPDATE Tabela SET Estado = "SC" WHERE Codigo = 425;") _SQLite_Exec($hBD_Disco, "UPDATE Tabela SET Estado = "SC" WHERE Codigo = 425;") ; faz as eventuais alterações no BD mem e no BD disco _SQLite_Exec($hBD_Mem, "DELETE FROM Tabela WHERE Idade < 18;") _SQLite_Exec($hBD_Disco, "DELETE FROM Tabela WHERE Idade < 18;") ; fecha tudo _SQLite_Close() _SQLite_Shutdown() Desta forma, mantemos os dois bancos de dados iguais e atualizados. E quaisquer consultas (SELECTs) devem ser feitos diretamente no BD em memória para obter um ganho considerável de velocidade! A outra possibilidade envolve não manter os 2 (dois) bancos equiparados ou sincronizados, mas fazer as alterações somente em memória e depois de tudo pronto, descarregar o BD da memória em disco. Este procedimento pode ser feito a qualquer momento, mas normalmente é efetivado na saída do programa (final do script). Para tanto, infelizmente não há um comando ou comandos que possam fazer isto rapidamente. Felizmente a partir da versão 3.6.x do SQLite, foi implemntadado a API de Backup, que permite fazer cópia do banco "on-the-fly" (com o banco aberto e operando). No fórum americano, tem um tópico sobre isto (cortesia do Belini que achou) e também tem uma função para fazer o backup: Se quiser ver o tópico original = https://www.autoitscript.com/forum/topic/108151-sqlite-backup-api-wrapper/ Vou anexar aqui uma versão modificada da original, já contendo as alterações sugeridas pelos integrantes do fórum naquele tópico e com algumas modificações minhas também. Para utilizar a função de Backup é bem simples. Segue exemplo: #include <Sqlite.au3> #include "sqlitebackup.au3" ; incializa SQLite _SQLite_Startup() ; Abre BD em mmória Local $hBD_Mem = _SQLite_Open() ; Abre BD em disco Local $hBD_Disco = _SQLite_Open(@ScriptDir & "\BancoDeDados.db") ; ... ; Faz a clonagem conforme as técnicas explicadas em post anterior ; ... ; faz as eventuais alterações SOMENTE na memória _SQLite_Exec($hBD_Mem, "UPDATE Tabela SET Estado = "SC" WHERE Codigo = 425;") ; faz as eventuais alterações SOMENTE na memória _SQLite_Exec($hBD_Mem, "DELETE FROM Tabela WHERE Idade < 18;") ; faz o backup do BD em memória de volta para o disco (recomendado ao final do script) _SQLite_Backup($hBD_Mem, @ScriptDir & "\BancoDeDadosCOPIA.db") ; fecha tudo _SQLite_Close() _SQLite_Shutdown() Mas conversando com um outro colega (meu ex-orientandor de mestrado) que é DBA, ele me comentou que alguns engines DBs aproveitam comandos de manutenção do banco (que exigem controle total sobre o mesmo) para efetivar algum tipo de cópia. Assim, fui pesquisar na documentação do SQLite e o comando VACUUM, que serve para fazer uma lmpeza interna do banco, a partir da versão 3.27 possui uma cláusula INTO que faz exatamente isto! Agora temos 2 (duas) opções de salvar o banco de dados da memória em disco. Faca os testes e veja qual a melhor (ou a mais rápida) que serve para o seu caso. A vantagem é que não precisa de uma função externa. #include <Sqlite.au3> ; incializa SQLite _SQLite_Startup() ; Abre BD em mmória Local $hBD_Mem = _SQLite_Open() ; Abre BD em disco Local $hBD_Disco = _SQLite_Open(@ScriptDir & "\BancoDeDados.db") ; ... ; Faz a clonagem conforme as técnicas explicadas em post anterior ; ... ; faz as eventuais alterações SOMENTE na memória _SQLite_Exec($hBD_Mem, "UPDATE Tabela SET Estado = "SC" WHERE Codigo = 425;") ; faz as eventuais alterações SOMENTE na memória _SQLite_Exec($hBD_Mem, "DELETE FROM Tabela WHERE Idade < 18;") ; faz o backup do BD em memória de volta para o disco (recomendado ao final do script) aproveitando o comando interno VACUUM _SQLite_Exec($hBD_Mem, "VACUUM INTO '" & @ScriptDir & "\BancoDeDadosCOPIA.db'") ; fecha tudo _SQLite_Close() _SQLite_Shutdown() Quanto à eficiência de gravação de volta em disco, temos que lembrar que estas funções, tanto a do SQLite como a do backup da SQLite, foram desenvolvidas tendo em mente uqe estes bancos estariam abertos, sendo utilizados por mais de 1 (um) usuário, portanto durante o procedimento de fazer a cópia, é possível que haja alterações por parte de outros usuários, sendo assim, a cópia já nasceria desatualizada. A API do Backup prevê isso e se necessário, recomeça a cópia par refletir estas alterações. Porém naturalmente que dependendo da quantidade de usuários conectados ou das alterações que estão sendo feitas, a cópia pode demorar eternamente! Outro ponto interessante a ser verificado é que o 5o (quinto) parâmetro da função de Backup é o tamanho do bloco que deve ser copiado. E por tamanho do bloco, temos que olhar a estrutura interna do banco de dados para entendermos melhor este parâmetro e o porque da fixação dele em 16. Todo banco de dados, internamente, possui as informações gravadas em blocos como se fossem páginas de um livro. Dentro da página tem as várias informações de vários registros. O procedimento de backup faz cópia de "x" folhas por vez (padrão de 16). Assim caso alguma dessas folhas sejam modificadas, ela recopia somente estas folhas que estão no bloco. Em teoria, quanto menor este bloco melhor, pois estaríamos reduzindo a recópia (se necessário), porém ao reduzirmos o tamanho do bloco, também aumentamos o tempo necessário para copiar tudo. Assim, aumentar o tamanho do bloco faz com que a cópia seja mais rápida, mas mais sujeita a recópias. Dependendo da situação, e eu estou imaginando que em 90% (ou mais) dos casos de SQLIte com AutoIt, os bancos são praticamente exclusivos, não tem niguém além do próprio script mexendo e também não há vários scripts rodando simultameamente na rede. Se for este o seu caso, pode aumentar o nro de blocos para 256 para obter uma melhor performance na cópia do banco ou até mesmo colocar o valor de -1, para que seja usada a velocidade máxima. Mas muito cuidado com estes parâmetros. Eles devem ser cuidadosamente considerados em razão do ambiente em que o banco de dados está sendo executado. _SQLite_Backup($hBD_Mem, $sCopiaBD, Default, Default, 256) ou _SQLite_Backup($hBD_Mem, $sCopiaBD, Default, Default, -1) SQLitebackup.au3
  23. Criar e ler um banco de dados SQlite

    Para clonar o banco de dados em memória, tem várias opções. Todas dá no mesmo, mas vc escolhe a melhor. Opção 1 (a mais rápida): #include <Sqlite.au3> ; inicializa SQLite _SQLite_Startup() Local $hBD_Mem = _SQLite_Open() ; importa os dados _SQLite_Exec($hBD_Mem, "ATTACH DATABASE '" & @ScriptDir & "\BancoDeDados.db' as Original;") _SQLite_Exec($hBD_Mem, "CREATE TABLE Dados AS SELECT * FROM Original.Dados;") _SQLite_Exec($hBD_Mem, "DETACH DATABASE Original;") ; fecha tudo _SQLite_Close($hBD_Mem) _SQLite_Shutdown() Opção 2 (a intermediária), precisa saber a estrutura do banco. É útil quando vc precisa mudar a estrutura ou precisa pegar apenas alguns campos: #include <Sqlite.au3> ; inicializa SQLite _SQLite_Startup() Local $hBD_Mem = _SQLite_Open() ; importa os dados _SQLite_Exec($hBD_Mem, "ATTACH DATABASE '" & @ScriptDir & "\BancoDeDados.db' as Original;") _SQLite_Exec($hBD_Mem, "CREATE TABLE IF NOT EXISTS Dados (Numeros TEXT);") _SQLite_Exec($hBD_Mem, "INSERT INTO Dados SELECT * FROM Original.Dados;") _SQLite_Exec($hBD_Mem, "DETACH DATABASE Original;") ; fecha tudo _SQLite_Close($hBD_Mem) _SQLite_Shutdown() Opção 3 (a mais lenta), mas é a que permite mostrar alguma coisa tipo uma barra de progresso. Útil quando a tabela é muito grande. #include <Sqlite.au3> ; inicializa SQLite _SQLite_Startup() Local $hBD_Mem = _SQLite_Open() Local $hBD_Disco = _SQLite_Open(@ScriptDir & "\BancoDeDados.db") If @error Then ConsoleWrite("Erro na abertura do banco de dados" & @CRLF) Exit EndIf ; seção que carrega a tabela em memória (array) Local $aConsulta, $nLinhas, $nColunas SplashTextOn("", "Inicializando banco de dados...", 600, 100, -1, -1, 1 + 32, "", 24) Local $nResultado = _SQLite_GetTable2d($hBD_Disco, "SELECT * FROM Dados;", $aConsulta, $nLinhas, $nColunas) Sleep(1000) SplashOff() ; importa os dados If $nResultado = $SQLITE_OK Then Local Enum $DB_NUMEROS ProgressOn("Atenção!", "Carregando banco de dados...", "0%") _SQLite_Exec($hBD_Mem, "CREATE TABLE IF NOT EXISTS Dados (Numeros TEXT);") For $nIndice = 1 to $nLinhas ProgressSet($nIndice / $nLinhas * 100, Round($nIndice / $nLinhas * 100, 2) & '%') _SQLite_Exec($hBD_Mem, 'INSERT INTO Dados (Numeros) VALUES ("' & $aConsulta[$nIndice][$DB_NUMEROS] & '");') Next ProgressSet(100, '100%') Sleep(250) ProgressOff() EndIf ; fecha tudo _SQLite_Close($hBD_Mem) _SQLite_Close($hBD_Disco) _SQLite_Shutdown()
  24. Criar e ler um banco de dados SQlite

    Entendi a questão da memória, mas daí não tem jeito de fazer isso diretamente. Vc trá que criar um "clone" do banco em memória e importar o conteúdo do BD em disco e a partir daí trabalhar só com o da memória. E se necessário, fazer as alterações em disco a medida que acontecem. Eu tenho um script assim. Ao iniciar, carrego todo o banco em memória, daí todas as consultas são no BD em memória e faço as gravações (eventuais) em disco simultaneamente. E os cartões? Como são divididos?
  25. Criar e ler um banco de dados SQlite

    Outra coisa. Quem fez o post americano tbm não entendia muito de BD ou estava começando. Em teoria, os passos são: vc abre o BD cria as tabelas internas e os relacionamentos inclue, altera, exclue ou consulta dos dados Os passos 1 e 2 ocorrem apenas uma vez, já o 3o passo ocorre gradativamente. Por isto que eu me arrepio quando vejo o código postado. If Not FileExists("database.db") Then $dbn = _SQLite_Open("database.db") _SQLite_Exec($dbn, "CREATE TABLE Dados (Numeros);") For $i = 1 To 10 $dados = "PM-S" & $i & "=02 05 06 08 15 20 23 26 28 30 35 36 38 43 45 47 52 54 55 56 66 68 71 74 75 PM-Q" & $i & " 10" $sql = "INSERT INTO Dados VALUES('" & $dados & "');" ;_Base_Execute($sql) _SQLite_Exec($dbn, $sql) Next Else $dbn = _SQLite_Open("database.db") EndIf Para começo de conversa, qual a diferença entre as linhas de abertura do BD com o _SQLite_Open? Se não existe o arquivo físico, abre o banco! E se existe, abre o banco? Não se deve confundir a abertura e criação do BD com sua manutenção. Eu faria assim: ; seção de abertura do BD $dbn = _SQLite_Open("database.db") _SQLite_Exec($dbn, "CREATE TABLE IF NOT EXIST Dados (Numeros TEXT);") ; seção de inclusão de dados For $i = 1 To 10 $dados = "PM-S" & $i & "=02 05 06 08 15 20 23 26 28 30 35 36 38 43 45 47 52 54 55 56 66 68 71 74 75 PM-Q" & $i & " 10" $sql = "INSERT INTO Dados VALUES('" & $dados & "');" _SQLite_Exec($dbn, $sql) Next Observe: a clásula IF NOT EXIST no comando CREATE TABLE (assim cria somente se a tabela não existir, evitando que a tabela seja zerada toda vez) o tipo TEXT para definição do campo Numeros. Apesar de opcional, é sempre importante colocar. Neste caso, o BD seria aberto, criado se necessário o arquivo físico e a(s) tabela(s) internas. Em um segundo momento, os dados seriam incluídos. Claro que olhando para o script, os dados seriam inclusos sempre, por isso que a inclusão só poderia acontecer em um script separado para alimentar o BD inicialmente (recomendado) ou uma condição que permitisse a inserção dos dados na tabela apenas uma única vez. ; seção de abertura do BD $dbn = _SQLite_Open("database.db") _SQLite_Exec($dbn, "CREATE TABLE IF NOT EXIST Dados (Numeros TEXT);") Local $aRegistro ; verifica se tem alguma coisa no BD _SQLite_QuerySingleRow($dbn, "SELECT COUNT(Numeros) FROM Dados;", $aRegistro) If $SQLITE_OK and not $aRegistro[0] Then ; se não existir NENHUM cartão, insere os dados ; seção de inclusão de dados For $i = 1 To 10 $dados = "PM-S" & $i & "=02 05 06 08 15 20 23 26 28 30 35 36 38 43 45 47 52 54 55 56 66 68 71 74 75 PM-Q" & $i & " 10" $sql = "INSERT INTO Dados VALUES('" & $dados & "');" _SQLite_Exec($dbn, $sql) Next EndIf Ok, agora temos um procedimento adequado para criar e inserir os dados (se necessário). Para criar um BD em memória basta mudar a linha $dbn = _SQLite_Open("database.db") para $dbn = _SQLite_Open() Porém, daí todos os dados colocados no BD desaparecerão quando e se o programa fechar ou a máquina desligar/reiniciar, etc Em compensação, as operações são super rápidas. Mas eu acho que a sua cartela pode ser desdobrada em campos menores. Seguindo o post anterior, me explique tbm o que são os nros? PM-S 1,2,3, etc - o que é? = 02 05 06 08 etc - imagino que são os nros sorteados na cartela PM-Q 1,2,3, etc - o que é? Pensei numa ideia maluca aqui, vamos ver se vinga ;)
×