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, that 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 bytes type packets and then send it to the client. When the client will receive the bytes type packets, it will have to convert into its original form. We will also perform the shutdown functionality. If a client sends 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 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());
- }
Shutdown and TakeScreenshot Functions
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.
-
-
- void Shutdown()
- {
- System.Diagnostics.Process.Start("Shutdown", "-s -t 10");
- }
-
-
-
- Bitmap SaveScreenshot()
- {
- var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
- Screen.PrimaryScreen.Bounds.Height,
- PixelFormat.Format32bppArgb);
-
-
-
- var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
-
-
-
- bottom corner.
- gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
- Screen.PrimaryScreen.Bounds.Y,
- 0,
- 0,
- Screen.PrimaryScreen.Bounds.Size,
- CopyPixelOperation.SourceCopy);
- return bmpScreenshot;
- }
-
-
-
- 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 its 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" />
Control Activity
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
- {
-
- 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;
-
- 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);
-
-
-
- btnSleep.Click += delegate
- {
- stream = client.GetStream();
- String s = "SLP2";
- byte[] message = Encoding.ASCII.GetBytes(s);
- stream.Write(message, 0, message.Length);
- };
-
-
-
- btnShutdown.Click += delegate
- {
- stream = client.GetStream();
- String s = "SHTD3";
- byte[] message = Encoding.ASCII.GetBytes(s);
- stream.Write(message, 0, message.Length);
- };
-
-
-
- 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);
- };
-
-
-
- btnLogout.Click += delegate
- {
- StartActivity(typeof(MainActivity));
- client.Close();
- };
- }
-
-
-
- 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;
-
- bytes = stream.Read(data, bytesRead, curDataSize);
- bytesRead += curDataSize;
- bytesLeft -= curDataSize;
- }
- return data;
- }
- }
Take Screenshot
Run both projects - server and client. Log into 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 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.