Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.04.04;
Скачать: [xml.tar.bz2];

Вниз

Коммандная строка и/или не запуск второй копии.   Найти похожие ветки 

 
Andy BitOff ©   (2004-03-14 19:54) [0]

Задача:
Прописываясь в реестре как;
r.RootKey:=HKEY_CLASSES_ROOT;
if R.OpenKey("\*\shell\Open ля-ля\command", True) then begin
 R.WriteString("",ParamStr(0)+" "%1"");
end;
Сделать так, чтобы при выборе каких-то файлов, нажатии на них RMB и выбора прописанного мной меню, открывалась моя программа с переданными в нее файлами.

Реализация:
Все сделано и работает, за исключение некоторых неясностей (см.Проблемы)

Проблемы:
Проблема вобщем-то одна, но большая. При выборе нескольких файлов винда не передает их списком в коммандной строке, а запускает по одной копии приложения для каждого выбранного файла, что недопустимо. В программе есть код, проверяющий запущено ли приложение, но почему-то не срабатывает именно в этом случае (выбора прописанного мной меню). Если прога работает и запустить еще одну все нормально, а вот при запуске двух копий ОДНОВРЕМЕННО, как это делает винда, запускаются обе. Но в принципе суть не столько в этом, сколько в том, чтобы получить список, именно список, выбранных файлов одной копией (читай первой) моей прораммы. Здесь есть еще маленькая тонкость, а именно: при получении файла или их списка программа его обрабатывает и начинает с ним(и) работать, добавить туда еще файлы, когда она с ними уже работает проблематично.

Вот собственно и все. Могу, если понадобится, привести любой кусок кода.

С уважением, Andy BitOff


 
Юрий Зотов ©   (2004-03-14 20:54) [1]

> Andy BitOff © (14.03.04 19:54)

Покажите, как Вы вытаскиваете список файлов из параметров.


 
Andy BitOff ©   (2004-03-14 21:19) [2]

procedure TMainForm.VerifyCommandLine;
var
 i:integer;
 a,b:int64;
 s:string;
begin
 a:=0;
 for i:=1 to ParamCount do begin
   s:=ParamStr(i);
   Case DirOrFile(s) of //определение каталог или файл
   1: begin  //dir
        SelectedFileList.Clear;
        SelectedFileList.Add(s);
        YesCommandLine:=CLDir;
        break;
      end;
   2: begin  //file
        if FileExists(s) then begin
          SelectedFileList.Add(s);
          b:=FileSizeByName(s);
          SelectedFileList.Add(IntToStr(b));
          YesCommandLine:=CLFile;
          a:=a+b;
        end;
      end;
   end;
 end;
 if YesCommandLine=CLFile then SelectedFileList.Add(IntToStr(a));
end;


Для работы программы создается StringList в формате:
путь файла и имя
размер файла

Но в общем, мне кажется, проблемя не здесь. При запуске программы из IDE с коммандной строкой вида "My.exe c:\f1.txt c:\f1.txt c:\f1.txt c:\f1.txt c:\f1.txt" все отрабатывается правильно. Как раз проблема в том, что если выбрать два файла и через меню запустить программу, то первая копия обработает первый файл, а вторая - второй.


 
Andy BitOff ©   (2004-03-14 21:25) [3]

Тьфу, прошу прощения за очепятку.
с коммандной строкой вида "My.exe c:\f1.txt c:\f2.txt c:\f3.txt c:\f4.txt c:\а5.txt" все отрабатывается правильно.


 
Andy BitOff ©   (2004-03-15 02:56) [4]

А вот если поместить ярлык программы в SendTo, создав тем самым ссылку на программу в том же меню по RMB, но в Отправить->Имя_Программы можно добиться желаемого эффекта.
Однако хочется понять почему винда не делает также в выше описанной ситуации.
----
Наверное топик плавно перетекает в ветку Система. Однако в любом случае хотелось бы получить от мастеров ответ. Потому, что вариант с ярлыком, хоть и работает, но это не то, что задумывалось.


 
kaif ©   (2004-03-15 03:29) [5]

Я не силен в таких вещах, как запрет на запуск второй копии. Поэтому я бы решил эту задачу очень примитивно: при запуске приложения где-нибудь до Application.CreateForm(TMyMainForm, "MyMainForm") я бы поискал с помощью функции API Windows FindWindow() окно с таким же имененм класса TMyMainForm и получил бы его Handle. Если такое окно найдено (экземпляр программы уже запущен), я бы передал параметры ParamStr(1), ParamStr(2)... (сколько есть, в цикле for) в виде сообщений главному окну приложения с помощью SendMessage или PostMessage и сразу завершил бы приложение (ненужный экземпляр) командой terminate или halt (точно не помню). Если само приложение слишком большое и грозит тормозом, я бы разбил его на два exe-файла (маленький - стартовый с командой FindWindow и SendMessage) и здоровый - основной, который запускается первым маленьким и получает имена файлов через систему сообщений Windows.
 В общем, предлагаю сначала профессионалам покритиковать этот подход. Если он не самый идиотский, то можно еще обсудить детали реализации.
 А вообще я думаю, что в Windows должен быть способ в Shell задать условие: новый экземляр работает или используется существующий... Говорят в Shell используется COM. А COM это умеет. Возможно нужно не приложение зарегистрировать, а интерфейс какой-нибудь (GUID). Но это так... В виде версии.


 
