:: Visual Foxpro, Foxpro for DOS
Убить насмерть Excel процесс
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
Здравствуйте
Программно создаю (точнее заполняю готовую форму файла Excel) товарную накладную.
Методика: в папке с формами хранится Excel шаблон, программа копирует его в tmp-папку с tmp-именем, открывает эту копию и заполняет. Причем Excel становится видимым
m.loExcel.Visible= .T.
только в самом конце процесса заполнения.
Если вдруг во время этого процесса что-то произошло (не корректные данные и пр.), то программа "вылетает". а Excel-процесс с tmp-именем остаётся "висеть" невидимым и при следующей попытке копирования шаблона в tmp-папку с tmp-именем возникает ошибка. Программа выводит соответствующее сообщение.
Изначально делалось для себя, я открывал Диспетчер и убивал процесс.
Но теперь пользуются другие и начинают орать "все пропало!"
Естественно методика не выдерживает критики, но самое простое решение - убить этот скрытый процесс и, ничего не сообщая, создать новый.
Поэтому:
1. Я легко получаю HWND этого окна
2. Легко его могу сделать видимым (но Юзеру придется превозмогая страх и непонимание его закрыть не сохраняя)
3. Легко могу послать
sendmessage(lhwnd,WM_CLOSE,0,0)
- опять паника, потому что появляется Сохранить Да Нет в корявом (или вообще невидимом файле)
4. Никак не могу убить этот процесс по HWND
Пытаюсь делать так:
LPARAMETERS lhwnd
DECLARE integer TerminateProcess IN WIN32API integer, integer
DECLARE integer OpenProcess IN WIN32API integer, integer, integer
DECLARE integer CloseHandle IN WIN32API integer
DECLARE integer GetWindowThreadProcessId IN WIN32API integer, integer @
LOCAL hProcess, pid
GetWindowThreadProcessId(lhwnd, @PID);
hProcess=OpenProcess(1,1,pid)
TerminateProcess(hProcess,0)
CloseHandle(hProcess)
и получаю ошибку "Syntax error" в строке GetWindowThreadProcessId(lhwnd, @PID);
?



Исправлено 2 раз(а). Последнее : Sandwich, 17.09.21 00:30
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
PuMa

Сообщений: 153
Откуда: Комсомольск-на-А
Дата регистрации: 19.04.2006
Проще всего, наверное, поместить процесс заполнения в TRY и в его секции CATCH выдать пользователю сообщение об ошибке и корректно закрыть Excel
m.loExcel.DisplayAlerts = .f.
m.loExcel.Quit()
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
Sandwich
Никак не могу убить этот процесс по HWND

Можно прибивать по имени процесса через скрипты, обычно без проблем.
Типа так:
cNameProcess = "excel.exe"
WshShell = CreateObject("WScript.Shell")
WshShell.Run("taskkill /IM " + cNameProcess, 0)
В офисных процессах еще, сколько помню, иногда вроде висело имя самого документа. Ну это глянуть просто надо, что там висит при его открытии.


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
ssa

Сообщений: 13007
Откуда: Москва
Дата регистрации: 23.03.2005
Sandwich
Программно создаю (точнее заполняю готовую форму файла Excel) товарную накладную.
Методика: в папке с формами хранится Excel шаблон, программа копирует его в tmp-папку с tmp-именем, открывает эту копию и заполняет.
То есть "стандартный" закат солнца вручную. Хотя есть не менее стандартные и давно встроенные в сами офисные пакеты методы работы с шаблонами. Но подавляющее большинство народу таки предпочитает сколхозить что-нить свое.
К тому же уже есть и способы создания Excel файлов без использования Excel.


------------------
Лень - это неосознанная мудрость.
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
ssa
К тому же уже есть и способы создания Excel файлов без использования Excel.
Просто программа рождена еще в самом начале этого века. Ну очень не хочется переделывать.
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
Равиль

Сообщений: 6549
Откуда: Уфа
Дата регистрации: 01.08.2003
Заброшенные при сбоях Excel-процессы - явление довольно частое, но тут не понятно почему возникает ошибка, если шаблон копируется с уникальным именем :
Sandwich
... Excel-процесс с tmp-именем остаётся "висеть" невидимым и при следующей попытке копирования шаблона в tmp-папку с tmp-именем возникает ошибка. Программа выводит соответствующее сообщение ...

