O funcionamento das interfaces do WMI se parecem com o acesso a um banco de dados, onde você pode submeter queries nas tabelas que detem as informações que se quer recuperar sobre o Sistema Operacional. Uma lista das "tabelas" (na verdade são classes) existentes pode ser encontrada no site para desenvolvedores da Microsoft.
A Microsoft disponibiliza o acesso ao WMI através de COM de modo que é possível realizar tarefas de gerenciamento até mesmo com scripts. Para usá-lo no Delphi ou C++ Builder, é preciso importar a type library correspondente cujo nome é Microsoft WMI Scripting V1.2 Library - o número da versão pode variar, dependendo do que você tem instalado em seu computador.
O primeiro passo é criar uma instância de classe que implemente a interface ISWbemLocator. Essa interface é responsável pela conexão com o serviço WMI, como no exemplo abaixo.
var Locator : ISWbemLocator;
Services: ISWbemServices;
begin
Locator := CoSWbemLocator.Create;
Services := Locator.ConnectServer('.', 'root\wmi','', '', '','', 0, Nil);
Services: ISWbemServices;
begin
Locator := CoSWbemLocator.Create;
Services := Locator.ConnectServer('.', 'root\wmi','', '', '','', 0, Nil);
A função ConnectServer permite também a conexão com o WMI de outro computador, bastando informar qual é esse computador e as credenciais de acesso (usuário e senha). No exemplo, estou conectando ao WMI do meu próprio computador, representado pelo nome '.'. O valor 'root\wmi' aponta o namespace onde está a informação que eu quero; consulte a documentação para mais detalhes sobre os namespaces. O que essa função retorna é a interface ISWbemServices, responsável por providenciar acesso às tarefas disponíveis no WMI.
No caso tratado por este post, a tarefa é apenas a execução de uma query para recuperar o nível do sinal WiFi percebido pelo computador. O nome da tabela (ou classe) que tem essa informação é a MSNdis_80211_ReceivedSignalStrength e por isso vou montar o SELECT nela:
var ObjSet: ISWbemObjectSet;
begin
ObjSet := Services.ExecQuery(
'SELECT * FROM MSNdis_80211_ReceivedSignalStrength',
'WQL', wbemFlagReturnImmediately , nil);
begin
ObjSet := Services.ExecQuery(
'SELECT * FROM MSNdis_80211_ReceivedSignalStrength',
'WQL', wbemFlagReturnImmediately , nil);
A função ExecQuery retorna uma espécie de record set, isto é, uma coleção de registros que atendem a query especificada. No caso aqui, será retornado um valor para cada placa de rede encontrada. Esse record set implementa a interface IEnumVariant para percorrer todos os "registros" que forem retornados pela query. Assim, posso obter o valor da propriedade Ndis80211ReceivedSignalStrength de cada um deles.
var SObject: ISWbemObject;
SProp: ISWbemProperty;
Enum: IEnumVariant;
Value: Cardinal;
ObjRet: OleVariant;
begin
Enum := ObjSet._NewEnum As IEnumVariant;
while (Enum.Next(1, objRet, Value) = S_OK) do
begin
SObject := IUnknown(objRet) As ISWBemObject;
SProp := SObject.Properties_.Item('Ndis80211ReceivedSignalStrength', 0);
if not VarIsNull(SProp.Get_Value) then
Result := String (SProp.Get_Value) + #13#10;
end;
SProp: ISWbemProperty;
Enum: IEnumVariant;
Value: Cardinal;
ObjRet: OleVariant;
begin
Enum := ObjSet._NewEnum As IEnumVariant;
while (Enum.Next(1, objRet, Value) = S_OK) do
begin
SObject := IUnknown(objRet) As ISWBemObject;
SProp := SObject.Properties_.Item('Ndis80211ReceivedSignalStrength', 0);
if not VarIsNull(SProp.Get_Value) then
Result := String (SProp.Get_Value) + #13#10;
end;
A propriedade Ndis80211ReceivedSignalStrength é tratada como se fosse um campo numa tabela no banco de dados e é ela que tem de fato o nível do sinal. Note, no entanto, que o valor retornado por ela não é fixo. Cada vez que a função for executada, o valor reportado será o nível do sinal percebido naquele momento. O número retornado é expresso em DBMs e pode assumir valores entre -50 (sinal mais forte) e -100 (sinal mais fraco).
No trecho de código acima, o cast String (SProp.Get_Value) só funciona porque o valor retornado por essa propriedade é conversível para String. Outras propriedades podem ter tipos diferentes e exigirão casts diferentes. Isso inclui até objetos, caso em que a conversão terá que ser feita de outra maneira - talvez uma interface específica.
O acesso ao WMI utilizando a versão .NET do Delphi é ligeiramente diferente. Nesta plataforma, o ObjSet não é compatível com a interface IEnumVariant e sim com a IEnumerator. Portanto, todo o laço onde é feita a navegação pelos registros tem que ser revisto para poder funcionar no .NET.
Esse tipo de abordagem com o WMI não funciona no Windows Vista. Veja este artigo, publicado no site Technet da Microsoft.
4 comentários :
Gostaria de agradecer ao Luís que me ajudou muito, sem ele não desenvolveríamos esse código. Graças a ele poderei dar continuidade ao meu trabalho de conclusão da faculdade.
Muito sucesso na vida e no blog. Sempre que eu puder, estarei aqui ajudando ou dando uma força.
Muito obrigado por tudo...
att,
Rodrigo de Souza Kuck
Material realmente interessante.
Pesquisei pela documentação WMI e verifiquei uma vasta listagem de objetos, métodos e propriedades realmente uteis, porém, nem todos os métodos e propriedades estão disponíveis ou foram implementadas ainda.
Pesquiso por uma forma de obter o sinal de rede independente do hardware utilizado e infelizmente o exemplo dado pelo Luíz Gustavo não solucionou o meu problema...
Tentei utilizar o objeto Win32_NetworkAdapter mas as propriedades que retornam velocidade (Speed), e velocidade máxima (MaxSpeed), que também seriam interessantes em meu trabalho, não retornaram valor algum, e a referencia da documentação diz que estas propriedades não foram implementadas para a plataforma Win2003Server.
Procuro, outra forma de capturar o nível de sinal da rede entre outras propríedades.
Olá,
Sabe como faço para alterar essa função para poder trazer o serial id do sistema operacional?
No dos fica assim: wmic os get serialnumber
A classe que vc está procurando provavelmente é a Win32_OperatingSystem. Ela está sob o root CIMV2 e a documentação dela no MSDN está no endereço http://msdn.microsoft.com/en-us/library/aa394239%28v=vs.85%29.aspx.
[]s
Postar um comentário
OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.
Observação: somente um membro deste blog pode postar um comentário.