Desenvolvimento - Mobile

Realizando chamadas a aplicações externas (Shell Application) com SDA usando C# .NET

Neste artigo iremos realizar uma operação que não é pouco comum no processo de desenvolvimento de aplicações, principalmente aonde existem sistemas legados.

por Edward E. Martins Jr.



Neste artigo iremos realizar uma operação que não é pouco comum no processo de desenvolvimento de aplicações, principalmente aonde existem sistemas legados.

Algumas vezes precisamos fazer uma chamada a alguma aplicação externa, como por exemplo, chamar alguma parte de um sistema legado feito para MSDOS®, ou até mesmo para chamar a calculadora do Windows®.

Para realizar uma chamada a uma aplicação externa em uma WA (Windows Application) tradicionalmente usamos "System.Diagnostics.Process.Start(string fileName, string arguments);".

Vamos primeiramente criar um novo projeto SDA.

Iniciando um novo projeto.

Chame o Microsoft Visual Studio .NET 2003 da área de trabalho ou do menu iniciar programas.

Clique em File » New Project.

Depois escolha Visual C# Projects e em Smart Device Application1, conforme a figura abaixo.

Clique em OK.

A nossa próxima missão será escolher a plataforma em que a aplicação irá rodar e que tipo de aplicação será. Neste projeto iremos selecionar a plataforma Pocket PC e o tipo do projeto será Windows Application.

Clique em OK.

Depois dê um duplo clique no Form1.cs[Design], abrindo o Form1.cs.

Bom, a classe "System.Diagnostics.Process" não existe para SDA, portanto é preciso fazer uma chamada à uma DLL nativa do sistema operacional do PPC que será encarregada da operação de chamar uma aplicação externa à SDA. O nome desta DLL é "CoreDll.DLL".

Iremos então adicionar em nosso projeto um "using" para o namespace "System.Runtime.InteropServices;"

Ficando assim:

using System.Runtime.InteropServices;

O que nos permitirá usar o "DllImport".

Dentro da classe principal (public class Form1 : System.Windows.Forms.Form), iremos "importar"*1 para dentro de nossa aplicação esta DLL e instanciar o método "CreateProcess".

[DllImport("CoreDll.DLL", SetLastError=true)] private static extern int CreateProcess(
   String imageName,
   String cmdLine,
   IntPtr lpProcessAttributes,
   IntPtr lpThreadAttributes,
   Int32 boolInheritHandles,
   Int32 dwCreationFlags,
   IntPtr lpEnvironment,
   IntPtr lpszCurrentDir,
   byte [] si,
   ProcessInfo pi );

A função "CreateProcess" é usada para chamar um programa. Ela cria um novo processo em uma thread primaria. Este novo processo executa um aplicativo específico definido em parâmetro.

Aonde:

  • "imageName" é a string para o local onde está o aplicativo que se deseja chamar.
  • "cmdLine" é utilizado para receber a string dos possíveis parâmetros que esta aplicação pode vir a receber.
  • "ProcessInfo" é uma estrutura que receberá identificação e informação sobre o novo processo e estes objetos serão atribuídos pelo "CreateProcess" e deve ser inserida na aplicação:
public class ProcessInfo
{
   public long hProcess;
   public long hThread;
   public long ProcessID;
   public long ThreadID;
}

Um método de chamada para este objeto ficaria assim:

private void M1()
{
   int Retval;

   ProcessInfo pi = new ProcessInfo();

   byte [] si = new byte[128]; 

   Retval = CreateProcess(@"\windows\iexplore.exe", "www.linhadecodigo.com.br", IntPtr.Zero , 
IntPtr.Zero, 0, 0, IntPtr.Zero, IntPtr.Zero, si, pi);
}

Aonde: "\windows\iexplore.exe", é o aplicativo que desejamos chamar e "www.linhadecodigo.com.br", é o parâmetro.

O retorno zero indica falha na chamada e qualquer não zero indica sucesso.

Segue abaixo toda implementação desta aplicação:

using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;

namespace SHELL_SDA
{
   /// <summary>
   /// Summary description for Form1.
   /// </summary>
   /// 
   public class Form1 : System.Windows.Forms.Form
   {
      private System.Windows.Forms.MainMenu mainMenu1;

      public Form1()
      {
         //
         // Required for Windows Form Designer support
         //
         InitializeComponent();

         //
         // TODO: Add any constructor code after InitializeComponent call
         //
      }
      /// <summary>
      /// Clean up any resources being used.
      /// </summary>
      protected override void Dispose( bool disposing )
      {
         base.Dispose( disposing );
      }
      #region Windows Form Designer generated code
      /// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
      private void InitializeComponent()
      {
         this.mainMenu1 = new System.Windows.Forms.MainMenu();
			// 
         // Form1
         // 
         this.Menu = this.mainMenu1;
         this.Text = "Form1";
         this.Load += new System.EventHandler(this.Form1_Load);

      }
      #endregion

      /// <summary>
      /// The main entry point for the application.
      /// </summary>

      static void Main() 
      {
         Application.Run(new Form1());
      }


      private void Form1_Load(object sender, System.EventArgs e)
      {
         int Retval;
         ProcessInfo pi = new ProcessInfo();

         byte [] si = new byte[128]; 

         Retval = CreateProcess(@"\windows\iexplore.exe", "www.linhadecodigo.com.br ", 
IntPtr.Zero, IntPtr.Zero, 0, 0, IntPtr.Zero, IntPtr.Zero, si, pi);

      }


      [DllImport("CoreDll.DLL", SetLastError=true)]
      private static extern int CreateProcess(
         String imageName,
         String cmdLine,
         IntPtr lpProcessAttributes,
         IntPtr lpThreadAttributes,
         Int32 boolInheritHandles,
         Int32 dwCreationFlags,
         IntPtr lpEnvironment,
         IntPtr lpszCurrentDir,
         byte [] si,
         ProcessInfo pi ); 
   }

   public class ProcessInfo
   {
      public long hProcess;
      public long hThread;
      public long ProcessID;
      public long ThreadID;
   }

}

É só copiar e rodar...

Agora vamos testar nossa aplicação.

Vá até Deployment Device e escolha Pocket PC 2003 Emulator.

Depois clique em clique em Start (Debug).

Neste fantástico processo de deploy, será chamado um emulador de Pocket PC rodando o windows CE que irá rodar sua aplicação.

O que deverá aparecer é a seguinte tela:

E depois de alguns instantes:

"Easy, easy, very easy Japanese"

Apenas observando:

Como estamos fazendo uso de uma DLL externa, que provavelmente não foi feita em .NET iremos definir a propriedade "Allow Unsafe Code Blocks" como True. Para isto vá em: Project » Properties » Configuration Properties » Build.

*1 "importar" » Na verdade a DLL não é importada para dentro do binário da aplicação, mas sim é chamada pela aplicação SDA em "run time" no momento do uso de algum método contido na DLL.

Mais informações sobre este método vá até o link: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcekernl/html/_wcesdk_win32_createprocess.asp

Os códigos desta SDA podem ser recebidos pelo seguinte e-mail: edward.martins@intermec.com.br.

Embora eu acredite que não vão precisar...

Abraços.

Edward E. Martins Jr.

Edward E. Martins Jr. - Edward E. Martins Jr.
Engenheiro de sistemas da Intermec South America