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

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

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


--


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

من هذا المقال وخاصة المقالين القادمين ، سندخل في باب حساس جدا ..

حيث ان هذه المقالات ستشكل الحجر الرئيسي لتكوين برامج الRAT

الكثير يعلم ماهي برامج الRAT وماتفعله للمستخدمين وكيف الهكرز يستعملونها لعمليات الاختراق

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

في المقال القادم ساكشف اسرار الاتصال وتجاوز جميع العقبات لتنفيذ اتصال مباشر بين شخصين على الانترنت

وذلك بدون الحاجة الى اعدادات خاصة بالروتر ولاتثبيت ايبي ولاغير ذلك

بل سنقوم بتخيل انفسنا كمبرمجين محترفين نصمم برنامج تورنت . كيف سنقوم بتفيذ اتصال Peer2Peer بدون اعدادات خاصة ؟

حيث ان التورنت وبرامج التحكم تعتمد على اتصال Peer2Peer بشكل عام

حسب معرفتي للهكرز فهم متلهثون لمثل هذه المواضيع الدسمة التي تطرح عربيا لأول مرة

ولكن هل ساضحي بكتمان المعلومة على الجميع بسبب مجموعة مختلة عقليا ؟

هذا السؤال طرحته على نفسي عدة مرات (كم شخص سيستفيد وكم شخص سيستعمل هذه الطرق لعمل الشر؟ )

ولكن في النهاية قررت اكمال السلسلة للإفادة العامة

وإني اقولها من الان وحتى الدروس القادمة ("لا يجوز استعمال هذه الطرق لاغراض غير شرعية")

ادري طولت في المقدمة ، ولكن سأكتفي الان ..










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


اولا :- كتابة 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 ك ب / التحميلات : 136)
الرد }}}}
تم الشكر بواسطة: 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
الرد }}}}
تم الشكر بواسطة:


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  [سلسلة التحكم] {2} - التحكم بواسطة Remoting الشاكي لله 8 3,444 06-12-16, 04:22 PM
آخر رد: الشاكي لله
  [سلسلة التعامل مع الويب] تحليل الصفحات باستخدام HtmlAgilityPack الشاكي لله 9 1,240 25-09-16, 12:19 PM
آخر رد: ابراهيم كركوكي
  [مقال] برمجة نظام تشغيل بواسطة #C الشاكي لله 9 4,061 02-06-16, 11:34 AM
آخر رد: CLARO
  انشاء قاعدة MySQL على الانترنت والتعامل معها من برنامجك بواسطة EF5 الشاكي لله 5 1,111 02-06-16, 11:29 AM
آخر رد: CLARO
  [سلسلة التحكم] {5} - التحكم بالمصباح بواسطة الـ USB و Arduino الشاكي لله 11 9,782 02-06-16, 11:28 AM
آخر رد: CLARO
  تجميعية مقالات [سلسلة التحكم] الشاكي لله 8 1,332 02-06-16, 11:25 AM
آخر رد: CLARO
  [سلسلة التحكم] {3} - خدمة الويب (Web Service) الشاكي لله 8 4,328 02-06-16, 11:25 AM
آخر رد: CLARO
  [سلسلة ادوات المبرمج] {2} - اداة تحليل صفحات الويب HAPXPathFinder الشاكي لله 9 2,011 02-06-16, 11:24 AM
آخر رد: CLARO
  [سلسلة التعامل مع الويب] - ارسال الطلبات HttpWebRequset الشاكي لله 14 4,835 02-06-16, 11:21 AM
آخر رد: CLARO
  [سلسلة التحكم] {1} - طرق التحكم في البرامج الشاكي لله 7 3,229 12-02-16, 10:16 PM
آخر رد: nani49

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


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