Форум: "Основная";
Текущий архив: 2013.07.07;
Скачать: [xml.tar.bz2];
ВнизБлокировка запущенной программы из программы Найти похожие ветки
← →
Сергей из Самары (2011-06-02 12:26) [0]Есть такая задача:
В БД хранится некий вордовский документ. Его нужно извлечь из базы, открыть. Если в нем внесена правка, сохранить и снова загрузить в базу. Понятно, что пока файл открыт ни другой пользователь не может получить доступ к этому файлу в базе, ни сам пользователь не должен работать в в программе. То есть программа должна висеть, пока человек либо не закроет файл без сохранения, либо сохранит его и тоже закроет.
Реализовал я механизм следующим образом:
time_start := GetFileDate(fname); //Получаем время создания файла
FillChar( Si, SizeOf( Si ) , 0 );
with Si do
begin
cb := SizeOf( Si);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := SW_SHOW;
end;
wp:= """+Form1.word_p+"" "+fname; //путь к ворду и параметр (имя файла)
Form1.WindowState:=wsminimized;
if Createprocess(nil, Pchar(wp), nil, nil,false,
CREATE_DEFAULT_ERROR_MODE, nil, nil, si, p) //запускаем
then begin
CloseHandle(p.hThread);
ShowWindow(Form1.Handle, SW_HIDE);
while (WaitForSingleObject(p.hProcess, 100) = WAIT_TIMEOUT) do //пока программа открыта, доступа к основной программе нет
Application.ProcessMessages;
CloseHandle(p.hProcess);
ShowWindow(Form1.Handle, SW_SHOWNOACTIVATE);
end;
Form1.WindowState:=wsMaximized;
time_fin := GetFileDate(fname); //получаем время изменения файла
if Form5.Tag = 1 then begin //индикатор (файл можно просто открыть для просмотра, тогда его не нужно сохранять в базе, даже если в него внесли изменения
If time_start <> time_fin then //проверяется вносили ли в файл изменения, если да, то сохраняем в файл
begin
DBm.Priem.Edit;
DBm.PriemPROTOKOL_BL.Clear;
DBm.PriemPROTOKOL_BL.LoadFromFile(fname);
DBm.Priem.Post;
end;
end;
DeleteFile(fname); //удаляем сам файл с диска
Все работает, все проверяется... до тех пор, пока не запущен как какой-либо другой вордовский файл, совершенно посторонний. Если запущен ворд, то WaitForSingleObject пролетает махом. В результате программа не блокируется и выполняется дальше. Даже если в файл внесены изменения в базу он записан не будет. Подскажите, как можно решить эту проблему? Возможно ли как-то, если на компе запущены другие вордовские процессы, блокировать и их?Или проблему можно решить иначе?
← →
QAZ (2011-06-02 12:58) [1]а зачем вообще эти файлы хранить в бд ? приэтом открывать с диска? и сохранять на дскже?
← →
Сергей из Самары (2011-06-02 13:16) [2]Есть некоторые шаблоны документов с готовым текстом. По тексту разбросаны маркеры, которые меняются при первой загрузке на данные из БД. Открывается заполненный документ, который пользователь должен внести еще дополнительные изменения: дописать то, что нет в БД, внести свои примечания и т.д. Вот этот документ и должен храниться в БД. При этом он должен быть доступен для редактирования. То есть его всегда должно быть можно достать, что-то в нем отредактировать и снова загрузить в БД.
← →
Юрий Зотов © (2011-06-02 13:46) [3]При открытии документа заблокировать запись в таблице, при сохранении в БД - разблокировать?
Но непонятно - почему документ не может редактироваться двумя юзерами одновременно? Кто последний запишет его обратно в БД - тот и прав. Это обычная практика, и не только для BLOB-полей.
← →
Сергей из Самары (2011-06-02 14:00) [4]При открытии документа запись переходит в состоянии update. Пока с ней работает пользователь больше никто не сможет ничего там изменить. Вопрос не в этом. Вопрос в том, что программа, из которой вызывается ворд с документом, должна блокироваться, пока пользователь не закроет этот самый документ. До тех пор, пока на компьютере не запущен ни один вордовский файл - все работает. Но стоит открыть хоть один и блокировка перестает работать, а потому не отслеживается момент закрытия документа и не сохраняются внесенные в него изменения. Вот этот момент и надо победить. И пока я даже не знаю в какую сторону копать.
← →
QAZ (2011-06-02 14:13) [5]копать в сторону с которой у тебя в шаблоне маркеры заменяются
← →
Сергей из Самары (2011-06-02 14:29) [6]А это тут причем? Тут все в порядке и они меняются всегда и везде и без ошибок. Причем делается это один раз при загрузке шаблона. В базе документ хранится уже без всяких маркеров. И открывается повторно без них. Проблема в том, что при открытом вордовом документе не срабатывается вот эта часть:
while (WaitForSingleObject(p.hProcess, 100) = WAIT_TIMEOUT) do
Application.ProcessMessages;
← →
sniknik © (2011-06-02 14:34) [7]а что возвращает вместо WAIT_TIMEOUT?
← →
sniknik © (2011-06-02 14:38) [8]Удалено модератором
← →
Сергей из Самары (2011-06-02 14:55) [9]WAIT_TIMEOUT = 258
WaitForSingleObject(p.hProcess, 100) = 258
Вот это и непонятно В одном случае все работает, в другом пролетает без задержки
← →
Anatoly Podgoretsky © (2011-06-02 15:13) [10]> Сергей из Самары (02.06.2011 14:00:04) [4]
Редактирование конечно Вордом?
Так он изначально предназначен для редактирования любого количества
документов и это не изменить.
← →
Anatoly Podgoretsky © (2011-06-02 15:13) [11]> Сергей из Самары (02.06.2011 14:00:04) [4]
Надо издать инструкцию по работе с этой корявой программой и под роспись.
← →
QAZ (2011-06-02 15:14) [12]
> А это тут причем?
ну вот как ты объщаешся с вордом чтобы заменить маркеры
← →
Anatoly Podgoretsky © (2011-06-02 15:14) [13]Удалено модератором
← →
Сергей из Самары (2011-06-02 15:32) [14]Вордом. Пользователи не хотят отказываться от его функционала.
И что, совсем никак эту проблему не решить?
← →
Сергей из Самары (2011-06-02 15:36) [15]
> стати странно... нужна блокировка программы пока не вышли
> из процесса, а тут таймаут добавлен и ProcessMessages...
>
Это уже в процессе экспериментов накрутилось. Изначально было только:
WaitForSingleObject(p.hProcess, Infinite)
> Надо издать инструкцию по работе с этой корявой программой
> и под роспись.
Если бы я хотел оставить как есть, так бы и сделал. Но я и пытаюсь решить эту пролему.
← →
sniknik © (2011-06-02 15:43) [16]Удалено модератором
← →
sniknik © (2011-06-02 16:04) [17]вот, весь код
procedure TForm1.Button1Click(Sender: TObject);
begin
Enabled:= false;
WordApplication1.Connect;
WordApplication1.Visible:= true;
//открыть нужный файл сам допишешь
end;
procedure TForm1.WordApplication1Quit(Sender: TObject);
begin
Enabled:= true;
end;
в дизайне кладем на форму TWordApplication, ставим у свойства ckNewInstance, в событии "на выход" прописываем то что выше показано.
все.
← →
Inovet © (2011-06-02 16:16) [18]Удалено модератором
← →
Anatoly Podgoretsky © (2011-06-02 16:40) [19]Удалено модератором
← →
Сергей из Самары (2011-06-02 17:59) [20]sniknik
Спасибо. Кажется, получается. Только один вопрос:
Я здесь
procedure TForm1.WordApplication1Quit(Sender: TObject);
begin
Enabled:= true;
end;
Еще прописываю загрузку файла в базу после закрытия:
Enabled:= true;
DBm.Priem.Edit;
DBm.PriemPROTOKOL_BL.Clear;
DBm.PriemPROTOKOL_BL.LoadFromFile(FilNm);
DBm.Priem.Post;
DeleteFile(FilNm);
Так вот, при закрытии в этом месте: DBm.PriemPROTOKOL_BL.LoadFromFile(FilNm); вылетает ошибка, что процесс не может получить доступ к файлу, так как он занят другим приложением если я внесу изменения в документ, нажму закрыть документ и на вопрос хочу ли я сохранить документ отвечу "Да". Если я перед закрытием нажму на "сохранить", то все проходит без проблем. При этом, если я сохранение в базу комменчу, то удаление файла (которое стоит сразу после записи в базу) происходит без проблем и файл оказывается никем не занят.
← →
Сергей из Самары (2011-06-02 18:29) [21]Кажется, разобрался сам. Спасибо за помощь.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2013.07.07;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.003 c