#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
есть. Прочитайте документацию .