Andy BitOff ©   (2004-03-15 03:47) [6]

Про регистрацию интерфейса я думал, но решил сначала здесь спросить и в зависимости от результатов уже стал бы или нет заниматься реализацией этой идеии.
По поводу определения второй копии. Вы не внимательно читали мой вопрос =) Я там как раз написал, что это уже реализовано и прекрасно работает во всех случаях, кроме одного. Когда винда через меню запускает энное количество (в зависимости от количества выбранных файлов) экземпляров моей программы одновременно, описанный Вами и мной реализованный метод не срабатывает.


 
Юрий Зотов ©   (2004-03-15 06:47) [7]

Посмотрел команду Open у MS Word - она такая же, как у Вас. Похоже, с этой стороны все верно. Сейчас прочитал ветку еще раз и подумал вот что.

Если выполняются 2 условия:
а). Проводник запускает не одну копию со списком файлов, а по одной копии на каждый файл, предоставляя программе самой разбираться с этой ситуацией.
б). Вы отлавливаете запуск второй копии через FindWindow

Так вот, если выполняются эти 2 условия, то эффект запросто может быть именно такой, как Вы описываете. Когда в командной строке передан список файлов, то Проводник успевает запустить соответствующее количество копий ДО того, как первая из них создаст окно - поэтому FindWindow не срабатывает и дубликаты спокойно запускаются. А при ручном запуске (в том числе, и через SendTo) ранее запущенная копия копия успевает создать окно и все работает ОК.

Как бы то ни было, но посмотрите, как Ваша задача решена здесь:
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=904


 
Andy BitOff ©   (2004-03-15 18:32) [8]

Да, указанный Вами пример, действительно работает так, как надо, но при его использовании возникают две дополнительные проблемы.
При выборе большого количества файлов (10, 20, 30 и более) программа ужасно долго грузится. Но вообщем это не страшно, можно сплеш повесить и т.п. А вот вторая проблема посущественнее. И я с Вашей помощью или, возможно, с помощью других экспертов хотел бы попробовать решить ее. Значит все по порядку. Программа, как я упоминал раннее, при получении списка файлов начинает их обработку, от сюда и вытекает проблема. Надо бы определить, когда окончется поступление новых файлов и только после этого начать с ними работать. В указанном Вами примере мы получаем по файлу, каждый раз, когда приходит зарегистрированное нами сообщение от вторых копий, но как определить, что их больше не придет, ведь в этот момент первая копии уже работает и жаждит начать обработку файлов, а допустить этого нельзя (по разным причинам), к моменту начала обработки, список должен быть завершен и какие-либо изменения в нем не допустимы.
Получаем сообщение следующим способом (при каждом новом сообщении файл добавляется в список.);

procedure TMainForm.WndProc;
var
 Buf:array[Byte] of Char;
 a,b:Int64;
 c:integer;
begin
if Message.Msg=WM_SendCommandLineToFirstApplication then begin
  GlobalGetAtomName(Message.LParam,Buf,255);
  YesCommandLine:=DirOrFile(Buf);
  b:=0;
  Case YesCommandLine of
   CLDir: begin
            SelectedFileList.Clear;
            SelectedFileList.Add(Buf);
          end;
   CLFile: begin
            if FileExists(Buf) then begin
              val(SelectedFileList.Strings[SelectedFileList.Count-1],b,c);
              SelectedFileList.Delete(SelectedFileList.Count-1);
              SelectedFileList.Add(Buf);
              a:=FileSizeByName(Buf);
              SelectedFileList.Add(IntToStr(a));
              b:=b+a;
            end;
          end;
   end;
   if YesCommandLine=CLFile then SelectedFileList.Add(IntToStr(b));
 end
else
 inherited WndProc(Message)
end;


 
Andy BitOff ©   (2004-03-15 18:38) [9]

Глюк форума! Добавил сообщение, а топик не всплыл.


 
Юрий Зотов ©   (2004-03-15 19:03) [10]

Я думаю, прежде всего надо ТОЧНО выяснить, какую командную строку формирует Проводник. Выведите CmdLine при запуске с несколькими файлами, а там будет видно.


 
Andy BitOff ©   (2004-03-15 19:31) [11]

Только проверил. Для каждой запущенной копии формируется CmdLine вида;
MyProg.exe "первый_из_выбранных_файлов"
для следующей
MyProg.exe "второй_из_выбранных_файлов"
для следующей
MyProg.exe "третий_из_выбранных_файлов"
и т.д.


 
Юрий Зотов ©   (2004-03-15 19:44) [12]

Так вот ты какой, цветочек аленький...
Значит, предположение было верным.

