Как заархивировать папку в моем приложении Win32 Visual C с помощью системного вызова

#winapi #visual-c #zip #system #call

#winapi #visual-c #застежка — молния #система #вызов

Вопрос:

Я пытаюсь заархивировать папку в моем приложении Win32 Visual C с помощью системного вызова. На моем компьютере я могу сделать это с помощью команды cmd:

 PowerShell -Command "Compress-Archive -Path  C:UsersttylerDesktopSoftwareFolder2RUN -DestinationPath C:UsersttylerDesktopSoftwareFolder2RUN"
 

Где «Попробовать» — это папка.

Я пытаюсь сделать это в своем приложении с помощью системного вызова, но в моем приложении «Path» и «DestinationPath» хранятся в переменных (потому что путь назначения вводится пользователем). Я не уверен, что правильно использую переменные в своем системном вызове, потому что это выдает мне ошибку: «‘ ‘: невозможно добавить два указателя» и «выражение должно иметь целочисленный или нерасчлененный тип перечисления».

 TCHAR path = L"C:UsersttylerDesktopSoftwareFolder2RUN";
TCHAR DestinationPath = L"C:UsersttylerDesktopSoftwareFolder2RUN.zip";
system("Compress-Archive -Path"   path[0]   "-DestinationPath"   DestinationPath[0]);
 

Что я делаю не так при использовании переменных в моем системном вызове?

Комментарии:

1. system() запускает экземпляр cmd.exe /C <command-line> where <command-line> является указанным параметром. PowerShell.exe это отдельное приложение со своими собственными параметрами командной строки. PowerShell.exe команды — это не cmd.exe команды. Используйте CreateProcess() вместо PowerShell.exe этого прямой запуск. В противном случае поместите команды PowerShell в .bat сценарий, а затем используйте system() для запуска этого сценария.

2. Я сделал: ‘STARTUPINFO info = { sizeof(info) }; PROCESS_INFORMATION ProcessInfo;

Ответ №1:

Ваш код не будет работать по многим причинам:

  • вы пытаетесь назначить широкие строковые литералы переменным с одним символом. Вместо этого вам нужно использовать массивы или указатели, например:
 TCHAR path[] = L"C:\Users\ttyler\Desktop\Software\Folder2\RUN";
TCHAR DestinationPath[] = L"C:\Users\ttyler\Desktop\Software\Folder2\RUN.zip";
 
 LPCTSTR path = L"C:\Users\ttyler\Desktop\Software\Folder2\RUN";
LPCTSTR DestinationPath = L"C:\Users\ttyler\Desktop\Software\Folder2\RUN.zip";
 
  • вы не можете объединить строковые литералы с массивом / одиночными символами так, как вы пытаетесь это сделать. Вам нужно будет выделить новые массивы и скопировать / отформатировать в них различные подстроки, например:
 WCHAR path[] = L"C:\Users\ttyler\Desktop\Software\Folder2\RUN";
WCHAR DestinationPath[] = L"C:\Users\ttyler\Desktop\Software\Folder2\RUN.zip";

WCHAR cmd[(MAX_PATH*2) 50] = {};
swprintf(cmd, L"Compress-Archive -Path "%s" -DestinationPath "%s"", path, DestinationPath);

// use cmd as needed...
 

Или просто используйте std::wstring вместо этого, например:

 std::wstring path = L"C:\Users\ttyler\Desktop\Software\Folder2\RUN";
std::wstring DestinationPath = L"C:\Users\ttyler\Desktop\Software\Folder2\RUN.zip";

std::wstring cmd = L"Compress-Archive -Path ""   path   L"" -DestinationPath ""   DestinationPath   L""";

// use cmd as needed...
 
  • system() принимает const char* указатель в качестве входных данных. Но вы используете TCHAR строки, которые будут корректно работать только для ваших широких строковых литералов, если TCHAR есть WCHAR . Это означает, что вы все равно не сможете передать свою объединенную строку system() . Вместо этого вам придется использовать _wsystem() , например:
 _wsystem(cmd); // when using WCHAR[]/LPWSTR
 
 _wsystem(cmd.c_str()); // when using std::wstring
 
  • system() / _wsystem() запускает экземпляр cmd.exe /C <command-line> , где <command-line> указана строка ввода. Но PowerShell.exe это собственное приложение со своими параметрами командной строки. PowerShell.exe команды НЕ ЯВЛЯЮТСЯ допустимыми cmd.exe командами, т. Е. Вы пытаетесь выполнить это:
 cmd.exe /C Compress-Archive -Path <path> -DestinationPath <dest>
 

Который не является допустимой командой, поскольку cmd.exe не знает, что Compress-Archive это такое. Вместо этого вам нужно будет выполнить это:

 cmd.exe /C PowerShell -Command "Compress-Archive -Path "<path>" -DestinationPath "<dest>""
 
 WCHAR cmd[(MAX_PATH*2) 70] = {};
swprintf(cmd, L"PowerShell -Command "Compress-Archive -Path \"%s\" -DestinationPath \"%s\"", path, DestinationPath);
 
 std::wstring cmd = L"PowerShell -Command "Compress-Archive -Path \""   path   L"\" -DestinationPath \""   DestinationPath   L"\"";
 

Но вам действительно следует использовать CreateProcess() вместо этого для PowerShell.exe прямого запуска, не используйте cmd.exe вообще, например:

 STARTUPINFO si = {sizeof(STARTUPINFO), 0};
PROCESS_INFORMATION pi = {};

if (CreateProcess(NULL, cmd/*cmd.data()*/, NULL, NULL, FALSE, 0, NULL, NULL, amp;si, amp;pi))
{
    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
}
 

В противном случае поместите свои команды PowerShell в .bat сценарий, например:

 @echo off
PowerShell -Command "Compress-Archive -Path "%0" -DestinationPath "%1""
 

И затем вы можете использовать system() / _wsystem() для запуска этого скрипта, например:

 WCHAR cmd[(MAX_PATH*2) 25] = {};
swprintf(cmd, L"myscript.bat "%s" "%s"", path, DestinationPath);
_wsystem(cmd);
 
 std::wstring cmd = L"myscript.bat ""   path   L"" ""   DestinationPath   L""";
_wsystem(cmd.c_str());
 

Комментарии:

1. Если используется процесс создания, какими будут «si» и «pi»? Это путь и путь назначения? Кроме того, при вводе команд PowerShell в сценарий .bat, должен ли сценарий .bat быть сохранен в каталоге проекта?

2. @Alyssa Я показал вам, что именно si и pi есть. Прочитайте документацию .