Call external functions from multiple PowerShell scripts in C# - c#

I have a C# application that runs PowerShell scripts after reading them off database as strings. Assume script1, script2 and utilityfunctions are scripts read from database.
var rs = RunspaceFactory.CreateRunspace();
rs.Open();
var ps = PowerShell.Create();
ps.Runspace = rs;
ps.AddScript(utilityFunctions);
ps.AddScript(script1);
Is there anyway possible that I can call functions in utilityFuntions from script1? I have tried using $MyInvocation and go through its properties but did not find anything useful. When going through ps.Commands properties, I can of course see two items but when going through commands within the script, I cannot get to anything inside utilityFunctions. I guess I can read all scripts and concatenate them as string and only pass one script but I am just wondering if there is a way to do it without string concatenation.

Related

Running the PowerShell Script from the c#

I am trying to call PowerShell ISE Script from the C#.
I have command that I am running it on the PowerShell
. .\Commands.ps1; Set-Product -bProduct 'Reg' -IPPoint 'ServerAddress' -Location 'testlocation' -Terminal 3
Now I am trying to create the Command with the c# I have wrote some code Like this.
//Set Execution Policy to un restrict
powershell.AddCommand("Set-ExecutionPolicy");
powershell.AddArgument("unrestricted");
powershell.Invoke();
powershell.Commands.Clear();
powershell.AddScript("K:\\Auto\\Cases\\Location\\Commands.ps1", false);
powershell.AddArgument("Set-Product").AddParameter("bProduct ", "Reg").
AddParameter("IPPoint", "ServerAddress").
AddParameter("Location", "testlocation").AddParameter("Terminal", 3);
powershell.Invoke();
I can see its running fine. But its not updating values in my xml file. It suppose to update my values in file. When I try to run it with powershell It does run and works file. But c# code does not work.
Any hint or clue will be appreciated.
Mind the semicolon, so this is basically two statements:
1.) Dot-sourcing the script Commands.ps1
. .\Commands.ps1
2.) Invoking the cmdlet Set-Product
Set-Product -bProduct 'Reg' -IPPoint 'ServerAddress' -Location 'testlocation' -Terminal 3
So, you have to treat them as such. Also, AddScript expects code, not a file name.
powershell
// dot-source the script
.AddScript(#". 'K:\Auto\Cases\Location\Commands.ps1'")
// this is the semicolon = add another statement
.AddStatement()
// add the cmdlet
.AddCommand("Set-Product")
.AddParameter("bProduct", "Reg")
.AddParameter("IPPoint", "ServerAddress")
.AddParameter("Location", "testlocation")
.AddParameter("Terminal", 3)
// invoke all statements
.Invoke();
(Alternatively to AddStatement() you can of course split this up in two calls and call Invoke() twice.)

Invoked PS command to string

Is there way to convert invoked powershell command from C# to string?.
Let's say for example i have something like this:
PowerShell ps = PowerShell.Create();
ps.AddCommand("Add-VpnConnection");
ps.AddParameter("Name", "VPN_" + ClientName);
ps.AddParameter("ServerAddress", VPN_SERVER_IP);
ps.AddParameter("AllUserConnection");
ps.AddParameter("SplitTunneling", true);
ps.AddParameter("TunnelType", "L2tp");
And i would like to save invoked command to log file.
Can i somehow return whole command as string?
I believe what you want essentially is this.
PowerShell ps = PowerShell.Create();
ps.AddScript($"Add-VpnConnection -Name \"VPN_{ClientName}\" -ServerAddress {VPNServerIP} -AllUserConnection -SplitTunneling -TunnelType L2tp");
ps.Invoke();
The invoke return will contain a collection of PSObject so you can read it and save the information like you want in a log in c#.
Note: This answer does not solve the OP's problem. Instead, it shows how to capture a PowerShell command's output as a string in C#, formatted in the same way that the command's output would print to the display (console), if it were run in an interactive PowerShell session.
Out-String is the cmdlet that produces formatted, for-display representations of output objects as strings, as they would print to the screen in a PowerShell console.
Therefore, you simply need to use another .AddCommand() in order to pipe the output from your Add-VpnConnection call to Out-String:
string formattedOutput;
using (PowerShell ps = PowerShell.Create())
{
ps.AddCommand("Add-VpnConnection")
.AddParameter("Name", "VPN_" + ClientName)
.AddParameter("ServerAddress")
.AddParameter("AllUserConnection", VPN_SERVER_IP)
.AddParameter("SplitTunneling", true)
.AddParameter("TunnelType", "L2tp");
// Add an Out-String call to which the previous command's output is piped to.
// Use a -Width argument (column count) large enough to show all data.
ps.AddCommand("Out-String").AddParameter("Width", 512);
// Due to use of Out-String, a *single string* is effectively returned,
// as the only element of the output collection.
formattedOutput = ps.Invoke<string>()[0];
}
Console.Write(formattedOutput);

Launching powershell scripts (with parameters) from c# app

I'm trying to make a simple (or so i thought) app that will make it easier to launch .ps1 scripts, so that non-powershell savvy users can use them.
Here is how its supposed to look like
Now, i managed to figure out one part about running scripts:
private string RunPowershell_1(string skripta)
{
StringBuilder stringBuilder = new StringBuilder();
foreach (string str in PowerShell.Create().AddScript(skripta).AddCommand("Out-String").Invoke<string>())
{
stringBuilder.AppendLine(str);
}
return stringBuilder.ToString();
}
But i would normally run scripts that require parameters, so i would like to be able to read list of parameters from the script i import, assign value to them and then run the scrip (output should go to either txtPreview or to a file).
Is there a way to do this?
If there is another (better) approach to this I'm all ears.
You can use this powershell command to get the list of parameters.
(get-command get-netadapter).Parameters
And this is how you can read its output in C#:
using (PowerShell ps = PowerShell.Create())
{
ps.AddScript("...");
Collection<PSObject> output = ps.Invoke();
}

C# - Utilize Quest active directory cmdlets for Powershell by calling PS script

C# code (Source):
private string RunScript(string scriptText)
{
// create Powershell runspace
Runspace runspace = RunspaceFactory.CreateRunspace();
// open it
runspace.Open();
// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
// add an extra command to transform the script
// output objects into nicely formatted strings
// remove this line to get the actual objects
// that the script returns. For example, the script
// "Get-Process" returns a collection
// of System.Diagnostics.Process instances.
pipeline.Commands.Add("Out-String");
// execute the script
Collection<psobject /> results = pipeline.Invoke();
// close the runspace
runspace.Close();
// convert the script result into a single string
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
return stringBuilder.ToString();
}
Powershell code
#Dummy code for example purpose
ASNP Quest*
#Example of cmdlet I want to use
$Users = Get-QADGroupMember -Identity $Group -Enabled
return $Users.count
As you can see, my goal is to call the script utilizing RunScript above in a Button_Click event in my WPF app. I've been able to correctly call the script but the call to Quest cmdlets clearly doesn't go trough as wanted since I would receive 0 in the above example.
TL;DR
Script is running correctly but calls to Quest cmdlets don't work since it return nothing (or 0 in the above example). Is there something I'm missing ?
EDIT
Important to note that the exact same script ran in Powershell returns the correct values. Calling it from C# don't.

Setting variable in powershell from C#

I wonder if you could help me being gods of the C# world and all!
I'm pretty new to C# and i think im a bit out of my depth, but i am trying to use C# to create a wpf that will ask the user for parameters and then pass these parameters to my script to perform an install.
At the moment i have it set to click a button to begin the install as that was requested (no idea why) so on button click i have the following.
string script = System.IO.File.ReadAllText(#"C:\my\script\path\script.ps1");
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.Runspace.SessionStateProxy.SetVariable("SiteCode", GlobalVariables.sitecode);
ps.AddScript(script);
ps.Invoke();
}
My first problem is i need to set the script file location using partially a variable that has been set earlier in the form
Now this i can probably do myself, but calling the powershell script and then setting variables that are used within the powershell script from variables that are declared in the C# form are a bit out of my depth, am i on the right line here? do i look like a complete idiot or should i go bang my head on a tree outside?
Thanks very much in advance for any help you can offer!

Categories