暂停程序,直到PowerShell脚本完成

时间:2018-01-22 18:39:35

标签: c++ windows shell powershell

我正在用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;有很多输出。我需要能够在第一次运行时获得所有输出,而不是让用户运行我的应用程序两次。

1 个答案:

答案 0 :(得分:1)

出了什么问题

system运行开始(doc link)。开始运行powershell并退出,允许system返回。在PowerShell运行时程序继续。

虚拟例子:

int main() {
    system("start cmd");
    std::cout << "Done.";
} 

退出程序并杀死命令提示符,然后你甚至可能会看到它。但

int main() {
    system("cmd");
    std::cout << "Done.";
} 

在继续之前等待命令提示符关闭。

解决方案1 ​​

删除开始。基于命令行中的“-windowstyle hidden”,这可能会抛出一堆你不想进入控制台输出的垃圾,但这对于概念验证很有用。

system("powershell.exe -windowstyle hidden Set-ExecutionPolicy  RemoteSigned \n");
system("powershell.exe -windowstyle hidden .//package_list_save.ps1");

解决方案2

请勿使用system。 Powershell建议提问者的目标操作系统是Windows,因此我们可以使用Windows系统功能。在这种情况下,我CreateProcessdoc link)并在WaitForSingleObject处理的hProcess句柄上调用PROCESS_INFORMATIONdoc linklpProcessInformationCreateProcess

此处的使用详情:Using CreateProcess() to exit/close an opened Application