2014-05-07 3 views
1

Я пытаюсь создать оболочку, которая позволяет пользователю вводить команды «ping» и использовать CreateProcess() для выполнения команды на основе пользовательского ввода. Я столкнулся с трудностями при работе команды ping при работе с переменными. Например, приведенный ниже код работает просто отлично, пока у меня есть L перед строкой. Тем не менее, строка должна быть задана пользователем, поэтому после некоторого исследования я столкнулся с возможной заменой L-литья в виде переменной wchar_t.Передача аргументов в CreateProcess() не работает в C

if (strcmp(buffer, "ping") == 0 || strcmp(buffer, "ping &") == 0){ 
     LPCTSTR path = L"C:\\Windows\\System32\\PING.exe"; 
     LPTSTR link = L"-t www.yahoo.com"; 
     CreateProcess(path, 
      link, 
      NULL, 
      NULL, 
      0, 
      0, 
      NULL, 
      NULL, 
      &start, 
      &info); 
     if (strcmp(buffer, "ping") == 0){ 
      WaitForSingleObject(info.hProcess, INFINITE); 
     } 
     CloseHandle(info.hProcess); 
     CloseHandle(info.hThread); 

     printf("MyShell: "); 
     scanf("%s", buffer); 

Если я это сделаю, он перестанет работать (сбой в консоли, отсутствие выхода).

 wchar_t wideC = "-t www.yahoo.com"; 
     LPCTSTR path = L"C:\\Windows\\System32\\PING.exe"; 
     LPTSTR link = wideC; 

Я пробовал различать различные типы переменных как в аргументах CreateProcess(), так и снаружи. Я не знаю, что еще делать. Как я могу заставить user scanf() в переменной, которая будет работать как аргумент для создания процесса?

+0

Вы действительно считаете, что * «CreateProcess() не работает» *. Вы можете подумать, насколько маловероятно это, прежде чем утверждать это довольно заметно. Очевидно, что * ваш код «не работает» - «CreatePorcess()» в порядке - мусор, мусор. – Clifford

+0

Я бы оспаривал дубликат метки - это не то, что он просил, и это не единственное решение проблемы . Вопрос можно прочитать как * «Как я могу использовать аргумент строки набора символов ANSI с CreateProcess()?» * – Clifford

+0

@Clifford, если вы думаете, что вопрос должен быть сформулирован так ... отредактируйте его? –

ответ

3

Здесь:

wchar_t wideC = "-t www.yahoo.com"; 

wideC имеет тип wchar_t но инициализируется с строковой константой типа const char*.

Это исправляется:

const wchar_t* wideC = L"-t www.yahoo.com"; 
^^^^^  ^  ^

Хотя безопаснее использовать типы портативных указателей строки Win32 и _T() макрос для того, чтобы обеспечить согласие типа и поддержки как Unicode and non-Unicode builds.

Однако фатальный недостаток здесь является то, что второй аргумент CreateProcess() не может быть const - от CreateProcess() documentation:

версия Unicode этой функции, CreateProcessW, может изменить содержимое этой строки. Поэтому этот параметр не может быть указателем на постоянную память (например, константную переменную или литеральную строку). Если этот параметр является константой, функция может вызвать нарушение доступа.

Даже если вы не используете тип const, строковая строка по-прежнему является константой и не может быть изменена без возникновения ошибки времени выполнения. То, что вы на самом деле нужно:

TCHAR wideC[] = _T("-t www.yahoo.com") ; 

или если вы не прислушаться к советам портативность:

wchar_t wideC[] = L"-t www.yahoo.com" ; 

Что касается принятия пользовательского ввода, возможно, wscanf() or better - _tscanf() более подходящим? Вы не можете просто применить бросок для изменения строковой кодировки, не в последнюю очередь потому, что строки не являются первоклассными типами данных в C, а для широких строк требуется дополнительное пространство для хранения.

Все, что сказано, консольный режим Win32 имеет плохую и плохо документированную поддержку Unicode. Может быть проще или принудительно использовать характер символа ANSI для всей сборки, или для этого конкретного случая использовать явно строчную версию ANSI для функции CreateProcessA() - CreateProcess() itslef - просто псевдоним для CreateProcessW() или CreateProcessA() в зависимости от режима набора символов сборки.

const char* path = "C:\\Windows\\System32\\PING.exe"; 
    char* link = "-t www.yahoo.com"; 
    CreateProcessA(path, 
     link, 
     NULL, 
     NULL, 
     0, 
     0, 
     NULL, 
     NULL, 
     &start, 
     &info); 
+0

Есть ли способ использовать wscanf () получить вход непосредственно в wideC? wchar_t wideC [80]; printf ("Команда:"); wscanf (L "% ls", wideC); Вот как я вижу это в некоторых онлайн-примерах, но в этом случае он не работает в CreateProcess(). – TImmuh

+0

@TImmuh. Если вы хотите задать вопрос о Unicode * input *, вы действительно должны опубликовать это как отдельный вопрос. В этом случае код в вашем вопросе имеет ошибки, независимые от пользовательского ввода, и даже не имеет пользовательского ввода. Трудно комментировать код, который мы не видим. Обратите внимание, что консольный режим Windows не полностью поддерживает Unicode и является плохой и плохо документирован - лучше всего этого избежать. Это может помочь: http://alfps.wordpress.com/2011/11/22/unicode-part-1-windows-console-io-approaches/ – Clifford

Смежные вопросы