Может кусочек кода этого копирования и открытия покажете ?


------------------
Тяжело согнать курсором муху с монитора ...
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
Равиль
Заброшенные при сбоях Excel-процессы - явление довольно частое, но тут не понятно почему возникает ошибка, если шаблон копируется с уникальным именем :
Sandwich
... Excel-процесс с tmp-именем остаётся "висеть" невидимым и при следующей попытке копирования шаблона в tmp-папку с tmp-именем возникает ошибка. Программа выводит соответствующее сообщение ...

Может кусочек кода этого копирования и открытия покажете ?
Имя файла не уникально, оно содержит номер документа
file_name = 'счет_'+alltrim(str(doc.nomer))+'.xlsx'
newfile='Общая папка\Документы\Счета\'+file_name
ON ERROR copy_error=.t.
copy file &form_dir\&form_file to (newfile)
ON ERROR
IF copy_error
* здесь надо убить процесс и скопировать снова
ENDIF
LOCAL loExcel as Excel.Application
loExcel=CREATEOBJECT('Excel.Application')
LOCAL loBook as Excel.Workbook
loBook = m.loExcel.workbooks.open(newfile)
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
Равиль

Сообщений: 6549
Откуда: Уфа
Дата регистрации: 01.08.2003
Sandwich
...
Имя файла не уникально, оно содержит номер документа
[code]
file_name = 'счет_'+alltrim(str(doc.nomer))+'.xlsx'
newfile='Общая папка\Документы\Счета\'+file_name
...

Так и думал, это приведет ко многим проблемам, например если 2 пользователя захотят одновременно создать один и тот же документ ?
Добавьте хотя бы sys(2015) к имени файла и не придется ловить процессы и убивать
file_name = 'счет_'+alltrim(str(doc.nomer))+sys(2015)+'.xlsx'
Или работайте с файлом во временной папке и уже потом сохраняйте его в общую.


------------------
Тяжело согнать курсором муху с монитора ...
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
AleksM

Сообщений: 17881
Дата регистрации: 11.11.2003
Работать нужно через шаблоны, в полном понимании этого слова в парадигме офиса.
Обсуждение по данному поводу можно найти через поиск.


------------------
Лучше переесть, чем недоспать.
Не спеши, а то успеешь.
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
Друзья, я в первом посте написал
Sandwich
Естественно методика не выдерживает критики
Ваши замечания, безусловно, по делу.
Но ведь вопрос стоит более широко: я не умею убивать процессы (и не важно Excel или нет, формы, парадигмы, юзеры, разделения полномочий и пр.)

Crispy
cNameProcess = "excel.exe"
WshShell = CreateObject("WScript.Shell")
WshShell.Run("taskkill /IM " + cNameProcess, 0)
убивает все Открытые Excel окна, а скрытый процесс продолжает висеть
Пока ковыряю в эту сторону.
Если ставлю
cNameProcess = "имя_окна_полученное_по_его_хэндлу"
тоже без результата
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
ssa

Сообщений: 13007
Откуда: Москва
Дата регистрации: 23.03.2005
Sandwich
Но ведь вопрос стоит более широко: я не умею убивать процессы (и не важно Excel или нет, формы, парадигмы, юзеры, разделения полномочий и пр.)
Это не умеют делать подавляющее большинство программистов. Ибо нефиг. Это лечение последствий, а не причин.
Sandwich
Просто программа рождена еще в самом начале этого века. Ну очень не хочется переделывать.
Но именно переделыванием кое-кто таки сейчас и занимается. К тому же, рекомендуемая переделка не такая уж и большая и сложная.

------------------
Лень - это неосознанная мудрость.
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
Владимир Максимов

Сообщений: 14097
Откуда: Москва
Дата регистрации: 02.09.2000
Бороться надо не с последствиями, а с причиной

У Вас произошел сбой при выполнении некой операции в FoxPro. Для перехвата таких ситуаций есть конструкция TRY...CATCH


