sexta-feira, 29 de abril de 2016

Trocar a Url de update do ClickOnce *

Você publica seu programa para ser baixado em uma certa URL. E está tudo certo, faz outros deploys, os clientes baixam felizes. Então você resolve mudar a pasta que está usando para fazer o update, por quaisquer motivos. E o ClickOnce dá erro no update, porque baixou de urls diferentes, e recomenda que você desinstale o programa original, baixe o novo e instale de novo.

Existem diversos passo-a-passo na web de como fazer isso, incluindo mageui, alterações direto na configuração do projeto do programa, etc. A ideia é fazer um deploy intermediário, que estaria na pasta antiga, mas apontaria o update para a nova pasta. Não funciona, o clickonce ainda reclama da nova url.

O que funcionou de verdade foi colocar um url rewrite no web.config da pasta de publish original. Quando o programa bate nessa pasta, ela passa a devolver o conteúdo da outra pasta. Na outra pasta, o programa será baixado com a nova url de update. Este seria o código a adicionar no web.config da pasta antiga, dentro de <system.webServer>:

        <rewrite>

            <rules>
                <clear />
                <rule name="Redirect New Path" stopProcessing="true">
              
                    <match url="^(.*)$" />
                    <action type="Rewrite" url="/[aqui você coloca a nova pasta]/{R:1}" redirectType="Temporary" appendQueryString="true" />
               
                </rule>
            </rules>

        </rewrite>




* ClickOnce é uma ferramenta do Visual Studio para fazer deploys / updates nos programas que você cria lá

terça-feira, 8 de março de 2016

Erro ao iniciar o MySQL Workbench

Tive um erro tentando iniciar o MySQL Workbench. Erro de windows mesmo. Abri a janela de detalhes e tentei ver quais informações poderiam ser úteis para buscar. Me pareceram estas:

Fault Module Name:    KERNELBASE.dll
Error Code:                    e0434352

Busquei e comecei a achar as mais diversas coisas. Uma pessoa disse que teve que trocar de windows pra funcionar. Então lembrei que tínhamos acabado de desinstalar o Visual Studio da máquina, fazia alguns dias. E pensei que talvez isso tivesse levado algo do Workbench junto.

Entrei na página do Workbench pra reinstalar. Baixei. Na instalação, o programa detectou que faltavam um pré-requisito: Microsoft Visual C++ 2013 Redistributable Package (x86 or x64). Fui pra página de pré-requisitos. Baixei o C++. Instalei.

Ia continuar a instalação do Workbench. Mas parei, pensei e fui testar se o que estava instalado funcionava. E não é que o bichinho tinha voltado?

Postando porque pode ser que a pessoa ache um bilhão de soluções mirabolantes, do tipo reinstalar o windows, e não precisa de tudo isso.

quinta-feira, 8 de outubro de 2015

Problema com wi-fi no windows 10

E aí eu instalei o windows 10 no computador de casa antes de instalar no do serviço. Vai que dá algum problema, né?

Tudo lindo, rodando, testei alguns dias, sem problemas. Mandei instalar no do serviço. Fui pra casa. Cheguei hoje... Liguei... Bonitinho... Abre o browser... Pera, cadê a Internet? Será que ele apagou as configurações de wi-fi? Como assim, que wi-fi?

Pois é, nem a luzinha do note de wi-fi tava mais acendendo. Tentei reiniciar. Nada. A mensagem era que o serviço de Wi-fi (WLAN AutoConfig) não estava startado. Fui na esperança, mandei o Start, deu "Windows cannot start the WLAN Autoconfig service on local computer". Ah, que bom, starta no computador do vizinho pra mim então.

Quando fui instalar, ele relatou incompatibilidade do software de VPN. Mas em casa também tinha dado isso e correu tudo bem. De qualquer forma, fui lá e desinstalei. Cisco VPN, está em Programs and Features, no Control Panel. Reiniciei com shutdown -r -t 0 porque tava sem paciência. Nada. Tentei usar uma internet de cabo para verificar se os drivers estavam atualizados. Funcionavam normal.

Reiniciei de novo, dessa vez com shutdown -r apenas. Deu tela azul (aeeee! Conhecia a tela azul do windows 10 em menos de uma hora de uso neste computador!). Reiniciou. Estava normal. Minha wi-fi de volta.

terça-feira, 1 de setembro de 2015

Problemas com a biblioteca apache no android 6

Fiquei duas horas e meia tentando resolver ontem, mais uma hora e meia hoje. Meu problema era um erro que encontrei no meu projeto, com a biblioteca do apache, para fazer webrequests. Achava que o problema era a migração para o Android Studio. E eu não pretendo voltar ao eclipse.

O erro que aparece é:

"error: package org.apache.http does not exist"

Procurei na internet e encontrei diversas recomendações. A primeira foi adicionar uma biblioteca do apache na lista de dependencies. Adicionei, mas ele ainda não encontrava a classe org.apache.http.client.utils.URLEncodedUtils. Uma outra sugestão foi forçar o uso da biblioteca apache, colocando o código android { useLibrary 'org.apache.http.legacy' } no gradle.

Encontrei pessoas falando para usar uma biblioteca chamada Volley, que deve substituir a do apache. E pensei em ajustar o projeto para usar. Descobri que a LVL, biblioteca do android para verificar licença, não está adaptada. Não encontrei qualquer versão dela que estivesse. Mesmo a versão oficial do site. Só bastante gente xingando por não terem adaptado ainda, pois a versão Marshmallow do android (6.0) vai cortar a biblioteca apache.

