PowerShell script run from C# is lacking several modules - c#

var runspace = RunspaceFactory.CreateRunspace()
runspace.Open();
var ps = PowerShell.Create()
ps.Runspace = runspace;
ps.AddCommand(...);
ps.Invoke()
Some cmdlets that exist in a regular shell are missing from the runtime started by C#, e.g. all the commands from the Microsoft.PowerShell.LocalAccounts module :
Error: System.Management.Automation.CommandNotFoundException: The term 'New-LocalUser' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
By comparing the Get-Module -ListAvailable output from a regular shell and a C# started one I noticed multiple modules are missing :
AppBackgroundTask
AssignedAccess
BitLocker
ConfigCI
Defender
Microsoft.PowerShell.LocalAccounts
MMAgent
NetworkSwitchManager
PcsvDevice
PSWorkflow, PSWorkflowUtility
SmbShare, SmbWitness
StartLayout
WindowsSearch
The version ($PSVersionTable) is reported as the same in both shells : 5.1.14393.693
Edit
Seems to be the same issue & solution : Why do powershell modules not import when running powershell via start process in c#?

You can import modules directly on your script instead of trying to do that from C#.
Import-module bitlocker
For example.

Related

System.Diagnostics.Process closing powershell immediately

I have an issue where I'm trying to deploy a driver installation via an MSI Installer, it contains the .CAT and .INF files and outputs them to a directory, typically from here an infrastructure engineer could right click the .INF file and press install, however we're trying to streamline this process and automate this step.
Via C# I have a class utilising the System.Diagnostics.Process namespace to spawn a powershell process to run a powershell script containing a simple command as follows:
var process = new System.Diagnostics.Process();
var newProcessInfo = new System.Diagnostics.ProcessStartInfo();
string powerShellScript = #"C:\PowershellScript\DriverInstall.ps1"
newProcessInfo.FileName = #"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
newProcessInfo.Verb = "runas";
string newArgs = "-File " + powerShellScript;
newProcessInfo.Arguments = newArgs;
process.StartInfo = newProcessInfo;
process.Start();
Powershell script command is as follows:
Get-ChildItem "C:\DriverLocation" -Recurse -Filter "*inf" | ForEach-Object {PNPUtil.exe /add-driver $_.FullName /install }
when running this from powershell it works as expected, however if I try and spawn a powershell process from a C# class it doesn't work, comes up with some red error message text but the process windows spawns and closes immediately so I can't identify what the error is.
Essentially I either need the output from the powershell process to a text file or I need the powershell window to persist so I can identify why the script won't work when running from the System.Diagnostics.Process namespace.
I have tried editing the registries so that powershell will remain open to no avail.
Please don't suggest using the System.Management.Automation.Powershell namespace because utilisation of .NET core is unavailable in our project scenario.
Thanks for taking the time to read this, any help is much appreciated.
Resolution was to specify the execution policy within the powershell script, when running from the powershell window it had local admin rights and therefore didn't need an execution policy specified, however because it was being spawned from a separate process it only had remote access rights, therefore it wouldn't allow the script to execute.. never managed to output the particular error message but by process of elimination identified the resolution.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine

Powershell Cmdlet Invocation Inconsistency

I am trying to call the specific cmdlet "Get-VpnConnection" from a PowerShell instance in a Windows service (.NET Framework 4.7).
I have been able to call this cmdlet successfully in a command-line project (also .NET Framework 4.7) and have been able to call other cmdlets from within this service (e.g. "Get-Date"). I have selected the highest account permissions for the package installer (LocalSystem).
Here is an excerpt of what I've tried:
using (PowerShell ps = PowerShell.Create())
{
ps.AddCommand("Get-VpnConnection");
Collection<PSObject> results = ps.Invoke();
WriteToFile(results.Count.ToString());
}
When I run this from within the service, WriteToFile (a method I've created to write to a log text file in the program's base directory) will write "0" to the log whereas for "Get-Date" it would write "1". When I run this from within the main function of a command-line project, I get "1" as expected. No exceptions are thrown and no PowerShell Stream (Error or Verbose) contains anything. It's almost as if the cmdlet isn't being recognized as valid since providing a gibberish argument to AddCommand will produce an identical result.
Thank you for you time.

Invoking Powershell file blocks referenced Libraries

I am executing a Powershell script file from C# with the following code:
Runspace _rs = RunspaceFactory.CreateRunspace();
_rs.ApartmentState = ApartmentState.STA;
_rs.Open();
PipeLine _pipeLine = _rs.CreatePipeline();
Command scriptCommand = new Command(filePath);
_pipeLine.Invoke();
In the powershell script file I am referencing libraries:
Add-Type -Path Filepath.dll
In C# i am disposing the runspace and pipeline afterwords trying to unlock the associated libraries.
finally
{
_rs.Dispose();
_pipeLine.Dispose();
}
Unfortunately in a later step when trying to delete the dll files associated in the script, i get a UnauthorizedException. Please note that i dont get the exception if i never run the script from C#. I def should have accss to it.

Calling Powershell from C# doesn't use environment variables

I'm calling a powershell script from my C# application using:
System.Diagnostics.Process.Start("powershell.exe", " -executionpolicy unrestricted -file myscript.ps1");
Within this script is a call to Java (which relies on the CLASSPATH & PATH system variables). This is where the script fails and reports that:
java is not recognized as an internal command or external command
I believe this is because the system variables for PATH are not being used when I'm executing Powershell from C#. Any help ?
FYI, if I open Powershell manually and run the command it works correctly.

The term 'connect-QADService' is not recognized as the name of a cmdlet... inside C# function

Can someone, please, help to understand why the following code inside a Csharp function
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipe = runspace.CreatePipeline();
Command connectToActDir = new Command("connect-QADService");
connectToActDir.Parameters.Add("Service", "'ip:port'");
connectToActDir.Parameters.Add("ConnectionAccount", "'user.local\administrator'");
connectToActDir.Parameters.Add("ConnectionPassword", "'password'");
pipe.Commands.Add(connectToActDir);
pipe.Invoke();
causes the following error
The term 'connect-QADService' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
while ActiveRoles cmdlets are installed and running the equivalent command in power shell succeeds. Do I miss some dll in project references?
Thanks
The Quest ActiveRoles cmdlets are not loaded into a PowerShell session by default, because they're not part of PowerShell.
PowerShell 3 will automatically load modules when needed. I don't know if this holds true when using a RunSpace as I've never used PowerShell this way.
Do you load the Quest snap-in or module in your PowerShell profile? You'll need to do the equivalent in your C# code.

Categories