VMware Cloud Community
rmrunal
Contributor
Contributor

How to use PowerCLI objects in c++

I need to use PowerCLI in CLI/CRL C++ application.

What I found out is, I cannot create a member handle in non-managed code. As a result I need to create the PowerShell object for each command/script I execute through code.  However, there are multiple scripts that I need to execute through application which means, eveytime a new object will be created. 

Is there a way to avoid creating the PowerShell connection per command/script? In other words, I want to keep the connection alive till execution of all commads/scripts are complete (within a thread).    

TIA

Mrunal

0 Kudos
6 Replies
LucD
Leadership
Leadership

Perhaps some sample code of what you are trying to do and where the issue is manifesting would help.
Is "... creating the PowerShell connection ..." meaning the Connect-VIServer cmdlet?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
rmrunal
Contributor
Contributor

Sure.

PowerShellExecutor::Execute()

{

 PowerShell^ PS = PowerShell::Create();

 PS->Commands->AddScript("Get-Module -Name VMware* -ListAvailable");

 Collection<PSObject^>^ PSResults_t = PS->Invoke();

 PS->Commands->AddScript("Import-Module Vmware.Vimautomation.core");

 PS->Commands->AddScript(gcnew strConnectionString);

 PS->Commands->AddScript(gcnew strCommand);

 PSResults = PS->Invoke();

}

This is the snippet of function which creates the poershell object, connects to vCenter server, adds commands to the object and then executes these commands. This seems to be impacting performace, since for each command/script, all the initialization steps are executed.

I want to seperate out connection and command execution part such that, connection will happen only once ( may be in constructor or Initializer) and then "addscript()" and "Invoke" for scipt can be called multiple times (in execute function). 

Problem here is, since Powershell is a handle, I cannot create a member variable of it, so that, once initialized it can be used accross the class for executing any command. 

Do you think, is there any better way to achieve this?

0 Kudos
LucD
Leadership
Leadership

Invoking PowerShell like that is like starting a new PowerShell session for each cmdlet/script.

Due to the design of PowerShell, you will have to set up the environment again each time, including the connection.

Not sure what you are trying to solve with C++ ?
If you have multiple cmdlets to execute, place them in a PS script.

If you have multiple scripts to run, create a wrapper script that calls them in all.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
rmrunal
Contributor
Contributor

Thanks for your reply.

Yes, the option of running all the requied commands in a script is already in our consideration. 

I just wanted to see if there is any way to cache the connection/Env so that the extra post parsing efforts can be saved.

This is a legacy C++ application in which we need to add support for VMware PowerCLI commands/scripts.

--Mrunal

0 Kudos
LucD
Leadership
Leadership

If you want to pass the connection to a vSphere server (VCSA or ESXi), you can use the SessionId of an open connection.
The last connection is stored in $global:defaultVIServer.
On a new Connect-VIServer you can then use the Session parameter with this value.

Similar to how background jobs in PowerShell can be done.
See for example Running a background job


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
rmrunal
Contributor
Contributor

Passing sessionID did not work, however we have gone ahead with the same sequential execution. 

I have more queries regarding Invoke() method, I shall open a different thread for that.

Thanks LucD for the help.

0 Kudos