loExcel = createobject("excel.application")
TRY
* Операция с Excel, которая может завершиться ошибкой
CATCH
* Если попали сюда, то произошла ошибка
* Штатное закрытие экземпляра Excel
loExcel.DisplayAlerts = .F.
loExcel.saved = .T.
loExcel.Workbooks.Close()
loExcel.quit()
ENDTRY
Ratings: 0 negative/1 positive
Re: Убить насмерть Excel процесс
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
Sandwich
убивает все Открытые Excel окна, а скрытый процесс продолжает висеть

Ну я же писал выше про "имя документа". Помнится убивался процесс именно по имени файла, который сам же и создаешь программно. Т.е. не надо было выковыривать откуда-то имя процесса - просто этой же переменной, что и при создании документа воспользоваться. И все прибивалось.

В принципе же - приведенные здесь советы по переделке программы все же более корректны могли бы оказаться.


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
of63

Сообщений: 25244
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
Вот тут пишут как получить PID потока, и как его убить, на примере Excel
stackoverflow.com

везде пишут
axforum.info



Исправлено 1 раз(а). Последнее : of63, 17.09.21 16:23
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
Всем большое спасибо за ответы.
Crispy
приведенные здесь советы по переделке программы все же более корректны могли бы оказаться.
Не подумайте, что я уперся и не слушаю:
я сделал и то, и это:
1. Разобрался и сделал функцию, которая при необходимости может убить любой процесс (видимый или не видимый)
2. Переделал функционал, используя TRY...CATCH
Еще раз спасибо
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Убивать процесс нехорошо уже хотя бы потому что потом, при очередном старте экселя он может предложить "восстановить файл после сбоя".

"Развести" генерируемые файлы с одним и тем же именем можно, создавая их в разных подпапках %TEMP% - имена подпапок уже сделать не одинаковыми (случайными, или последовательными типа 1,2,3...)

Если вдруг штатного функционала перехвата и обработки ошибок (try ... catch, on error ...) окажется недостаточно (это возможно, если ошибка будет связана с крахом фоксового процесса - а эксель будет вполне себе продолжать работать), то можно попытаться "подключиться" к уже запущенному эксель-процессу, используя GETOBJECT(,"Excel.Application") и как-то "разрулить" ситуацию - например найти и закрыть недоформированный документ. Главное держать в уме, что таким образом можно запросто вломиться в интерактивный экселевский процесс запущенный самим пользователем (а что-то делать с его документами не есть хорошо).

Как общая рекомендация к програмной работе с экселем - формировать документ (заполнять шаблон) стоит в отдельной, независимой копии экселя (созданной по CreateObject("Excel.Application") и по возможности максимально "изолированной" от взаимодействия с пользователем - подавить все предупреждения, заблокировать "внешние запросы", НЕ делать окно видимым). По завершению формирования документа сохранить его в нужное место под нужным именем и завершить рабочий экселевский процесс. Затем "открыть" на просмотр готовый документ при помощи ShellExecute() или иным способом - уже в "обычной" копии экселя, возможно запущенной ранее самим пользователем - без контроля над тем что там будет пользователь с этим документом делать (это тоже не всегда возможно, но если нет требований "следить" за юзером и тем что он с документом делает, то будет норм).


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
Sandwich
Автор

Сообщений: 137
Дата регистрации: 08.02.2014
Igor Korolyov
Убивать процесс нехорошо уже хотя бы потому что потом, при очередном старте экселя он может предложить "восстановить файл после сбоя".
Он и предлагает, доработаю.
Igor Korolyov
По завершению формирования документа сохранить его в нужное место под нужным именем и завершить рабочий экселевский процесс.
А если в нужном месте с нужным именем есть и открыт предыдущий файл, да еще и в процессе корректировки данных? тут уже без юзера не обойтись.
Пишу и сам думаю: а я ведь до начала формирования проверяю такое событие и активирую такое окно.
Спасибо за советы
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
andrewk

Сообщений: 174
Откуда: Красноярск
Дата регистрации: 15.05.2005
PuMa
Проще всего, наверное, поместить процесс заполнения в TRY и в его секции CATCH выдать пользователю сообщение об ошибке и корректно закрыть Excel
Проблема может быть не только в программной ошибке. Например, если офис палёный, то через несколько секунд (не сразу) после запуска экселя он выводит окно насчёт активации, которое полностью блокирует его работу. Но, поскольку в нашем случае loExcel.Visible=.F., то и это окно не видно. А у нас, насколько помню, через некоторое время вылетает что-то мутное типа "ole не отвечает".


Igor Korolyov
формировать документ (заполнять шаблон) стоит в отдельной, независимой копии экселя (созданной по CreateObject("Excel.Application") и по возможности максимально "изолированной" от взаимодействия с пользователем
Владимир Максимов
loExcel.Workbooks.Close()
loExcel.quit()
В более свежих версиях, насколько помню, ситуация изменилась. Но в Excel-2007 (только что проверил под WinXP) получается вот что:
Если процесс заполнения относительно долгий, и за это время юзер успел открыть какой-то «свой» Excel, то в диспетчере задач новый процесс не появляется. Более того, наш невидимый эксель становится видимым, и человек может чего-то делать – и в своём, и в нашем. Заблокировать его телодвижения можно с помощью loExcel.Interactive=.F.. Или даже loExcel.ScreenUpdating=.F., но так юзер совсем напугается. Если же не блокировать, то, возможно, юзер чего-то нарисовал, а по командам Close+Quit «его» эксель тоже молча закроется, без сохранения.

Думаю, лучше как-то так:
loExcel.DisplayAlerts = .F. && чтоб не просил сохранить
loBook.Close && закрываем нашу книгу
* Если храним не объекты-книги, а их имена, то примерно так:
* this.oExcel.Workbooks(this.aBooks[m.li]).Close
If loExcel.Workbooks.Count =0 && были открыты только наши книги
loExcel.Quit && гасим процесс
Else && возвращаем Excel в состояние интерактива
loExcel.DisplayAlerts = .T.
* остальное если меняли:
loExcel.ScreenUpdating = .T.
loExcel.Interactive = .T.
loExcel.UserControl = .T.
loExcel.Visible = .T.
EndIf


Владимир Максимов
loExcel.saved = .T.
Наверное, имелось ввиду loBook.Saved, но это, вроде, лишнее.
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
andrewk
В более свежих версиях, насколько помню, ситуация изменилась. Но в Excel-2007 (только что проверил под WinXP) получается вот что:
Если процесс заполнения относительно долгий, и за это время юзер успел открыть какой-то «свой» Excel, то в диспетчере задач новый процесс не появляется. Более того, наш невидимый эксель становится видимым, и человек может чего-то делать – и в своём, и в нашем.
Для борьбы с этим я в своё время сразу же после получения ссылки на объект экселя делал:
loXl = CREATEOBJECT("Excel.Application")
loXl.DisplayAlerts = .F.
loXl.IgnoreRemoteRequests = .T.
Ну про предупреждения понятно - в невидимой копии они не нужны - лучше чтобы ошибку до фокса добрасывало, нежели "подвисало" на диалоге который никто не сможет закрыть (увы, но насколько я помню подавляются не все диалоги).

А последняя строка как раз и отключает DDE в экселе, и винда не сможет при открытии excel файла в проводнике "достучаться" до нашей копии

Единственный косяк с этим подходом состоит в том, что эта настройка весьма "глобальная", и может вообще поломать открытие файлов в экселе, если её не сбросить обратно в .F. перед окончанием программной работы с экселем (т.е. вдвойне важно чтобы эксель не умирал, не зависал и корректно доходил до завершения - пусть и в блоке обработки ошибок - чтобы мы могли вернуть этот флажок в исходное положение).


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Убить насмерть Excel процесс
of63

Сообщений: 25244
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
> Единственный косяк с этим подходом состоит в том, что эта настройка весьма "глобальная", и может вообще поломать открытие файлов в экселе, если её не сбросить

Поэтому лучше его просто убить.
() Эксель и правда, висит в процессах долго, после штатного закрытия, вроде не вечно, но висит... что-то делает... и мешает морально! )
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 36 PaulWist  (Гостей: 35)

© 2000-2024 Fox Club 
Яндекс.Метрика