| 
| 
 | Вопрос # 6 088/ вопрос открыт / | 
 |  Доброго времени суток, уважаемые эксперты!Здравствуйте, пишу мониторинг процессов в системе по технологии WMI. Столкнулся с проблемой обновления Items в ListView. Нашел статью о виртуальном ListView (на этом сайте), попробовал переделать свой код, но почему-то список вообще не обновляется, даже не выводит из масива данные в список (если это делать по таймеру). Если делать по событию form1.create  то он один раз выводит, но мне это не подходит. В статье пишет про обновление  Items через  UpdateItems(n,m), но у меня это так-же не работает... пожалуйста подкоректируйте мой код или скажите что я делаю не так ? как заставить обновлять данные (как в диспетчере задач windows) ?
 Приложение:Переключить в обычный режим unit Unit100000000000000; interface uses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, WbemScripting_TLB, ComCtrls, ExtCtrls,Math, Grids, StdCtrls; type  TForm1 = class(TForm)    Timer1: TTimer;    ListView1: TListView;  type   TSimpleRec=record      caption:string;      data:integer;  end;     TSimpleArr = array of TSimpleRec;  procedure Timer1Timer(Sender: TObject);procedure ListView1Data(Sender: TObject; Item: TListItem);procedure FormCreate(Sender: TObject); private    arr:TSimpleArr;    services : ISWbemServices;    refresher : ISWbemRefresher;     refresherItem : ISWbemRefreshableItem;        pObject    : ISWbemObject;     pid,mem    : cardinal;//      pItem : TListItem;  public    { Public declarations }  end;var  Form1: TForm1; implementation {$R *.dfm}  procedure TForm1.FormCreate(Sender: TObject);var locator : ISWbemLocator;    i          : cardinal;     lc:TListColumn;begin     locator := CoSWbemLocator.Create();    services := locator.ConnectServer('.','root\cimv2','','','','',0,nil);    refresher := CoSWbemRefresher.Create;    refresherItem := refresher.AddEnum(services as
ISWbemServicesEx,'Win32_PerfFormattedData_PerfProc_Process',0,nil);     timer1.Enabled := true;    Refresher.Refresh(0);  Listview1.OwnerData:=True;   ListView1.ViewStyle:=vsReport;  lc:=ListView1.Columns.Add;  lc.Caption:='PID';  lc.Width:=150;  lc:=ListView1.Columns.Add;  lc.Caption:='Memory';  lc.Width:=150;   ListView1.RowSelect:=true;     SetLength(arr,refresherItem.ObjectSet.Count);   ListView1.Items.Count:=Length(arr);   Caption:=IntToStr(Length(arr));     end;   procedure TForm1.Timer1Timer(Sender: TObject);var    i          : cardinal;    pItem : TListItem;begin   Refresher.Refresh(0);    SetLength(arr,refresherItem.ObjectSet.Count);    ListView1.Items.Count:=Length(arr);    Caption:=IntToStr(Length(arr));      for i:=0 to refresherItem.ObjectSet.Count-1  do    begin      pObject := refresherItem.ObjectSet.ItemIndex(i);      pid  := pObject.Properties_.Item('IdProcess',0).Get_Value;     // name := pObject.Properties_.Item('Name',0).Get_Value;     // usage:= pObject.Properties_.Item('PercentProcessorTime',0).Get_Value;      mem:= pObject.Properties_.Item('WorkingSetPrivate',0).Get_Value;       arr[i].caption:=IntToStr(pid);      arr[i].data:=mem;       pObject._Release;     end;     end;  procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);  begin  item.Caption:=arr[item.Index].caption;  item.SubItems.Add(IntToStr(arr[item.Index].data));  end; end.
|  |   Вопрос задал: darkziman (статус: Посетитель)Вопрос отправлен: 18 апреля 2012, 22:55
 Состояние вопроса: открыт, ответов: 0.
 |  
 Мини-форум вопросаВсего сообщений: 9; последнее сообщение — 2 мая 2012, 02:03; участников в обсуждении: 3. 
|   | Вадим К (статус: Академик), 18 апреля 2012, 23:35 [#1]:Ну, и где же Вы вызываете UpdateItems ? Как минимум один вызов нужен сразу перед окончанием процедуры для таймера. 
 ListView1.UpdateItems(0, length(arr)-1);С другой стороны - промежуточный массив Вам абсолютно не нужен. Данные можно брать напрямую. Галочка "подтверждения прочтения" - вселенское зло. |  
|   | darkziman (статус: Посетитель), 18 апреля 2012, 23:51 [#2]:на строчку, что Вы написали программа никак не реагирует. При запуске у меня первая колонка пустая, а вторая забита нолями (так-как там должны вписыватся данные типа integer). 
 Я пробовал сделать обновление с помощью сравнения итема PID (уникального номера) и значения PID, которое должно получить от WMI .. но тоже ничего не работало...
 |  
|   | min@y™ (статус: Доктор наук), 19 апреля 2012, 08:17 [#3]:Ну, раз не получается с UpdateItems(), попробуй в конце обработчика таймера грубо ввалить ListView1.Invalidate(). Если и это не поможет, то ставь точку останова и тыкай в отладчике по шагам, просматривая, что же происходит там на самом деле. Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | Вадим К (статус: Академик), 19 апреля 2012, 11:55 [#4]:Программа может не реагировать по одной простой причине - в массиве arr ничего не заполнялось. Либо Refresher начинает работать в отдельном потоке (и получается, что он к примеру в этот момент может быть чистым). 
 Самое первое, что рекомендую - в конце процедуры таймера вывести его содержимое в файл или мемо и посмотреть, а что же там.
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | darkziman (статус: Посетитель), 19 апреля 2012, 23:22 [#5]:проверил, в массиве arr идет заполнение и обновление данных (вывел в цикле в memo). 
 строчка Caption:=IntToStr(Length(arr)); в названии формы обновляется (показывает число запущеных процессов)...
 
 Listview меняет количество итемов каждую секунду (в зависимости от количества процессов),но все итемы пустые ... подскажите почему ?!
 |  
|   | min@y™ (статус: Доктор наук), 20 апреля 2012, 08:11 [#6]:Поставь бряк в обработчик события OnData, может быть у тебя туда исполнение не доходит? Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | darkziman (статус: Посетитель), 20 апреля 2012, 08:51 [#7]:да, действительно, процедура procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem); не работает, он до нее не доходит, после записи всех процессов в массив оно начинает делать это сначала  =( ... как заставить её работать  ?!... |  
|   | min@y™ (статус: Доктор наук), 20 апреля 2012, 09:01 [#8]: Цитата (darkziman): как заставить её работать ?!. Ну, для начала надо присвоить событию обработчик. В Object Inspector'e или вручную. А затем в конце обработчика таймера - ListView1.Refresh().
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | darkziman (статус: Посетитель), 2 мая 2012, 02:03 [#9]:работает, спасибо ! |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |