Конференция "WinAPI" » CreateFile [D5, NT4, WinXP]
 
  • OlegNik (25.12.08 12:12) [0]
    var
    hFile : THandle;
      Tmp : LPDWORD;
     INRT : Int64;

    hFile := CreateFile (PChar(FileName),
                          FILE_ATTRIBUTE_READONLY,
                          FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
                          nil,
                          OPEN_EXISTING,
                          FILE_ATTRIBUTE_NORMAL,
                          0);

     if hFile = INVALID_HANDLE_VALUE then Exit;
     INRT := GetFileSize (hFile, @Tmp);
     StrError := PChar(SysErrorMessage(GetLastError));
     StrError  = 'Параметр задан неверно'
     Не подскажите в чем дело, что за параметр?
     От себя добавлю, что FileName является ВЗУ.
     Открываю я этот файл(ВЗУ) для редактирования filesystem.
     Конечно можно использовать цикл записи по n(512) байт, но
     это уморительно долго.
     И сразу второй вопрос.
      Произвожу запись файла
      ReadFile(FhDrive,GLArrayByte[0],SizeFile,br,nil)
     (с одной стороны здорово разом файл размером SizeFile байт)
     но возникает следущая задачка файл необходимо записывать в
     разные места диска (ВЗУ файловая система QNX4 - кто знает тот плавал)
     При записи файла размером 200м возникает не ловкая пауза перед пользователем.
     Опять же поблочная запись, по блокам(512)  позволяет пользователю
     определить время на перекур по прогрессу, не подскажите как определить прогресс состояния
     записи в в случае быстрой(не поблочной) записи ReadFile(FhDrive,GLArrayByte[0],SizeFile,br,nil)
  • Сергей М. © (25.12.08 12:20) [1]
    GetFileSize
    ..
    Parameters

    hFile

    Specifies an open handle of the file whose size is being returned. The handle must have been created with either GENERIC_READ or GENERIC_WRITE access to the file.


    > не ловкая пауза перед пользователем


    Изловчись выполнять подобного рода операции в дополнительном кодовом потоке, тогда будет "ловкая пауза"
  • OlegNik (25.12.08 12:44) [2]

    > дополнительном кодовом потоке

    что  в этом потоке крутить? Я думал может есть какие ловушки, ну на
    крайний запустить процесс секунды на 3 глянуть сколько и за что.  

    > GENERIC_READ or GENERIC_WRITE

    заменил не помогло.
  • Сергей М. © (25.12.08 13:02) [3]

    > что  в этом потоке крутить?


    Крути все операции, за которые тебе стыдно перед юзером)


    > думал может есть какие ловушки


    Можно и без ловушек и без доп.потоков.
    На то существует overlapped-ввод/вывод, а также порты завершения

    см. все что касается OVERLAPPED-режима Create/Read/WriteFile
  • Slym © (26.12.08 10:50) [4]
    OlegNik   (25.12.08 12:12)
    но возникает следущая задачка файл необходимо записывать в
    разные места диска

    MMF не подойдет? мапить только то что нужно а не весь файл
  • Slym © (26.12.08 10:50) [5]
    OlegNik   (25.12.08 12:12)
    но возникает следущая задачка файл необходимо записывать в
    разные места диска

    MMF не подойдет? мапить только то что нужно а не весь файл
  • OlegNik (26.12.08 16:58) [6]
    пытался через OVERLAPPED но

    hFile := CreateFile (PChar(FileName),
                         FILE_ATTRIBUTE_READONLY,
                         FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
                         nil,
                         OPEN_EXISTING,
                         FILE_FLAG_OVERLAPPED,
                         0);

    Да вроде можно посмотреть через WaitForSingleObjectEx сколько записал
    к определенной секунде, но увы не могу понять почему перестал работать
    SetFilePointer или аналог _llSeek, может знает кто?
  • Сергей М. © (26.12.08 19:51) [7]

    > перестал работать
    > SetFilePointer


    Неужели вот прямо так и говорит "Я перестал работать" ?
  • OlegNik (27.12.08 09:51) [8]

    > Неужели вот прямо так и говорит "Я перестал работать" ?

    Да нет, не прямо так. Говорит 'Параметр задан неверно'. Функция возвращает High(DWord);
    SetFilePointer(hFile, tmpLo , @tmpHi, FILE_BEGIN);
  • Leonid Troyanovsky © (27.12.08 11:54) [9]

    > OlegNik   (26.12.08 16:58) [6]

    > увы не могу понять почему перестал работать
    > SetFilePointer или аналог _llSeek, может знает кто?

    The file pointer identified by the value of the hFile parameter is not used for overlapped read and write operations. To specify the offset for overlapped
    operations, use the Offset and OffsetHigh members
    of the OVERLAPPED structure.

    --
    Regards, LVT.
  • OlegNik (27.12.08 12:39) [10]

    > To specify the offset for overlapped
    > operations, use the Offset and OffsetHigh members
    > of the OVERLAPPED structure.

    А не в курсе как заполнять OVERLAPPED?
  • Leonid Troyanovsky © (27.12.08 12:57) [11]

    > OlegNik   (27.12.08 12:39) [10]

    > А не в курсе как заполнять OVERLAPPED?

    Ну, каждое поле и заполнять.
    А чего, msdn.microsoft.com не работает?

    --
    Regards, LVT.
  • OlegNik (29.12.08 09:56) [12]
    Виноват не то спросил.

    FillChar(Overlap,SizeOf(TOVERLAPPED),0);
    Overlap.hEvent := CreateEvent(0,True,False,0);
    Overlap.offSet := 512 * 9000;
    res := WriteFileEx();

    while WaitForSingleObjectEx(Overlap.hEvent,1000,True) = WAIT_TIMEOUT do
          begin
          Application.ProcessMessages;
          end;

    В части записи с нужной мне позиции все нормально  запись прозводится в поном объеме, но по истечению времени t=1с, я  не вижу фактического изменения числа записанных байт в Overlap, что не так. Или возможно путь указаный т. Сергей М. ложный.
  • Сергей М. © (29.12.08 14:38) [13]
    см. GetOverlappedResult
  • OlegNik (29.12.08 15:34) [14]

    > см. GetOverlappedResult


    while WaitForSingleObjectEx(Overlap.hEvent,1000,True) = WAIT_TIMEOUT do
         begin
           GetOverlappedResult(hFile,Overlap,realW,False);
           Form1.Caption := IntToStr(realW);
           {при GetOverlappedResult(hFile,Overlap,realW,True); уходит ПО   в "себя"}  
           Application.ProcessMessages;
         end;
  • OlegNik (29.12.08 15:35) [15]
    ну и понятно realW = 0.
  • Сергей М. © (29.12.08 16:20) [16]
    while True do
    begin
     case WaitForSingleObjectEx(Overlap.hEvent,1000,True) of
       WAIT_TIMEOUT: //прошла секунда, но сигнал окончания ovl-операции не обнаружен
       begin
         Application.ProcessMessages;
         continue; //ждем дальше
       end;
       WAIT_OBJECT_0: // обнаружен сигнал завершения ovl-операции
       begin
         Win32Check(GetOverlappedResult(hFile,Overlap,realW,False) <> 0);
         Form1.Caption := IntToStr(realW);
         break;
       end;
     end;
    end;
  • OlegNik (30.12.08 10:28) [17]
    Это понятно и здорово. Но мне хотелось бы узнать сколько байт записано
    по истечению секунды на  WAIT_TIMEOUT:
    Win32Check(GetOverlappedResult(hFile,Overlap,realW,False) <> False);
    выдает ошибку "наложенное событие ввода/вывода не находится в сигнальном состоянии" короче code : 996. Как быть?
  • Сергей М. © (30.12.08 10:42) [18]
    Никак.

    WAIT_TIMEOUT означает, что по истечении указанного периода операция не завершилась.
    Запрашивать результаты незавершенной операции бессмысленно, о чем собссно и говорит отказ с кодом 996.
  • OlegNik (30.12.08 10:56) [19]
    Ну а теперь самое главное.
    Я против того, чтобы делать ради того чтобы делать.
    Мой вопрос заключался в следующем: Можно ли при записи
    данных большого объема что называется "за раз" узнать сколько
    байт записано к определенному моменту времени, хотябы для вывода
    вывода этих данных в прогресс.
    А что был за совет с

    > см. все что касается OVERLAPPED-режима Create/Read/WriteFile


    Блеск знаниями или что?
    Но всеравно спасибо за "науку".
  • Сергей М. © (30.12.08 12:15) [20]

    > При записи файла размером 200м возникает не ловкая пауза
    > перед пользователем


    Чтобы она была "ловкая", нужно как минимум оживить UI, согласен ?
    Сделать это можно любым из двух способов - вынос операции (блокирующей или неблокирующей - неважно) в доп.процесс/доп.поток или запуск операции в UI-потоке в асинхронном неблокирующем режиме. Последнее реализуется как раз с использованием overlapped i/o механизма.

    Прогресс-нотификация же - это совсем другая (и весьма нетривиальная по ряду важных причин) задача, напрямую не связанная с i/o-режимами.

    Win32API предлагает единственную функцию, предоставляющую интерфейс прогресс-нотификации - CopyFileEx. Но если посмотреть на ее "внутренности", то там можно увидеть то самое блочное чтение/запись, от которых ты пытаешься уйти. И уйти по непонятным мне пока причинам, ибо ничто не мешает использовать блоки более крупного размера, нежели 0,5К
  • OlegNik (30.12.08 12:55) [21]
    Реализовал следующим способом
    1. Убедился что файл действительно большой
    2. Запускаю пробную запись(чтение) отследил время
    3. Ну а потом действительно твоя помощь
                в цикл к варианту WAIT_TIMEOUT добавил расчет положения
                прогресса (формулу определения дальности еще не отменили)
    В случае с WAIT_OBJECT_0 позиция прогресса = 100 (Ух ты высокое методическое мастерство позволило завершить процесс записи/чтения несколько быстрее чем ожидалось).
    Все спасибо, вопрос закрываю.
  • Сергей М. © (30.12.08 13:01) [22]
    Фигня это, а не прогресс. В топку его.
    Любое изменение в общесистемных условиях выполнения операции приведет к обрушению этого карточного домика по самый фундамент.

    Уж лучше честную липу показать юзеру - анимашку какую-нить.. Главное чтобы не скучал)
  • Сергей М. © (30.12.08 13:04) [23]

    > в цикл к варианту WAIT_TIMEOUT добавил расчет положения


    Это называется "К соседу за спичками через Северный полюс".
    По сути мощь и возможности wait-функции сводятся до использования в качестве банального таймера.
 
Конференция "WinAPI" » CreateFile [D5, NT4, WinXP]
Есть новые Нет новых   [134435   +34][b:0.001][p:0.001]