Работа мечты в один клик 💼

💭Мечтаешь работать в Сбере, но не хочешь проходить десять кругов HR-собеседований? Теперь это проще, чем когда-либо!
💡AI-интервью за 15 минут – и ты уже на шаг ближе к своей новой работе.
Как получить оффер? 📌 Зарегистрируйся 📌 Пройди AI-интервью 📌 Получи обратную связь сразу же!
HR больше не тянут время – рекрутеры свяжутся с тобой в течение двух дней! 🚀
Реклама. ПАО СБЕРБАНК, ИНН 7707083893. Erid 2VtzquscAwp
Введение
Неправильное использование рабочих компьютеров компании является обычной практикой среди пользователей во многих компаниях, где отсутствуют надлежащие механизмы мониторинга. Это приводит к напрасной трате ресурсов и снижает скорость достижения общих целей организации. Таким образом, для достижения желаемых результатов необходим эффективный механизм, с помощью которого системный администратор может отслеживать и контролировать рабочие станции сотрудников.
Целью рассматриваемого проекта является разработка приложения на основе Xamarin.Forms, которое позволит системному администратору проводить удаленное наблюдение и контроль рабочих станций на рабочем месте. Проект будет включать разработку двух приложений: одно будет работать на рабочих станциях, другое – на мобильном телефоне администратора. Внедрение механизма позволит администратору не только следить за действиями пользователей, но и даст возможность удаленно контролировать конкретные рабочие станции.
Идея проекта
Итак, в проекте мы создадим два приложения, серверное и клиентское.
Серверное приложение будет постоянно работать на каждой рабочей станции. Приложение сервера будет связано с клиентским приложением через Wi-Fi соединение. Программа делает скриншот активности пользователя по требованию администратора и отправляет его в клиентское приложение. Серверное приложение будет принимать, интерпретировать и выполнять команды, полученные от мобильного (клиентского) приложения.
Клиентское приложение на Xamarin.Forms – Android-приложение на смартфоне администратора, предоставляющее интерфейс, через который администратор может управлять серверным приложением. С помощью клиентского приложения администратор даёт команду серверному приложению сделать скриншот и отправить изображение на смартфон. С помощью клиентского приложения администратор может контролировать каждую рабочую станцию, отправлять сообщения, выключать или переводить компьютер в спящий режим и т. д.
1. Серверное приложение
1.1. Создаем консольное приложение
Начнём с создания проекта консольного приложения с .NET Framework.

1.2. Добавляем соответствующее пространство имен
Создаем экземпляр TcpClient
и TcpListener
. Объявляем строку локальной переменной с именем ipString
.
public static TcpClient client;
private static TcpListener listener;
private static string ipString;
1.3. Узнаем IP адрес вашей машины
Напишем метод внутри функции Main
, который будет перехватывать и возвращать IP-адрес машины.
IPAddress[] localIp = Dns.GetHostAddresses(Dns.GetHostName());
foreach(IPAddress address in localIp) {
if (address.AddressFamily == AddressFamily.InterNetwork) {
ipString = address.ToString();
}
}
1.4. Слушаем порт 1234
Теперь мы готовы принимать сообщения, например, по порту 1234
. Этот порт и IP-адрес текущего компьютера будет использоваться в качестве конечных точек. Тогда мы сможем связаться с клиентом по TCP.
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ipString), 1234);
listener = new TcpListener(ep);
listener.Start();
Console.WriteLine(@"
===================================================
Started listening requests at: {0}:{1}
===================================================",
ep.Address, ep.Port);
client = listener.AcceptTcpClient();
Console.WriteLine("Connected to client!" + " \n");

1.5. Создаем соединение с клиентом
Создадим функцию приема и обработки сообщения о том, что рабочая станция должна быть переведена в спящий режим. В качестве команды от клиента мы должны получить строку “
. SLP2
”
while (client.Connected) {
try {
const int bytesize = 1024 * 1024;
byte[] buffer = new byte[bytesize];
string x = client.GetStream().Read(buffer, 0, bytesize).ToString();
var data = ASCIIEncoding.ASCII.GetString(buffer);
if (data.ToUpper().Contains("SLP2")) {
Console.WriteLine("Pc is going to Sleep Mode!" + " \n");
Sleep();
}
} catch (Exception exc) {
client.Dispose();
client.Close();
}
}
1.6. Пишем метод Sleep
Расширяем пространство имён проекта. Добавляем внутри функции Main
метод Sleep
:
using System.Windows.Forms;
void Sleep() {
Application.SetSuspendState(PowerState.Suspend, true, true);
}
2. Клиентское приложение
2.1. Создаем проект Xamarin.Forms
Открываем Visual Studio и переходим в New Project-> Cross-platform-> Xamarin.Forms-> Blank app
. Даем ему имя, например, XamarinFormsClient
.
2.2. Создаем класс соединения
Далее в нашем проекте нужно определить класс соединения для создания экземпляра TCP Client. Создаем новый класс с именем Connection.cs
и записываем в него следующий код.
using System;
using System.Collections.Generic;
using System.Net.Sockets;
namespace XamarinForms.Client
{
public class Connection
{
private static Connection _instance;
public static Connection Instance
{
get
{
if (_instance == null) _instance = new Connection();
return _instance;
}
}
public TcpClient client { get; set; }
}
}
2.3. Создание пользовательского интерфейса
Нам нужны два редактируемых текстовых поля для IP-адреса и порта, и одна кнопка для соединения с сервером. Откроем файл макета MainPage
и заменим код на следующий:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamarinForms.Client"
x:Class="XamarinForms.Client.MainPage">
<StackLayout>
<Label Text="Connect to Server"
FontSize="Medium"
HorizontalOptions="Center" />
<Entry x:Name="IPAddress" Placeholder="IP Address"/>
<Entry x:Name="Port" Placeholder="Port Number"/>
<Button x:Name="Connect" Text="Connect" Clicked="Connect_Clicked"/>
</StackLayout>
</ContentPage>

