Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Получение последнего измененного файла


Автор: 1Age 13.1.2015, 16:07
Здравствуйте , уважаемые форумчанины . 
Я новичок в Delphi , и при написании программы у меня возникло пару проблем , которые я не смог решить.

1. Не могу сохранить файл при загрузке на диск C:\

Цитата
var q:tmemorystream;
begin 
idHTTP1.Get('ссылка/prog1.1',q); //Окончание "1" так как с сервера нельзя качать exe файлы .
q.SaveToFile('C:\prog1.exe'); // Далее он сохраняет с форматом "exe"

Но при сохранение у меня выдает ошибку...
Цитата
 Cannot create file "С:\prog1.exe". Системе не удается найти указанный путь

Как давать разрешение на сохранение? 
Если запускать от имени администратора , то тогда все нормально сохраняет . Но хотел бы без этого как бы . 
Так же , я бы хотел сразу сохранять в папку TEMP.
Цитата
C:\Users\Alexey\AppData\Local\Temp

Как определять путь до папки TEMP ? Не до Windows TEMP , а вот именно до пользовского TEMP'a.

2. У меня вообще была программы на AutoHotKey , легкий язык я бы сказал , даже очень. Но там уже почти все изучил , и вот решил перейти на Delphi .
И там у меня была такая вот функция , которая узнает в папке последний измененный файл. И записывает в переменную и потом устанавливает это параметры для этой папки. 
Цитата

Loop, %AdressFolder%\*,1,0
{
    If A_Index=1
    {
    Last_Time:=A_LoopFileTimeModified
    Last_Name:=A_LoopFileFullPath
    continue
    }
    If (Last_Time < A_LoopFileTimeModified)
    {
    Last_Time:=A_LoopFileTimeModified
    Last_Name:=A_LoopFileFullPath
    }
} 
    FileSetTime , %Last_Time%, %AdressFolder %, M, 2

Вот этот код у меня на AutoHotKey написан , перевести его на Delphi у меня совсем не получается :((

3. И третья проблемка , совсем легкая , но на просторах интернета там и не нашел нужного .
У меня лицензия вообщем . Через IDhhtp берется в переменную текстовик, а в другую переменную берется еще одно значение . 
И как мне сравнить эти две переменные ? 
Цитата

if (txthttp = IntToStr(am)) 

Пробовал вот таким вот методом , но он сравнивает со всем файлом . А как сравнить именно строку? Проверить, содержит ли переменная указанную строку.
Надеюсь внятно объяснил))
Заранее большое спасибо!!

Автор: Illusion Dolphin 13.1.2015, 21:30
Цитата

Не могу сохранить файл при загрузке на диск C:\

А не надо всякое безобразие в корень писать, для этого другие папки есть
Цитата

Как определять путь до папки TEMP ? Не до Windows TEMP , а вот именно до пользовского TEMP'a.

Код

System.IOUtils;

TPath.GetTempPath


Цитата

перевести его на Delphi у меня совсем не получается :((


Код

uses
  System.IOUtils;

var
  FileName, LastFileName: string;
  FileDateTime, LastDateTime: TDateTime;
begin
  LastDateTime := MinDateTime;
  for FileName in TDirectory.GetFiles('C:\') do
  begin
    FileDateTime := TFile.GetLastWriteTime(FileName);
    if FileDateTime > LastDateTime then
    begin
      LastDateTime := FileDateTime;
      LastFileName := FileName;
    end;
  end;
end;


Цитата

Надеюсь внятно объяснил))

Я ничего не понял.

Автор: 1Age 13.1.2015, 23:19
Вообщем , пока 3 проблемку опустим, я там пока что смотрю всякие видео про строки , может увижу то что мне надо .

Цитата
А не надо всякое безобразие в корень писать, для этого другие папки есть

Безобразие кидать не собираюсь) У меня файлик обновления качался раньше туда . Почему диск С? Так как у некоторых пользователей вообще один диск ) И это диск C , по этому и хочу туда сохранять , во избежании потом проблем с обновой.

Код

