c ++ - Paus program indtil et magasin script færdiggøres

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg skriver en ansøgning i C ++, der skal gribe en liste over installerede pakker fra Windows 10. Jeg har fundet en måde at dumpe den i en tekstfil via Powershell script.


Jeg starter scriptet som sådan:


system("start powershell.exe -windowstyle hidden Set-ExecutionPolicy RemoteSigned 
");
system("start powershell.exe -windowstyle hidden .//package\_list\_save.ps1");


hvor package\_list\_save.ps1 er det script, der skaber .txt filen. Her er indholdet af package\_list\_save.ps1:


Start-Transcript -Path ts.txt -Force
Get-AppxPackage
Stop-transcript


Mit problem er, at det ser ud som om C + + -delen af ​​applikationen vil fortsætte, før Powershell-scriptet har en chance for at oprette tekstfilen, hvilket får resten af ​​mine funktioner til at mislykkes, da de afhænger af pakker listen, der ville være indenfor tekstfil. Her er den del, der opfører sig forkert:


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;
        }
 }


Indtil videre har jeg forsøgt at gøre ting som en tidssløjfe, der kun ophører, når tekstfilen opdages:


while (!isFileExists("thing.txt")) {
}


Men det resulterer heller i, at det ignorerer hele løkken (og efterfølgende stadig forårsager fiasko) eller bliver fast for altid.


Jeg har forsøgt at bruge detekteringsmetoder som denne (taget herfra):


inline bool exists\_test1 (const std::string& name) {
    if (FILE *file = fopen(name.c\_str(), "r")) {
        fclose(file);
        return true;
    } else {
        return false;
    }   
}


Men jeg kan stadig ikke få det til at opføre mig som jeg vil. Er der en bedre måde for mig at sætte min C ++ kode i pause, indtil Powershell er færdig?


EDIT: Her er et minimalt, verificerbart eksempel:


#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 
");
    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;
}


På første runde er der ingen output udover 'Done', men i andet runde (forudsat at du ikke sletter ts.txt 'er der meget output. Jeg skal kunne få alle de output på første runde og Lad ikke brugeren køre min ansøgning to gange.

Bedste reference


Hvad gik galt



system kører start (doc link). Start kører powerhell og udgange, så system kan returnere. Programmet fortsætter, mens powershell kører. [21]


Dummy eksempel:


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


forlader programmet og dræber kommandoprompten, før du sikkert får se det. Men


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


venter på, at kommandoprompten skal lukkes, inden du fortsætter.


Løsning 1



Fjern starten. Baseret på '-windowstyle hidden' i kommandolinjen smider det nok en masse crap, du ikke vil have til konsoludgangen, men det er godt for et bevis på konceptet.


system("powershell.exe -windowstyle hidden Set-ExecutionPolicy  RemoteSigned 
");
system("powershell.exe -windowstyle hidden .//package\_list\_save.ps1");


Løsning 2



Brug ikke system. Powershell foreslår spørgerens mål OS er Windows, så vi kan bruge Windows systemfunktioner. I dette tilfælde er jeg 'd CreateProcess (doc link) og påberåber WaitForSingleObject (doc link) på hProcess håndtaget gemt i PROCESS\_INFORMATION leveret som lpProcessInformation til CreateProcess. [22] [23]


Brugsdetaljer her: Brug CreateProcess () til at lukke/lukke et åbent program