I'm working on a c# project where i'm trying to run powershell scripts, output them to a CSV and read the CSV and output it to a Checked list box.
I've added a powershell file as a resource with Build Action 'Compile' and Copy to output directory 'Do Not Copy'.
The basic content of the file is :
Get-CimInstance -Query "SELECT * from Win32_Service where name LIKE 'sql%'" | select Name, State , StartMode | convertto-csv > proctest.csv
i try to access this file using this string
string ps_path = System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + "\\GetSvc.ps1";
The PS code i use is
RunspaceConfiguration runspaceconfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceconfiguration);
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
Pipeline pipeline = runspace.CreatePipeline();
Command mycommand = new Command(ps_path);
pipeline.Commands.Add(mycommand);
pipeline.Invoke();
runspace.Close();
This works fine during compilation but when i build an exe and try to run it, i get an error saying the GetSvc.ps1 file is not found.
How do i make the file a part of the build ?!
Make the build action for the script be Embedded Resource. Then take a look at lines 149-155 on how to extract the script inside the C# exe. In this example, I had zipped the script to compact it. If you skip that step then you can remove line 152 and in line 153 use stream instead of gZipStream.
Related
I'm currently writing some code to execute PowerShell using C#.
Here is my code
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
// create a pipeline and feed it the script text
PowerShell ps = PowerShell.Create();
ps.Commands.AddScript(scriptText);
// execute the script
Collection<PSObject> results = ps.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();
I will pass my command through scriptText variable.
I tried some commands like "Get-Process", "Get-Service",... and it worked fine.
But when I tried "Get-BIOS" from GetBIOS module, it didn't. It returned an empty result.
I ran "Get-BIOS" command on the system's PowerShell with Admin's right, it showed a lot of information that I want.
What I've tried so far:
-Using app.manifest file to require Admin right when execute
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
-Or try execute this first to install the module first
scriptText = "install-module GetBIOS"
and execute this after
scriptText = "Get-BIOS"
But none of them worked.
How can I fix this, or can we have another way to do this?
Thanks in advance.
I figured it out.
Just try to change the project's Target Framework.
I've changed to .NET 4.8 and it worked.
I know we can can run physical powershell script from c# but how to create powershell script file itself dynamically based on input params.
Kindly suggest.
you can execute powershell script/ commands directly from your c# project.
you'll need to add a reference to system.managment.automation dll in project's references.
example:
function that will take script as a string , execute it and then returns a result:
private string RunScript(string script)
{
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipline = runspace.CreatePipeline();
pipline.Commands.AddScript(script);
pipline.Commands.Add("Out-String");
Collection<PSObject> results = pipline.Invoke();
runspace.Close();
StringBuilder stringBuilder = new StringBuilder();
foreach(PSObject pSObject in results)
{
stringBuilder.AppendLine(pSObject.ToString());
}
return stringBuilder.ToString();
}
function call be like:
Console.WriteLine(RunScript("Your Powershell Script"));
you can check out the full code examples on github - PowershellCommand-CSharp
This question already has an answer here:
Calling ps script file in c# using automation dll
(1 answer)
Closed 5 years ago.
I have the following c# code:
var runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
var runSpaceInvoker = new RunspaceInvoke(runspace);
runSpaceInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
// create a pipeline and feed it the script text
var pipeline = runspace.CreatePipeline();
var command = new Command(#". .\MyScript.ps1");
command.Parameters.Add("MyParam1", value1);
command.Parameters.Add("MyParam2", value2);
pipeline.Commands.Add(command);
pipeline.Invoke();
runspace.Close();
But I am getting the error Powershell ps1 file “is not recognized as a cmdlet, function, operable program, or script file.”
MyScript.ps1 is copied to the bin folder so it is at the same level as the running program.
I found this Powershell ps1 file "is not recognized as a cmdlet, function, operable program, or script file."
But it did not solve the problem. Any idea what else could cause this error?
Problem is likely that your application inherits its working directory from the parent process, so you can't predict that . refers to the directory in which the executable resides.
You could construct the full path to the script with something like:
using System.Reflection;
using System.IO;
// ...
string exePath = Assembly.GetExecutingAssembly().Location;
string exeFolder = Path.GetDirectoryName(exePath);
string scriptPath = Path.Combine(exeFolder,"MyScript.ps1");
var command = new Command(". " + scriptPath);
I'm attempting to execute a SQL Query from within Powershell, within C#. I have been successful in doing so with ActiveDirectory cmdlets and wanted to take it one step further.
My first issue is while the following format works with ActiveDirectory (and in the ISE) it fails in C#:
using (PowerShell pS = PowerShell.Create())
{
pS.AddCommand("import-module");
pS.AddArgument("sqlps");
pS.Invoke();
}
I've long since had the security set to Unrestricted, but the error I'm getting is:
CmdletInvocationException was unhandled
File C:\Program Files (x86)\Microsoft SQL Server\110\Tools\PowerShell\Modules\sqlps\Sqlps.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at http://go.microsoft.com/fwlink/?LinkID=135170.
However, if I run like this I get no error, though a later "Get-Module -all" call shows no sign of the module:
using (PowerShell pS = PowerShell.Create())
{
pS.AddScript("Import-Module sqlps");
pS.Invoke();
}
If I then try importing the ActiveDirectory module and calling Get-Module, it shows nothing.
What's going on here?
I'm not that great with C sharp but when calling scripts from outside of powershell there is a flag when executing the program to bypass the execution policy, i.e.
powershell.exe -executionpolicy bypass -command "& '\\somepath\somescript.ps1' "
This allows remote scripts to be called, as even with unrestricted set I still found that it wanted to prompt for the execution of some scripts so for instance in the task scheduler it would simply fail to run.
Also when importing SQLPS I've also found it's useful to add the -DisableNameChecking flag, you may also want to push your location beforehand and pop it afterwards otherwise you will end up in the SQLPS PSdrive with no access to local locations if you need it.
Did you try something like this?
PowerShell ps = PowerShell.Create();
ps.AddScript("set-executionpolicy unrestricted -scope process");
ps.AddScript("import-module sqlps");
ps.AddScript("get-module sqlps");
var m = ps.Invoke();
foreach (var mm in m.Select(x => x.BaseObject as PSModuleInfo))
Console.WriteLine(new { mm.Name, mm.Version });
I had a similar issue with the sqlServer ps module. Looks like when executing from C# you need to load the modules manually into the runspace in order for this to work.
string scriptText = File.ReadAllText("yourScript.ps1");
//This is needed to use Invoke-sqlcommand in powershell. The module needs to be loaded into the runspace before executing the powershell.
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] { #"SqlServer\SqlServer.psd1" });
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
using (PowerShell psInstance = PowerShell.Create())
{
psInstance.Runspace = runspace;
psInstance.AddScript(scriptText);
var PSOutput = psInstance.Invoke();
}
Also add all the references located in the SqlServer.psd1. This file is usually found in "C:\Program Files\WindowsPowerShell\Modules\SqlServer". I added to folder to my solution to be able to execute on remote servers.
You need to add Microsoft.SqlServer.BatchParser.dll reference in order to execute invoke-sqlcommand from the Powershell.
You should be able to do the same for sqlps module. Rather use SqlServer as it is newer.
I need to start a powershell script from C# and get the PSSSecurityException on pipeline.Invoke()
AuthorizationManager check failed.
My code:
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
using (Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration))
{
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
Command scriptCommand = new Command(scriptfile);
pipeline.Commands.Add(scriptCommand);
pipeline.Invoke();
}
Questions
I suspect that I need to set PSCredential. But I can not promt for it, so I have to handle this in code. Can this be done in a secure way? (This was not the case)
Check out this SuperUser post: https://superuser.com/questions/106360/how-to-enable-execution-of-powershell-scripts
You probably just need to allow unsigned scripts to run. In the PS console, type the following:
set-executionpolicy remotesigned
Another resource echoes this: http://tgnp.me/2011/09/powershell-authorizationmanager-check-failed-resolution/
Give that a try and let me know what happens.
To capture the output from the script, try this:
Collection output = pipeline.Invoke();
foreach (PSObject psObject in output)
{
<here you can ToString the psObject for the output and write it line by line to your log>
}
The problem was that the script was placed on a share. To run scripts on this share I needed to add the share to Trusted Sites.