fajo Postado Janeiro 29, 2007 Denunciar Share Postado Janeiro 29, 2007 Oi pessoal,estou precisando de uma rotina que me retorne num listbox por exemplo todos os usuarios conectados nos computadores da minha rede!!Obrigado Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Micheus Postado Janeiro 29, 2007 Denunciar Share Postado Janeiro 29, 2007 Oi pessoal,estou precisando de uma rotina que me retorne num listbox por exemplo todos os usuarios conectados nos computadores da minha rede!!ObrigadoApenas o administrador pode obter esta lista.Utilize a funcão NetUserEnum - link Torry's Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Guest Visitante Postado Janeiro 29, 2007 Denunciar Share Postado Janeiro 29, 2007 To usando essa aqui, mas num aparece nada no listbox:procedure TForm4.Button1Click(Sender: TObject);var hEnum, dwResult, dwResultEnum : DWORD; lpnrLocal : array [0..16384 div SizeOf(TNetResource)] of TNetResource; // ponteiro para as estruturas enumeradas i : integer; cEntries : Longint; cbBuffer: DWORD;begin Screen.Cursor := crHourGlass; centries := -1; // enumera todas as entradas possíveis cbBuffer := 16384; // 16K // chama a função WNetOpenEnum para inciar a enumeração. dwResult := WNetOpenEnum( RESOURCE_CONTEXT, // Enumera o recursos atualmente conectados. RESOURCETYPE_DISK, // todos os recursos 0, // enumera todos os recursos nil, // NULL hEnum // handle para os recursos ); if (dwResult <> NO_ERROR) then begin // poderia processar os erros com um manipulador de erros // definido na aplicação. Exit; end; // inicializa o buffer. FillChar( lpnrLocal, cbBuffer, 0 ); // chama a função WNetEnumResource para continuar a enumeração dwResultEnum := WNetEnumResource(hEnum, // manipulador DWORD(cEntries), // definido localmente como -1 @lpnrLocal, // LPNETRESOURCE cbBuffer); // tamanho do buffer ListBox1.Clear; // preencho uma listbox for i := 0 to cEntries - 1 do begin // lê cada estrutura para pegar o nome do // recurso remoto (lpnrLocal.lpRemoteName) ListBox1.Items.Add( lpnrLocal.lpRemoteName ); end; // chama WNetCloseEnum para finalizar a enumeração. dwResult := WNetCloseEnum(hEnum); screen.Cursor := crDefault;end; Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Micheus Postado Janeiro 29, 2007 Denunciar Share Postado Janeiro 29, 2007 Já verificou se dwResult não está retornando algo diferente de NO_ERROR?Pões um break-point na linha: if (dwResult <> NO_ERROR) then e, quando ele parar nela, executa passo-a-passo (F8) para verificar se ele não está saindo da procedure pelo Exit. Como disse antes, só vai obter sucesso se você estiver logado com uma conta de administrador. Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Micheus Postado Janeiro 31, 2007 Denunciar Share Postado Janeiro 31, 2007 To usando essa aqui, mas num aparece nada no listbox:procedure TForm4.Button1Click(Sender: TObject);var hEnum, dwResult, dwResultEnum : DWORD; lpnrLocal : array [0..16384 div SizeOf(TNetResource)] of TNetResource; // ponteiro para as estruturas enumeradas i : integer; cEntries : Longint; cbBuffer: DWORD;begin Screen.Cursor := crHourGlass; centries := -1; // enumera todas as entradas possíveis cbBuffer := 16384; // 16K // chama a função WNetOpenEnum para inciar a enumeração. dwResult := WNetOpenEnum( RESOURCE_CONTEXT, // Enumera o recursos atualmente conectados. RESOURCETYPE_DISK, // todos os recursos 0, // enumera todos os recursos nil, // NULL hEnum // handle para os recursos ); ...end;fajo, copiei seu código e realmente não lista nada, nem ocorre erro como eu sugerí no post anterior.Entretanto, conferindo no msdn os parâmetros da função, observei que o primeiro parâmetro só pode ter os seguintes valores:RESOURCE_CONNECTED - All currently connected resources (the dwUsage parameter is ignored).RESOURCE_GLOBALNET - All resources on the network.RESOURCE_REMEMBERED - All remembered (persistent) connections (the dwUsage parameter is ignored). These connections may or may not currently be connected. Logo, pelo comentário no código, o 1º parâmetro dever ser RESOURCE_CONNECTED e não RESOURCE_CONTEXT.Fazendo a alteração, o que obtive foi a relação dos path's dos discos mapeados na minha máquina, ou seja, pastas compartilhadas em outros micros da rede as quais eu mapei.Acho que não é isto que você está procurando.Fuçando aqui e ali, lá no msdn, cheguei na função NetWkstaUserEnum (link), até pensei em implementar algo, mas o Google tá ai para que, né? :D Tem um exemplo prontinho na página do Torry's. Acho que com ele você consegue ajustar o seu programa.Abraços Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 fajo Postado Janeiro 31, 2007 Autor Denunciar Share Postado Janeiro 31, 2007 Grande Micheus, belezaobrigado pela grande ajuda que você vem me dando;o código do Torry's não funcionou, mas, encontrei um outro:*** CODE START ***unit Example_Unit;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;//Declaration of the returning structures.//These are part of LanMan 2.x and are not supported by Delphi.//Translated from C++ code in the SDK help files.//As you can see we are using lpWStr instead of the C++ lpTStrType_WKSTA_USER_INFO_0 = Record User_Name : Array[0..255] Of lpWStr;End;Type_WKSTA_USER_INFO_1 = Record User_Name, Logon_Domain, Other_Domains, Logon_Server : Array[0..255] Of lpWStr;End;TypeWKSTA_USER_INFO_0 = _WKSTA_USER_INFO_0;WKSTA_USER_INFO_1 = _WKSTA_USER_INFO_1;//Declaration of the Function//Notice the Var clause in front of the pointer.//This means that this is a returning parameter//in addition to the Function Result.Function NetWkstaUserEnum(ServerName : lpWStr; Level : DWord; Var Buffer : Pointer; PrefMaxLen : DWord; Const EntriesRead, TotalEntries, Resume_Handle : lpDWord) : LongInt; StdCall; External 'NETAPI32.DLL';Function NetApiBufferAllocate(ByteCount : DWord; Buffer : Pointer) : LongInt; StdCall; External 'NETAPI32.DLL';Function NetApiBufferFree(Buffer : Pointer) : LongInt; StdCall; External 'NETAPI32.DLL';Type TForm1 = Class(TForm) Button1: TButton; Edit1: TEdit; Label1: TLabel; Memo1: TMemo; procedure Button1Click(Sender: TObject); Private Public //This is useful later to stear our program according to the system versions. Function ReturnSystemVersion : DWord; End;Var Form1: TForm1; Buffer : Pointer; ServerName : Array[0..255] Of Char; EntriesRead, TotalEntries, Resume_Handle : DWord; NET_API_STATUS : LongInt; WKSTA_STRUCT_0 : WKSTA_USER_INFO_0; WKSTA_STRUCT_1 : WKSTA_USER_INFO_1;Implementation{$R *.DFM}//And ofcoarse ... we need som code inside it ... :o)Function TForm1.ReturnSystemVersion : DWord;BeginResult := Win32PlatForm;End;Procedure TForm1.Button1Click(Sender: TObject);VarI : Integer;Begin//We make a case loop to control what we will do.//Since I'm not familiar with other than NT programming,//I'll show you an NT example.Case ReturnSystemVersion Of VER_PLATFORM_WIN32s : Begin //System is Win32s End; VER_PLATFORM_WIN32_WINDOWS : Begin //System is Win95 End; VER_PLATFORM_WIN32_NT : Begin //System is WinNT Memo1.Lines.Clear; StringToWideChar(Edit1.Text,@ServerName,256); //Convert the string to UNICode VERY IMPORTANT ! Resume_Handle := 0; //This must be 0 in the first call. NET_API_STATUS := NetWkstaUserEnum(@ServerName,0,Buffer,SizeOf(WKSTA_USER_INFO_0),@EntriesRead,@TotalEntries,@Resume_Handle); If NET_API_STATUS = 0 Then //We don' want to do this if an error occurs, otherwise we get a nasty error message. Begin //Remember to select the CORRECT structure according to your level. WKSTA_STRUCT_0 := WKSTA_USER_INFO_0(Buffer^); //This syntax returns an error if you execute it with an NET_API_STATUS > 0. //And now if youre member of the administrator account ... just watch the wonderful result og API programming.... :o) For I := 0 To EntriesRead - 1 Do Memo1.Lines.Add(WideCharToSTring(WKSTA_STRUCT_0.User_Name)); //Remember to convert from UNICode to String. //Good luck ... and pls. mail me if you have firther questions... ;o) End Else ShowMessage(SysErrorMessage(NET_API_STATUS)); End;End;End;End.*** CODE END ***caiu como uma luva, me retorna tanto o nome da máquina como o usuário, agora, você me disse em outra oportunidade que só poderia ser executado pelo Administrador, ainda continua sua afirmação? porque se sim, volto a estaca zero; Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Churc Postado Janeiro 31, 2007 Denunciar Share Postado Janeiro 31, 2007 opacaiu como uma luva, me retorna tanto o nome da máquina como o usuário, agora, você me disse em outra oportunidade que só poderia ser executado pelo Administrador, ainda continua sua afirmação? porque se sim, volto a estaca zero;Seus problemas acabaram!! asuhsuhavocê pode usar esta rotina pra detectar se o usuárioé Admin no Windows...retirada do código fonte do Inno setup rsFunction isAdmin: Boolean; const DOMAIN_ALIAS_RID_ADMINS = $00000220; function IsMemberOfGroup(const DomainAliasRid: DWORD): Boolean; const SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5)); SECURITY_BUILTIN_DOMAIN_RID = $00000020; SE_GROUP_ENABLED = $00000004; SE_GROUP_USE_FOR_DENY_ONLY = $00000010; var Sid: PSID; CheckTokenMembership: function(TokenHandle: THandle; SidToCheck: PSID; var IsMember: BOOL): BOOL; stdcall; IsMember: BOOL; Token: THandle; GroupInfoSize: DWORD; GroupInfo: PTokenGroups; I: Integer; begin if Win32Platform <> VER_PLATFORM_WIN32_NT then begin Result := True; Exit; end; Result := False; if not AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DomainAliasRid, 0, 0, 0, 0, 0, 0, Sid) then Exit; try { Use CheckTokenMembership if available. MSDN states: "The CheckTokenMembership function should be used with Windows 2000 and later to determine whether a specified SID is present and enabled in an access token. This function eliminates potential misinterpretations of the active group membership if changes to access tokens are made in future releases." } CheckTokenMembership := nil; if Lo(GetVersion) >= 5 then CheckTokenMembership := GetProcAddress(GetModuleHandle(advapi32), 'CheckTokenMembership'); if Assigned(CheckTokenMembership) then begin if CheckTokenMembership(0, Sid, IsMember) then Result := IsMember; end else begin GroupInfo := nil; if not OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True,Token) then begin if GetLastError <> ERROR_NO_TOKEN then Exit; if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, Token) then Exit; end; try GroupInfoSize := 0; if not GetTokenInformation(Token, TokenGroups, nil, 0, GroupInfoSize) and (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then Exit; GetMem(GroupInfo, GroupInfoSize); if not GetTokenInformation(Token, TokenGroups, GroupInfo, GroupInfoSize, GroupInfoSize) then Exit; for I := 0 to GroupInfo.GroupCount-1 do begin if EqualSid(Sid, GroupInfo.Groups[I].Sid) and (GroupInfo.Groups[I].Attributes and (SE_GROUP_ENABLED or SE_GROUP_USE_FOR_DENY_ONLY) = SE_GROUP_ENABLED) then begin Result := True; Break; end; end; finally FreeMem(GroupInfo); CloseHandle(Token); end; end; finally FreeSid(Sid); end; end; begin Result := IsMemberOfGroup(DOMAIN_ALIAS_RID_ADMINS); end;pra usarif isAdmin thené admin elsenão é;lembrando que só a partir do windows 2000 existe isso de Administrador,pra windows 9x/ME sempre vai retornar true...abraço Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Micheus Postado Janeiro 31, 2007 Denunciar Share Postado Janeiro 31, 2007 o código do Torry's não funcionouQue pena, mas o que não funcionou?...caiu como uma luva, me retorna tanto o nome da máquina como o usuário, agora, você me disse em outra oportunidade que só poderia ser executado pelo Administrador, ainda continua sua afirmação? porque se sim, volto a estaca zero;Como você continua utilizando a função NetWkstaUserEnum (também no exemplo do Torry's), vale o que está lá no remarks do msdn (dá uma olhada naquele link que postei):Windows 2000: If you call this function on a domain controller that is running Active Directory, access is allowed or denied based on the access control list (ACL) for the securable object.Windows NT: Only members of the Administrators local group can successfully execute NetWkstaUserEnum function both locally and on a remote server.só por esses dois comentários, é possível ver que há a possibilidade de você não obter o resultado da função.Abraços Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 fajo Postado Janeiro 31, 2007 Autor Denunciar Share Postado Janeiro 31, 2007 Fiquei triste,se vou colocar essa rotina em um programa, não posso exigir que todos que se loguem sejam usuários Administradores para usarem esse programa, já que quem não for não terá listado os usuários de outros computadores para poder se comunicarem; será que não tem outra maneira?e agora pouco fiz um teste, tenho 2 pcs aqui, mesmo estando conectado como adminstrador nas duas máquinas em uma consegui listar o nome do pc e o usuário da outra, mas, quando fiz o contrário, deu uma mensagem "Acesso Negado", porque? Já desabilitei firewall e tudo!!!! Citar Link para o comentário Compartilhar em outros sites More sharing options...
Pergunta
fajo
Oi pessoal,
estou precisando de uma rotina que me retorne num listbox por exemplo todos os usuarios conectados nos computadores da minha rede!!
Obrigado
Link para o comentário
Compartilhar em outros sites
8 respostass a esta questão
Posts Recomendados
Participe da discussão
Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.