Nesse momento, me dei conta de que tinha atualizado o arquivo gradle para usar a última API do Android, a 23, do Marshmallow, assim que migrei para o Android Studio. Estava usando a API 19 como máxima antes, muito atrasado. Mudei para 22. Tudo voltou a funcionar.

sexta-feira, 13 de março de 2015

Relacionamento 1:1 no Nhibernate

Ah, a alegria de fazer o relacionamento 1:1 funcionar no NHibernate! Faz anos que tento!

A solução descrita aqui é para FluentNHibernate e usando IAutoMappingOverride.

No map da classe que corresponde a entidade que tem o ID apontando para a outra, não precisa fazer nada. Já no outro map, é necessário colocar este código:
-
mapping.HasOne(m => m.[outra classe]).PropertyRef(b => b.[classe dona do map]);
-
-
Como a gente entende mais vendo código que falando, aqui vai o exemplo:
-
SQL
create table Mother
(
    ID int
)
-
create table Daughter
(
    ID int,
    Mother_ID int
)
-
-
Entidades
class Mother
{
    int ID { get; set; }
    Daughter Daughter { get; set; }
}
-
class Daughter
{
    int ID { get; set; }
    Mother Mother { get; set; }
}
-
-
Mappings
public class MotherMap : IAutoMappingOverride<Mother>
{
    public void Override(AutoMapping<Mother> mapping)
    {
        mapping.HasOne(m => m.Daughter).PropertyRef(b => b.Mother);
    }
}

-
public class DaughterMap : IAutoMappingOverride<Daughter>
{
    public void Override(AutoMapping<Daughter> mapping)
    {
    }
}

-

quinta-feira, 2 de outubro de 2014

Pontos em parâmetros no MVC - Problema com virtual directory

Tive um problema com meus parâmetros no MVC. Se você costuma mexer com MVC e já brincou com o routeConfig, sabe que pode mexer na Url como quiser. No meu caso, tudo que eu estava fazendo era passar uma string como parâmetro na url. E funcionava lindamente. Na minha máquina.

Subimos para o ambiente de homologação, tudo certo. Subimos para produção. O cliente pediu para subir temporariamente oculto por uma pasta. Fácil, virtual directory. Tudo funcionando, ótimo... Até aparecer um ponto entre as palavras que estavam como parâmetro. Foi lindo:

"The resource you are looking for has been removed, had its name changed, or is temporarily unavailable."

Muito bonito. Um 404. De uma página que existe. A diferença? O maldito ponto. E vai fazer busca por MVC dot parameter. Enfim, busquei e acabei encontrando uma solução para colocar no web.config: http://stackoverflow.com/questions/11048863/modules-runallmanagedmodulesforallrequests-true-meaning.

Logo abaixo, alguém pergunta sobre a vulnerabilidade da solução. Me deu insegurança. Ninguém respondeu. Mas, em um dos comentários, a pessoa cita outro post: http://stackoverflow.com/questions/20998816/dot-character-in-mvc-web-api-2-for-request-such-as-api-people-staff-45287

Apesar da solução aceita ser a mesma, logo abaixo alguém postou outra solução:

      <remove name="UrlRoutingModule-4.0" />
      <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />

Procurei apenas pelo trecho e achei lugares afirmando que seria mais segura, por ser menos aberta.

Fora isso, apenas uma coisa: para simular o erro com virtual directory não foi necessário ficar publicando diversas vezes. Apenas colocar o path a mais no routeConfig foi suficiente, o erro que aconteceu foi o mesmo.

quarta-feira, 23 de julho de 2014

Criando seu "bloco" de execução

Faz algum tempo que procuro um meio de executar códigos antes e depois da execução de um método, de forma limpa. Estava procurando isto especificamente por causa desde tipo de código:

    public void MyMethod()
    {
            BeginTransaction();

            try
            {

                    [meu código para executar no DB]

                    CommitTransaction();
            }
            catch (Exception)
            {
                    RollbackTransaction();
                    throw;
            }

    }

Este código é complexo de entender, e suja muito os métodos, principalmente se eu tiver que repeti-lo diversas vezes. Além disso, corre o risco, como já aconteceu, de eu esquecer de colocar alguma parte dele (por exemplo, o CommitTransaction).

Procurei um meio de colocar apenas um Attribute acima do método, e ele entender que quero cercar o método com o meu código. Descobri que é necessário mexer com um nível mais baixo, e até há uma biblioteca (paga) que posso baixar para fazer isso por mim.

Mas encontrei uma sugestão que, apesar de não ser tão limpa quanto colocar um Attribute, deixa o código simples e é como se você criasse um bloco de execução seu: http://stackoverflow.com/questions/6046382/suggestions-for-making-a-reusable-try-catch-block-in-c

Seguindo o exemplo, meu código acima ficaria assim:

    public void MyMethod()
    {
            InTransaction(() =>
            {
                    [meu código para executar no DB]
            });
    }

    protected void InTransaction(Action action)
    {
            BeginTransaction();
            try
            {

                    action();

                    CommitTransaction();
            }
            catch (Exception)
            {
                    RollbackTransaction();
                    throw;
            }

    }

Assim todos os métodos que forem usar transaction apenas precisarão ser colocados dentro desse bloco novo. Se for necessário retornar valor, a mudança nesse código seria esta:

    public T MyMethod()
    {
            return InTransaction(() =>
            {
                    return [meu código para executar no DB]
            });
    }

    protected T InTransaction<T>(Func<T> action)
    {
            BeginTransaction();
            try
            {

                    var result = action();

                    CommitTransaction();




                    return result;
            }
            catch (Exception)
            {
                    RollbackTransaction();
                    throw;
            }

    }

Assim é possível encurtar o código e diminuir os erros que podem ser cometidos ao programar.