Проблемата по време на карантинната работа на предприятието стана следната: наистина е нужно да се минимизира броят на посещенията в кабинетите на специалистите, които обслужват и консултират по приложен софтуер, и да го кажем откровено, потребителите често злоупотребяват с помощта на специалисти, без да искат да се запознаят с въпроса, тъй като "ще дойдат — ще помогнат — ще направят, а аз докато пуша/пия кафе и т.н.". Консултацията по телефона при съвместен достъп до сървъра е по-ефективна, ако се преглежда отдалеченият екран.

Вече след "изобретяването" на нашия велосипед се появи разумна информация по темата на статията: или или . Всички те предвиждат използване на конзолата, дори с елементи на прост диалог.
Всичката изложена по-долу информация е предназначена за онези, които нормално понасят ненормалните извращения за постигане на желания резултат, изобретявайки ненужни начини.
За да "не дърпам котката за опашката", ще започна с последното: велосипедът работи при обикновения потребител чрез утилитата , за което на автора й благодаря.
I. Конзола и shadow RDP.
Тъй като използването с административни права на конзолата Server Manager -> QuickSessionCollection -> щраквайки върху сесията на интересуващия потребител, избирайки в контекстното меню Shadow (Тенева копие) за персонала, който инструктира по работа с ПО, — не е вариант, беше разгледан друг "дървен" начин, а именно:
1. Научаваме RDP id на сесията:
query user | findstr Administratorили:
qwinsta | findstr Administrator При това "| findstr Administrator" беше удобно само когато знаеш, какво точно Administrator търсиш, или да използваш само първата част, за да видиш всички, които са влезли на сървера.
![]()
2. Свързваме се с тази сесия, при условие че в доменните групови политики параметърът "Установява правила за отдалечено управление на потребителските сесии на услуги за отдалечен работен плот" е избран най-малко като "Наблюдение на сесия с разрешение от потребителя" ():
mstsc /shadow:127Моля, обърнете внимание, че в списъка ще бъдат само логините на потребителите.
Повтарям, че без административни права ще получите следното:

Но за предварителното отстраняване на грешки в програмата, за която ще става дума, използвах акаунт с права на администратор.
II. Програма
И така, задачата е: създаване на прост графичен интерфейс за свързване с обект на потребителя с негово съгласие, изпращане на съобщение на потребителя. Средата за програмиране е избрана Lazarus.
1. Получаваме пълен списък с домейни на потребители "логин" — "пълно име" от администратора, или чрез конзолата:
wmic useraccount get Name,FullName никой не забранява дори така:
wmic useraccount get Name,FullName > c:testusername.txtИскам да кажа, че именно в Lazarus имаше проблем с обработката на този файл, тъй като по подразбиране неговото кодиране е UCS-2, затова се наложи да го преобразувам ръчно в обикновен UTF-8. В структурата на файла има много табулации, по-скоро множество интервали, които решихме да обработим програмно; рано или късно задачата с кодировката ще бъде решена и файлът ще се обновява програмно.
И така, в замисъла папката, достъпна за потребителите на програмата, например c:test, в която ще има 2 файла: първият с login и fullname, вторият с id_rdp и login на потребителите. След това тези данни обработваме, каквото можем:).
А за момента, за асоцииране със списъка със сесии, прехвърляме това (login и fullname) съдържание в масив:
procedure Tf_rdp.UserF2Array;
var
F:TextFile; i:integer; f1, line1:String; fL: TStringList;
begin
f1:=f_d+'user_name.txt';
fL := TStringList.Create;
fL.Delimiter := '|'; fL.StrictDelimiter := True;
AssignFile(F,f1);
try
reset(F); ReadLn(F,line1);
i:=0;
while not eof(F) do
begin
ReadLn(F,line1);
line1:= StringReplace(line1, ' ', '|',[]);
while pos(' ',line1)>0 do line1:= StringReplace(line1, ' ', ' ', [rfReplaceAll]);
begin
if (pos('|',line1)>0) then
begin
fL.DelimitedText :=line1;
if (fL[0]'' ) then
begin
inc(i);
fam[0,i]:=StringReplace(fL[1],' ','',[rfReplaceall, rfIgnoreCase]);
fam[1,i]:=fL[0];
end;end;end;end;
CloseFile(F);
Fl.Free;
except
on E: EInOutError do ShowMessage('Грешка при обработката на файла. Подробности: '+E.Message);
end;end;Искрено се извинявам за "много код", следващите точки ще бъдат по-лаконични.
2. По аналогичен метод от предишната точка се считывает резултата от обработката на списъка в елемента StringGrid, при това давам „значим“ фрагмент от кода:
2.1 Получаваме актуален списък с RDP сесии в файл:
f1:=f_d+'user.txt';
cmdline:='\/c query user >'+ f1;
if ShellExecute(0,nil, PChar('cmd'),PChar(cmdline),nil,1)=0 then;
Sleep(500); \/\/ може и по-дълго, за да изчакате създаването на файла за четене2.2 Обработваме файла (указани са само значимите редове от кода):
StringGrid1.Cells[0,i]:=fL[1]; StringGrid1.Cells[2,i]:=fL[3]; \/\/ добавяме в цикъл в StringGrid1
login1:=StringReplace(fL[1],' ','',[rfReplaceall, rfIgnoreCase]); \/\/ премахваме интервалите от логина
if (SearchArr(login1)>=0) then \/\/ търсим в масива от п1. логина и записваме в таблицата ФИО
StringGrid1.Cells[1,i]:=fam[1,SearchArr(login1)]
else StringGrid1.Cells[1,i]:='+'; \/\/ или записваме плюсче:)
.... \/\/ в зависимост от избора на потребителя сортираме и форматираме по данни
if (b_id.Checked=true) then SortGrid(0) else SortGrid(1);
StringGrid1.AutoSizeColumn(0);StringGrid1.AutoSizeColumn(1); StringGrid1.AutoSizeColumn(2); 3. Непосредствено самото свързване при клик върху реда с потребителя и номера на неговата сесия:
id:=(StringGrid1.Row);\/\/ разбираме номера на реда IntToStr(StringGrid1.Row)
ids:=StringGrid1.Cells[2,id]; \/\/ получаваме идентификатора на rdp
cmdline:='\/c mstsc \/shadow:'+ ids; \/\/ и се свързваме....
if (b_rdp.Checked=True) then if ShellExecute(0,nil, PChar('cmd'),PChar(cmdline),nil,1) =0 then; 4. Направени са още няколко украшения като сортиране при клик върху radiobutton, и съобщения на потребителя, или на всички потребители.

→ Пълният изходен код може да се види
III. Приложение на AdminLink — какво видях:
AdminLink наистина генерира пряк път, в който сочи към местоположението на инструмента admilaunch.exe, и лична копия на инструмента за стартиране AdmiRun.Exe която се намира в папката на потребителя, например vasya, по подобие на C:UsersvasyaWINDOWS. Общо взето, не всичко е толкова лошо: с правата за достъп до файла на пряк път и други, за да се освободи собствената административна съвест, може да се поиграе.
Източник: habr.com
