تقييم الموضوع :
  • 1 أصوات - بمعدل 5
  • 1
  • 2
  • 3
  • 4
  • 5
[سلسلة التحكم] {4} - التحكم عن بعد بواسطة خدمة الويب
#1
بسم الله الرحمن الرحيم

السلام عليكم ورحمة الله وبركاته

والصلاة والسلام على اشرف الخلق محمد وعلى اله الطيبين الطاهرين


--


اهلا وسهلا بكم اخواني في المقالة الرابعة من [سلسلة التحكم]



 



صفر :- اجزاء المقالة


اولا :- كتابة Remote object
ثانيا :- كتابة Web Service
ثالثا :- كتابة برنامج Server
رابعا :- كتابة برنامج Client
خامسا :- فيديو نتيجة الدرس (من تصويري)
سادسا :- المراجع & الخاتمة









اولا :- Remote object


الRemote object هو مصطلح يعلمه كل من تابع المقالة الثانية من هذه السلسلة

هذا الRemote object يحتوي على دوال تتحكم في الحاسوب فور استدعائها

ولكن من الذي يستدعي هذه الدالة ؟؟

البرنامج Client هو من يعطي اشارة للServer ليقوم باستدعاء الدالة من الRemote object

فيتم اسدعاء الدالة وتنفيذها على الServer ، كل هذا تم بأمر من برنامج الClient.

في البداية علينا إنشاء Remote object وهو عبارة عن Class library


--

خطوات انشاء Remote object :-

1-
سنسمي الRemote object باسم Control وسنقوم بانشاء مشروع جديد من نوع Class Library





2-
دائما اول شيئ تفكر فيه هو "الاوامر" ، فتسأل نفسك : ماهي الاوامر التي اريد من الServer ان ينفذها ؟؟

وتكتب كل الاوامر داخل enum


PHP كود :
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace 
Control
{
 
   public class Controls
    
{
 
       public enum Commands
        
{
 
           TurnOffPC,
 
           ViewMessage,
 
           PlayBeebs,
 
           SetClipboard,
 
           GetClipboard,
 
           GetScreenShot,
 
           GetPCName
        
}
 
   }



الاوامر التي اريد من الجهاز الاخر (Server) ان ينفذها هي :
- اطفاء الحاسوب ، عرض رسالة ، تشغيل صوت ، اضافة قيمة للحافظة ، جلب قيمة الحافظة ، جلب صورة سطح المكتب الحالية - جلب اسم جهاز السيرفر

هذه الاوامر التي خطرت في بالي فقمت بكتابتها في enum.




3-
الان علينا كتابة دالة لكل امر كتبته فوق :-


PHP كود :
       public void TurnOffPC()
 
       {
 
           System.Diagnostics.Process.Start("shutdown""-s -t 1");
 
       }

 
       public void ViewMessage(string message)
 
       {
 
           MessageBox.Show(message"Message From Client"MessageBoxButtons.OKMessageBoxIcon.Information);
 
       }

 
       public void PlayBeebs()
 
       {
 
           System.Media.SystemSounds.Beep.Play();
 
       }

 
       public void SetCliboard(string str)
 
       {
 
           Clipboard.SetText(str);
 
       }

 
       public string GetCliboard()
 
       {
 
           try
            
{
 
               return Clipboard.GetText();
 
           }
 
           catch { return ""; }        
        
}

 
       public byte[] GetScreenShot()
 
       {
 
           try
            
{
 
             var  bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
 
                          Screen.PrimaryScreen.Bounds.Height,
 
                          PixelFormat.Format32bppArgb);

 
               // Create a graphics object from the bitmap.
 
             var  gfxScreenshot Graphics.FromImage(bmpScreenshot);

 
               // Take the screenshot from the upper left corner to the right bottom corner.
 
              gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
 
                                           Screen.PrimaryScreen.Bounds.Y,
 
                                           0,
 
                                           0,
 
                                           Screen.PrimaryScreen.Bounds.Size,
 
                                           CopyPixelOperation.SourceCopy);

 
               // Save the screenshot to the specified path that the user has chosen.
 
              using (var ms = new System.IO.MemoryStream())
 
              {
 
                  bmpScreenshot.Save(msImageFormat.Png);
 
                  return ms.ToArray();
 
              }
 
           }
 
           catch { return null; }
 
       }

 
       public string GetPCName()
 
       {
 
           try
            
{
 
               return System.Environment.MachineName;
 
           }
 
           catch { return ""; }
 
       



--


وهكذا قمنا بكتابة الدوال التي ستقوم بتنفيذ طموحاتنا على جهاز الServerBig Grin

والكود النهائي :-

PHP كود :
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace 
Control
{
 
   public class Controls
    
{
 
       public enum Commands
        
{
 
           TurnOffPC,
 
           ViewMessage,
 
           PlayBeebs,
 
           SetClipboard,
 
           GetClipboard,
 
           GetScreenShot,
 
           GetPCName
        
}

 
       public void TurnOffPC()
 
       {
 
           System.Diagnostics.Process.Start("shutdown""-s -t 1");
 
       }

 
       public void ViewMessage(string message)
 
       {
 
           MessageBox.Show(message"Message From Client"MessageBoxButtons.OKMessageBoxIcon.Information);
 
       }

 
       public void PlayBeebs()
 
       {
 
           System.Media.SystemSounds.Beep.Play();
 
       }

 
       public void SetCliboard(string str)
 
       {
 
           Clipboard.SetText(str);
 
       }

 
       public string GetCliboard()
 
       {
 
           try
            
{
 
               return Clipboard.GetText();
 
           }
 
           catch { return ""; }        
        
}

 
       public byte[] GetScreenShot()
 
       {
 
           try
            
{
 
             var  bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
 
                          Screen.PrimaryScreen.Bounds.Height,
 
                          PixelFormat.Format32bppArgb);

 
               // Create a graphics object from the bitmap.
 
             var  gfxScreenshot Graphics.FromImage(bmpScreenshot);

 
               // Take the screenshot from the upper left corner to the right bottom corner.
 
              gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
 
                                           Screen.PrimaryScreen.Bounds.Y,
 
                                           0,
 
                                           0,
 
                                           Screen.PrimaryScreen.Bounds.Size,
 
                                           CopyPixelOperation.SourceCopy);

 
               // Save the screenshot to the specified path that the user has chosen.
 
              using (var ms = new System.IO.MemoryStream())
 
              {
 
                  bmpScreenshot.Save(msImageFormat.Png);
 
                  return ms.ToArray();
 
              }
 
           }
 
           catch { return null; }
 
       }

 
       public string GetPCName()
 
       {
 
           try
            
{
 
               return System.Environment.MachineName;
 
           }
 
           catch { return ""; }
 
       }
 
   }














