Из этой ситуации выходит задача, сделать так что бы измененный файл загружался в базу. Как это сделать? На первый взгляд легко и просто, если задуматься не так тривиально.
Файлы ведь могут быть разных форматов, и ворд и эксель, и текстовый и может даже фотография формата GIMP. Из этого следует что CreateProcess нам не подходит, так как в коде определять какой программой открывать файл - лишние проблемы и подводные грабли. Не стоит так извращаться.
В свою очередь ShellExecute имеет другой недостаток, он хоть и способен автоматически открыть файл в ассоциированной ему программе, но он не дает хэнд процесса, что не позволяет нам дождаться завершения процесса. А раз мы не можем дождаться завершения процесса, стало быть как мы узнаем через какое время пользователю надумается сохранить изменения в файле и закрыть его, для того что бы затянуть измененный файл назад в базу. Это основная проблема на которую я наткнулся при решении задачи.
Но Google никогда не подводил, буквально час ушел на поиск нужного решения. Есть такой промежуточный метод между CreateProcess и ShellExecute. И имя его ShellExecuteEx.
Его использование несколько заморочено, посему не стал много времени тратить на копание вглубь, но нашел отличную такую процедурку, которая выполняет это действо внутри себя, а нам нужно лишь вызвать её передав в неё путь к файлу, если надо параметр запуска и параметр запуска процесса.
Код процедуры:
procedure RunAndWaitShell(Executable, Parameter: STRING; ShowParameter: INTEGER);{Если форма приложения имеет свойство AlwaysOnTop заменить SEE_MASK_NOCLOSEPROCESS на SEE_MASK_FLAG_DDEWAIT }
var
Info: TShellExecuteInfo;
pInfo: pShellExecuteInfo;
exitCode: DWord;
begin
pInfo := @Info;
Info.cbSize := SizeOf(Info);
Info.fMask := SEE_MASK_NOCLOSEPROCESS;
Info.wnd := application.Handle;
Info.lpVerb := NIL;
Info.lpFile := PChar(Executable);
Info.lpParameters := PChar(Parameter + #0);
Info.lpDirectory := NIL;
Info.nShow := ShowParameter;
Info.hInstApp := 0;
ShellExecuteEx(pInfo);
repeat
exitCode := WaitForSingleObject(Info.hProcess, INFINITE); //было 500
Application.ProcessMessages;
until (exitCode <> WAIT_TIMEOUT);
end;
Теперь пример использования:
//...
RunAndWaitShell('D:\test.txt','',SW_SHOWNORMAL); //Открываем файлик, где бы он ни находился.
//Идет ожидание пока не закроется программа которая открыла файл. Если пользователь внес
//свои изменения, то мы можем их получить и записать в базу.
//Тут в общем-то берем этот же файл и пишем его в базу, заменяя старый вариант, по желанию
//можно устроить проверку на изменения в файле.
// ShowMessage('The End or the programm.');
//...
Такое в общем простое решение на такую в общем-то нужную в жизни задачу, если у кого-то есть более оптимальные решения - пишите :) Если что-то не понятно, тоже пишите =)

Комментариев нет:
Отправить комментарий