uses
  var
  FileName, LastFileName: string;
  FileDateTime, LastDateTime: TDateTime;
  newDateTime : TDateTime;
begin
  LastDateTime := MinDateTime;
  for FileName in TDirectory.GetFiles(AdressFolder) do
  begin
    FileDateTime := TFile.GetLastWriteTime(FileName);
    if FileDateTime > LastDateTime then
    begin
      LastDateTime := FileDateTime;
      LastFileName := FileName;
    end;
  end;
    fileName := 'D:\prog\Files';
    FileSetDate(fileName, DateTimeToFileDate(LastDateTime));
end;



Отлично работает , только вот опять проблемка )
Не могу установить на папку эту дату , на файл все хорошо устанавливается , а вот только на папку не получается что - то :(

Нашел вот такую вот функцию , но больно она уж большая , может есть вариант поменьше ? 

Код

 function NT_SetDateTime(FileName: string; dtCreation, dtLastAccessTime, dtLastWriteTime: TDateTime): Boolean;
 // by Nicholas Robinson 
var
   hDir: THandle;
   ftCreation: TFiletime;
   ftLastAccessTime: TFiletime;
   ftLastWriteTime: TFiletime;

   function DTtoFT(dt: TDateTime): TFiletime;
   var
     dwft: DWORD;
     ft: TFiletime;
   begin
     dwft := DateTimeToFileDate(dt);
     DosDateTimeToFileTime(LongRec(dwft).Hi, LongRec(dwft).Lo, ft);
     LocalFileTimeToFileTime(ft, Result);
   end;

 begin
   hDir := CreateFile(PChar(FileName),
                      GENERIC_READ or GENERIC_WRITE,
                      0,
                      nil,
                      OPEN_EXISTING,
                      FILE_FLAG_BACKUP_SEMANTICS,
                      0);
   if hDir <> INVALID_HANDLE_VALUE then
    begin
     try
       ftCreation       := DTtoFT(dtCreation);
       ftLastAccessTime := DTtoFT(dtLastAccessTime);
       ftLastWriteTime  := DTtoFT(dtLastWriteTime);
       Result := SetFileTime(hDir, @ftCreation, @ftLastAccessTime, @ftLastWriteTime);
     finally
       CloseHandle(hDir);
     end;
   end
   else
     Result := False;
 end;

 procedure TForm1.Button2Click(Sender: TObject);
 begin
   NT_SetDateTime('c:\temp\MyFolder', now, now, now);
 end;

Автор: kami 13.1.2015, 23:57
Цитата(1Age @  13.1.2015,  23:19 Найти цитируемый пост)
Так как у некоторых пользователей вообще один диск ) И это диск C

smile навскидку припоминаю:
- пару компьютеров, у которых диском C был DVD, а система стояла на D.
- несколько, где диск C был скрытым (фактически - его не было), а первым (и системным) диском был D.

3.
Если я правильно понял, то нужно что-то типа
Код

var
  SL: TStringList;
begin
  SL:=TStringList.Create;
  try
    SL.Text:=мой_супер_текст_на_много_строк;
    if SL.IndexOf(строка_которую_ищем_в_супер_тексте)<>-1 then
      ShowMessage('О-ля-ля, такая строка есть!!!');
  finally
    SL.Free;
  end;


Автор: Alexeis 14.1.2015, 00:48
Цитата(kami @  14.1.2015,  00:57 Найти цитируемый пост)
навскидку припоминаю:
- пару компьютеров, у которых диском C был DVD, а система стояла на D.
- несколько, где диск C был скрытым (фактически - его не было), а первым (и системным) диском был D.

  Я думаю все гораздо банальней. Наверняка UAC не пускает. Элементарно кидаю файл с рабочего стола на диск С и получаю "Нет доступа к целевой папке Для перемещения нужно обладать правами администратора" и это при том что у меня UAC выкручен в самый минимум. 

Поэтому поддерживаю.
Цитата(Illusion Dolphin @  13.1.2015,  22:30 Найти цитируемый пост)
А не надо всякое безобразие в корень писать, для этого другие папки есть
 Для засирания есть рабочий стол или любая другая папка в директории пользователя типа мои документы. Там есть все права.