2.4. Описываем метод соединения
Опишем взаимосвязь элементов управления пользовательского интерфейса с классом MainPage
. Далее свяжемся с приложением сервера, используя IP-адрес и порт рабочей станции.
using System;
using System.Net.Sockets;
using Xamarin.Forms;
namespace XamarinForms.Client
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private async void Connect_Clicked(object sender, EventArgs e)
{
try
{
TcpClient client = new TcpClient();
await client.ConnectAsync(IPAddress.Text, Convert.ToInt32(Port.Text));
if (client.Connected)
{
Connection.Instance.client = client;
Application.Current.MainPage = new NavigationPage(new OperationsPage());
await DisplayAlert("Connected", "Connected to server successfully!", "Ok");
}
else
{
await DisplayAlert("Error", "Connection unsuccessful!", "Ok");
}
}
catch (Exception ex)
{
await DisplayAlert("Error", ""+ex.ToString(), "Ok");
}
}
}
}
2.5. Обновление класса приложения
Открываем файл App.xaml
внутри этого класса и добавляем следующий код в конструктор класса App.
MainPage = new NavigationPage(new MainPage());
3. Проверка соединения
Давайте проверим соединение сервера и клиентского приложения, которое мы только что создали. Основной модуль запуска приложения Xamarin.Forms отобразит главную страницу. Запустим серверное приложение, скопируем IP-адрес и порт рабочей станции из серверного приложения. Поместим в клиентское приложение и нажимаем Connect.

4. Работаем с функцией скриншота и выключения
Поговорим о том, как будет работать функция скриншота. Клиент запрашивает скриншот, отправляет команду в виде строки "TSC1"
, на рабочей станции серверное приложение делает скриншот. Размер изображения может быть большим, поэтому мы преобразуем данные снимка экрана в пакеты байтового типа и отправляем клиентскому приложению. Когда клиент получит пакеты байтового типа, он преобразует их в исходную форму.
Добавим функцию выключения рабочей станции. Если клиент отправляет команду “SHTD3”
серверному приложению, сервер выполнит функцию выключения компьютера.
5. Возвращаемся к серверному приложению
Вернемся к серверному приложению и опишем функции снимка экрана выключения рабочей станции. Откроем файл program.cs и запишем следующий код внутри цикла while
, который мы реализовали ранее.
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());
}
6. Функции съемки экрана и выключения
Добавим в серверное приложение следующие пространства имен. Иначе Visual Studio не распознает ключевое слово graphics
функции снимка экрана.
using System.Drawing;
using System.Drawing.Imaging;
Вернемся к program.cs
и поместите эти функции в основной класс.
// Функция выключения рабочей станции
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);
// Создание графического bitmap-объекта
var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
// Берем скриншот из Take the screenshot от верхнего левого до нижнего правого угла
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;
}
}
Итак, мы закончили с серверным приложением.
7. Возвращаемся к клиентскому приложению
7.1. Создаем страницу операций
Возвращаемся в клиентское приложение (Xamarin.Forms) и добавляем новый ContentPage
с именем OperationsPage
. Внутри этого макета добавим следующий код, чтобы создать больше кнопок.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamarinForms.Client"
x:Class="XamarinForms.Client.OperationsPage">
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<Button x:Name="Screenshot" Text="Screenshot" Clicked="Screenshot_Clicked"/>
<Button x:Name="Sleep" Text="Sleep" Clicked="Sleep_Clicked"/>
<Button x:Name="Shutdown" Text="Shutdown" Clicked="Shutdown_Clicked"/>
<Image x:Name="imageView"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
7.2. Добавляем в класс операций методы ожидания
Открываем файл OperationPage.xaml
и переносим следующий код.
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace XamarinForms.Client
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class OperationsPage : ContentPage
{
public OperationsPage ()
{
InitializeComponent ();
}
// Команда для кнопки Sleep
private void Sleep_Clicked(object sender, EventArgs e)
{
var client = Connection.Instance.client;
NetworkStream stream = client.GetStream();
String s = "SLP2";
byte[] message = Encoding.ASCII.GetBytes(s);
stream.Write(message, 0, message.Length);
}
// Команда для кнопки Shutdown
private void Shutdown_Clicked(object sender, EventArgs e)
{
var client = Connection.Instance.client;
NetworkStream stream = client.GetStream();
String s = "SHTD3";
byte[] message = Encoding.ASCII.GetBytes(s);
stream.Write(message, 0, message.Length);
}
// Команда для снимка экрана
private void Screenshot_Clicked(object sender, EventArgs e)
{
var client = Connection.Instance.client;
NetworkStream stream = client.GetStream();
String s = "TSC1";
byte[] message = Encoding.ASCII.GetBytes(s);
stream.Write(message, 0, message.Length);
var data = getData(client);
imageView.Source = ImageSource.FromStream(() => new MemoryStream(data));
}
// Сбор данных с сервера
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;
}
}
}
8. Тестируем!
Запускаем оба приложения – сервер и клиент. Вводим IP-адрес и порт рабочей станции, которые вы видите на экране вывода приложения сервера, в клиентское приложение и нажимаем Connect
.

После подключения к серверу теперь мы можем выполнять различные команды.

Ура! Всё работает. При нажатии на Sleep
рабочая станция переходит в спящий режим. При нажатии на Take Screenshot
через пару мгновений скриншот рабочей станции оказывается внутри клиентского приложения.
Если вы любите C#, мы также советуем вам обратить внимание на другие статьи тега C#, например, недавние:
Комментарии