Mono – Portabilidade – Compilando no Visual Studio e rodando em Linux – C#

Publicado: 22 de setembro de 2014 em Linux

Você pode desenvolver aplicações escritas para o .NET Framework no Microsoft Visual Studio e utilizar os arquivos executáveis (“binários”) compilados no sistema operacional Windows, rodando-os diretamente no sistema operacional Linux através do Framework Mono.

O Mono contém as bibliotecas de desenvolvimento do núcleo do Framework da Microsoft e as ferramentas de desenvolvimento e implantação necessárias para portar suas funcionalidades, entretanto existe algumas limitações de portabilidade devido aos conceitos de cada sistema operacional, mas existe uma série de estratégias que você pode adotar, dependendo de como você está confortável com o uso do Linux.

Application Portability: http://www.mono-project.com/docs/getting-started/application-portability/

Distribuindo o Mono

Você pode distribuir o Framework Mono no Linux de um modo fácil, sem precisar ter contato manual com o repositório do projeto, utilizando um PPA (Personal Package Archive), o PPA é uma plataforma para disponibilizar pacotes de softwares empacotados por desenvolvedores para usuários do Ubuntu, você encontra os PPAs no site Launchpad, mantido pela empresa Canonical que é a desenvolvedora do Ubuntu Linux. Utilize as instruções abaixo no terminal do Linux para instalar o Framework Mono:

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:inizan-yannick/mono
sudo apt-get update
sudo apt-get install mono-devel

Testando a Portabilidade: Windows – Linux

Para efetuar um teste de portabilidade, vamos criar uma aplicação básica no sistema operacional Windows utilizando o Microsoft Visual Studio, vamos escrever uma aplicação Windows Forms dinamicamente, utilizando algumas técnicas especificas, como alguns Event Handlers dinâmicos, Hot Keys e a previsão de teclas (Key Preview) do Windows e portar o aplicativo compilado que será executado no sistema operacional Linux.

1 – Crie uma nova solução Windows Forms chamada PortabilidadeCs e quando o formulário aparecer na tela aperte a tecla F7 para ir para a unidade de código csharp, troque o código da classe gerada automaticamente pelo código encontrado abaixo:

Windows - Aplicação - Visual Studio

Windows – Aplicação – Visual Studio

2 – Compile e teste seu aplicativo, atente-se para o recurso de previsão de teclas do Windows utilizando as teclas A, B, C e D e também o recurso de teclas de atalhos utilizando as teclas ALT + A e assim por diante:

Aplicação - C# - .NET - Windows

Aplicação – C# – .NET – Windows

3 – Após testar sua aplicação envie uma cópia do arquivo compilado PortabilidadeCS.exe para o sistema operacional Linux, você pode utilizar o método de sua preferencia para efetuar esta operação :

Aplicativo - C# - Linux

Aplicativo – C# – Linux

4 – Quando o Framework Mono está instalado no Linux, o sistema operacional reconhece arquivos de extensão EXE criados no .NET Framework como um arquivo executável do Linux. Utilize um duplo clique para executar sua aplicação C#:

C# - Portabilidade - Windows - Linux

C# – Portabilidade – Windows – Linux

Você pode perceber que todas as funcionalidades básicas do formulário funcionam perfeitamente. Agora você já pode portar suas aplicações Windows para outras plataformas, tenha em mente que você deve seguir sempre as melhores praticas para o desenvolvimento e respeitar as diferentes tecnologias de cada sistema operacional.

Uma opção é encontrar um meio termo para que suas aplicações .NET cruzem as mais diferentes plataformas sem que você tenha que reescrever seu código, por exemplo a tecnologia COM para Windows, mais especificamente DCOM é equivalente a tecnologia CORBA para Linux, porem é possível utilizar CORBA no Windows e portar seus aplicativos sem reescrever os arquivos binários que interagem entre si, dentro é claro, das diferenças e limitações existentes entre as duas tecnologias.

Corba: http://www.corba.org/

As classes comuns de pedido de arquitetura (CORBA) Broker são convertidas para as classes no namespace: System.Runtime.Remoting

Remoting: http://msdn.microsoft.com/pt-br/library/system.runtime.remoting(v=vs.110).aspx

Exemplo:

Neste exemplo criamos uma aplicação C# no Microsoft Visual Studio e a rodamos no sistema operacional Linux através do Framework Mono utilizando o mesmo arquivo “binário”.

