如何使用系统调用在我的 Win32 Visual C++ 应用程序中压缩文件夹

How to zip a folder in my Win32 Visual C++ app using a system call

我正在尝试使用系统调用在我的 Win32 Visual C++ 应用程序中压缩一个文件夹。在我的电脑上,我可以通过cmd命令来做到这一点:

PowerShell -Command "Compress-Archive -Path  C:\Users\ttyler\Desktop\Software\Folder2\RUN -DestinationPath C:\Users\ttyler\Desktop\Software\Folder2\RUN"

其中“Try”是一个文件夹。

我正在尝试使用系统调用在我的应用程序上执行此操作,但在我的应用程序中,我将“路径”和“DestinationPath”存储在变量中(因为目标路径由用户拉入).我不确定我在系统调用中是否正确使用了变量,因为这给了我错误:“'+':无法添加两个指针”和“表达式必须具有整数或无作用域的枚举类型”。

TCHAR path = L"C:\Users\ttyler\Desktop\Software\Folder2\RUN";
TCHAR DestinationPath = L"C:\Users\ttyler\Desktop\Software\Folder2\RUN.zip";
system("Compress-Archive -Path" + path[0] + "-DestinationPath" + DestinationPath[0]);

我在系统调用中使用变量时做错了什么?

您的代码无法运行的原因有很多:

  • 您正在尝试将宽字符串文字分配给单字符变量。您需要改用数组或指针,例如:
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";
  • 您不能按照您尝试的方式将字符串文字与 array/single-chars 连接起来。您将不得不分配新数组并将 copy/format 各种子字符串放入其中,例如:
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 字符串,如果 TCHARWCHAR,它只会对您的宽字符串文字正确工作。这意味着您无论如何都无法将连接的字符串传递给 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, &si, &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());