【发布时间】:2018-01-22 18:39:34
【问题描述】:
我正在用 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
我的问题是,在 Powershell 脚本有机会创建文本文件之前,应用程序的 C++ 部分似乎会继续运行,导致我的其余函数失败,因为它们依赖于包列表在文本文件中。以下是行为不正确的部分:
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;
}
}
但我似乎仍然无法让它按照我想要的方式运行。有没有更好的方法让我暂停我的 C++ 代码,直到 Powershell 完成?
编辑:这是一个最小的、可验证的示例:
#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;
}
在第一次运行时,除了“完成”之外没有任何输出,但在第二次运行时(假设你不删除 ts.txt”有很多输出。我需要能够在第一次运行,而不是让用户运行我的应用程序两次。
【问题讨论】:
-
“似乎无法让它按照我想要的方式运行” - 它的行为如何?
-
“应用程序的 C++ 部分将在 Powershell 脚本有机会创建文本文件之前继续运行,从而导致我的其余功能失败”。当我更多地考虑它时,也可能是 .txt 文件已创建,但 powershell 脚本在另外 50 毫秒左右没有填充实际文本。
-
@Aaron 您如何从应用程序中调用您的 powershell 脚本?使用
system()应该阻塞(在同一个线程中)。 -
脚本是从什么开始的?另一个程序?您是否尝试过以独占访问权限打开文件?
-
@Aaron 那些
system()调用和while()循环在同一个线程中运行?请您提供minimal reproducible example。
标签: c++ windows shell powershell