Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > БД в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 28.10.2010, 09:17   #11
Karabash
Форумчанин
 
Регистрация: 26.07.2009
Сообщений: 216
По умолчанию

Попробую объяснить все позиции по своему разумению, естественно (кроме "попробовала кинуть в другое место, копия получилась" - кто знает что на самом деле происходит в отдельно взятом компе).
Может кому в будущем пригодится.

Если обрамлять путь+имя файла двойными кавычками (на что указал Stilet, и что правильно делает Liones), то неважно на каком языке написан путь к файлам. Испытано сотни раз.

Ошибку 126 - можно не считать ошибкой (забавно?). Дело в том, что ShellExecute возвращает при успешном выполнении handl экземпляра запущенного приложения (не окна). При этом функция RaiseLastWin32Error вернет последнюю ошибку, которая произошла раньше (может в этом, а может быть и в другом месте приложения) и значение handl не совпадает со значением ошибки.
Исчерпывающий список ошибок для ShellExecute приведен в справке к этой функции и только эти значения можно считать ошибками. Т.е. функция RaiseLastWin32Error в нашем случае для постоянного применения не годиться.

В сухом остатке применение функции ShellExecute для запуска консольных приложений.
Код:
ShellExecute(0, //актуально для оконных приложений, здесь может быть и ноль
      nil, //так как запускается exe'шник, то nil
      PChar(comstr), PChar(parstr), //здесь все понятно (двойные кавычки)
      nil,  //каталог по умолчанию указывать не требуется
      SW_SHOWNORMAL  //все равно что указывать кроме значения, которое показано ниже
      {SW_HIDE} //консольное окно не показывается и непонятно когда закончится выполнение команды, 
      //впрочем, это и неважно, т.к. после запуска функции управление 
      //тут же передается обратно в процедуру и дальше приложение  
      //выполняется параллельно с консольным
);
Karabash вне форума Ответить с цитированием
Старый 01.11.2010, 13:12   #12
Liones
Пользователь
 
Аватар для Liones
 
Регистрация: 26.11.2008
Сообщений: 81
По умолчанию

В общем, по результатам "народного тыка" получаем сухой остаток:
1. в коде все правильно
Код:
comstr := '"'+utilitpath+ 'gbak.exe"';
parstr := '-user SYSDBA -pas masterkey -b  "'+datpath+'BD.gdb" "'+datpath+'BD.gbk" -v -y "'+datpath+'cop'+DateToStr(Date)+'.txt"';
ShellExecute(Application.Handle, nil, PChar(comstr), PChar(parstr),PChar(ExtractFilePath(utilitpath)), SW_SHOWNORMAL);
в мануале написано, что ключ -y позволяет вывести процесс в файл, что я и сделала (-y "'+datpath+'cop'+DateToStr(Date)+'. txt")
Вот его содержание:
gbak: ERROR:I/O error for file "D:\PRIL\DATA\BD.GDB"
gbak: ERROR: Error while trying to open file
gbak: ERROR: Процесс не может получить доступ к файлу, так как этот файл занят другим процессом.
gbak:Exiting before completion due to errors

В коде пыталась написать так:
Код:
DM.IBDatabase1.Connected:=False;
ShellExecute(Application.Handle, nil, PChar(comstr), PChar(parstr),PChar(ExtractFilePath(utilitpath)), SW_SHOWNORMAL);
DM.IBDatabase1.Connected:=True;
В результате вывод: копию можно сделать только когда приложение не запущено.

Может кто знает как это обойти?
Liones вне форума Ответить с цитированием
Старый 01.11.2010, 13:48   #13
Karabash
Форумчанин
 
Регистрация: 26.07.2009
Сообщений: 216
По умолчанию

Цитата:
Сообщение от Liones Посмотреть сообщение
В коде пыталась написать так:
Код:
DM.IBDatabase1.Connected:=False;
ShellExecute(Application.Handle, nil, PChar(comstr), PChar(parstr),PChar(ExtractFilePath(utilitpath)), SW_SHOWNORMAL);
DM.IBDatabase1.Connected:=True;
В результате вывод: копию можно сделать только когда приложение не запущено.
Может кто знает как это обойти?
А что попытка не увенчалась успехом (Connected:=False > Connected:=True)?

