Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум на Исходниках.RU > Delphi: Система, Windows API > Как заменить SetLength? |
Автор: navodri 17.07.18, 15:28 |
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> function TRestoreViewer.GetRestorePoints: TRestorePoints; var ObjWMIService : OLEVariant; ColItems : OLEVariant; ColItem : OLEVariant; OEnum : IEnumvariant; // IValue : PLongint; CountOfRestorePoint : Integer; I: Integer; RestorePoint : TRestorePoint; begin ObjWMIService := GetWMIObject('winmgmts:\\localhost\root\default'); ColItems := objWMIService.ExecQuery('SELECT * FROM SystemRestore','WQL',0); OEnum := IUnknown(colItems._NewEnum) as IEnumVariant; if not VarIsNull(ColItems.Count) then CountOfRestorePoint := StrToInt(VarToStr(ColItems.Count)) else CountOfRestorePoint := 0; if (CountOfRestorePoint = 0) then Exit; // SetLength(Result, CountOfRestorePoint); I := 0; while OEnum.Next(1, colItem, nil {IValue}) = 0 do begin RestorePoint.Description := ColItem.Description; RestorePoint.EventType := EventTypeToStr(ColItem.EventType); RestorePoint.SequenceNumber := ColItem.SequenceNumber; RestorePoint.CreationTime := WMITimeToStr(ColItem.CreationTime); RestorePoint.RestorePointType := RestorePointTypeToStr(ColItem.RestorePointType); Result[i] := RestorePoint; Inc(i); end; end; |
Автор: MBo 17.07.18, 15:58 |
SetLength нельзя заменить ничем, если оно применяется к переменным соответствующих типов. А про тип мы не знаем, т.к. не телепаты. |
Автор: navodri 17.07.18, 17:36 |
Сорри. Вот тип: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> type TRestorePoint = record Description:string; EventType:string; SequenceNumber:string; CreationTime:string; RestorePointType:string; end; TRestorePoints = array [0..255]of TRestorePoint; |
Автор: Gonarh 17.07.18, 18:24 |
getmem/freemem |
Автор: navodri 17.07.18, 19:53 |
В моем случае Result не Pointer. Так не компилится: Incompatible types <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> GetMem(Result, sizeOf(CountOfRestorePoint)); |
Автор: MBo 18.07.18, 02:11 |
Массив статический, так что задавать длину ему не нужно, память под результат уже выделена компилятором. При этом неизвестно, сколько реально элементов заполнено SetLength требуется для динамических массивов <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> TRestorePoints = array of TRestorePoint; |
Автор: navodri 18.07.18, 06:24 |
Это не помогает. ListView1 заполняется множеством пустых пунктов. Может, в заполнении ошибка: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> procedure TForm1.Button1Click(Sender: TObject); var MyRestoreViewer:TRestoreViewer; AllRestorePoint:TRestorePoints; I: Integer; begin ListView1.Items.Clear; MyRestoreViewer := TRestoreViewer.Create; AllRestorePoint := MyRestoreViewer.GetRestorePoints; for I := 0 to High(AllRestorePoint) do with ListView1.Items.Add do begin Caption := AllRestorePoint[i].Description; SubItems.Add(AllRestorePoint[i].EventType); SubItems.Add(AllRestorePoint[i].SequenceNumber); SubItems.Add(AllRestorePoint[i].RestorePointType); SubItems.Add(AllRestorePoint[i].CreationTime); end; MyRestoreViewer.Free; end; |
Автор: MBo 18.07.18, 06:33 |
А длина динамического массива установлена в соответствии с реальным содержанием? Если используется код из первого поста, то i после цикла содержит счётчик записей. |
Автор: Fr0sT 18.07.18, 06:58 |
1) Поставь точку останова после заполнения массива и посмотри в отладчике, что туда записалось 2) (а) Возвращай кол-во заполненных элементов либо (б) выставляй флаг внутри записи, что она содержит данные, чтобы не рассматривать незаполненные элементы 3) Если выберешь вариант (б), обнуляй массив перед каждым заполнением. |
Автор: navodri 18.07.18, 08:04 |
Сенкс! Нашел ошибку. Закрывайте тему. |
Автор: Fr0sT 19.07.18, 08:40 |
Сам и закрывай) |
Автор: Jin X 19.07.18, 15:23 |
navodri, используй динамический массив (см. выше строку кода от MBo) и используй с ним SetLength, High и пр. Это гораздо лучше, чем забивать стек массивом и потом копировать его с одного места на другое. К тому же, SetLength обнуляет выделенные элементы массива – ещё один плюс. А если ты создаёшь динамический массив как локальную переменную в вызывающей процедуре: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> то потом этот массив уничтожается автоматически при выходе из процедуры (т.е. не надо будет писать SetLength(RestorePoints, 0)). procedure Example; var RestorePoints: TRestorePoints; begin . . . RestorePoints := TRestoreViewer.GetRestorePoints; . . . end; |