Access Powershell via Visual C++ (API)

11,213

Solution 1

You can certainly do this but you'll need to use managed code as PowerShell's architecture is based entirely on the CLR object model.

I'm not sure of the C++ syntax but you can start with the PowerShell class in System.Management.Automation.dll and use its static Create method to create an instance to which you can pipe data and run commands.

Solution 2

I have an answer that might solve your problem although it is not literally an answer to the question you asked.

Well, what I need in my current project is a system call that does not open a window and that does give me the opportunity to read out the results written to standard-output or standard-error.

In case you can live with that - here is some code from the before-mentioned codebase:

public class RsbSystem
{
    string command = null;
    string param = null;
    string commandLine = null;
    public int ExitCode = 0;

    //..

    /// <summary>Exec for apps that don't want console output</summary>
    /// <param name="msg">returns output of called program</param>
    /// <returns>0 if ok</returns>
    /// <remarks>RsbSystem instance keeps the result in member ExitCode</remarks>
    public int Exec(ref string msg)
    {
        var p = new Process();
        p.StartInfo.FileName = command;
        p.StartInfo.Arguments = param;
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardError = true;
        p.Start();
        if (!p.StandardOutput.EndOfStream)
            msg = p.StandardOutput.ReadToEnd();
        if (!p.StandardError.EndOfStream)
            msg += p.StandardError.ReadToEnd();
        p.WaitForExit(120000);  // this needs to come after readToEnd() RSB: https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput(v=vs.110).aspx
        ExitCode = p.ExitCode;
        p.Dispose();
        return ExitCode;
    }

    // ..

    public RsbSystem(string cmdLine)
    {
        commandLine = cmdLine;
        var pos = 0;
        if (cmdLine[0] == '"')
            pos = cmdLine.IndexOf("\" ") + 1;
        else pos = cmdLine.IndexOf(" ");
        command = pos > -1 ? cmdLine.Substring(0, pos).Trim() : cmdLine;
        param = pos > -1 ? cmdLine.Substring(pos + 1).TrimStart() : "";
    }
}

Also: please forgive me that the code is in C# instead of C++.

As you can see it calls any program - and does not use PowerShell. If that's already a workaround for you - fine. If not, you might consider calling the Powershell from the commandline using this approach and possible get where you want to be that way.

Hope it helps or at least gives you an idea.

Share:
11,213

Related videos on Youtube

Disco
Author by

Disco

Updated on May 14, 2022

Comments

  • Disco
    Disco almost 2 years

    I'd like to write a program that effectively "pipes" Powershell, so that I can send commands and parse the responses in C++, without actually opening the prompt on the screen.

    Any tips?

  • CherryDT
    CherryDT almost 8 years
    Note that you could also create a managed DLL specifically for this and use one of the solutions here for calling it from unmanaged C++.