Problemet under virksomhedens karantænearbejde blev følgende: det er virkelig nødvendigt at minimere antallet af besøg i kontorerne af specialister, der ynder og rådgiver om anvendt software. Ærligt talt misbruger brugerne ofte hjælpen fra specialister, idet de ikke ønsker at sætte sig ind i spørgsmålet, som om 'de kommer - hjælper - gør det, mens jeg kan ryge / drikke kaffe osv.'. Telefonrådgivning ved fælles adgang til serveren er mere effektivt, hvis man ser den fjerne skærm.

Allerede efter 'opfindelsen' af vores cykel dukkede der fornuftig information op om emnet for artiklen: eller eller . Alle de beskrevne metoder indebærer brug af konsollen, selv med elementer af simpel dialog.
Al informationen nedenfor er rettet mod dem, der normalt tåler unormale udskejelser for at opnå det ønskede resultat ved at finde på unødvendige metoder.
For ikke at 'trække katten i halen', vil jeg begynde med det sidste: cyklen fungerer for den almindelige bruger med hjælp fra værktøjet , tak til dens forfatter.
I. Konsol og shadow RDP.
Da brugen af administratorrettigheder i konsollen Server Manager -> QuickSessionCollection -> ved at klikke på den session, som interesserer brugeren, vælge i kontekstmenuen Shadow (Skyggekopi) for personalet, der instruerer i brugen af software, - er ikke en mulighed, en anden 'træ' metode blev overvejet, nemlig:
1. Find RDP-id for sessionen:
query user | findstr Administratoreller:
qwinsta | findstr Administrator Og "| findstr Administrator" var praktisk kun når du ved, hvad præcist Administrator du har brug for, eller blot bruge den første del for at se alle, der er logget ind på serveren.
![]()
2. Opret forbindelse til denne session, forudsat at i domæne gruppepolitikkerne parameteren 'Sætter reglerne for fjernstyring af brugersessioner i fjern skrivebordsservice' er valgt som minimum 'Overvågning af sessionen med brugerens tilladelse' ():
mstsc /shadow:127Bemærk, at der kun vil være brugerlogin i listen.
Jeg gentager, at uden administratorrettigheder vil du få følgende:

