我正在用C ++编写一个应用程序,需要从Windows 10中获取已安装的软件包列表。我已经找到了一种通过Powershell脚本将其转储到文本文件中的方法。
我像这样启动脚本:
system("start powershell.exe -windowstyle hidden Set-ExecutionPolicy RemoteSigned \n");
system("start powershell.exe -windowstyle hidden .//package_list_save.ps1");
其中package_list_save.ps1
是创建.txt文件的脚本。以下是package_list_save.ps1的内容:
Start-Transcript -Path ts.txt -Force
Get-AppxPackage
Stop-transcript
我的问题是,看起来应用程序的C ++部分会在Powershell脚本有机会创建文本文件之前继续运行,导致其余的函数失败,因为它们依赖于包列表在文本文件中。这是行为不正确的部分:
void loadPackageList(string PATH) {
string temp;//a string to be used for any temporary holding of values
ifstream fs;//create an in-file-stream
fs.open(PATH);
//skip 17 lines (all the junk up front)
for (int i = 0; i < 17; ++i) {
getline(fs, temp);
}
//clear out temp just in case.
temp = "";
string currentLine;
string name;
string packageName;
bool isFramework;
while (getline(fs, currentLine)) {
//read: name
if ((currentLine.length() > 4) && (currentLine.substr(0, 4) == "Name")) {
//get the name
name = currentLine.substr(20);
//skip four more lines
for (int i = 0; i < 4; ++i) {
getline(fs, temp);
}
//grab the fullPackageName line
getline(fs, currentLine);
packageName = currentLine.substr(20);
//skip a line
getline(fs, temp);
//get the isFramework line
getline(fs, temp);
if (temp.substr(20) == "False") {
isFramework = false;
} else {
isFramework = true;
}
//store all the relevent details of the package as a tuple
tuple<string, string, bool>packageData;
get<0>(packageData) = name;
get<1>(packageData) = packageName;
get<2>(packageData) = isFramework;
packages.push_back(packageData);
}
}
//DEBUG:
for (tuple<string, string, bool> tp: packages) {
clog << "Name: " << get<0>(tp) << endl;
clog << " PackageName: " << get<1>(tp) << endl;
clog << " IsFramework: " << get<2>(tp) << endl;
}
}
到目前为止,我尝试过像while循环这样的事情,只有在检测到文本文件时才会终止:
while (!isFileExists("thing.txt")) {
}
但是这或者导致它完全忽略了while循环(并且随后仍然导致失败)或者永远陷入困境。
我尝试过使用这样的检测方法(取自here):
inline bool exists_test1 (const std::string& name) {
if (FILE *file = fopen(name.c_str(), "r")) {
fclose(file);
return true;
} else {
return false;
}
}
但我仍然无法让它按照我想要的方式行事。在Powershell完成之前,我有更好的方法暂停我的C ++代码吗?
编辑:这是一个最小的,可验证的例子:
#include <fstream>
#include <iostream>
#include <windows.h>
using namespace std;
int main() {
ofstream fs;
fs.open("package_list_save.ps1");
fs << "Start-Transcript -Path ts.txt -Force" << endl;
fs << "Get-AppxPackage" << endl;
fs << "Stop-transcript" << endl;
fs.close();
system("start powershell.exe -windowstyle hidden Set-ExecutionPolicy RemoteSigned \n");
system("start powershell.exe -windowstyle hidden .//package_list_save.ps1");
ifstream ifs;
ifs.open("ts.txt");
string currentLine;
while (getline(ifs, currentLine)) {
cout << currentLine << endl;
}
cout << "Done." << endl;
}
在第一次运行时,除了&#34; Done&#34;之外没有输出,但是在第二次运行时(假设你不删除ts.txt&#34;有很多输出。我需要能够在第一次运行时获得所有输出,而不是让用户运行我的应用程序两次。
答案 0 :(得分:1)
system
运行开始(doc link)。开始运行powershell并退出,允许system
返回。在PowerShell运行时程序继续。
虚拟例子:
int main() {
system("start cmd");
std::cout << "Done.";
}
退出程序并杀死命令提示符,然后你甚至可能会看到它。但
int main() {
system("cmd");
std::cout << "Done.";
}
在继续之前等待命令提示符关闭。
删除开始。基于命令行中的“-windowstyle hidden”,这可能会抛出一堆你不想进入控制台输出的垃圾,但这对于概念验证很有用。
system("powershell.exe -windowstyle hidden Set-ExecutionPolicy RemoteSigned \n");
system("powershell.exe -windowstyle hidden .//package_list_save.ps1");
请勿使用system
。 Powershell建议提问者的目标操作系统是Windows,因此我们可以使用Windows系统功能。在这种情况下,我CreateProcess
(doc link)并在WaitForSingleObject
处理的hProcess
句柄上调用PROCESS_INFORMATION
(doc link) lpProcessInformation
至CreateProcess
。
此处的使用详情:Using CreateProcess() to exit/close an opened Application