Хм, а как же получить список файлов ДО их обработки... Тут думать надо, однако. По времени - не катит, это ясно, каждый файл может по полминуты открываться. Idle - вроде, тоже не из той оперы.

А что за обработка и почему ее надо вести непременно списком? Может быть, можно загнать обработку каждого файла в отдельный поток? Это, пожалуй, был бы выход.


 
Andy BitOff ©   (2004-03-15 19:55) [13]

Да, надо подумать.

Я переодически буду топик подымать, может кто еще чего надумает. Ведь как-то это делают, ну Рар например или WinHex.


 
Юрий Зотов ©   (2004-03-15 20:02) [14]

> Andy BitOff ©   (15.03.04 19:55) [13]

Кстати, а посмотрите, как зарегистрирована команда Open для Rar и WinHex. Может быть есть какие-то особенности и можно заставить Проводник работать по-человечески...

И еще - что все же за обработка. Почему обязательно списком?


 
Defunct ©   (2004-03-15 23:44) [15]

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

Есть смутная идея.. не знаю насколько она реализуема, но все же..

Допустим проводник формирует строки вида "MyProg.exe Имя_i-го_файла", пока он формирует эти строки, он в своем окне держит эти файлы выделенными, а после того как сформирует все командные строки - снимит выделение с файлов. Как считаете, может можно проверять (после поступления очередного файла в WndProc) состояние окна проводника, и когда не останется выделенных элементов начинать обработку списка файлов?

Надо полагать все данные у нас имеются:
- Handle вызывающего приложения.
- Момент передачи последнего файла.


 
Defunct ©   (2004-03-16 03:02) [16]

Defunct ©   (15.03.04 23:44) [15]
Насчет выделения и снятия выделения в проводнике, беру свои слова назад. А все остальное остается в силе. Должно быть хоть что-то, какое-то событие в проводнике, которое соответствует завершению запусков.


 
Andy BitOff ©   (2004-03-16 18:41) [17]

>Defunct © (15.03.04 23:44) [15]
>Должно быть хоть что-то, какое-то событие в проводнике, которое соответствует завершению запусков.

Вот я как раз и хотел бы это знать. Тогда и проблемы бы не было =)

В принципе это не обязательно проводник, может быть любой файл-менеджер поддерживающий стандартное (виндовое) меню по RMB на файлах.

>Юрий Зотов ©   (15.03.04 20:02) [14]
>И еще - что все же за обработка. Почему обязательно списком?

Да вообщем просто потому, что процедуры обработки уже написаны и занимают достаточно много места. Не особо хочется их ковырять, проще создать список с которым они работают и подсунуть им его.

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

И еще обнаружил маленькую тонкость. Через ярлык нельзя передать более 40 файлов. У меня XP, на 98 не пробовал.


 
Юрий Зотов ©   (2004-03-16 18:49) [18]

> Через ярлык нельзя передать более 40 файлов

Возможно, это просто ограничение длины командной строки. Но если файлов может быть так много, то не лучше ли, чтобы юзер сам сформировал их список в любом текстовом файле, а уже этот файл передал в параметре (единственном!). Тогда все вопросы снимаются.


 
Andy BitOff ©   (2004-03-16 19:07) [19]

Так все сделано =)
Пользователь выбирает каталог, а прога в нем работает, ищет что надо, перебирает, убирает дубликаты (вложенность настройкой, могут попаться одинаковые) и готовый список в обработку. Но как всегда хочется, что бы лучше и удобнее, вот и задумал... Не думал, что такие проблемы поплывут =(

Вобщем наверное оставлю ярлык (в SendTo) очень удобно оказалось, пользователи пищали от восторга, что можно так быстро отправить нужные файлы. Единственное, два недостатка (спорных=)) огранечение 40 файлов, но можно указать каталог уровнем вверх где сами файлы лежат, и второе, что по RMB надо еще в подменю "Отправить" заходить =))), лень им видиш ли =)).

А то что предлагал Юрий Зотов © (15.03.04 06:47) [7] и действительно работает (если не начинать обработку сразу, а подождать), пока закоментирую, могет потом разберусь.


 
alless ©   (2004-03-16 19:09) [20]

Избежать запуск второй копии можно еще проще (может быть):

в *.dpr файле
--------------------------------------------------------------------------------
   ActivatePrevInstance("TForm1","Значение Caption ")


 
Andy BitOff ©   (2004-03-16 20:02) [21]

>alless ©   (16.03.04 19:09) [20]

Спасибо =)



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2004.04.04;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.033 c
14-1079013272
Denrom
2004-03-11 16:54
2004.04.04
ИК волны (область применения)


1-1079210877
AlexT
2004-03-13 23:47
2004.04.04
Stream read error


1-1079228001
Demik
2004-03-14 04:33
2004.04.04
-= MainMenu - в нем BitMap -=-


9-1063898465
greenrul
2003-09-18 19:21
2004.04.04
Смена дня и ночи в 2D изометрии


14-1077786871
Voland2000
2004-02-26 12:14
2004.04.04
Что круче?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский