Msmq no Compact Framework 2.0
Num outro artigo vimos como utilizar o recurso de enfileiramento de mensagens do Windows, o MSMQ ( Microsoft Message Queuing ), no .Net Framework. Neste veremos como utilizar um dos novos recursos do .Net Compact Framework 2.0, o uso do MSMQ no Windows Mobile.
Preparando ambiente
Nós utilizaremos o Windows Mobile 2003, e a primeira coisa a fazer é baixar o seu SDK, cujo link se encontra logo abaixo:
http://www.microsoft.com/downloads/details.aspx?FamilyID=9996b314-0364-4623-9ede-
Criando o projeto
Agora no Visual Studio 2005 vamos criar nosso projeto ( Visual C# -> Smart Device -> Pocket PC 2003 -> Device Application ), o qual daremos o nome de MsmqCF.
Adicionando referências
O SDK que baixamos possui alguns arquivos os quais farão a instalação do Msmq no Windows Mobile. Esses arquivos devem está localizados no diretório “C:\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Support\Msmq\armv4”, ou algo similar, dependendo do idioma do S.O .
Para isso vamos adicionar todos os arquivo deste diretório no nosso projeto ( Add->Existing Item..).
Em todos eles, a propriedade “Build Action” deve está como Content e a propriedade “Copy to Output Directoy” como Copy if newer.
Dividindo o desenvolvimento em duas etapas
Vamos dividir o desenvolvimento em duas etapas: a primeira será em relação ao processo de instalação automática do MSMQ no Pocket PC, e a segunda será a utilização realmente do serviço de enfileiramento de mensagens.
1 - Instalação automática do MSMQ no Windows Mobile
A seguir veremos o código responsável pela instalação do MSMQ no Pocket. Não entraremos em detalhe pois não é nosso objetivo e sua explicação tornaria o artigo demasiadamente longo.
No FORM ( Form1) criado no projeto, vamos adicionar o código a seguir:
public class ProcessInfo
{
public IntPtr hProcess;
public IntPtr hThread;
public Int32 ProcessId;
public Int32 ThreadId;
}
[DllImport("CoreDll.DLL", SetLastError = true)]
private extern static
int CreateProcess(String imageName,
String cmdLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
Int32 boolInheritHandles,
Int32 dwCreationFlags,
IntPtr lpEnvironment,
IntPtr lpszCurrentDir,
IntPtr lpsiStartInfo,
ProcessInfo pi);
[DllImport("CoreDll.dll")]
private extern static Int32 GetLastError();
[DllImport("CoreDll.dll")]
private extern static Int32 GetExitCodeProcess(IntPtr hProcess, out Int32 exitcode);
[DllImport("CoreDll.dll");
private extern static Int32 CloseHandle(IntPtr hProcess);
[DllImport("CoreDll.dll")]
private extern static
IntPtr ActivateDevice(string lpszDevKey, Int32 dwClientInfo);
[DllImport("CoreDll.dll")]
private extern static
Int32 WaitForSingleObject(IntPtr Handle, Int32 Wait);
public static bool CreateProcess(String ExeName, String CmdLine)
{
Int32 INFINITE;
unchecked { INFINITE = (int)0xFFFFFFFF; }
ProcessInfo pi = new ProcessInfo();
if (CreateProcess(ExeName, CmdLine, IntPtr.Zero, IntPtr.Zero, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, pi) == 0)
{
return false;
}
WaitForSingleObject(pi.hProcess, INFINITE);
Int32 exitCode;
if (GetExitCodeProcess(pi.hProcess, out exitCode) == 0)
{
MessageBox.Show("Failure in GetExitCodeProcess");
CloseHandle(pi.hThread);
// Liberando handles
CloseHandle(pi.hProcess);
return false;
}
CloseHandle(pi.hThread);
// Liberando handles
CloseHandle(pi.hProcess);
if (exitCode != 0)
return false;
else
return true;
}
//This is the MSMQAdm.exe utility we’ll be using
private const String MSMQ_ADM = @"\windows\msmqadm.exe";
private const String MSMQ_DRIVER_REG = @"Drivers\BuiltIn\MSMQD";
private static void CopyFilesRequired()
{
string _path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().
GetName().CodeBase);
if (!File.Exists(@"\windows\msmqadm.exe"))
File.Copy(_path + "\\msmqadm.exe", @"\windows\msmqadm.exe");
if (!File.Exists(@"\windows\msmqadmext.dll"))
File.Copy(_path + "\\msmqadmext.dll", @"\windows\msmqadmext.dll");
if (!File.Exists(@"\windows\msmqd.dll"))
File.Copy(_path + "\\msmqd.dll", @"\windows\msmqd.dll");
if (!File.Exists(@"\windows\msmqrt.dll"))
File.Copy(_path + "\\msmqrt.dll", @"\windows\msmqrt.dll");
File.Delete(_path + "\\msmqadm.exe");
File.Delete(_path + "\\msmqadmext.dll");
File.Delete(_path + "\\msmqd.dll");
File.Delete(_path + "\\msmqrt.dll");
}
Adicionaremos no evento de Load do Form o código que irá verificar a presença do MSMQ no dispositivo, e instalá-lo caso este ainda não esteja presente .
//We need to move the MSMQ components deployed to the system folder
CopyFilesRequired();
//Check status of MSMQ (is it installed and running yet?
if (!(CreateProcess(MSMQ_ADM, "status")))
{
//Deletes the MSMQ registry key and store directory.
//All messages are lost.
CreateProcess(MSMQ_ADM, "register cleanup");
//Installs MSMQ as device drivcers.
if (CreateProcess(MSMQ_ADM, "register install"))
{
MessageBox.Show("Registered Drivers Successfully");
}
else
{
MessageBox.Show("Failed to install MSMQ! System Error = " + GetLastError().ToString());
return;
}
//Creates the MSMQ Configuration in Registry
if (CreateProcess(MSMQ_ADM, "register"))
{
MessageBox.Show("Registered MSMQ Successfully");
}
else
{
MessageBox.Show("Failed to Register MSMQ! System Error = " + GetLastError().ToString());
// return;
}
//Enables the native MSMQ protocol
if (CreateProcess(MSMQ_ADM, "enable binary"))
{
MessageBox.Show("Enable Binary Successfully");
}
else
{
MessageBox.Show("Failed to enable Binary! System Error = " + GetLastError().ToString());
return;
}
//Starts the MSMQ service
if (CreateProcess(MSMQ_ADM, "start"))
{
MessageBox.Show("Started MSMQ Successfully");
}
else
{
//This is one additional step that is needed for PocketPCs
//The Device Drivers have to be loaded before the service
//can be started
//ActivateDevice will load the device drivers
IntPtr handle = ActivateDevice(MSMQ_DRIVER_REG, 0);
CloseHandle(handle);
//Let us check if MSMQ is running
if (CreateProcess(MSMQ_ADM, "status"))
{
MessageBox.Show("MSMQ is up and running");
}
else
{
MessageBox.Show("Failed to start MSMQ! System Error = " + GetLastError().ToString());
}
}
}
else
MessageBox.Show("MSMQ is already up and running");
2 – Utilização do MSMQ no dispositivo
Finalmente vamos adicionar o código para a utilização propriamente dita do MSMQ no dispositivo, pois até agora tudo que vimos foi em relação à instalação automática do serviço.
Adicionando os controles do Form
Adicione os controles a seguir (verificar o layout na figura ao lado):
|
|
Agora vamos inserir o código do button (btnSendMsg) responsável por enviar a mensagem para a fila do MSMQ. Para isso dê um duplo-clique no Button e insira o seguinte código:
if (txtSendMsg.Text.Trim() == "") return;
string strDestQ = @".\private$\testq"; //nome da fila
try
{
if (!MessageQueue.Exists(strDestQ))
{
MessageQueue.Create(strDestQ);
}
MessageQueue mq = new MessageQueue(strDestQ);
mq.Send(txtSendMsg.Text);
txtSendMsg.Text = "";
}
Catch
{
}
E por último vamos inserir o código do button (btnReceiveMsg) responsável por ler da fila do MSMQ as mensagens disponíveis. Para isso dê um duplo-clique no Button e insira o seguinte código:
lblReceiveMsg.Text = ""; Refresh();
MessageQueue mq = new MessageQueue(@".\private$\testq");
//especifica o formatter para des-serializar a mensagem
mq.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });
try
{
Message messageReceived = mq.Receive(new TimeSpan(0, 0, 1));//timeout em 1s
txtRecMsg.Text = (string)messageReceived.Body;
}
catch { txtRecMsg.Text = "- timeout -"; }
Pronto, isso é tudo. Observe que código para utilização do MSMQ é muito pequeno, apenas algumas poucas linhas, lembrando que grande parte do código neste artigo foi para a instalação do MSMQ no dispositivo.
Agora é só executar e testar a aplicação. Vale ressaltar que ao rodar a aplicação pela primeira, o MSMQ será instalado no dispositivo, o que resultará em um tempo maior no deploy.
É isso ai pessoal, até a próxima.
Gustavo Barros
OBS: Este artigo foi baseado no blog do Mark Ihimoyan´s:
http://blogs.msdn.com/ihimmar/archive/2004/06/14/154911.aspx