Il problema durante il periodo di lavoro in quarantena dell'azienda è diventato il seguente: è davvero necessario ridurre al minimo il numero di visite negli uffici da parte degli specialisti che assistono e consigliano su software applicativo, e ad essere onesti, gli utenti spesso abusano dell'aiuto degli specialisti senza voler approfondire la questione, dicendo "arriveranno – aiuteranno – faranno, mentre io posso farmi un caffè/una pausa, ecc.". La consulenza telefonica con accesso condiviso al server è più efficace se si visualizza lo schermo remoto.

Già dopo "l'invenzione" della nostra bici è emersa un'informazione sensata sull'argomento dell'articolo: o o . Tutti richiedono l'uso della console, anche con elementi di semplice dialogo.
Tutte le informazioni di seguito sono destinate a coloro che tollerano normalmente le perversioni anomale per ottenere il risultato desiderato, inventando modi non necessari.
Per "non tirare per le lunghe", inizierò dall'ultimo: la bici funziona per l'utente normale grazie all'utilità , grazie per l'autore.
I. Console e shadow RDP.
Poiché l'utilizzo della console di Server Manager con diritti di admin -> QuickSessionCollection -> facendo clic sulla sessione dell'utente di interesse, selezionando nel menu contestuale Shadow (Copia Shadow) per il personale che istruisce sull'uso del software, – non è un'opzione, è stata considerata un'altra opzione "legnosa", ossia:
1. Scopriamo l'ID RDP della sessione:
query user | findstr Administratoroppure:
qwinsta | findstr Administrator In particolare, "| findstr Administrator" era conveniente solo quando sapevi che precisamente Administrator ti serviva, oppure usare solo la prima parte per vedere tutti gli utenti loggati sul server.
![]()
2. Ci connettiamo a questa sessione, a condizione che nelle policy di gruppo il parametro "Imposta le regole di gestione remota per le sessioni utenti dei servizi desktop remoti" sia selezionato con impostazione almeno "Osservazione della sessione con il permesso dell'utente" ():
mstsc /shadow:127Nota che nell'elenco saranno mostrati solo i login degli utenti.
Ripeto che senza diritti di admin otterrete quanto segue:

Ma per il debug preliminare del programma di cui si parlerà, ho utilizzato un account con diritti di amministratore.
II. Programma
Quindi, la richiesta è: creare una semplice interfaccia grafica per connettersi al sensore shadow dell'utente con il suo permesso, inviando un messaggio all'utente. L'ambiente di programmazione scelto è Lazarus.
1. Otteniamo l'elenco completo degli utenti «login» — «nome completo» dall'amministratore, oppure di nuovo attraverso la console:
wmic useraccount get Name,FullName Nessuno vieta di farlo anche in questo modo:
wmic useraccount get Name,FullName > c:testusername.txtDico subito che Lazarus ha avuto problemi con l'elaborazione di questo file, poiché per impostazione predefinita la sua codifica è UCS-2, quindi è stato necessario convertire manualmente in un normale UTF-8. La struttura del file presenta molte tabulazioni, o meglio, numerosi spazi, che è stato deciso di elaborare programmaticamente. Prima o poi, il problema della codifica sarà risolto e il file sarà aggiornato automaticamente.
Quindi, l'idea è di avere una cartella accessibile agli utenti del programma, ad esempio c:test, in cui ci saranno 2 file: il primo con login e nome completo, il secondo con id_rdp e login degli utenti. Successivamente, elaboriamo questi dati come possiamo:).
Nel frattempo, per associare con l'elenco delle sessioni, trasferiamo il contenuto (login e nome completo) in un array:
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('Errore nell'elaborazione del file. Dettagli: '+E.Message);
end;end;Mi scuso per «tanto codice», i prossimi punti saranno più concisi.
2. Analogamente, usando il metodo del punto precedente, leggiamo il risultato dell'elaborazione dell'elenco nell'elemento StringGrid, ecco un "pezzo significativo" di codice:
2.1 Otteniamo l'elenco attuale delle sessioni RDP in un file:
f1:=f_d+'user.txt';
cmdline:='\/c query user >'+ f1;
if ShellExecute(0,nil, PChar('cmd'),PChar(cmdline),nil,1)=0 then;
Sleep(500); \/\/ si può aspettare anche di più mentre il file per la lettura viene creato2.2 Elaboriamo il file (vengono indicati solo le righe significative di codice):
StringGrid1.Cells[0,i]:=fL[1]; StringGrid1.Cells[2,i]:=fL[3]; \/\/ aggiungiamo in ciclo a StringGrid1
login1:=StringReplace(fL[1],' ','',[rfReplaceall, rfIgnoreCase]); \/\/ rimuoviamo gli spazi dal login
if (SearchArr(login1)>=0) then \/\/ cerchiamo nell'array da p1. il login e registriamo nella tabella nome e cognome
StringGrid1.Cells[1,i]:=fam[1,SearchArr(login1)]
else StringGrid1.Cells[1,i]:='+'; \/\/ oppure registriamo un segno:)
.... \/\/ a seconda della scelta dell'utente, ordiniamo e formattiamo in base ai dati
if (b_id.Checked=true) then SortGrid(0) else SortGrid(1);
StringGrid1.AutoSizeColumn(0);StringGrid1.AutoSizeColumn(1); StringGrid1.AutoSizeColumn(2); 3. La connessione stessa avviene cliccando sulla riga con l'utente e il numero della sua sessione:
id:=(StringGrid1.Row);\/\/ scopriamo il numero di riga IntToStr(StringGrid1.Row)
ids:=StringGrid1.Cells[2,id]; \/\/otteniamo l'identificatore rdp
cmdline:='\/c mstsc \/shadow:'+ ids; \/\/ e ci connettiamo....
if (b_rdp.Checked=True) then if ShellExecute(0,nil, PChar('cmd'),PChar(cmdline),nil,1) =0 then; 4. Sono state fatte anche alcune decorazioni come la selezione attraverso il clic sul radiobutton, e messaggi all'utente o a tutti gli utenti.

→ Il codice sorgente completo può essere visualizzato
III. Applicazione di AdminLink — cosa ho visto:
AdminLink genera effettivamente un collegamento che fa riferimento alla posizione dell'utilità admilaunch.exe, e una copia personale dell'utilità di avvio AdmiRun.Exe che si trova nella cartella dell'utente, ad esempio vasya, come C:UsersvasyaWINDOWS. In generale, non è tutto così male: con i diritti di accesso al file di collegamento e altri, per ripulire la propria coscienza da amministratore, si può giocare.
Fonte: habr.com
