Service |
A service is a program that runs in the background of the computer. The program starts when the computer starts, and ends when the computer is shutdown. Services can be accessed from the Services in the Control Panel. Microsoft SQL Server, My SQL and Oracle all are services. Un servicio es un programa que corre en segundo plano en una computadora. El programa comienza cuando la computadora comienza, y termina cuando se apaga la computadora. Los servicios se pueden acceder desde los Servicios en el Control Panel. Microsoft SQL Server, My SQL y Oracle son servicios. |
Problem 1 |
Create a Service program called MyService. When creating the project, select the Service project. Wintempla will create a basic project to hold two services in two classes: Service1 and Service2. Cree un programa de Servicios llamado MyService usando Wintempla. Cuando cree el proyecto, seleccione el tipo de proyecto de Service. Wintempla creará un proyecto básico con dos servicios en dos classes: Service1 y Service2. |
Services Snap In |
Services can be managed from the Control Panel using the Services Snap In (or Services Manager). In order for a service to interact with the Services Snap In and the operative system, a service must implement very specific functions (remember that a set of functions is an Interface):
Los servicios pueden ser administrados desde el Panel de Control usando el Administrador de Servicios. A fin de que un Servicio pueda interactuar con el Administrador de Servicios y el sistema operativo, un servicio debe implementar funciones muy específicas (recuerde que un conjunto de funciones es una Interface):
|
Mt::Service class |
Wintempla provides the Mt::Service class to ease services development; you may inspect this class to learn how to implement a Service without Wintempla assistance. Wintempla propociona la clase Mt::Service para facilitar el desarrollo de servicios; usted puede inspeccionar esta clase para aprender a implementar un Servicio sin la asistencia de Wintempla. |
Step A |
Inspect the MyService.h file. In this case, Service1 has a Pipe and Service2 has a File, you may, however, edit this file to suit your service requirements. We will not edit this file for our purposes. Inspeccione el archivo MyService.h. En este caso, Service1 tiene un Tubo y Service2 tiene un archivo, usted puede, sin embargo, editar este archivo para cumplir con los requerimientos de su servicio. Nosotros no editaremos este archivo para nuestros propósitos. |
Step B |
Service1 will return the current exchange rate from pesos to dollars. Service2 will periodically write a file with the current time using an Input Output Completion Port Timer. Edit the MyService.cpp file as shown. |
MyService.cpp |
#include "stdafx.h" //________________________________________ MyService.cpp #include "MyService.h" ... //___________________________ Service1 (Provides the exchange rate from pesos to dollars) Service1::Service1() { } Service1::~Service1() { } wchar_t* Service1::GetName() { return L"PesosToDollars"; } wchar_t* Service1::GetDisplayName() { return L"PesosToDollars"; } wchar_t* Service1::GetDescription() { return L"Provides the exchange rate from pesos to dollars"; } void Service1::OnStart(DWORD dwArgc, PTSTR* pszArgv) { pipe.CreateServer(L"\\\\.\\pipe\\PesosToDollars", sizeof(double), 1000); inputOutputCompletionPort.AssociateDevice(pipe.GetHandle(), Mt::Service::Server); pipe.Connect(); } void Service1::OnRequestProcessing() { if (pipe.IsOpen()) { //_____________________ A client request: Send exhange rate from pesos to dollars double exchangeRate = 13.22; const DWORD bytesToWrite = sizeof(double); DWORD bytesWriten; pipe.Write(&exchangeRate, bytesToWrite, &bytesWriten); pipe.Flush(); pipe.Disconnect(); //___________________ Allow another client to connect pipe.Connect(); } } void Service1::OnStop() { pipe.Close(); } //_____________________________________________ Service2 (Creates a file with the current time) Service2::Service2() { } Service2::~Service2() { } wchar_t* Service2::GetName() { return L"LogFile"; } wchar_t* Service2::GetDisplayName() { return L"LogFile"; } wchar_t* Service2::GetDescription() { return L"It periodically writes a file with the current time"; } void Service2::OnStart(DWORD dwArgc, PTSTR* pszArgv) { file.CreateForWritting(L"C:\\history.txt"); inputOutputCompletionPortTimer.Start(&inputOutputCompletionPort, Mt::Service::Server, 1000, 1000); //IOCP Timer every second } void Service2::OnRequestProcessing() { Sys::Time time; wchar_t text[256]; _snwprintf_s(text, 256, _TRUNCATE, L"%02d:%02d:%02d\r\n", time.wHour, time.wMinute, time.wSecond); file.WriteText(text); } void Service2::OnStop() { file.Close(); inputOutputCompletionPortTimer.Stop(); } |
Step C |
Build your project and run the program. As a service must be managed by the Services Snap In (Services Manager) you will get the following message when running the service. Compile su proyecto y corra el programa. Como un servicio debe ser administrado por el Administrador de Servicios usted recibirá el siguiente mensaje cuando corra el servicio. |
Step D |
There are four different ways to run the service: install, remove, debug, list and service. In order to use the service, we need to install the service. To do that, you need to open a command window by running cmd.exe as Administrator (you need to locate the cmd.exe file and use the context menu to run the program as Administrator). Once the command window is open, you need to change to the location where your service was created, and run the program as shown. Hay cuatro formas diferentes para correr el servicio: instalarlo, removerlo, depurarlo, listar y servicio. A fin de usar el servicio, nosotros necesitamos instalar el servicio. Para hacer esto, usted necesita abrir una ventana de comandos ejecutando el programa cms.exe como administrador (usted necesita ubicar el archivo cmd.exe y usar el menú de contexto para correrlo como administrador). Una vez que la ventana de comandos está abierta, usted necesita cambiarse a la ubicación donde el servicio se creo, y correr el programa como se muestra. |
MSDOS: cmd.exe |
cd .. cd MyService C:\Users\Me\MyService cd Debug C:\Users\Me\MyService\Debug MyService -install |
Step E |
Use the Service Snap In (Service Manager) to start both of the services: PesosToDollars and LogFile. Use el Administrador de Servicios para iniciar los dos servicios: PesosToDollars y LogFile. |
Step F |
Let the LogFile service run for a couple of minutes, then, stop the service. Open history.txt file to verify that your service was running properly. The file can be found at the root folder of the C drive. Dejer corre el servicio LogFile por un par de minutos, entonces, detenga el servicio. Abra el archivo history.txt para verificar que su servicio estaba corriendo en forma correcta. El archivo puede encontrarse en el directorio raíz del disco C. |
Problem 2 |
Create a Wintempla dialog application called MyClient to use the PesosToDollars service. Cree una apliacion de dialogo llamama MyClient usando Wintempla para accesar al servicio PesosToDollars. |
MyClient.cpp |
... void MyClient::btRetrieve_Click(Win::Event& e) { Win::HourGlassCursor hgc(true); HANDLE pipe = ::CreateFile(L"\\\\.\\pipe\\PesosToDollars", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (pipe != INVALID_HANDLE_VALUE) { double exchangeRate = 0.0; const DWORD bytesToRead = sizeof(double); DWORD bytesRead = 0; ::ReadFile(pipe, &exchangeRate, bytesToRead, &bytesRead, NULL); tbxExchangeRate.DoubleValue = exchangeRate; ::CloseHandle(pipe); } else { Sys::DisplayLastError(hWnd, L"PesosToDollars"); } } |
Problem 2a |
Repeat the previous problem using Win32. Repita el problema anterior usando Win32. |
MyClien32.cpp |
//_________________________________________________ MyClient32.cpp #include "stdafx.h" #include "MyClient32.h" INT_PTR Window_Open(HWND hWnd, WPARAM wParam, LPARAM lParam) { ::SetWindowText(hWnd, L"MyClient32"); return TRUE; } INT_PTR btRetrieve_Click(HWND hWnd, WPARAM wParam, LPARAM lParam) { HCURSOR hCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT)); ::ShowCursor(TRUE); HANDLE pipe = ::CreateFile(L"\\\\.\\pipe\\PesosToDollars", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (pipe != INVALID_HANDLE_VALUE) { double exchangeRate = 0.0; const DWORD bytesToRead = sizeof(double); DWORD bytesRead = 0; ::ReadFile(pipe, &exchangeRate, bytesToRead, &bytesRead, NULL); // wchar_t text[32]; _snwprintf_s(text, 32, _TRUNCATE, L"%f", exchangeRate); ::SetWindowText(::GetDlgItem(hWnd, ID_TBX_EXCHANGE_RATE), text); ::CloseHandle(pipe); } else { ::MessageBox(hWnd, L"CreateFile", L"Error", MB_OK | MB_ICONERROR); } if (hCursor != NULL) ::SetCursor(hCursor); return TRUE; } INT_PTR CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return Window_Open(hWnd, wParam, lParam); case WM_COMMAND: if (LOWORD(wParam) == ID_BT_RETRIEVE) return btRetrieve_Click(hWnd, wParam, lParam); if (LOWORD(wParam) == IDCANCEL) ::EndDialog(hWnd, 0); break; } return (INT_PTR)FALSE; } int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR cmdLine, int cmdShow) { ::DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, WndProc); return 0; } |
Tip |
Observe that you may access the service from other computer by using its IP address instead of a dot in the previous problem. When done playing with your services, do not forget to remove the services by running the MyService.exe program with the -remove option. Note that you need to stop the service, before removing it. Observe que usted puede accesar el servicio desde otra computadora usando su dirección de IP en lugar del punto en el problema anterior. Cuando termine de jugar con sus servicios, no se olvide de remover los servicios ejecutando el programa MyService.exe con la opción de -remove. Observe que usted necesita detener el servicio, antes de removerlo. |
Services Command Line |
It is possible to use a CMD (DOS promt) running as Administrator to manage a service:
Es posible usar CMD (DOS promt) corriendo como Administrador para administrar un servicio:
|