Het probleem tijdens de quarantaineperiode van de onderneming werd het volgende: het is echt nodig om het aantal bezoeken aan kantoren door specialisten die onderhoud en advies geven over applicatiesoftware te minimaliseren, en eerlijk gezegd maken gebruikers vaak misbruik van de hulp van specialisten zonder zich te willen verdiepen in over de kwestie zelf zeggen ze: “ze zullen komen – ze zullen helpen – ze zullen het doen, maar ik zal roken/koffie drinken, enz.” Telefonisch overleg bij het delen van een server is effectiever als u het externe scherm bekijkt.
Na de "uitvinding" van onze fiets verscheen er verstandige informatie over het onderwerp van het artikel:
Alle onderstaande informatie is bedoeld voor degenen die tolereert normale perversies om het gewenste resultaat te verkrijgen, door onnodige methoden uit te vinden.
Om niet “de kat bij de staart te trekken”, begin ik met de laatste: de fiets werkt voor de gemiddelde gebruiker die het hulpprogramma gebruikt
I. Console en schaduw-RDP.
Sinds gebruik met beheerdersrechten van de Server Manager-console -> QuickSessionCollection -> door op de sessie van de gewenste gebruiker te klikken en Schaduw te selecteren in het contextmenu voor personeel dat instructies geeft over het gebruik van de software, geen optie is, werd een andere “houten” methode overwogen, namelijk:
1. Ontdek de RDP-id van de sessie:
query user | findstr Administrator
of:
qwinsta | findstr Administrator
Bovendien "| findstr beheerder‘Het was alleen handig als je wist wat precies Beheerder je nodig hebt, of gebruik alleen het eerste deel om te zien dat iedereen is ingelogd op de server.
2. Maak verbinding met deze sessie, op voorwaarde dat deze zich in het domein bevindt groepsbeleid De optie "Regels voor beheer op afstand instellen voor gebruikerssessies van Remote Desktop Services" is geselecteerd, waarbij minimaal de optie "Sessie met gebruikerstoestemming monitoren" is geselecteerd (
mstsc /shadow:127
Houd er rekening mee dat de lijst alleen gebruikersaanmeldingen bevat.
Ik herhaal dat je zonder beheerdersrechten het volgende krijgt:
Maar voor het voorlopig debuggen van het programma dat zal worden besproken, heb ik een account met beheerdersrechten gebruikt.
II. Programma
Dus de probleemstelling: het creëren van een eenvoudige grafische interface om met zijn toestemming verbinding te maken met het schaduwgevoel van de gebruiker, en een bericht naar de gebruiker te sturen. De gekozen programmeeromgeving is Lazarus.
1. We krijgen de volledige domeinlijst met gebruikers “login” - “volledige naam” van de beheerder, of opnieuw via de console:
wmic useraccount get Name,FullName
niemand verbiedt zelfs dit:
wmic useraccount get Name,FullName > c:testusername.txt
Ik zal meteen zeggen dat het Lazarus was die een probleem had met het verwerken van dit bestand, omdat de codering standaard UCS-2 is, dus ik moest het gewoon handmatig converteren naar gewone UTF-8. Er zijn veel tabbladen in de bestandsstructuur, of beter gezegd, veel spaties, waarvan besloten is om programmatisch te verwerken; vroeg of laat zal het coderingsprobleem worden opgelost en zal het bestand programmatisch worden bijgewerkt.
Het idee is dus om een map toegankelijk te maken voor gebruikers van het programma, bijvoorbeeld c:test, waarin zich 2 bestanden bevinden: de eerste met login en volledige naam, de tweede met id_rdp en login van gebruikers. Vervolgens verwerken wij deze gegevens zo goed als we kunnen :).
In de tussentijd, om te associëren met de lijst met sessies, dragen we deze (login en volledige naam) inhoud over naar een array:
procedure Tf_rdp.UserF2Array;
var
F:TextFile; i:integer; f1, line1:String; fL: TStringList;
begin //f_d глобальный путь к размещению файлов
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, ' ', '|',[]); //заменяем первый попавш.2пробела разделителем |
// удаляем все двойные пробелы
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;
Mijn excuses voor de “veel code”, de volgende punten zullen beknopter zijn.
2. Met dezelfde methode uit de vorige paragraaf lezen we het resultaat van het verwerken van de lijst in het StringGrid-element, terwijl ik een “significant” stukje code zal geven:
2.1 Wij ontvangen de actuele lijst met RDP-sessies in een bestand:
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 Verwerk het bestand (alleen significante coderegels worden aangegeven):
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. Directe verbinding zelf door op de regel met de gebruiker en zijn sessienummer te klikken:
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. Er zijn nog een paar versieringen aangebracht, zoals sorteren door op het keuzerondje te klikken, en berichten aan de gebruiker of alle gebruikers.
→ Volledige broncode is zichtbaar
III. AdminLink gebruiken - wat ik zag:
AdminLink genereert wel een snelkoppeling die verwijst naar de locatie van het hulpprogramma admilaunch.exeen een persoonlijk exemplaar van het startprogramma AdmiRun.Exe die zich bijvoorbeeld in de map van de gebruiker bevindt vasja, typ C: UsersvasyaWINDOWS. Over het algemeen is niet alles zo slecht: je kunt spelen met toegangsrechten tot het snelkoppelingsbestand en andere om je eigen beheerdersgeweten te zuiveren.
Bron: www.habr.com