ثانيا :- كتابة Web Service


الان يجب علينا التفكير مليا ... ماهي الطريقة التي سنستعملها للتحكم بالجهاز الاخر ؟؟

هناك طريقة ذكية وسنستعملها في هذه المقالة وهي "الرسائل" .

مبدأها يشبه مبدأ الChatting تماااااما ، حيث انك ترسل من برنامجك Client الى البرنامج الاخر (Server) الرقم 3

فيقوم الServer باستدعاء الدالة TurnOffComputer مثلا ... نفس الشيئ لو ارسلت الرقم 7 ، سيقوم السيرفر باستدعاء GetScreenShot.

اذن النظام الذي سنستخدمه هو الرسائل . فالان علينا التفكير في طريقة لنقل الرسائل من عندنا الى الطرف الاخر !

الجواب هو باستعمال خدمة الويب كأحد طرق نقل الرسائل ...



فالطريقة بالتفصيل ستكون بهذه الكيفية :-

1- اولا يقوم البرنامج الClient بارسال الرقم 1 مع اسم السيرفر الهدف الى خدمة الويب
2- تقوم خدمة الويب بحفظ الرقم + اسم الserver في مكان مخصص في الذاكرة
3- في برنامج الServer يوجد timer يعمل كل 3 ثواني مثلا .. وظيفته هو فحص هذا المكان في الذاكرة للبحث عن الجديد
4- فاذا عثر على الرقم 1 في المكان المخصص ... يقوم بترجمة الرقم ويفهمه على انه استدعاء لدالة معينة



طبعا نظام الارقام صار قديم في البرمجة .. الان يتم استخدام enum ، لذلك قمنا في بداية المقالة بانشاء enum لتسهيل الموضوع

--

نقوم اولا بإنشاء WebService ونسميها WebKernel مثلا او اي اسم يحلو لك




إقتباس :خطوات إنشاء خدمة الويب :-

1- إنشاء مشروع جديد من نوع ASP.NET Empty Web Application
2- قم بإضافة WebService من خلال Project > Add new item > Web Service



خطوات إنشاء خدمة الويب (بالصور) :-

1


2





ثم نقوم بادراج الRemote object في هذا المشروع عبر :-




بعدها نقوم بكتابة دالة يطلبها الClient لكي تخزن رقم في الذاكرة

