Invoking Powershell file blocks referenced Libraries - c#

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.

Related

Execute PowerShell script without 'PowerShell.SDK'

I want to execute the PowerShell script without SDK. In my project, I have to execute the PowerShell script and also want to create an EXE file for the same. But the problem is:
When I remove Microsoft.PowerShell.SDK then the script is not executed and gives an error but creates an exe file. Error is "Cannot load PowerShell snap-in Microsoft.PowerShell.Diagnostics because of the following error: Could not load file or assembly".
When the above package is not removed from the project then the script is working fine but it gives an error while creating an exe file.
Please share your suggestion.
Here is my code:
string readLocationFile = File.ReadAllText(#"gravity_location.ps1");
using (PowerShell powerShell = PowerShell.Create())
{
powerShell.AddScript(readLocationFile);
powerShell.AddParameter("name", _locationName.Text);
powerShell.AddParameter("targetPath", filePath);
powerShell.Invoke();
}
You can use System.Management.Automation which is the core of the PowerShell SDK like this
using System.Management.Automation;
using System.Management.Automation.Runspaces;
//...
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
//Here's how you add a new script with arguments
Command myCommand = new Command("your/script/file/path.ps1");
CommandParameter testParam = new CommandParameter("key","value"); //e.g. "-Path" "value"
myCommand.Parameters.Add(testParam);
pipeline.Commands.Add(myCommand);
// Execute PowerShell script
results = pipeline.Invoke();
Detailed information about the packages.
https://learn.microsoft.com/en-us/powershell/scripting/dev-cross-plat/choosing-the-right-nuget-package?view=powershell-7.2
Another post about the topic:
Execute PowerShell Script from C# with Commandline Arguments

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 script run from C# is lacking several modules

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.

How to get PowerShell script execution error - System.Management.Automation.dll

I execute a PowerShell script from C# code. I use System.Management.Automation.dll Nuget package. Although my script has an obvious error, powerShell.Invoke() returns no results, nor error messages.
using (var powerShell = PowerShell.Create())
{
powerShell.AddScript("an erroneous script");
powerShell.Invoke(); // yields an empty PSObject list
}
How can I get a list of errors?

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