The image shows the same powershell command executed in a C# and Powershell ISE. My question is, Powershell shows complete list of process and process directory, but the result of the code executed in C# does not contain windows processes like svchost.exe.
Of course, both my C# Form and Powershell ISE are running as Administrator.
Also, I made sure to code my form to launch with administrative privileges.
To be double sure, I executed my C# by right click - Run as Administrator (what I also did with Powershell ISE)
Command/s: Powershell and C#
get-process | get-item -erroraction silentlycontinue | format-table name, directory
get-process | format-table name, directory
Although this particular command shows all the process:
get-process
Unfortunately, combining it with the syntax above will show different output from C#.
private string RunScript(string script)
{
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(script);
pipeline.Commands.Add("Out-String");
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject pSObject in results)
stringBuilder.AppendLine(pSObject.ToString());
return stringBuilder.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
output.Clear();
output.Text = RunFilePs1(input.Text);
}
For some reason, Get-Process doesn't return the Path of some processes (probably the 64-bit ones) when running in 32-bit mode, so passing those to Get-Item fails to find anything.
You can see this by running your PS script from the x86 PS ISE.
So if you switch your C# Form to 64-bit, it will return all processes.
Related
I'm trying to write some C# code to interact with Lync using PowerShell, and I need to import the Lync module before executing the Lync cmdlets. However, my code doesn't seem to import the module and I keep getting a "get-csuser command not found" exception. Here is my code:
PowerShell ps = PowerShell.Create();
ps.AddScript(#"import-module Lync");
ps.Invoke();
ps.Commands.AddCommand("Get-csuser");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine(result.Members["Name"].Value);
}
Any idea how can I import the Lync module?
Got it, the module needs to be imported by its full path, and also the execution policy for both 64-bit powershell and 32-bit powershell need to be set to Unrestricted (or anything other than restricted depending on your case). Here's the code:
static void Main(string[] args)
{
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] {"C:\\Program Files\\Common Files\\Microsoft Lync Server 2010\\Modules\\Lync\\Lync.psd1"} );
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.Commands.AddCommand("Get-csuser");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine(result.Members["Identity"].Value);
}
}
Try to use the PowerShell class AddCommand method.
ps.AddCommand("import-module Lync");
Or you can use the Runspace class, you can find an example here : http://www.codeproject.com/Articles/18229/How-to-run-PowerShell-scripts-from-C
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.
I'm trying to write some C# code to interact with Lync using PowerShell, and I need to import the Lync module before executing the Lync cmdlets. However, my code doesn't seem to import the module and I keep getting a "get-csuser command not found" exception. Here is my code:
PowerShell ps = PowerShell.Create();
ps.AddScript(#"import-module Lync");
ps.Invoke();
ps.Commands.AddCommand("Get-csuser");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine(result.Members["Name"].Value);
}
Any idea how can I import the Lync module?
Got it, the module needs to be imported by its full path, and also the execution policy for both 64-bit powershell and 32-bit powershell need to be set to Unrestricted (or anything other than restricted depending on your case). Here's the code:
static void Main(string[] args)
{
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] {"C:\\Program Files\\Common Files\\Microsoft Lync Server 2010\\Modules\\Lync\\Lync.psd1"} );
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.Commands.AddCommand("Get-csuser");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine(result.Members["Identity"].Value);
}
}
Try to use the PowerShell class AddCommand method.
ps.AddCommand("import-module Lync");
Or you can use the Runspace class, you can find an example here : http://www.codeproject.com/Articles/18229/How-to-run-PowerShell-scripts-from-C
So a while back I wrote a Powershell script that would Parse an IIS Log and then do some stuff (email, create a report, and other nifty stuff). Well I am working on excuting that from a C# console app. Before I post my code I just wanted to make one thing clear, i would like to try and stay away from log parser to parse this log cause of many reasons but one specifically, why use something when you can write something else to your liking ;). So here is my code
PS Script:
$t1 =(get-date).AddMinutes(-10)
$t2 =$t1.ToUniversalTime().ToString("HH:mm:ss")
$IISLogPath = "C:\inetpub\logs\LogFiles\W3SVC1\"+"u_ex"+(get-date).AddDays(-3).ToString("yyMMdd")+".log"
$IISLogFileRaw = [System.IO.File]::ReadAllLines($IISLogPath)
$headers = $IISLogFileRaw[3].split(" ")
$headers = $headers | where {$_ -ne "#Fields:"}
$IISLogFileCSV = Import-Csv -Delimiter " " -Header $headers -Path $IISLogPath
$IISLogFileCSV = $IISLogFileCSV | where {$_.date -notlike "#*"}
$tape = $IISLogFileCSV | Format-Table time,s-ip,cs-uri-stem | Out-Host
C# app thus far:
Runspace runSpace = RunspaceFactory.CreateRunspace();
runSpace.Open();
Pipeline pipeline = runSpace.CreatePipeline();
pipeline.Commands.AddScript(#"D:\PS-Scripts\IIS\IISLogScan.ps1");
Collection<PSObject> results = pipeline.Invoke();
foreach (PSObject obj in results)
{
Console.WriteLine(results);
}
Console.ReadLine();
Now when I run my App it just sits and doesnt display anything and i Set my breakpoints and it says that there is nothing to display within my foreach which i am completely hung up on cause running my ps1 script it works perfectly and shows many lines. Any insight anyone can give would be great.
Try changing in .ps1 file:
$global:tape =$IISLogFileCSV | Format-Table time,s-ip,cs-uri-stem
and in c#
pipeline.Commands.AddScript(#"D:\PS-Scripts\IIS\IISLogScan.ps1");
pipeline.Commands.AddScript("$tape");
pipeline.Commands.AddScript("out-string");
or in .ps1:
$tape =$IISLogFileCSV | Format-Table time,s-ip,cs-uri-stem
$tape
and in c#
pipeline.Commands.AddScript(#"D:\PS-Scripts\IIS\IISLogScan.ps1");
pipeline.Commands.AddScript("out-string");