PHP كود :
       [WebMethod]
 
       public void SendCommandTo(string SenderNamestring ReceiverNameControls.Commands cmdstring addtionalData)
 
       {
 
           Application.Set(ReceiverName "|CMD", ((int)cmd).ToString());
 
           Application.Set(ReceiverName "|ADD"addtionalData);
 
           Application.Set(ReceiverName "|Sender"SenderName);
 
       


Application.Set هي دالة تقوم بحفظ بيانات لفترة قدرها نصف ساعة تقريبا ثم تحذف .

هي تستقبل بارمترين .. الاول هو key  ،  والاخر هو data

اي انها شبيهة جدا بHashtable او Dictionary

طبعا اعلم ان الكود يسوده الغموض وهذا طبيعي لأن البرنامج يعتمد على نمط لايعلم عنه سوا كاتب الكود .




الدالة المقابلة والتي تقوم باسترجاع البيانات من الذاكرة هي


PHP كود :
       [WebMethod]
 
       public string[] ReceiveCommand(string name)
 
       {
 
           try
            
{
 
               string[] obj = new string[3];
 
               obj[0] = (string)Application.Get(name "|CMD");
 
               obj[1] = (string)Application.Get(name "|ADD");
 
               obj[2] = (string)Application.Get(name "|Sender");
 
               return obj;
 
           }
 
           catch { return null; }
 
       



Application.Get تستقبل بارمتار واحد وهو key .. وسترجع لك الdata المحفوظة على هذا الkey

كما قلت سابقا مبدأها يشبه مبدا HashTable فالي فاهمنه مابواجه مشكلة.


بقية الكود هي دوال مساعدة :-

PHP كود :
using Control;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

namespace 
WebKernel
{
 
   /// <summary>
 
   /// Summary description for MyService
 
   /// </summary>
 
   [WebService(Namespace = "http://tempuri.org/")]
 
   [WebServiceBinding(ConformsTo WsiProfiles.BasicProfile1_1)]
 
   [System.ComponentModel.ToolboxItem(false)]
 
   // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
 
   // [System.Web.Script.Services.ScriptService]
 
   public class MyService System.Web.Services.WebService
    
{

 
       [WebMethod]
 
       public void SendCommandTo(string SenderNamestring ReceiverNameControls.Commands cmdstring addtionalData)
 
       {
 
           Application.Set(ReceiverName "|CMD", ((int)cmd).ToString());
 
           Application.Set(ReceiverName "|ADD"addtionalData);
 
           Application.Set(ReceiverName "|Sender"SenderName);
 
       }

 
       [WebMethod]
 
       public object SendCommandAndWaitResult(string SenderNamestring ReceiverNameControls.Commands cmd)
 
       {
 
           Application.Set(ReceiverName "|CMD", ((int)cmd).ToString());
 
           Application.Set(ReceiverName "|ADD"null);
 
           Application.Set(ReceiverName "|Sender"SenderName);
 
           //wait for result
 
           while (Application.Get(SenderName) == null) { }

 
           object result Application.Get(SenderName);
 
           Application.Remove(SenderName);

 
           return result;
 
       }

 
       [WebMethod]
 
       public void ReturnResultToClient(string nameobject result)
 
       {
 
           Application.Set(nameresult);
 
       }

 
       [WebMethod]
 
       public string[] ReceiveCommand(string name)
 
       {
 
           try
            
{
 
               string[] obj = new string[3];
 
               obj[0] = (string)Application.Get(name "|CMD");
 
               obj[1] = (string)Application.Get(name "|ADD");
 
               obj[2] = (string)Application.Get(name "|Sender");
 
               return obj;
 
           }
 
           catch { return null; }
 
       }

 
       [WebMethod]
 
       public void RemoveRegisterName(string name)
 
       {
 
           try
            
{
 
               Application.Remove(name "|CMD");
 
               Application.Remove(name "|ADD");
 
               Application.Remove(name "|Sender");
 
           }
 
           catch { }
 
       }


 
       [WebMethod]
 
       public bool CheckNameExist(string name)
 
       {
 
           if (Application[name "|Alive"] != null)
 
           {
 
               return true;
 
           }
 
           else
            
{
 
               Application.Set(name "|Alive", -1);
 
               return false;
 
           }
 
           
        
}

 
   }




ستفهم جميع هذه الدوال في النهاية اذا ركزت في الجزئين التاليين .


ولكن عليك ان تقوم برفع الخدمة الى استضافة كي نستطيع التحكم عن بعد













ثانيا :- كتابة Server


دائما اغلب مبرمجي تطبيقات (Client/server) يقومون بكتابة الserver اولا

فنحن بدورنا سنقوم بفعل ذلك ، لذلك قم بإنشاء مشروع جديد في نفس السلوشن

ومن نوع Windows App واسمه Server :





اولا علينا اضافة المراجع الضرورية ك Remote object الي سويناها في الجزء الاول

وخدمة الويب المرفوعة على استضافة .







بعدها نعرف متغير عام على المشروع يمثل الclient تبع الخدمة
ومتغير اخر عام نحفظ فيه اسمنا


PHP كود :
       Service.MyServiceSoapClient _serviceClient = new Service.MyServiceSoapClient();
 
       private string _MyName string.Empty; 



قد تقول معليش انا فهمت ليش سويت متغير يعبر عن الخدمة وذلك لكي تستطيع استعمال دوال خدمة الويب

ولكن لم افهم ليش سويت متغير _MyName ؟؟؟


طبيعي في اي برنامج server/client ان يكون هناك عنوان فريد يدل على الاخر

فكيف يستطيع الclient ان يتصل بالسيرفر بدون عنوانه ؟

العنوان في العادة يكون عبارة عن IP Address ولكن باستعمال خدمة الويب يمكنك الاستغناء عن الايبي

واضافة اي اسم كي يستطيع الclient الوصول له ...


فنحن سنكتب اسمنا في الtextbox وثم ناخذ قيمته ونضعه في المتغير العام MyName .


والان كود الButtonOK هو :-


PHP كود :
       private void OKbutton_Click(object senderEventArgs e)
 
       {
 
           if (_serviceClient.CheckNameExist(textBox1.Text.Trim()))
 
           {
 
               MessageBox.Show("Choose another name""Error : name exist"MessageBoxButtons.OKMessageBoxIcon.Error);
 
               return;
 
           }
 
           _MyName textBox1.Text.Trim();
 
           textBox1.Enabled false;
 
           OKbutton.Enabled false;
 
           StatusLable.Text "Waiting for commands ...";
 
           ServerTimer.Start();
 
       



--

شرح الكود :-

في السطر الاول : نقوم بفحص الاسم المدخل ، هل يستخدمه شخص اخر ام لا ؟ فكما لايمكن ان يتشابه IP address على وجه الارض
كذلك لايمكننا ان ندع الاسماء تتشابه كي نستلم الرسائل من الجهة الصحيحة .

بقية الاسطر : مفهومة وواضحة .

السطر الاخير : تشغيل تايمر لفحص الاوامر الجديدة . فهذا تايمر يعمل كل 3 ثواني ويقوم بالاستعلام عن اخر الاوامر


وكوده هو :-

PHP كود :
       private async void ServerTimer_Tick(object senderEventArgs e)
 
       {
 
           //الاستعلام عن اخر امر
 
           Task<ReceiveCommandResponsecmdTask  _serviceClient.ReceiveCommandAsync(_MyName);
 
           ReceiveCommandResponse cmdResb await cmdTask;
 
           Service.ArrayOfString arr cmdResb.Body.ReceiveCommandResult;
 
           if (arr[0] == null) { return; }
 
           Control.Controls controlObj = new Control.Controls();
 
           
            
//حذف اخر من  ذاكرة السيرفر
 
           await _serviceClient.RemoveRegisterNameAsync(_MyName);

 
           //استخلاص الامر والعنوان من الاستعلام
 
           Commands CMD = (Commands)int.Parse(arr[0]);
 
           string addtionalInfo = (string)arr[1];
 
           string senderName = (string)arr[2];

 
           //اذا كان الامر المرسل يساوي كذا قم باستدعاء الدالة المناسبة
 
           switch (CMD)
 
           {
 
               case Commands.TurnOffPC:
 
                   controlObj.TurnOffPC();
 
                   break;
 
               case Commands.ViewMessage:
 
                   controlObj.ViewMessage(addtionalInfo);
 
                   break;
 
               case Commands.PlayBeebs:
 
                   controlObj.PlayBeebs();
 
                   break;
 
               case Commands.SetClipboard:
 
                   controlObj.SetCliboard(addtionalInfo);
 
                   break;
 
               case Commands.GetClipboard:
 
                   string data0 controlObj.GetCliboard();
 
                   await _serviceClient.ReturnResultToClientAsync(senderNamedata0);
 
                   break;
 
               case Commands.GetScreenShot:
 
                   byte[] data1 controlObj.GetScreenShot();
 
                   await _serviceClient.ReturnResultToClientAsync(senderNamedata1);
 
                   break;
 
               case Commands.GetPCName:
 
                   string data2 controlObj.GetPCName();
 
                   await _serviceClient.ReturnResultToClientAsync(senderNamedata2);
 
                   break;
 
           }
 
       



الكود مشروح بالتعليقات الخضراء

ولكن اهم شيئ فيه هو المتغير CMD وهو يعبر عن الامر المرسل من الClient

فإذا كان الامر الذي ارسله Client يساوي Commands.TurnOffPC قم باستدعاء دالة اغلاق الحاسوب

ونفس الشيئ للبقية .



--

الكود كامل :-


PHP كود :
using Server.Service;
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 
Server
{
 
   public partial class ServerForm Form
    
{
 
       Service.MyServiceSoapClient _serviceClient = new Service.MyServiceSoapClient();
 
       private string _MyName string.Empty;

 
       public ServerForm()
 
       {
 
           InitializeComponent();
 
       }


 
       private void OKbutton_Click(object senderEventArgs e)
 
       {
 
           if (_serviceClient.CheckNameExist(textBox1.Text.Trim()))
 
           {
 
               MessageBox.Show("Choose another name""Error : name exist"MessageBoxButtons.OKMessageBoxIcon.Error);
 
               return;
 
           }
 
           _MyName textBox1.Text.Trim();
 
           textBox1.Enabled false;
 
           OKbutton.Enabled false;
 
           StatusLable.Text "Waiting for commands ...";
 
           ServerTimer.Start();
 
       }

 
       private async void ServerTimer_Tick(object senderEventArgs e)
 
       {
 
           //الاستعلام عن اخر امر
 
           Task<ReceiveCommandResponsecmdTask  _serviceClient.ReceiveCommandAsync(_MyName);
 
           ReceiveCommandResponse cmdResb await cmdTask;
 
           Service.ArrayOfString arr cmdResb.Body.ReceiveCommandResult;
 
           if (arr[0] == null) { return; }
 
           Control.Controls controlObj = new Control.Controls();
 
           
            
//حذف اخر من  ذاكرة السيرفر
 
           await _serviceClient.RemoveRegisterNameAsync(_MyName);

 
           //استخلاص الامر والعنوان من الاستعلام
 
           Commands CMD = (Commands)int.Parse(arr[0]);
 
           string addtionalInfo = (string)arr[1];
 
           string senderName = (string)arr[2];

 
           //اذا كان الامر المرسل يساوي كذا قم باستدعاء الدالة المناسبة
 
           switch (CMD)
 
           {
 
               case Commands.TurnOffPC:
 
                   controlObj.TurnOffPC();
 
                   break;
 
               case Commands.ViewMessage:
 
                   controlObj.ViewMessage(addtionalInfo);
 
                   break;
 
               case Commands.PlayBeebs:
 
                   controlObj.PlayBeebs();
 
                   break;
 
               case Commands.SetClipboard:
 
                   controlObj.SetCliboard(addtionalInfo);
 
                   break;
 
               case Commands.GetClipboard:
 
                   string data0 controlObj.GetCliboard();
 
                   await _serviceClient.ReturnResultToClientAsync(senderNamedata0);
 
                   break;
 
               case Commands.GetScreenShot:
 
                   byte[] data1 controlObj.GetScreenShot();
 
                   await _serviceClient.ReturnResultToClientAsync(senderNamedata1);
 
                   break;
 
               case Commands.GetPCName:
 
                   string data2 controlObj.GetPCName();
 
                   await _serviceClient.ReturnResultToClientAsync(senderNamedata2);
 
                   break;
 
           }
 
       }



 
   }





الان نذهب لتصميم الClient فيقوم بارسال امر الى الخدمة الويب ، فتقوم خدمة الويب بحفظها في ذاكرة الHost لمدة قدرها تقريبا نصف ساعة

طبعا كما ذكرنا في الفقرة السابقة ان الserver سيقوم كل 3 ثواني بفحص ذاكرة الHost للحصول على جديد الاوامر .















رابعا :- كتابة Client


كما قلنا سابقا سنقوم بعمل برنامج Client يقوم بارسال امر الى الخدمة ويقوم الServer بالاستعلام من الخدمة .

سنقوم بإنشاء برنامج Client في نفس السلوشن ايضا ، وهو من نوع Windows App وباسم Client :





كلعادة نقوم باضافة الموارد اللازمة (خدمة الويب + الRemote object)






والان اصبح السلوشن بهذا الشكل :





الان نبدأ البرمجة ونقول بتعريف المتغيرات العامة :-


PHP كود :
       Service.MyServiceSoapClient _serviceClient = new Service.MyServiceSoapClient();
 
       private string _ServerName string.Empty;
 
       private string _MyName string.Empty; 




ونبرمج زر OK بنفس طريقة الServer :-

PHP كود :
       private void OKbutton_Click(object senderEventArgs e)
 
       {
 
           if (_serviceClient.CheckNameExist(textBox1.Text.Trim()))
 
           {
 
               MessageBox.Show("Choose another name (My Name)""Error : name exist"MessageBoxButtons.OKMessageBoxIcon.Error);
 
               return;
 
           }
 
           groupBox1.Enabled false;
 
           groupBox2.Enabled true;
 
           _MyName textBox1.Text.Trim();
 
           _ServerName textBox2.Text.Trim();
 
       




والان نقوم بكتابة كود الازرار ال6 :-


PHP كود :
       private void SendMessageBtn_Click(object senderEventArgs e)
 
       {
 
          string str Interaction.InputBox("Enter your message to server");
 
          if (str != string.Empty)
 
          {
 
              //ارسال امر
 
              _serviceClient.SendCommandTo(_MyName_ServerNameService.Commands.ViewMessagestr);
 
          }
 
       }

 
       private void SendBeebsBtn_Click(object senderEventArgs e)
 
       {
 
           _serviceClient.SendCommandTo(_MyName_ServerNameService.Commands.PlayBeebsnull);
 
       }

 
       private void SendClipboardBtn_Click(object senderEventArgs e)
 
       {
 
           string str Interaction.InputBox("Enter your text to save it in server clipboard");
 
           if (str != string.Empty)
 
           {
 
               _serviceClient.SendCommandTo(_MyName_ServerNameService.Commands.SetClipboardstr);
 
           }
 
       }

 
       private void GetDataClipboardBtn_Click(object senderEventArgs e)
 
       {
 
           //ارسال امر وانتظار النتيجةSendCommandAndWaitResult
 
           string savedClipBoard = (string)_serviceClient.SendCommandAndWaitResult(_MyName,_ServerName,
 
               Service.Commands.GetClipboard);

 
           MessageBox.Show("The content of server clipboard is : " savedClipBoard"Server Clipboard"
 
               MessageBoxButtons.OKMessageBoxIcon.Information);
 
       }

 
       private void ScreenshotBtn_Click(object senderEventArgs e)
 
       {
 
           //ارسال امر جلب الصورة وانتظار الصورة
 
           byte[] serverShot = (byte[])_serviceClient.SendCommandAndWaitResult(_MyName_ServerName,
 
               Service.Commands.GetScreenShot);

 
           using (System.IO.MemoryStream ms = new System.IO.MemoryStream(serverShot))
 
           {
 
               Image shot Image.FromStream(ms);
 
               ScreenShotForm shotForm = new ScreenShotForm();
 
               shotForm.pictureBox1.BackgroundImage shot;
 
               shotForm.Show();
 
               ms.Close();
 
           }
 
       }

 
       private void MachinenameBtn_Click(object senderEventArgs e)
 
       {
 
           //ارسال امر جلب اسم جهاز السيرفر وانظار النتيجة
 
           string serverMachineName = (string)_serviceClient.SendCommandAndWaitResult(_MyName_ServerName,
 
               Service.Commands.GetPCName);

 
           MessageBox.Show("The server machine name is : " serverMachineName"Server Machine Name",
 
               MessageBoxButtons.OKMessageBoxIcon.Information);
 
       }

 
       private void ShutdownBtn_Click(object senderEventArgs e)
 
       {
 
           _serviceClient.SendCommandTo(_MyName_ServerNameService.Commands.TurnOffPC,null);
 
       



استخدمت في الكود الدالة SendCommandTo هي لكي ترسل امر الى الخدمة
والدالة SendCommandAndWaitResult لارسال امر وانتظار النتيجة التي سيرجعها الServer


فمثلا هذا الزر يتطلب ارسال امر وجلب نتيجة تنفيذه :




فهذا الزر يتطلب استعمال دالة SendCommandAndWaitResult لانتظار النتيجة

بعد وصول النتيجة سيتم عرضها على فورم اخر .


ولكن هناك شيئ مهم جدا يخص Get screen shot ، فكما نعلم من اسم الزر انه امر لجلب صورة سطح المكتب للسيرفر

وهذا يتطلب نقل الصورة من الserver الى client ، ولكن انتبه فلا يجوز نقل صورة حجمها اكبر من 60 كيلو بايت !!!


60 كيلو بايت !!! . هي مساحة صغيرة جدا واغلب الصور تكون اكبر من هذا الحجم فما الحل ؟؟


الحل بسيط اكثر مماتتخيل . فقط قم بالدخول الى App.config والخاص بالمشروع Client الذي نعمل عليه حاليا


وقم بالتالي :-




كما ترا قمت باضافة maxReceivedMessageSize لزيادة حجم اقصى حد لاستقبال الرسائل

ووضعت قيمته 2000000 مما يساوي 2 ميغا بايت

ومستحيل صورة سطح المكتب التي سيتم التقاطها بتنسيق jpg ان يتجاوز حجمها ال700 كيلو  ولكن للاحتطيات فقط وضعت 2 مب.




الكود كامل :-


PHP كود :
using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace 
Web_Remote
{
 
   public partial class ClientForm Form
    
{
 
       Service.MyServiceSoapClient _serviceClient = new Service.MyServiceSoapClient();
 
       private string _ServerName string.Empty;
 
       private string _MyName string.Empty;

 
       public ClientForm()
 
       {
 
           InitializeComponent();
 
       }

 
       private void OKbutton_Click(object senderEventArgs e)
 
       {
 
           if (_serviceClient.CheckNameExist(textBox1.Text.Trim()))
 
           {
 
               MessageBox.Show("Choose another name (My Name)""Error : name exist"MessageBoxButtons.OKMessageBoxIcon.Error);
 
               return;
 
           }
 
           groupBox1.Enabled false;
 
           groupBox2.Enabled true;
 
           _MyName textBox1.Text.Trim();
 
           _ServerName textBox2.Text.Trim();
 
       }

 
       private void SendMessageBtn_Click(object senderEventArgs e)
 
       {
 
          string str Interaction.InputBox("Enter your message to server");
 
          if (str != string.Empty)
 
          {
 
              //ارسال امر
 
              _serviceClient.SendCommandTo(_MyName_ServerNameService.Commands.ViewMessagestr);
 
          }
 
       }

 
       private void SendBeebsBtn_Click(object senderEventArgs e)
 
       {
 
           _serviceClient.SendCommandTo(_MyName_ServerNameService.Commands.PlayBeebsnull);
 
       }

 
       private void SendClipboardBtn_Click(object senderEventArgs e)
 
       {
 
           string str Interaction.InputBox("Enter your text to save it in server clipboard");
 
           if (str != string.Empty)
 
           {
 
               _serviceClient.SendCommandTo(_MyName_ServerNameService.Commands.SetClipboardstr);
 
           }
 
       }

 
       private void GetDataClipboardBtn_Click(object senderEventArgs e)
 
       {
 
           //ارسال امر وانتظار النتيجةSendCommandAndWaitResult
 
           string savedClipBoard = (string)_serviceClient.SendCommandAndWaitResult(_MyName,_ServerName,
 
               Service.Commands.GetClipboard);

 
           MessageBox.Show("The content of server clipboard is : " savedClipBoard"Server Clipboard"
 
               MessageBoxButtons.OKMessageBoxIcon.Information);
 
       }

 
       private void ScreenshotBtn_Click(object senderEventArgs e)
 
       {
 
           //ارسال امر جلب الصورة وانتظار الصورة
 
           byte[] serverShot = (byte[])_serviceClient.SendCommandAndWaitResult(_MyName_ServerName,
 
               Service.Commands.GetScreenShot);

 
           using (System.IO.MemoryStream ms = new System.IO.MemoryStream(serverShot))
 
           {
 
               Image shot Image.FromStream(ms);
 
               ScreenShotForm shotForm = new ScreenShotForm();
 
               shotForm.pictureBox1.BackgroundImage shot;
 
               shotForm.Show();
 
               ms.Close();
 
           }
 
       }

 
       private void MachinenameBtn_Click(object senderEventArgs e)
 
       {
 
           //ارسال امر جلب اسم جهاز السيرفر وانظار النتيجة
 
           string serverMachineName = (string)_serviceClient.SendCommandAndWaitResult(_MyName_ServerName,
 
               Service.Commands.GetPCName);

 
           MessageBox.Show("The server machine name is : " serverMachineName"Server Machine Name",
 
               MessageBoxButtons.OKMessageBoxIcon.Information);
 
       }

 
       private void ShutdownBtn_Click(object senderEventArgs e)
 
       {
 
           _serviceClient.SendCommandTo(_MyName_ServerNameService.Commands.TurnOffPC,null);
 
       }
 
   }
















خامسا :- فيديو نتيجة الدرس (من تصويري)







او من على اليوتيوب مباشرة

كود :
https://www.youtube.com/watch?v=DClwZ_m9dAs












سابعا :- المراجع & الخاتمة


المراجع المعتمد عليها في هذه المقالة :-

[سلسلة التحكم] {3} - خدمة الويب (Web Service)

--


أتمنى أن تستفيدو من هذه المقالة

اعلم ان بعضكم قد يتسآل ويقول "مادام مبدأك نقل رسائل فقط ليش استعملت WebService ولم تقم بإرسال الرسائل مباشرة للServer" ؟

في الواقع الاتصال المباشر بين طرفين يسمى Peer2Peer وهو اتصال سهل يمكنك عمله بسهولة ولكن ...

لو كان الطرفان بعيدان وعلى شبكة مختلفة ، أعلم ان Peer2Peer ستواجه المصاعب والمآسي ولن يتم الاتصال

وكل هذا بسبب الجدران النارية والNAT ، ولكن في الاجزاء القادمة سنقوم بكشف الستار عن اسرار الاتصال المباشر

وسنقوم بعمل برنامج مثل TeamViewer يقوم بالتحكم الكامل عن بعد بواسطة Peer2Peer ولن نقوم بالاستعان بطرف ثالث (Third party).

نلقاكم بخير





إنتهى


[/size]


الملفات المرفقة
.zip   Web Remote.zip (الحجم : 267.71 ك ب / التحميلات : 240)
الرد }}}
تم الشكر بواسطة: Easy4ever , VanToM , mamas1 , kslawy , مالكـ
#2
بارك الله فيك
وجعله في ميزان حسناتك
وبإنتظار جديدك دائماً
والله أنت فخر للمسلمين !

Rolleyes
الرد }}}
تم الشكر بواسطة: الشاكي لله , essam.com2008
#3
السلام عليكم ورحمة الله وبركاته شكرا لك أخي الكريم على هذا الموضوع القييم
لدي سؤال لو سمحت لي
قمت بعمل web service ورفعته على هوستينج Somee وهو يعمل بنجاح
قمت بتطوير المشروع وقمت بإضافة Database اليه من نوع Sql Serever باستخدام تقنية Linq 2 Sql

بعد التطوير , المشروع يعمل بنجاح على حاسوبي الشخصي "Local Machine"
قمت برفع البرنامج مرة أخرى إلى ال Hosting
ولكن عندما أقوم باستدعاء التابع الذي يقوم بالقراءة من ال Database يظهر لي الخطأ التالي
error: 26 - Error Locating Server/Instance Specified

هنا الكودات التي يتألف منها مشروعي

Web.Config
PHP كود :
<?xml version="1.0"?>

<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->

<configuration>
    <connectionStrings>
        <add name="Database1ConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database1.mdf;Integrated Security=True;User Instance=True"
            providerName="System.Data.SqlClient" />
    </connectionStrings>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>

</configuration> 

Web Service1
PHP كود :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

namespace 
test2
{
    
/// <summary>
    /// Summary description for WebService1
    /// </summary>
    
[WebService(Namespace = "http://tempuri.org/")]
    [
WebServiceBinding(ConformsTo WsiProfiles.BasicProfile1_1)]
    [
System.ComponentModel.ToolboxItem(false)]
    
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    
public class WebService1 System.Web.Services.WebService
    
{

        [
WebMethod]
        public 
string DataBaseTest()
        {
            try
            {
                
DataClasses1DataContext db = new DataClasses1DataContext();
                return 
db.Table1s.Select(=> c).First().name;
            }
            catch (
Exception x)
            {
                return 
x.Message;
            }
        }
    }


Client Windows Application

PHP كود :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace 
WindowsFormsApplication1
{
    public 
partial class Form1 Form
    
{
        public 
Form1()
        {
            
InitializeComponent();
        }

        private 
void Form1_Load(object senderEventArgs e)
        {
            
ServiceReference1.WebService1SoapClient c = new ServiceReference1.WebService1SoapClient();
            
MessageBox.Show(c.DataBaseTest());
        }
    }


أرجة منك أخي الكريم تنبيهي إلى الخطأ فيما سبق
وشكرا لك
الرد }}}
تم الشكر بواسطة:
#4
الخطأ هنا

إقتباس :Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database1.mdf;Integrat​ed Security=True;User Instance=True"

حسب مافهمت انك رفعت القاعدة على الاستضافة، فيجب عليك ان تستبدل نص الاتصال بنص القاعدة المرفوعة


تحصل عليه من صفحة ال Ms-Sql :manage database


كما في الصورة :
الرد }}}
تم الشكر بواسطة:
#5
شكرا لك أخي الكريم
نعم كانت مشكلتي في ال connection string
سوف أقوم بتجربة ماتفضلت به
وأذكر النتيجة هنا إن شاء الله
الرد }}}
تم الشكر بواسطة:
#6
شكرا لك أخي الكريم
حلت المشكلة عندما استبدلت نص الاتصال Smile
الرد }}}
تم الشكر بواسطة:
#7
السلام عليكم اخي
ما شاء الله موضوع جميييل وجزاك الله كل خير
انا محمد عبدالصمد
طالب في قسم هندسة المعدات السنة الاخيرة
واريد مساعتك لو امكن
مشروعي عن تحريك كرسي الاسنان عن طريق الصوت باستخدام الاردوينو
بس ما لقيت شخص يساعد في PHP كود
مثل ما انت شارح
وهاذا ايميلي
navigator.on.line001@gmail.com
وشكرا
الرد }}}
تم الشكر بواسطة:
#8
ما شاء الله موضوع جميييل وجزاك الله كل خير










