Mar 11, 2016

Showing mercurial current branch in ConEmu prompt

As a long time git user, I had a relatively hard time when I started using mercurial CVS; one of the things that I really missed (this one goes to the list of annoyances) was the lack of support for showing the current branch in the console. In the following screenshot you can see that GIT console does show me the current branch (in the example, ofx)


Considering that I have a terrible memory and usually have at least 5 ~ 6 consoles open at any given time, it is not hard to conclude that, from time to time, I simply forget which is the current branch in each console. 

Since mercurial do not provide any help (other than keeping issuing hg branch command all the time ;), it happened, not once, but many times, that I found myself working in one console under the assumption that I was operating on branch Foo when in fact I was working in a completely different one.

Some days ago I had the idea of using mercurial hooks to detect when I am changing branches and setting the console prompt accordingly, but that did not worked out very well. To be fair, mercurial hooks worked as expected; the problem was that my hook was run by hg.exe process which itself is spawned from the console when one type, for instance, hg up -r Foo to change to branch Foo and this process (hg.exe) would need to change the PROMPT of its parent console, which is not allowed (at least AFAIK).

My next step was check whether ConEmu (it is not a secret that I'm in love with ConEmu ;))  had some support to achieve my goal and bingo! ConEmu support some extended ANSI codes, more specifically $E ] 9 ; 7 ; ”cmd“$E\  which allows one to execute the command specified in the string (cmd) and use its output as part of the PROMP string. 

With that information, I just created the following batch file:

@echo off
IF NOT EXIST .hg GOTO NOT_A_MERCURIAL_REPO
hg branch
GOTO END

:NOT_A_MERCURIAL_REPO
@echo !repo
:END

and set the PROMP to:

SET PROMPT=$E[32m$E]9;8;"USERNAME"$E\@$E]9;8;"COMPUTERNAME"$E\$S$E[1D$S$E[92m$P$E[90m$E[38;5;14m $Q$G $E]9;7;"path_to_above.bat"$E\$E[90m$G$E[m$S

and voalá!



In the picture above you can see that when the current directory is not a mercurial repository the string "!repo" is shown (I'll probably change that later and in this case will show nothing); also, as soon as I initialized a local repository the PROMPT changed to indicate that I was in the default branch. 

Now, the only missing bit was to configure ConEmu to automatically set that prompt when it creates a new console, which can be done by specifying a custom batch file (in my case I created a file named ConEmuInit.cmd):




Basically I copied the original file (that can be found in "%ConEmuBaseDir%\CmdInit.cmd") and change it accordingly.

Now I am happier ;) The changes of making mistakes are small now :)

Happy coding

Leia este post em Português!

Mostrando a branch corrente (mercurial) no prompt do ConEmu

Uma das funcionalidades que sempre gostei no GIT é o fato do GitBash (o console do mesmo) mostrar o nome da branch corrente (no exemplo abaixo, o a branch corrente é a ofx):


Não é de se admirar que quando comecei a usar o mercurial este recurso (ou melhor, a falta do mesmo) me causou certa dificuldade / desconforto.

Considerando que tenho uma memória muito ruim e que facilmente costumo ter entre 5 ~ 6 consoles abertos, é fácil entender a razão do porque, por mais de uma vez, eu estar trabalhando em um console assumindo que estava em uma branch qualquer quando na realidade estava em uma branch completamente diferente (não preciso dizer que isso me deu bastante dor de cabeça).

Alguns dias atras tive a ideia usar o conceito de hooks do mercurial para detectar quando eu mudasse de branch e assim setar o prompt com o nome da mesma; infelizmente esta ideia não funcionou muito bem pois hooks do mercurial são executados pelo processo hg.exe que por sua vez é executado a partir do console e assim sendo minhã solução não era viável pois um processo não pode mudar variáveis de ambiente (no caso o prompt) do processo parente, ou seja, o processo que o iniciou  (muito menos do processo parente do processo parente como neste caso).

Minha próxima tentativa foi verificar se o ConEmu (meu console preferido) tinha algum suporte que me permitisse definir o prompt dinamicamente; felizmente ConEmu suporta uma sintaxe estendida de códigos ANSI, mais precisamente $E ] 9 ; 7 ; ”cmd“$E\  o qual permite executar um programa (especificado pela string cmd) e usar a saída padrão do mesmo como parte do prompt

Munido destas informações eu simplesmente criei o aquivo bat abaixo:

@echo off
IF NOT EXIST .hg GOTO NOT_A_MERCURIAL_REPO
hg branch
GOTO END

:NOT_A_MERCURIAL_REPO
@echo !repo
:END

e defini a variável de ambiente PROMP como:

SET PROMPT=$E[32m$E]9;8;"USERNAME"$E\@$E]9;8;"COMPUTERNAME"$E\$S$E[1D$S$E[92m$P$E[90m$E[38;5;14m $Q$G $E]9;7;"caminho_do_arquivo_acima.bat"$E\$E[90m$G$E[m$S

e voalá!



Como você pode ver na imagem acima, quando o diretório corrente é um repositório mercurial a string => nome_da_branch_corrente é mostrada no prompt (caso o diretório corrente não seja um repositório mercurial a string !repo é apresentada). 

Como último passo configurei o ConEmu para definir o prompt toda vez que um novo console / tab é criado (para tanto eu simplesmente copiei o conteúdo do arquivo "%ConEmuBaseDir%\CmdInit.cmd" par um aquivo chamado ConEmuInit.cmd e o editei de forma que o memo defina o prompt com o valor desejado):



Agora sim, certamente minas dores de cabeça diminuirão :)

Happy coding

Read this post in English!

Jan 21, 2016

Finding references to assemblies


The current task at my job requires me to patch (a fancy name for change) .NET assemblies, sometimes adding new members, sometimes changing type references, sometimes messing with the method implementation and sometimes doing a bit of all.

From time to time I need to find out why a assembly (A) has a reference to some other assembly (B); basically what I need to know is which type/member(s) from assembly B is being used by assembly A.

One particularly easy way (IMO) is to simply ildasm assembly A and look for references to B; in order to accomplish that you can do something like:


c:\temp> ildasm /all /out=c:\temp\assembly-a.il assembly-a.dll

After you generated the CIL from your assembly your next step is to search for the name of the assembly you want to find references for (in this example, Assembly_B); you'll find one or more (actually one for each referenced assembly) sessions in the IL code like:

.assembly extern /*23000005*/ Assembly_B
{

}

Now, you can either search for the name Assembly_B or by the number to its left (in this case 23000005)

.assembly extern /*23000005*/ Assembly_B
{
  .ver 1:0:0:0
}
.
.
.

IL_0006:  /* 28   | (0A)0000B2       */ call instance void [Assembly_B/*23000005*/]NamespaceName.TypeName::DoSomething()
.
.
.

In this example assembly A is using the instance method DoSomething() from type TypeName in namespace NamespaceName from assembly B.

What do you think?

Happy coding.

(Leia este post em português)

Encontrando referências para um assembly específico


Atualmente meu trabalho tem envolvido a manipulação / modificação de assemblies .NET, as vezes incluindo novos membros, outras mudando referências para tipos e/ou membros, etc.

Invariavelmente, de tempos em tempos acabo necessitando descobrir porque um assembly específico (vamos chamá-lo de A) possui uma referência para outro assembly (B); basicamente o que tenho que descobrir é quais tipos/membros do assembly B estão sendo referenciados (usados) pelo assembly A.

Existem várias formas de obter tal informação; na minha opinião, a mais simples, é converter, através do aplicativo 
 ildasm que vem junto com o .NET Framework, o assembly em questão (A) para IL e procurar por referências para o assembly B; para tanto você pode fazer algo como:

c:\temp> ildasm /all /out=c:\temp\assembly-a.il assembly-a.dll

Depois de gerar o IL do assembly desejado seu próximo passo é procurar pelo nome do assembly que você deseja encontrar referências (neste exemplo, Assembly_B); você verá uma ou mais (para ser mais preciso, uma entrada para cada assembly referenciado) 
sessões parecidas com:
.assembly extern /*23000005*/ Assembly_B
{

}

Agora você pode tanto procurar pelo nome do assembly (Assembly_B) ou pelo número que se encontra à sua esquerda (neste exemplo 23000005)

.assembly extern /*23000005*/ Assembly_B
{
  .ver 1:0:0:0
}
.
.
.

IL_0006:  /* 28   | (0A)0000B2       */ call instance void [Assembly_B/*23000005*/]NamespaceName.TypeName::DoSomething()
.
.
.


Como você pode notar no trecho de IL acima, no offset 06 do IL existe uma referência ao método DoSomething() da classe TypeName, definida no namespace 'Namespace' no assembly Assembly_B.

Happy coding.

(read this post in english)

Aug 15, 2015

Invalid offsets in IL instructions after modifying assembly with Mono.Cecil

Hi

Since 2008 I've been using Mono.Cecil, an amazing piece of software, that exposes .Net assemblies contents in a relatively easy and intuitive way so one can inspect and/or change the assembly's contents. 

Unfortunately, in order to use Mono.Cecil effectively, you need a fair amount of knowledge about how MS IL works and Mono.Cecil documentation is kind of sparse (to say the least).

Some time ago I was using it to change some assembly IL and to my surprise after applying the changes peverify complained that some IL instructions had invalid offsets

After some head scratching I've figured out that the issue was that the target of a (short) branch instruction have crossed the threshold that would require it to be  a normal branch (i.e, one that could use 32 bits offsets instead of 8 bits of the short version).

So now the issue was that I'd be forced to scan every single IL instruction in the method body and check/fix the target offset of branches; fortunately, Mono.Cecil has  two methods: MethodBody.SimplifyMacros() and  MethodBody.OptimizeMacros() that can be used to achieve my goal. 

Basically before start doing changes to the method body's IL, you call SimplifyMacros() and when you've finished with your changes on that method body you call OptimizeMacros() and Cecil will take care of adjusting branches accordingly. Nice!


Thanks everybody that helped to develop Mono.Cecil! It's really a handy library! :)

(Leia este post em português)

Instruções com offsets IL inválidos após modificar assembly com Mono.Cecil

Desde 2008 venho usando a biblioteca (muito boa diga-se de passagem) Mono.Cecil que permite você tanto ler quanto modificar o conteúdo de assemblies .Net de uma forma relativamente simples (depois que você compreende como utilizá-la, pois infelizmente,  usar tal biblioteca de forma efetiva exige um bom conhecimento sobre como o MS IL funciona e a documentação do Mono.Cecil deixa a desejar).

Algum tempo atras, um dos testes de um dos meus aplicativos (que usa esta biblioteca) começou a falhar; para ser mais preciso peverify começou a reportar algumas instruções com offsets inválidos

Após investigar por algum tempo concluí que o problema se encontrava no offset (operando) usado em alguma instruções de desvio (branch), as quais estavam ultrapassando o limite de um byte (-127 / 128) (isto ocorria devido a dois motivos: i) o código IL usava a forma (short) branch, ou seja, a instrução de desvio utilizada aceitava um único byte como offset e ii) meu aplicativo adicionava instruções entre a instrução de desvio e o alvo do desvio efetivamente exigindo um offset maior que 128).

Munido desta nova informação, tudo que tinha que fazer agora era verificar instrução por instrução (é claro, apenas as de desvio) se o operando da mesma estava dentro da faixa válida (-127 a 128) e corrigir quaisquer uma que não esteja. É claro que eu queria evitar isto a qualquer custo, pois este processo adicionaria mais código (e possíveis bugs) a meu aplicativo. 

Felizmente, Mono.Cecil possui dois método (MethodBody.SimplifyMacros() e  MethodBody.OptimizeMacros()) que, quando usados, se encubem em garantir que os operandos (offset) das instruções de desvio estão dentro das faixas válidas e caso não estejam, trocam a instrução para uma instrução de desvio que suporte o offset em questão (neste  case uma que use 4 bytes).

Basicamente, antes de iniciar qualquer modificação nas instruções (IL) de um método, você executa o método SimplifyMacros() e quando finalizar suas modificações você executa OptimizeMacros() e Mono.Cecil se incumbirá em ajustar as instruções de desvio (se necessário).


Desenvolvedores do Mono.Cecil: meu muito obrigado! :)

Have fun

(Read this post in english)

Aug 7, 2015

Resolução de métodos sobrecarregados (overloaded) em C#

Depois de um longo e tenebroso tempo em silêncio, eu voltei :)

Desta vez com um pequeno teste.

Dado o seguinte programa em C# (não importa muito a versão da linguagem), oque você espera ver no console?

using static System.Console;

class Foo 
{ 
 public void Bar(string[] o) { WriteLine("string[]"); } 
 public void Bar(object o) { WriteLine("object"); } 

 static void Main()
 {
  var foo = new Foo();
  foo.Bar(null); 
 } 
}

Responda através dos comentários

Boa diversão!

Read this post in English!