C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PortabiliadeCs
{
    public partial class Form1 : Form
    {
        // Define componentes dinamicamente
        Label rotulo;
        RadioButton soma;
        RadioButton subtrai;
        RadioButton multiplica;
        RadioButton divide;
        Label rotulo1;
        TextBox campo1;
        Label rotulo2;
        TextBox campo2;
        Button botao;
        TextBox texto;
        double total;

        public Form1()
        {
            InitializeComponent();

            // Evento OnShown do Formulario
            this.Shown += new System.EventHandler(this.Form1_Shown);
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            // Cria componentes dinamicamente no evento form shown
            rotulo = new Label();
            soma = new RadioButton();
            subtrai = new RadioButton();
            multiplica = new RadioButton();
            divide = new RadioButton();
            rotulo1 = new Label();
            campo1 = new TextBox();
            rotulo2 = new Label();
            campo2 = new TextBox();
            botao = new Button();
            texto = new TextBox();

            // posiciona componentes no form
            rotulo.Location = new Point(5, 10);
            soma.Location = new Point(5, 30);
            subtrai.Location = new Point(5, 50);
            multiplica.Location = new Point(5, 70);
            divide.Location = new Point(5, 90);
            rotulo1.Location = new Point(5, 120);
            campo1.Location = new Point(60, 120);
            rotulo2.Location = new Point(170, 120);
            campo2.Location = new Point(220, 120);
            botao.Location = new Point(330, 120);
            texto.Location = new Point(5, 150);

            // adiciona a propriedade de texto nos componentes
            rotulo.Text = "Escolha um RadioButton ou pressione (A, B, C ou D) ou (Alt + A, B, C ou D)";
            soma.Text = "Som&a";
            subtrai.Text = "Su&btrai";
            multiplica.Text = "Multipli&ca";
            divide.Text = "&Divide";
            rotulo1.Text = "Numero:";
            rotulo2.Text = "Numero:";
            botao.Text = "OK";

            // seta a propriedades para a caixa de texto
            texto.Multiline = true;
            texto.ScrollBars = ScrollBars.Vertical;
            texto.ReadOnly = true;

            // Define o tamanho dos objetos no form
            Form1.ActiveForm.Size = new Size(550, 400);
            rotulo.Size = new Size(450, 20);
            soma.Size = new Size(130, 20);
            subtrai.Size = new Size(130, 20);
            multiplica.Size = new Size(130, 20);
            divide.Size = new Size(130, 20);
            texto.Size = new Size(410, 100);
            rotulo1.Size = new Size(50, 20);
            rotulo2.Size = new Size(50, 20);
            texto.Size = new System.Drawing.Size(520, 200);

            // Define eventos para o checkbox
            soma.CheckedChanged += new System.EventHandler(soma_CheckedChanged);
            subtrai.CheckedChanged += new System.EventHandler(subtrai_CheckedChanged);
            multiplica.CheckedChanged += new System.EventHandler(multiplica_CheckedChanged);
            divide.CheckedChanged += new System.EventHandler(divide_CheckedChanged);
            botao.Click += new System.EventHandler(botao_Click);

            // Ativa a previsão de teclas do formulario
            Form1.ActiveForm.KeyPreview = true;

            // Nome do formulario
            Form1.ActiveForm.Text = "Desenvolvimento Aberto - Portabilidade Windows - Linux";

            // Adiciona componentes ao formulario
            Form1.ActiveForm.Controls.Add(rotulo);
            Form1.ActiveForm.Controls.Add(soma);
            Form1.ActiveForm.Controls.Add(subtrai);
            Form1.ActiveForm.Controls.Add(multiplica);
            Form1.ActiveForm.Controls.Add(divide);
            Form1.ActiveForm.Controls.Add(rotulo1);
            Form1.ActiveForm.Controls.Add(campo1);
            Form1.ActiveForm.Controls.Add(rotulo2);
            Form1.ActiveForm.Controls.Add(campo2);
            Form1.ActiveForm.Controls.Add(botao);
            Form1.ActiveForm.Controls.Add(texto);

        }

        // Eventos de Click dos botões
        private void botao_Click(object sender, EventArgs e)
        {
            if (soma.Checked)
            {
                total = Convert.ToDouble(campo1.Text) + Convert.ToDouble(campo2.Text);
                texto.AppendText(campo1.Text + " + " + campo2.Text + " = " + total + "\n");
            }

            if (subtrai.Checked)
            {
                total = Convert.ToDouble(campo1.Text) - Convert.ToDouble(campo2.Text);
                texto.AppendText(campo1.Text + " - " + campo2.Text + " = " + total + "\n");
            }

            if (multiplica.Checked)
            {
                total = Convert.ToDouble(campo1.Text) * Convert.ToDouble(campo2.Text);
                texto.AppendText(campo1.Text + " * " + campo2.Text + " = " + total + "\n");
            }

            if (divide.Checked)
            {
                total = Convert.ToDouble(campo1.Text) / Convert.ToDouble(campo2.Text);
                texto.AppendText(campo1.Text + " / " + campo2.Text + " = " + total + "\n");
            }
        }

        // Eventos do RadioButton - mudança de estado
        // Verifica o estado do componente pois este evento é executado duas vezes
        // 1 - Quando o botão é selecionado e
        // 2 - Quando o botão é deselecionado

        private void soma_CheckedChanged(object sender, EventArgs e)
        {
            if (soma.Checked)
            {
                texto.AppendText("Soma:\n");
            }
        }

        private void subtrai_CheckedChanged(object sender, EventArgs e)
        {
            if (subtrai.Checked)
            {
                texto.AppendText("Subtração:\n");
            }
        }
        private void multiplica_CheckedChanged(object sender, EventArgs e)
        {
            if (multiplica.Checked)
            {
                texto.AppendText("Multiplicação:\n");
            }
        }

        private void divide_CheckedChanged(object sender, EventArgs e)
        {
            if (divide.Checked)
            {
                texto.AppendText("Divisão:\n");
            }
        }     

        // Evento de tecla pressionada (Key Preview)
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {

            if (e.KeyCode == Keys.A)
            {

                if (soma.Checked == true)
                {
                    soma.Checked = false;
                }
                else
                {
                    soma.Checked = true;
                }

            }
            if (e.KeyCode == Keys.B)
            {

                if (subtrai.Checked == true)
                {
                    subtrai.Checked = false;
                }
                else
                {
                    subtrai.Checked = true;
                }

            }

            if (e.KeyCode == Keys.C)
            {

                if (multiplica.Checked == true)
                {
                    multiplica.Checked = false;
                }
                else
                {
                    multiplica.Checked = true;
                }

            }

            if (e.KeyCode == Keys.D)
            {

                if (divide.Checked == true)
                {
                    divide.Checked = false;
                }
                else
                {
                    divide.Checked = true;
                }

            }

        }
    }
}
Publicidade
comentários
  1. Agnaldo disse:

    Olá, boa noite!
    gostaria de aprender esse processo, pois fiz da mesma forma e não conseguir

    • Olá Agnaldo.

      Verifique se seu framework Mono está instalado corretamente no Linux, entre no terminal e digite:

      mono -V

      Aparecerá a versão do mono instalado, o exemplo acima é só um programa comum criado no sistema operacional Windows com Visual Studio e que foi enviado para o Ubuntu Linux.

      O programa acima usa eventos dinâmicos, teclas de atalho, e a previsão de teclas para testar a compatibilidade com o Linux que possui conceitos um pouco diferentes.

      Você pode criar um programa “Hello World” só com um Form e um Label na tela, compile no Visual Studio (Windows) e o copie para o Linux. Se o Mono estiver instalado corretamente o programa deve rodar sem problemas.

      Espero ter ajudado.
      Abraços.

  2. Olá prezado!
    Parabéns pelo bog.
    Possuo um semelhante, porém sobre outro assunto que não deixa de estar relacionado a este.
    Mas o motivo do meu comentário é que eu já consigo rodar uma aplicação win32 no mono em ambiente linux, porem eu não to conseguindo rodar o app disponivel em http://zello.com da mesma forma.
    Você poderá dar-me uma idéia do que pode ser feito para contornar o problema?

    Desde já lhe agradeço!

    • Olá Airam,

      Dificil falar de um software pronto e fechado sem conhecer suas especificações a fundo, visto que o MONO não é totalmente compativel para rodar programas .NET, você precisa ter uma serie de adaptações, pois o mesmo não comtempla varias funcionalidades do sistema operacional Windows como por exemplo COM e algumas implementações Enterprise.

      Vale salientar que MONO é um framework .NET e não Win32 nativo, existe outras formas para rodar programas Windows win32 em Linux como o Wine: https://www.winehq.org/

      Você pode se guiar mais a fundo pela documentação de portabilidade do Mono usando o link no começo deste post.

      Espero ter ajudado,
      Abraços.

      • Ajudou sim amigo.
        O problema pe que a distribuição que utilizo não roda Wine.
        Estou usando Raspibian.
        Já tentei adicionar o endereço na lista de repositórios para instalar o Wine mas não instala.
        Estou usando Raspberry Pi B+

        Mas obrigado pela atenção.
        Continuarei a busca.

Deixe uma resposta para Ricardo Mantovani Cancelar resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s