Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.217.144.32] |
|
Сообщ.
#1
,
|
|
|
Добрый день!
Возникла разовая задача: нужна программа, без интерфейса, с функцией ShellExecute внутри. Получает в командной строке параметр и выполняет его ShellExecute'ом. Всё Я на VBA пишу, там exe файлов нет Надо писать на чём-то, что в конечном результате даст исполняемый файл. Первый раздел на форуме это С++ и по нему есть много инфы, можно быстро нагуглить вопрос. Поэтому решил делать на нём. Вот что получилось: #include <iostream> #include <cstdlib> #include <ShellAPI.h> int main(int argc, char *argv[]) { if (argc == 1) { ShellExecute(0, NULL, argv[1], NULL, NULL, SW_SHOWNORMAL); } exit(1); } Это мой первый С++ код за последние лет так 15 Предполагаю, что он содержит ошибки. У меня не установлена среда разработки, код написан в редакторе сообщений форума. Конечно можно скачать и установить, но задача разовая, пока не вижу смысла. В итоге один вопрос и одна просьба: Есть ошибки в коде? Если нет, сделайте, пожалуйста, exe файл! |
Сообщ.
#2
,
|
|
|
Ты не указал, под какую систему тебе нужен бинарник. 64-битный не запустится под 32-битной ОСью. |
Сообщ.
#3
,
|
|
|
Qraizer большое спасибо!
64bit поправил, по списку замечаний: #include <iostream> #include <windows.h> #include <ShellAPI.h> int main(int argc, char *argv[]) { if (argc == 2) { ShellExecute(0, NULL, argv[1], NULL, NULL, SW_SHOWNORMAL); } } З.Ы. Вот это не совсем понял: argv[0] - имя собственно самой запущенной программы argv[1] - переданный параметр откуда 2 ? |
Сообщ.
#4
,
|
|
|
Цитата SV() @ Длина массива argv[], два элемента.argv[0] - имя собственно самой запущенной программы argv[1] - переданный параметр откуда 2 ? Прикреплённый файлshellExec.zip (44,72 Кбайт, скачиваний: 174) Собрал VS2017. На всякий случай со статическими либами, бо не факт, что .dll-ки у тебя инсталлированы. Добавлено P.S. Если твой argv[1] нужно запускать с параметрами, что имеет смысл, то программка слишком проста. Нужно доработать на сбор последующих argv[] в строку и передавать вместе с argv[1] в начале. |
Сообщ.
#5
,
|
|
|
Есть пара непредвиденных проблем:
1. Вместо SW_SHOWNORMAL видимо надо SW_RESTORE. (если argv[1] это "С:\text.docx" и Word уже запущен, то в текущей конфигурации text.docx откроется, тут всё ок, но Word при этом не становится активным окном - это уже не ок) 2. При запуске на долю секунды на экране появляется чёрное окно. Погуглил - кто-то пишет что надо добавить ShowWindow(NULL,HIDE_WINDOW); другое мнение - настроить компилятор, чтобы окна вообще не было: Цитата Чтобы консольное окно скрыть, не надо его вообще создавать, для компилятора g++ опция -mwindows Тут я научил людей как сие делать:MessageBox Читай с сообщения номер 11, можешь также использовать FreeConsole, если поможет. можно как-то убрать окно? Цитата Qraizer @ Да, так конечно будет правильней. Но этот функционал 99,9999% не будет востребован.P.S. Если твой argv[1] нужно запускать с параметрами, что имеет смысл, то программка слишком проста. Нужно доработать на сбор последующих argv[] в строку и передавать вместе с argv[1] в начале. З.Ы. Не думал, что вылезет столько нюансов. Чую всё таки придётся ставить студию. Что качать? |
Сообщ.
#6
,
|
|
|
Цитата SV() @ можно как-то убрать окно? Надо создать приложение не как консольное, а как GUI. Но при этом окна не создавать. Т.е. вместо int main(int argc, char *argv[]) { // ... } Надо делать: int WINAPI _tWinMain (HINSTANCE hThisInst,HINSTANCE hPrevInst,TCHAR* lpszArgs,int nWinMode) { // ... } Кроме того, вариант if (argc == 2) { ShellExecute(0, NULL, argv[1], NULL, NULL, SW_SHOWNORMAL); } Не удачен. Лучше приблизительно так: if (argc > 1) { TCHAR* pCommandStr = ::GetCommandString(); ShellExecute(0, NULL, pCommandStr, NULL, NULL, SW_SHOWNORMAL); } |
Сообщ.
#7
,
|
|
|
SV(), я и не сомневался, что не всё учтено. 2-3 итерации – это норма. Пересоберу, не вопрос.
"Окончательное" ТЗ подытожишь? |
Сообщ.
#8
,
|
|
|
Ничего не поменялось, всё как в моем предыдущем сообщении:
- если argv[1] это "С:\text.docx" и Word уже запущен, то в результате Word с открытым "С:\text.docx" должен стать активным окном. Предполагаю, что для этого надо заменить SW_SHOWNORMAL на SW_RESTORE. - сама программа должна быть невидимкой. Её окно не должно мелькать на экране. ЫукпШ предлагал варианты, я добавил их в код, но это уже выше моего уровня, совсем не уверен в том, что получилось. Собрал все правки вот так: #include <iostream> #include <windows.h> #include <ShellAPI.h> #include <TCHAR.H> int WINAPI _tWinMain (HINSTANCE hThisInst,HINSTANCE hPrevInst,TCHAR* lpszArgs,int nWinMode) { TCHAR* pCommandStr = ::GetCommandString(); ShellExecute(0, NULL, pCommandStr, NULL, NULL, SW_RESTORE); } Qraizer, очень извиняюсь, я уже чувствую, что перехожу рамки, и это превращается в работу... |
Сообщ.
#9
,
|
|
|
Цитата SV() @ ЫукпШ предлагал варианты, я добавил их в код, но это уже выше моего уровня, совсем не уверен в том, что получилось. Увы. Виноват, ошибся. 1. Не "GetCommandString", а "GetCommandLine". 2. Так TCHAR* pCommandStr = ::GetCommandString(); ShellExecute(0, NULL, pCommandStr, NULL, NULL, SW_RESTORE); Работать не будет. Придётся разбирать командную строку. Либо самому, либо используя "CommandLineToArgvW" Тут есть пример. |
Сообщ.
#10
,
|
|
|
Вообще-то GetCommandString() возвращает всю строку, включая имя программы. Т.е. туда будут входить все argv[], начиная с нулевого. Коли мы делам ГУЙный стартер, тогда уж лучше брать третий параметр WinMain(): который lpszArgs. Ну и iostream тебе не нужен, в консоль ничего не выдаётся. Он и раньше не был нужен, но у меня был вопрос, который я хотел задать, на предмет обработки ошибок: нормально ли, что при ошибках ничего никому никуда не выдаётся?
Вот текст: #include <windows.h> #include <ShellAPI.h> #include <TCHAR.H> int WINAPI _tWinMain (HINSTANCE hThisInst,HINSTANCE hPrevInst,TCHAR* lpszArgs,int nWinMode) { ShellExecute(0, NULL, lpszArgs, NULL, NULL, SW_RESTORE); } Прикреплённый файлshellExec.zip (40,25 Кбайт, скачиваний: 168) Если есть желание, можно вообще избавиться от стартового кода, но тогда придётся всё-таки GetCommandString() и отрезать от него первый параметр руками. Зато .exeшичек будет совсем маленький. |
Сообщ.
#11
,
|
|
|
Цитата Qraizer @ да нормально ли, что при ошибках ничего никому никуда не выдаётся? Тут всё так просто, что если ничего не произошло - без всяких сообщений понятно, что накосячил с параметрами в командной строке. Размер exe-шника честно говоря не важен. 84kb в современном мире это фактически ноль. Если будет работать быстрее - есть смысл. Но на первый взгляд она и так шустрая. Протестил - всё работает как надо: окно не мелькает, выполняется без задержки. Проблема Цитата SV() @ не решена.если argv[1] это "С:\text.docx" и Word уже запущен, то в результате Word с открытым "С:\text.docx" должен стать активным окном. Но эти все SW_SHOWNORMAL, SW_RESTORE и т.д. никогда на моей памяти вменяемо не работали. Я наколхозил так: создал ярлык и передаю его проге. Т.е. argv[1] это "С:\text.docx — ярлык.lnk" Сейчас внедрю прогу, создам все ярлычки, посмотрим, как себя покажет в реальной работе. |
Сообщ.
#12
,
|
|
|
У меня консольная утилитка, юзаю это, как ведет за пределами консоли не скажу:
https://docs.microsoft.com/ru-ru/cpp/c-runt...ue&view=vs-2019 |
Сообщ.
#13
,
|
|
|
Добрый день!
Сменил работу и эта программа снова понадобилась. Но наряду с 64 bit версией, нужна и 32 (несколько машин, с разными windows) Возможно собрать ещё 32 bit версию? З.Ы. Теперь windows 7, не 10. В нём вылезла старая проблема: на секунду появляется чёрное окно. Но это просто к слову, вдруг есть идеи. |
Сообщ.
#14
,
|
|
|
Та нам не жалко, на здоровье:
Прикреплённый файлshellExec.zip (42,93 Кбайт, скачиваний: 41) Скомпилено VS2022. Под Win7 работать должно, под XP почти наверняка не будет. Цитата SV() @ Не должно. Скорее, что пытается запуститься процесс, который не корректно распознан Shell-ом или его обработчик сам по себе консольный. З.Ы. Теперь windows 7, не 10. В нём вылезла старая проблема: на секунду появляется чёрное окно. Но это просто к слову, вдруг есть идеи. |
Сообщ.
#15
,
|
|
|
Спасибо!
Отлично работает! Цитата Qraizer @ Скорее, что пытается запуститься процесс, который не корректно распознан Shell-ом или его обработчик сам по себе консольный. Думаю это всё-таки какая-то проблема с 64bit: Сделал все ярлычки на 32bit машине - работает без окошка. Перенёс на машину 64bit - мало того, что работает, так ещё и без окошка)) В общем просто с самого начала не стоило связываться с 64. 32bit версия работает везде, да ещё и артефакта в виде окошка нет |