Автор: 1Age 14.1.2015, 00:57
@Kami , спасибо большое! В точку прям))

@Alexeis , Точно UAC . Забыл уже совсем как это называется ) 
Уже просто по дефолту хочу оставить TEMP , так как когда будет у человека появляться файлик апдейта на рабочем столе , уже как то не очень . Ну это лично мое мнение . 
Я так понимаю надо хук использовать? (Я мало что знаю о хуках , так что если это не то , не кричите особо :P)

Автор: Illusion Dolphin 14.1.2015, 08:12
Цитата

Нашел вот такую вот функцию , но больно она уж большая , может есть вариант поменьше ? 

Код

TDirectory.SetLastWriteTime();


Цитата

И это диск C , по этому и хочу туда сохранять , во избежании потом проблем с обновой.

Диска С вообще может не быть.

Цитата

так как когда будет у человека появляться файлик апдейта на рабочем столе , уже как то не очень . 

Так работает KMPlayer, но я бы в темп кидал

Цитата

Я так понимаю надо хук использовать? (Я мало что знаю о хуках , так что если это не то , не кричите особо :P)

Для чего?

Автор: Poseidon 14.1.2015, 09:27
Цитата(Alexeis @  14.1.2015,  00:48 Найти цитируемый пост)
Для засирания есть рабочий стол или любая другая папка в директории пользователя типа мои документы.
Обалдел? Для "засирания" есть только TEMP! При чем не тот TEMP, что в папке Windows, а тот, который в Users/...

Записывать на прямую в C: не дает сама Windows. UAC тут не при чем. Записывать что-то временное надо в TEMP. Что-то постоянное - в Application Data\...

Автор: 1Age 14.1.2015, 10:10
Остался последний вопросик , как мне получить букву вставленной флешки ? Пример : "F:\"
В виде чего то  типо этого .

Цитата

if найдена then 
ShowMessaeg(Буква флешки F:\);
else then
ShowMessage(Флешка не найдена);
Application.Terminate


И нормально ли вообще закрывать свое приложение ? "Aplplication.Terminate" ? 

Автор: Illusion Dolphin 14.1.2015, 12:05
Цитата

Остался последний вопросик , как мне получить букву вставленной флешки ? Пример : "F:\"

А если вставлено 3 флешки?

Цитата

Aplplication.Terminate

Имхо вполне.

Автор: 1Age 14.1.2015, 12:09
Цитата(Illusion Dolphin @ 14.1.2015,  12:05)
Цитата

Остался последний вопросик , как мне получить букву вставленной флешки ? Пример : "F:\"

А если вставлено 3 флешки?

Цитата

Aplplication.Terminate

Имхо вполне.

Ну так скажем , не надо 3 флешки сразу вставлять  smile 
Да и это уже запарка какая то получается)

Автор: Poseidon 14.1.2015, 13:26
Цитата(1Age @  14.1.2015,  10:10 Найти цитируемый пост)
И нормально ли вообще закрывать свое приложение ? "Aplplication.Terminate" ? 
Даже Halt зачастую нормально.

Автор: Illusion Dolphin 14.1.2015, 21:50
Чтобы проверить "флешки":
Код

for I := Ord('A') to Ord('Z') do

Флешка:
Цитата

if (GetDriveType(PChar(Chr(I) + ':\')) = DRIVE_REMOVABLE) 

Диск подключен по USB (переносной):
Код

if GetDriveType(PChar(Chr(I) + ':\')) = DRIVE_FIXED) and (GetBusType(AnsiChar(I)) = BusTypeUsb

Код


{$MINENUMSIZE 4}
const
  IOCTL_STORAGE_QUERY_PROPERTY =  $002D1400;

type
  STORAGE_QUERY_TYPE = (PropertyStandardQuery = 0, PropertyExistsQuery, PropertyMaskQuery, PropertyQueryMaxDefined);
  TStorageQueryType = STORAGE_QUERY_TYPE;

  STORAGE_PROPERTY_ID = (StorageDeviceProperty = 0, StorageAdapterProperty);
  TStoragePropertyID = STORAGE_PROPERTY_ID;

  STORAGE_PROPERTY_QUERY = packed record
    PropertyId: STORAGE_PROPERTY_ID;
    QueryType: STORAGE_QUERY_TYPE;
    AdditionalParameters: array [0..9] of AnsiChar;
  end;
  TStoragePropertyQuery = STORAGE_PROPERTY_QUERY;

  STORAGE_BUS_TYPE = (BusTypeUnknown = 0, BusTypeScsi, BusTypeAtapi, BusTypeAta, BusType1394, BusTypeSsa, BusTypeFibre,
    BusTypeUsb, BusTypeRAID, BusTypeiScsi, BusTypeSas, BusTypeSata, BusTypeMaxReserved = $7F);
  TStorageBusType = STORAGE_BUS_TYPE;

  STORAGE_DEVICE_DESCRIPTOR = packed record
    Version: DWORD;
    Size: DWORD;
    DeviceType: Byte;
    DeviceTypeModifier: Byte;
    RemovableMedia: Boolean;
    CommandQueueing: Boolean;
    VendorIdOffset: DWORD;
    ProductIdOffset: DWORD;
    ProductRevisionOffset: DWORD;
    SerialNumberOffset: DWORD;
    BusType: STORAGE_BUS_TYPE;
    RawPropertiesLength: DWORD;
    RawDeviceProperties: array [0..0] of AnsiChar;
  end;
  TStorageDeviceDescriptor = STORAGE_DEVICE_DESCRIPTOR;

function GetBusType(Drive: AnsiChar): TStorageBusType;
var
  H: THandle;
  Query: TStoragePropertyQuery;
  dwBytesReturned: DWORD;
  Buffer: array [0..1023] of Byte;
  sdd: TStorageDeviceDescriptor absolute Buffer;
  OldMode: UINT;
begin
  Result := BusTypeUnknown;

  OldMode := SetErrorMode(SEM_FAILCRITICALERRORS);
  try
    H := CreateFile(PChar(Format('\\.\%s:', [AnsiLowerCase(string(Drive))])), 0, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
    if H <> INVALID_HANDLE_VALUE then
    begin
      try
        dwBytesReturned := 0;
        FillChar(Query, SizeOf(Query), 0);
        FillChar(Buffer, SizeOf(Buffer), 0);
        sdd.Size := SizeOf(Buffer);
        Query.PropertyId := StorageDeviceProperty;
        Query.QueryType := PropertyStandardQuery;
        if DeviceIoControl(H, IOCTL_STORAGE_QUERY_PROPERTY, @Query, SizeOf(Query), @Buffer, SizeOf(Buffer), dwBytesReturned, nil) then
          Result := sdd.BusType;
      finally
        CloseHandle(H);
      end;
    end;
  finally
    SetErrorMode(OldMode);
  end;
end;


Ещё есть Portable Devices, которые тоже вроде как флешки, но это отдельная тема

Автор: 1Age 15.1.2015, 09:21

Код

procedure TForm1.FormCreate(Sender: TObject);
var i : integer;
var a : string;
begin
  for i := Ord('A') to Ord('Z') do begin
  if (GetDriveType(PChar(Chr(i) + ':\')) = DRIVE_REMOVABLE) then begin
  a := IntToStr(i);
  ShowMessage(a);
  end;
  end

end;

Мне вот такой вариант подойдет , он определяет . Только вот , он выдает результат в виде числа , перевод в строку не чего не дает((
Как можно исправить? Что бы он в ShowMessage выдавал букву .

Автор: ТоляМБА 15.1.2015, 09:45
Код
a := Chr(i);

Автор: 1Age 15.1.2015, 10:07
Цитата(ТоляМБА @ 15.1.2015,  09:45)
Код
a := Chr(i);

Thanks smile

Автор: 1Age 28.1.2015, 20:31
Подниму темочку , дабы не создавать лишнюю .
И так , устанавливаю функцией ниже , время для файлов,папок .  Вообщем часто использую .
Но заметил очень странный баг , а может и не баг .
Суть - Пару раз в коде устанавливается время папки . Но если сидеть в самой папке , на которую хочу установить время , то время тупо не устанавливается .
Если папка не открыта , то все нормально работает.
Можно ли это как то фиксануть?
Код

function NT_SetDateTime(FileName: string; dtCreation, dtLastAccessTime, dtLastWriteTime: TDateTime): Boolean;
 // by Nicholas Robinson 
var
   hDir: THandle;
   ftCreation: TFiletime;
   ftLastAccessTime: TFiletime;
   ftLastWriteTime: TFiletime;
   function DTtoFT(dt: TDateTime): TFiletime;
   var
     dwft: DWORD;
     ft: TFiletime;
   begin
     dwft := DateTimeToFileDate(dt);
     DosDateTimeToFileTime(LongRec(dwft).Hi, LongRec(dwft).Lo, ft);
     LocalFileTimeToFileTime(ft, Result);
   end;
 begin
   hDir := CreateFile(PChar(FileName),
                      GENERIC_READ or GENERIC_WRITE,
                      0,
                      nil,
                      OPEN_EXISTING,
                      FILE_FLAG_BACKUP_SEMANTICS,
                      0);
   if hDir <> INVALID_HANDLE_VALUE then
    begin
     try
       ftCreation       := DTtoFT(dtCreation);
       ftLastAccessTime := DTtoFT(dtLastAccessTime);
       ftLastWriteTime  := DTtoFT(dtLastWriteTime);
       Result := SetFileTime(hDir, @ftCreation, @ftLastAccessTime, @ftLastWriteTime);
     finally
       CloseHandle(hDir);
     end;
   end
   else
     Result := False;
 end;
 procedure TForm1.Button2Click(Sender: TObject);
 begin
   NT_SetDateTime('c:\temp\MyFolder', now, now, now);
 end;

Автор: Illusion Dolphin 28.1.2015, 21:56
https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360%28v=vs.85%29.aspx

Автор: 1Age 28.1.2015, 22:10
Цитата(Illusion Dolphin @ 28.1.2015,  21:56)
https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360%28v=vs.85%29.aspx

Ошибку я в принципе знал , но не уверен был . Теперь убедился .
Цитата

32: Процесс не может получить доступ к файлу, так как этот файл занят другим процессом.

Походу из - за того что получает хендл папки. 
Исправить я так понимаю нельзя?

Автор: Illusion Dolphin 28.1.2015, 23:27
Цитата

Походу из - за того что получает хендл папки. 

А попробуйте другие опции доступа. Я правильно понимаю, что ошибка в CreateFile? Что если добавить что-нибудь вроде FILE_SHARE_WRITE/FILE_SHARE_READ ?

Автор: 1Age 29.1.2015, 16:52
Цитата(Illusion Dolphin @ 28.1.2015,  23:27)
Цитата

Походу из - за того что получает хендл папки. 

А попробуйте другие опции доступа. Я правильно понимаю, что ошибка в CreateFile? Что если добавить что-нибудь вроде FILE_SHARE_WRITE/FILE_SHARE_READ ?

Код

hDir := CreateFile(PChar(FileName),
                      GENERIC_READ or GENERIC_WRITE,
                      0,
                      nil,
                      OPEN_EXISTING,
                      FILE_FLAG_BACKUP_SEMANTICS,
                      0);

Я так понимаю , что вы написали выше, надо подставить за место этого?

Автор: Illusion Dolphin 29.1.2015, 20:28
Это надо добавить к GENERIC_READ or GENERIC_WRITE через OR

Автор: 1Age 29.1.2015, 21:23
Цитата(Illusion Dolphin @ 29.1.2015,  20:28)
Это надо добавить к GENERIC_READ or GENERIC_WRITE через OR

Не помогло ( 
Можете еще что нибудь подсказать? Ошибка такая же .

Автор: Illusion Dolphin 1.2.2015, 13:12
Цитата

Не помогло ( 
Можете еще что нибудь подсказать? Ошибка такая же .

Без финального кода и примера папок сложно сказать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)