Introduction
Last time, we performed the workstation's sleep functionality on the basis of the client app SLP2 command. In this third and final part of my article series, we will complete the functionality of both of our applications, client, and server. First, we will talk about how the screenshot functionality will perform because the client will only send the TSC1 command and the server will receive this. Then, on the basis of this command, the TakeScreenshot function will perform, which we will write inside the server app.
After capturing the screenshot of the current activity of the workstation, we will send it to the client. The size of the picture could be large and we cannot send the large data to the client. Therefore, to achieve this target, we will convert the screenshot data into byte-type packets and then send it to the client. When the client will receive the bytes type packets, it will have to convert them into their original form. We will also perform the shutdown functionality. If a client sends the SHTD3 command to the server application, the server will execute the shutdown function. Finally, if the admin wants to log out from the client application, then we will give this opportunity too to the admin. We will put the "logout" button at the end of the control page. If the admin clicks the "logout" button, the application will navigate to the login page.
Server Application
Let's go back to the server application and write the functionality of the screenshot and shutdown workstation. Open the program.cs file and write the following code inside the while loop, that we had implemented in the last episode. In the while loop, we put the try-catch block, and inside, we wrote the condition of If-Else. After if sleep check, you will write the following code.
- else if (data.ToUpper().Contains("SHTD3"))
- {
- Console.WriteLine("Pc is going to Shutdown!" + " \n");
- Shutdown();
- }
- else if (data.ToUpper().Contains("TSC1"))
- {
- Console.WriteLine("Take Screenshot!" + " \n");
- var bitmap = SaveScreenshot();
- var stream = new MemoryStream();
- bitmap.Save(stream, ImageFormat.Bmp);
- sendData(stream.ToArray(), client.GetStream());
- }
Add the following namespaces to the server application. Otherwise, Visual Studio will not recognize the graphics keyword of the screenshot function.
- using System.Drawing;
- using System.Drawing.Imaging;
Go back to program.cs and put these functions inside the main class.
- //Workstation Shutdown function
- void Shutdown()
- {
- System.Diagnostics.Process.Start("Shutdown", "-s -t 10");
- }
- //Save Screenshot function
- Bitmap SaveScreenshot()
- {
- 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);
- return bmpScreenshot;
- }
- //Convert Image to byte type data.
- void sendData(byte[] data, NetworkStream stream)
- {
- int bufferSize = 1024;
- byte[] dataLength = BitConverter.GetBytes(data.Length);
- stream.Write(dataLength, 0, 4);
- int bytesSent = 0;
- int bytesLeft = data.Length;
- while (bytesLeft > 0)
- {
- int curDataSize = Math.Min(bufferSize, bytesLeft);
- stream.Write(data, bytesSent, curDataSize);
- bytesSent += curDataSize;
- bytesLeft -= curDataSize;
- }
- }
We have finished our server application and it's all functionality. Let's start to code our client application.
Client Application
Go back to the client application and open the control.axml file. Inside a linear layout, add the following code to create more buttons and picture holders.
(Folder Name: Layout , File Name: Control.axml)
- <Button
- android:text="Take Screenshot"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="15dp"
- android:id="@+id/btnTakeScreen" />
- <Button
- android:text="Shutdown"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:id="@+id/btnShutdown" />
- <ImageView
- android:id="@+id/imageView"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
- <Button
- android:text="Logout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="15dp"
- android:id="@+id/btnLogout" />
Open the control.cs file that we had created in the last episode and replace the following code with appropriate namespaces.
- [Activity]
- public class Control : Activity
- {
- //Instances
- private Button btnTakeScreen, btnSleep, btnShutdown ,btnLogout;
- private ImageView imageView;
- NetworkStream stream;
- protected override void OnCreate(Bundle savedInstanceState)
- {
- base.OnCreate(savedInstanceState);
- var client = Connection.Instance.client;
- // Create your application here
- SetContentView(Resource.Layout.Control);
- btnTakeScreen = FindViewById<Button>(Resource.Id.btnTakeScreen);
- btnSleep = FindViewById<Button>(Resource.Id.btnSleep);
- btnShutdown = FindViewById<Button>(Resource.Id.btnShutdown);
- btnLogout = FindViewById<Button>(Resource.Id.btnLogout);
- imageView = FindViewById<ImageView>(Resource.Id.imageView);
- //Sleep command button
- btnSleep.Click += delegate
- {
- stream = client.GetStream();
- String s = "SLP2";
- byte[] message = Encoding.ASCII.GetBytes(s);
- stream.Write(message, 0, message.Length);
- };
- //Shutdown command button
- btnShutdown.Click += delegate
- {
- stream = client.GetStream();
- String s = "SHTD3";
- byte[] message = Encoding.ASCII.GetBytes(s);
- stream.Write(message, 0, message.Length);
- };
- //Take Screenshot command button
- btnTakeScreen.Click += delegate
- {
- stream = client.GetStream();
- String s = "TSC1";
- byte[] message = Encoding.ASCII.GetBytes(s);
- stream.Write(message, 0, message.Length);
- var data = getData(client);
- var image = BitmapFactory.DecodeByteArray(data, 0, data.Length);
- imageView.SetImageBitmap(image);
- };
- //Logout button
- btnLogout.Click += delegate
- {
- StartActivity(typeof(MainActivity));
- client.Close();
- };
- }
- //Convert byte to Image
- public byte[] getData(TcpClient client)
- {
- NetworkStream stream = client.GetStream();
- byte[] fileSizeBytes = new byte[4];
- int bytes = stream.Read(fileSizeBytes,0,fileSizeBytes.Length);
- int dataLength = BitConverter.ToInt32(fileSizeBytes,0);
- int bytesLeft = dataLength;
- byte[] data = new byte[dataLength];
- int buffersize = 1024;
- int bytesRead = 0;
- while(bytesLeft > 0)
- {
- int curDataSize = Math.Min(buffersize, bytesLeft);
- if (client.Available < curDataSize)
- curDataSize = client.Available;//This save me
- bytes = stream.Read(data, bytesRead, curDataSize);
- bytesRead += curDataSize;
- bytesLeft -= curDataSize;
- }
- return data;
- }
- }
Take Screenshot
Run both projects - server and client. Log in to the client application as admin if you are already registered. Else, register as admin. Put the workstation IP address and port that you can see on the server application output screen into the client application and hit "Connect".
After connecting with the server, now you can perform your task. Click on the "Take Screenshot" button; after a few seconds, you will see the screenshot of the workstation inside the client application.
Shutdown
After login and building the connection with the server, hit the "Shutdown" button. You will see a notification that your PC will be shut down in 30 seconds.
0 Comments:
Post a Comment