На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
  
> Маленькая программка с ShellExecute из командной строки , Посмотреть ошибки и скомпилировать
    Добрый день!

    Возникла разовая задача: нужна программа, без интерфейса, с функцией ShellExecute внутри.
    Получает в командной строке параметр и выполняет его ShellExecute'ом. Всё 8-)

    Я на VBA пишу, там exe файлов нет :)
    Надо писать на чём-то, что в конечном результате даст исполняемый файл.
    Первый раздел на форуме это С++ и по нему есть много инфы, можно быстро нагуглить вопрос. Поэтому решил делать на нём.
    Вот что получилось:
    ExpandedWrap disabled
      #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 :blush:
    Предполагаю, что он содержит ошибки.
    У меня не установлена среда разработки, код написан в редакторе сообщений форума.
    Конечно можно скачать и установить, но задача разовая, пока не вижу смысла.

    В итоге один вопрос и одна просьба:
    Есть ошибки в коде?
    Если нет, сделайте, пожалуйста, exe файл! :rolleyes:
      • К ShellAPI.h всё равно нужен windows.h.
      • argc указывает количество строк в argv, поэтому сравнивать надо с 2, если ожидаешь там параметры; в argv[0] лежит имя собственно самой запущенной программы.
      exit() там не нужен, достаточно return, т.к. это конец main(). Нормальное завершение программы "по соглашению сторон" означает 0 как результат, а не 1. При этом return 0; писать в конце main() не обязательно, по дефолту именно это и предполагается.
      Ты не указал, под какую систему тебе нужен бинарник. 64-битный не запустится под 32-битной ОСью.
        Qraizer большое спасибо!

        64bit

        поправил, по списку замечаний:
        ExpandedWrap disabled
          #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 ?
          Цитата SV() @
          argv[0] - имя собственно самой запущенной программы
          argv[1] - переданный параметр
          откуда 2 ?
          Длина массива argv[], два элемента.
          Прикреплённый файлПрикреплённый файлshellExec.zip (44,72 Кбайт, скачиваний: 174)
          Собрал VS2017. На всякий случай со статическими либами, бо не факт, что .dll-ки у тебя инсталлированы.

          Добавлено
          P.S. Если твой argv[1] нужно запускать с параметрами, что имеет смысл, то программка слишком проста. Нужно доработать на сбор последующих argv[] в строку и передавать вместе с argv[1] в начале.
            Есть пара непредвиденных проблем:
            1. Вместо SW_SHOWNORMAL видимо надо SW_RESTORE.
            (если argv[1] это "С:\text.docx" и Word уже запущен, то в текущей конфигурации text.docx откроется, тут всё ок, но Word при этом не становится активным окном - это уже не ок)
            2. При запуске на долю секунды на экране появляется чёрное окно.
            Погуглил - кто-то пишет что надо добавить
            ExpandedWrap disabled
              ShowWindow(NULL,HIDE_WINDOW);

            другое мнение - настроить компилятор, чтобы окна вообще не было:
            Цитата
            Чтобы консольное окно скрыть, не надо его вообще создавать, для компилятора g++ опция
            -mwindows
            Тут я научил людей как сие делать:MessageBox
            Читай с сообщения номер 11, можешь также использовать FreeConsole, если поможет.

            можно как-то убрать окно?

            Цитата Qraizer @
            P.S. Если твой argv[1] нужно запускать с параметрами, что имеет смысл, то программка слишком проста. Нужно доработать на сбор последующих argv[] в строку и передавать вместе с argv[1] в начале.
            Да, так конечно будет правильней. Но этот функционал 99,9999% не будет востребован.

            З.Ы. Не думал, что вылезет столько нюансов. Чую всё таки придётся ставить студию. Что качать?
              Цитата SV() @
              можно как-то убрать окно?

              Надо создать приложение не как консольное, а как GUI.
              Но при этом окна не создавать.
              Т.е. вместо
              ExpandedWrap disabled
                int main(int argc, char *argv[])
                {
                // ...
                }

              Надо делать:
              ExpandedWrap disabled
                int WINAPI _tWinMain (HINSTANCE hThisInst,HINSTANCE hPrevInst,TCHAR* lpszArgs,int nWinMode)
                {
                // ...
                }


              Кроме того, вариант
              ExpandedWrap disabled
                   if (argc == 2)
                    {
                        ShellExecute(0, NULL, argv[1], NULL, NULL, SW_SHOWNORMAL);      
                    }

              Не удачен.
              Лучше приблизительно так:
              ExpandedWrap disabled
                   if (argc > 1)
                    {
                        TCHAR* pCommandStr = ::GetCommandString();
                        ShellExecute(0, NULL, pCommandStr, NULL, NULL, SW_SHOWNORMAL);      
                    }
              Сообщение отредактировано: ЫукпШ -
                SV(), я и не сомневался, что не всё учтено. 2-3 итерации – это норма. Пересоберу, не вопрос.
                "Окончательное" ТЗ подытожишь?
                  Ничего не поменялось, всё как в моем предыдущем сообщении:
                  - если argv[1] это "С:\text.docx" и Word уже запущен, то в результате Word с открытым "С:\text.docx" должен стать активным окном.
                  Предполагаю, что для этого надо заменить SW_SHOWNORMAL на SW_RESTORE.
                  - сама программа должна быть невидимкой. Её окно не должно мелькать на экране.
                  ЫукпШ предлагал варианты, я добавил их в код, но это уже выше моего уровня, совсем не уверен в том, что получилось.
                  Собрал все правки вот так:
                  ExpandedWrap disabled
                    #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);  
                    }
                  :blush:

                  Qraizer, очень извиняюсь, я уже чувствую, что перехожу рамки, и это превращается в работу...
                    Цитата SV() @
                    ЫукпШ предлагал варианты, я добавил их в код, но это уже выше моего уровня, совсем не уверен в том, что получилось.

                    Увы.
                    Виноват, ошибся.
                    1. Не "GetCommandString", а "GetCommandLine".
                    2. Так
                    ExpandedWrap disabled
                         TCHAR* pCommandStr = ::GetCommandString();
                          ShellExecute(0, NULL, pCommandStr, NULL, NULL, SW_RESTORE);

                    Работать не будет.
                    Придётся разбирать командную строку.
                    Либо самому, либо используя "CommandLineToArgvW"
                    Тут есть пример.
                    Сообщение отредактировано: ЫукпШ -
                      Вообще-то GetCommandString() возвращает всю строку, включая имя программы. Т.е. туда будут входить все argv[], начиная с нулевого. Коли мы делам ГУЙный стартер, тогда уж лучше брать третий параметр WinMain(): который lpszArgs. Ну и iostream тебе не нужен, в консоль ничего не выдаётся. Он и раньше не был нужен, но у меня был вопрос, который я хотел задать, на предмет обработки ошибок: нормально ли, что при ошибках ничего никому никуда не выдаётся?
                      Вот текст:
                      ExpandedWrap disabled
                        #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);  
                        }
                      Собрал под UNICODE.
                      Прикреплённый файлПрикреплённый файлshellExec.zip (40,25 Кбайт, скачиваний: 168)
                      Если есть желание, можно вообще избавиться от стартового кода, но тогда придётся всё-таки GetCommandString() и отрезать от него первый параметр руками. Зато .exeшичек будет совсем маленький.
                        Цитата Qraizer @
                        нормально ли, что при ошибках ничего никому никуда не выдаётся?
                        да :yes:
                        Тут всё так просто, что если ничего не произошло - без всяких сообщений понятно, что накосячил с параметрами в командной строке.

                        Размер exe-шника честно говоря не важен. 84kb в современном мире это фактически ноль. Если будет работать быстрее - есть смысл. Но на первый взгляд она и так шустрая.

                        Протестил - всё работает как надо: окно не мелькает, выполняется без задержки.
                        Проблема
                        Цитата SV() @
                        если argv[1] это "С:\text.docx" и Word уже запущен, то в результате Word с открытым "С:\text.docx" должен стать активным окном.
                        не решена.
                        Но эти все SW_SHOWNORMAL, SW_RESTORE и т.д. никогда на моей памяти вменяемо не работали.
                        Я наколхозил так: создал ярлык и передаю его проге. Т.е. argv[1] это "С:\text.docx — ярлык.lnk"

                        Сейчас внедрю прогу, создам все ярлычки, посмотрим, как себя покажет в реальной работе.
                          У меня консольная утилитка, юзаю это, как ведет за пределами консоли не скажу:
                          https://docs.microsoft.com/ru-ru/cpp/c-runt...ue&view=vs-2019
                            Добрый день!

                            Сменил работу и эта программа снова понадобилась.
                            Но наряду с 64 bit версией, нужна и 32 (несколько машин, с разными windows)
                            Возможно собрать ещё 32 bit версию?

                            З.Ы. Теперь windows 7, не 10. В нём вылезла старая проблема: на секунду появляется чёрное окно. Но это просто к слову, вдруг есть идеи.
                              Та нам не жалко, на здоровье:
                              Прикреплённый файлПрикреплённый файлshellExec.zip (42,93 Кбайт, скачиваний: 41)
                              Скомпилено VS2022. Под Win7 работать должно, под XP почти наверняка не будет.
                              Цитата SV() @
                              З.Ы. Теперь windows 7, не 10. В нём вылезла старая проблема: на секунду появляется чёрное окно. Но это просто к слову, вдруг есть идеи.
                              Не должно. Скорее, что пытается запуститься процесс, который не корректно распознан Shell-ом или его обработчик сам по себе консольный.
                                Спасибо!
                                Отлично работает! :thanks:

                                Цитата Qraizer @
                                Скорее, что пытается запуститься процесс, который не корректно распознан Shell-ом или его обработчик сам по себе консольный.

                                Думаю это всё-таки какая-то проблема с 64bit:
                                Сделал все ярлычки на 32bit машине - работает без окошка.
                                Перенёс на машину 64bit - мало того, что работает, так ещё и без окошка))

                                В общем просто с самого начала не стоило связываться с 64.
                                32bit версия работает везде, да ещё и артефакта в виде окошка нет :wub:
                                Сообщение отредактировано: SV() -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0464 ]   [ 23 queries used ]   [ Generated: 24.04.24, 20:57 GMT ]