Обойти создание резервной копии, когда к базе есть коннект нельзя.
Это общее место, о котором талдычут везде, где есть упоминание об IB и FB.
"Если хотите иметь 100% испорченную копию, то пожалуйста, копируйте на здоровье когда к базе подключен клиент (клиенты)".
А gbak этого вообще не позволяет.
Можно, конечно, сделать shutdown базе перед резервным копированием, но в этом случае надо понимать что делаешь. Если без этого никак (что очень сомнительно), ищите по этому слову материал на ibase.ru.
Karabash вне форума Ответить с цитированием
Старый 01.11.2010, 14:18   #14
Liones
Пользователь
 
Аватар для Liones
 
Регистрация: 26.11.2008
Сообщений: 81
По умолчанию

Цитата:
Сообщение от Karabash Посмотреть сообщение
А что попытка не увенчалась успехом (Connected:=False > Connected:=True)?
В том то и дело, что нет.

Цитата:
Сообщение от Karabash Посмотреть сообщение
Обойти создание резервной копии, когда к базе есть коннект нельзя.
Это общее место, о котором талдычут везде, где есть упоминание об IB и FB.
а в "Firebird Руководство разработчика баз данных" Х.Борри сказано, что можно делать "горячую копию"

Я тут еще одну фишку заметила. Если в папке уже существует копия, то новая не создается. Т.е. получается надо удалить предыдущую, потом уже делать новую. А как ее удалить?
Liones вне форума Ответить с цитированием
Старый 01.11.2010, 14:52   #15
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Если в папке уже существует копия, то новая не создается.
ИМХО не создается потому что старая обновляется дифферентными данными. Проверь размер выходного файла. MS SQL по крайней
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 01.11.2010, 15:01   #16
Karabash
Форумчанин
 
Регистрация: 26.07.2009
Сообщений: 216
По умолчанию

Если "в том то и дело, что нет", то скорее всего, из-за того что соединение на самом деле не сброшено (компоненты IBX грешат этим) или, может быть, не были завершены транзакции. В первом случае сложно сказать что делать (может быть попробовать в цикле отсоединяться). Во втором, перед Connected:=False проверить активность транзакций всех Dataset и завершить их (Commit). Хотя тоже "по воде вилами..."

Если Х.Борри "сказал", то почему бы не сделать как им сказано?

Новая копия не создается из-за особенностей gbak (не позволяет перезаписывать).
Самое простое - это создать bat-файл, в котором есть две команды: удаление копии и создание новой (с помощью gbak), а из приложения запускать этот bat-файл.

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

Нет, Stilet, gbak не умеет делать инкрементное добавление. Здесь причина прозаична (как выше сказано).
Karabash вне форума Ответить с цитированием
Старый 03.11.2010, 12:30   #17
Liones
Пользователь
 
Аватар для Liones
 
Регистрация: 26.11.2008
Сообщений: 81
По умолчанию

Цитата:
Сообщение от Karabash Посмотреть сообщение
А вообще то, резервные копии добрые люди делают не из основного приложения, а, уделяя этому особое внимание, применяют несколько иные способы.
Т.е. предлагаете написать утилиту для резервного копирования?
Только вот загвоздка: рядовому юзеру в принципе пофиг есть резервная копия базы или нет, поэтому я хотела сделать бэкап автоматом

у меня тут еще одна мысль появилась: написать батник (удаление старого архива, архивация, запуск приложения), закрыть приложение, запустить батник, запустить приложение.
Код:
AssignFile(f, workdir+'bakup.bat');
ReWrite(f);
comstr := '"'+utilitpath+ 'gbak.exe"';
parstr := '-b "'+datpath+'BD.gdb" "'+arhivpath+'BD.gbk" -v';
//WriteLn(f, 'DEL /F /Q "'+arhivpath+'BD.gbk"');
WriteLn(f, comstr+' '+parstr);
WriteLn(f, workdir+'\pril.exe');
WriteLn(f, 'exit');
CloseFile(f);
Glav.Close;
Application.Destroy;
ShellExecute(Application.Handle, nil,PChar(workdir+'bakup.bat'), nil,nil, SW_SHOWNORMAL);
WinExec(PChar(workdir+'pril.exe'), SW_SHOW);
Application.Terminate;
Только теперь другие фишки:
1. файл не удаляется, ругается на команду del
2. после команды Application.Destroy; выдается сообщение "Runtime error 216 at 0040399 E" и приложение не запускается

Последний раз редактировалось Stilet; 03.11.2010 в 13:13.
Liones вне форума Ответить с цитированием
Старый 03.11.2010, 13:17   #18
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
файл не удаляется, ругается на команду del
Если мне не изменяет Память (а она у меня блондинка хорошая) то BATник тебе не помошник, наоборот даже опасен, и вот почему. Дело в том что запустив в батнике командой gbak.exe, интерпретатор не будет ждать пока она завершит свое действо, а сразу перейдет к следующей команды. Получается ерунда - запускашь gbak.exe и сразу же пытаешся удалить файл, в который он пишет.

В принициппе по-моему есть опция WAIT, которая заставляет ждать консоль пока эта команда (с этой опцией) отработает полностью и только тогда интерпретатор возьмется за выполнение другой команды.
попробуй ее прикрутить может поможет.
http://www.nevor.ru/comp/bat_files2.php
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 09.11.2010, 12:42   #19
Liones
Пользователь
 
Аватар для Liones
 
Регистрация: 26.11.2008
Сообщений: 81
По умолчанию

В общем я пришла к выводу, что самое простое пойти по пути разработчиков 1С. Написать отдельный модуль с набором административных действий, включить туда архивацию, лечение, восстановление БД и т.п.
Liones вне форума Ответить с цитированием
Старый 09.11.2010, 13:15   #20
Karabash
Форумчанин
 
Регистрация: 26.07.2009
Сообщений: 216
По умолчанию

Liones, очень правильное решение. Только это не "путь разработчиков" 1С, а путь реально мыслящих разработчиков баз данных, о котором в литературе упоминание (если память не изменяет) было еще лет 40 назад.
"Если вы хотите сберечь свои и пользователей нервы, не давайте пользователям заниматься администрированием баз данных, а тем более из клиентских приложений". Что-то в этом роде.

Stilet, подзабыли, наверное. Консольные приложения, которые вызываются в bat-файлах не отдают управление сразу же в батник до тех пор пока не закончат свою работу. Скоро 7 лет как использую этот прием для резервирования файлов БД, размеры которых от 50 до 1800 Мб (на объемных файлах задумчивости gbak позавидуют и аксакалы). Работают батники и работают - "все простенько и со вкусом".
Пример одного из таких файлов (может кому сгодится):
Код:
rem сперва обязательно делаем резервную копию.
copy "E:\_E_\Bases\MP.gdb" "E:\_E_\Bases\archive\MP.gdb"

rem резервирование базы (backup) Необходимо удалять лог-файлы, 
rem иначе gbak откажется работать обнаружив файл, в который ему необходимо писать протокол 
del MP.bkp
gbak -b -v -t -user SYSDBA -pas masterkey -y MP.bkp "localhost:E:\_E_\Bases\MP.gdb" "E:\_E_\Bases\MP.gbk"

rem восстановление (restore). 
del MP.rst
gbak -c -o -r -p 4096 -v -user SYSDBA -pas masterkey -y MP.rst "E:\_E_\Bases\MP.gbk" "localhost:E:\_E_\Bases\MP.gdb"
Karabash вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Delphi и командная строка nusik Общие вопросы Delphi 5 26.10.2010 11:10
Командная строка Morphling Помощь студентам 9 01.02.2010 00:27
Командная строка Vladya Помощь студентам 4 09.02.2009 18:29
Командная строка Dj_smart Свободное общение 2 23.08.2008 20:12
командная строка Mails Помощь студентам 2 12.05.2008 18:29