Men til den foreløbige fejlfinding af det program, der vil blive diskuteret, brugte jeg en konto med administratorrettigheder.
II. Programmet
Så det stillede opgave: at lave en simpel grafisk grænseflade til at oprette forbindelse til brugerens skygge-sensor med deres tilladelse og sende en besked til brugeren. Programmeringsmiljøet er valgt som Lazarus.
1. Få den fulde domæneliste over brugere "login" — "fuldstændigt navn" fra administratoren, eller igen via konsollen:
wmic useraccount get Name,FullName Ingen forbyder at gøre det sådan:
wmic useraccount get Name,FullName > c:testusername.txtJeg vil med det samme sige, at der netop med Lazarus var et problem med at håndtere denne fil, da dens standardkodning er UCS-2, så jeg var nødt til manuelt at konvertere den til almindelig UTF-8. Filens struktur indeholder mange tabuleringer, eller rettere mange mellemrum, som man besluttede at behandle programmæssigt, før eller senere vil kodningsopgaven blive løst, og filen vil blive opdateret programmatisk.
Så i tankerne er en mappe, der er tilgængelig for programmets brugere, f.eks. c:test, som vil indeholde 2 filer: den første med login og fulde navn, den anden med id_rdp og login for brugerne. Derefter behandler vi disse oplysninger som vi kan :).
Og indtil videre, for at associere med listen over sessioner, overfører vi dette (login og fulde navn) indhold til et array:
procedure Tf_rdp.UserF2Array;
var
F:TextFile; i:integer; f1, line1:String; fL: TStringList;
begin _d global sti til placering af filer
f1:=f_d+'user_name.txt'; Opgaven er at læse filens indhold ind i et array
fL := TStringList.Create; L.strengen undergår metamorfoser med separatorer
fL.Delimiter := '|'; fL.StrictDelimiter := True;
AssignFile(F,f1);
try Åbn filen til læsning
reset(F); ReadLn(F,line1);
i:=0;
while not eof(F) do Læser linjerne, indtil filen er slut
begin
ReadLn(F,line1);
line1:= StringReplace(line1, ' ', '|',[]); Erstatte den første forekomst af 2 mellemrum med separatoren |
Fjern alle dobbelte mellemrum
while pos(' ',line1)>0 do line1:= StringReplace(line1, ' ', ' ', [rfReplaceAll]);
begin
if (pos('|',line1)>0) then
begin Hvis separatoren eksisterer, så tilføjer vi den til arrayet
fL.DelimitedText :=line1; Deler op i kolonner
if (fL[0]'') then Hvis kontoen har et navn
begin Så tilføjer vi den til arrayet
inc(i); Fjern potentielle enkelt rum i login
fam[0,i]:=StringReplace(fL[1],' ','',[rfReplaceall, rfIgnoreCase]);
fam[1,i]:=fL[0];
end;end;end;end; Færdig. Luk filen.
CloseFile(F);
Fl.Free;
except
on E: EInOutError do ShowMessage('Fejl ved behandling af fil. Detaljer: '+E.Message);
end;end;Jeg undskylder for "mange koder", de følgende punkter vil være mere kortfattede.
2. Tilsvarende metoden fra det foregående punkt læser vi resultatet af behandlingen af listen ind i elementet StringGrid, her præsenteres et "betydeligt" stykke kode:
2.1 Vi får den aktuelle liste over RDP-sessioner i filen:
f1:=f_d+'user.txt';
cmdline:='\/c query user >'+ f1;
if ShellExecute(0,nil, PChar('cmd'),PChar(cmdline),nil,1)=0 then;
Sleep(500); \/\/ man kan vente længere, mens filen til at læse bliver oprettet2.2 Vi behandler filen (kun de betydelige kode-rækker er angivet):
StringGrid1.Cells[0,i]:=fL[1]; StringGrid1.Cells[2,i]:=fL[3]; \/\/vi indsætter i cyklus i StringGrid1
login1:=StringReplace(fL[1],' ','',[rfReplaceall, rfIgnoreCase]); \/\/fjerner mellemrum fra login
if (SearchArr(login1)>=0) then \/\/søger i arrayet fra punkt 1. login og skriver ind i tabellen FIO
StringGrid1.Cells[1,i]:=fam[1,SearchArr(login1)]
else StringGrid1.Cells[1,i]:='+'; \/\/ ellers skriver vi et plus:
.... \/\/afhængigt af brugerens valg sorterer vi og formaterer efter data
if (b_id.Checked=true) then SortGrid(0) else SortGrid(1);
StringGrid1.AutoSizeColumn(0);StringGrid1.AutoSizeColumn(1); StringGrid1.AutoSizeColumn(2); 3. Selve forbindelsen, når man klikker på rækken med brugeren og nummeret på hans session:
id:=(StringGrid1.Row);\/\/ finder rækkenumret IntToStr(StringGrid1.Row)
ids:=StringGrid1.Cells[2,id]; \/\/får RDP-identifikatoren
cmdline:='\/c mstsc \/shadow:'+ ids; \/\/og vi forbinder....
if (b_rdp.Checked=True) then if ShellExecute(0,nil, PChar('cmd'),PChar(cmdline),nil,1) =0 then; 4. Der er lavet et par dekorationer som sortering ved klik på radioboks og beskeder til brugeren, eller til alle brugerne.

→ Den komplette kildekode kan ses
III. Anvendelse af AdminLink — hvad jeg så:
AdminLink genererer faktisk en genvej, som henviser til placeringen af værktøjet admilaunch.exe, og en personlig kopi af værktøjet AdmiRun.Exe som er placeret i brugerens mappe, for eksempel vasya, i stil med C:UsersvasyaWINDOWS. Generelt er det ikke så skidt: med adgangsrettigheder til genvejsfilen og andet, kan man lege med sin eget administrativ samvittighed.
Kilde: habr.com