Speed Test
الرد }}}
تم الشكر بواسطة:


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  [سلسلة التحكم] {5} - التحكم بالمصباح بواسطة الـ USB و Arduino الشاكي لله 12 25,186 30-12-19, 01:38 AM
آخر رد: mohammed abdalsamed
  [سلسلة التحكم] {3} - خدمة الويب (Web Service) الشاكي لله 9 12,809 25-09-19, 05:47 PM
آخر رد: al9atl
  تجميعية مقالات [سلسلة التحكم] الشاكي لله 10 7,503 15-07-19, 09:14 AM
آخر رد: mrsalnet
  [سلسلة التعامل مع الويب] - ارسال الطلبات HttpWebRequset الشاكي لله 42 28,394 29-05-19, 10:38 PM
آخر رد: egbest2
  [C#.NET] سلسلة حلقات نضف كودك Devahmedsalim 1 2,625 10-10-17, 11:28 PM
آخر رد: nani49
  [سلسلة ادوات المبرمج] {2} - اداة تحليل صفحات الويب HAPXPathFinder الشاكي لله 10 8,492 30-08-17, 06:49 PM
آخر رد: ابو روضة
  انشاء قاعدة MySQL على الانترنت والتعامل معها من برنامجك بواسطة EF5 الشاكي لله 6 5,640 29-04-17, 11:41 AM
آخر رد: sendbad100
  [سلسلة التحكم] {2} - التحكم بواسطة Remoting الشاكي لله 8 10,353 06-12-16, 04:22 PM
آخر رد: الشاكي لله
  [سلسلة التعامل مع الويب] تحليل الصفحات باستخدام HtmlAgilityPack الشاكي لله 9 7,024 25-09-16, 12:19 PM
آخر رد: ابراهيم كركوكي
  [مقال] برمجة نظام تشغيل بواسطة #C الشاكي لله 9 10,173 02-06-16, 11:34 AM
آخر رد: CLARO

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم