powershell cmdlet C#? - c#

I'm tired to search about way to use powershell in C#, this first time to use Powershell and I don't know how to add it in C#, i have my codes working in Powershell any help to add in C#?
New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts"
New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList"
New-ItemProperty -path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" -name BigBear -value "0" -propertyType DWord
(BigBear) it's name and I want to change it with textbox
i tried this
private void Shell()
{
using (var runspace = RunspaceFactory.CreateRunspace())
{
// using (var powerShell = PowerShell.Create())
// {
// powerShell.Runspace = runspace;
// powerShell.AddScript(#"Hidden.ps1");
// //powerShell.AddParameter("UserName", UserName.Text);
// powerShell.Invoke();
// }
using (var powerShell = PowerShell.Create())
{
powerShell.Runspace = runspace;
powerShell.AddCommand("New-Item -Path \"HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\SpecialAccounts\"");
powerShell.AddCommand("New-Item -Path \"HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\SpecialAccounts\\UserList\"");
powerShell.AddCommand("New-ItemProperty -path \"HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\SpecialAccounts\\UserList\" -name " + UserName.Text + " -value \"0\" -propertyType DWord");
//powerShell.AddParameter("ParamA", varA);
var results = powerShell.Invoke();
// Do whatever with results
}
}

What have you tried?
Here are some links that describes how it can be done. But your question is not very detailed on your requirements... The last one have code you can download and try/modify!
https://blogs.msdn.microsoft.com/kebab/2014/04/28/executing-powershell-scripts-from-c/
http://www.codeproject.com/Articles/18229/How-to-run-PowerShell-scripts-from-C

Related

How to run PowerShell comands in C#

In cmd I write this and it works (this command removes N first lines from file):
powershell.exe
$file = "C:\Test\file.txt"
$content = Get-Content $file
$content[10..($content.length-1)]|Out-File $file -Force
I want to write this code on C# but my way isn't correct. Can you explain why?
using (PowerShell ps = PowerShell.Create())
{
ps.AddCommand($"$file = \"{fullPathToTxt}\"")
.AddCommand("$content = Get-Content $file")
.AddCommand($"$content[{numLine}..($content.length-1)]|Out-File $file -Force")
.Invoke();
}
Instead of AddCommand, i have to use AddScript method.
You can use this command for execute powershell script
PowerShell ps = PowerShell.Create();
ps.AddScript(File.ReadAllText(#"D:\PSScripts\MyScript.ps1")).Invoke();

Powershell return different results running the same script from c#

I am trying to run a simple script for getting file attributes.
string script = #"$path = 'C:\Temp\Indexing\Asm1.asm'
$shell = New-Object -COMObject Shell.Application
$folder = Split-Path $path
$file = Split-Path $path -Leaf
$shellfolder = $shell.Namespace($folder)
$shellfile = $shellfolder.ParseName($file)
0..500 | Foreach-Object { '{0} = {1}' -f $shellfolder.GetDetailsOf($null, $_), $shellfolder.GetDetailsOf($shellfile, $_).toString()}";
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();
When running within powershell I get more attribute results which are empty when running it through the code.
It seems like an access issue.
any help will be much appreciated!
Try adding #!/usr/bin/env pwsh as first line of the script.

Output of a runspace factory in c#

I run this c# code in a asp.net application. I use c# to execute a powershell file. The powershell file search for a mailbox and delete a particular email.
The execution works, but when I try to get the output, I get a System.NullReferenceException'.
The problem is this line :
weboutput.InnerHtml += result.Members["Success"].ToString();
I tried various things to get some values :
pipeline.Commands.Add("Out-String");
I added/removed : |Out-String in the powershell file.
I tried with result.properties, then I tried to cast the object and it outputed like this :
weboutput.InnerHtml += result.ToString();
It gives me the following :
Microsoft.Exchange.InfoWorker.Common.Search.SearchMailboxResult
So here is the c# code :
InitialSessionState initialSession = InitialSessionState.CreateDefault();
initialSession.ImportPSModule(new[] { "MSOnline" });
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
Pipeline pipeline = runspace.CreatePipeline();
Command connectCommand = new Command(#"C:\DeleteMail.ps1");
using (Runspace psRunSpace = RunspaceFactory.CreateRunspace(initialSession))
{
// Open runspace.
psRunSpace.Open();
//Iterate through each command and executes it.
foreach (var com in new Command[] { connectCommand })
{
var pipe = psRunSpace.CreatePipeline();
pipe.Commands.Add(com);
// Execute command and generate results and errors (if any).
//Collection<PSObject> results = pipe.Invoke();
foreach (PSObject result in pipe.Invoke()) {
weboutput.InnerHtml += result.Members["Success"].ToString();
}
var error = pipe.Error.ReadToEnd();
}
// Close the runspace.
psRunSpace.Close();
}
}
Here is the powershell file.
Import-Module MsOnline
$AdminUsername = "admin#domain.com"
$AdminPassword = "SuperSecret!111"
$SecurePassword = ConvertTo-SecureString $AdminPassword -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $AdminUsername,$SecurePassword
Connect-MSOLService -Credential $cred
$exchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential $cred -Authentication "Basic" -AllowRedirection
Import-PSSession $exchangeSession –DisableNameChecking
Get-Mailbox -ResultSize unlimited -Filter {Name -eq "bigboss"} | Search-Mailbox -SearchQuery "me#domain.com Subject:'test'" -DeleteContent -Force | Out-String
Finally here is the output when I run the powershell file alone.
RunspaceId : random #
Identity : bigboss
TargetMailbox :
Success : True
TargetFolder :
ResultItemsCount : 1
ResultItemsSize : 124 KB (124 kilobytes)
How can I get the output of the file and/or how can I parse the values of the PSObject ?

Get powershell script text that is executed before calling System.Management.Automation.PowerShell.Invoke()

Is there a way to get text of executed powershell script in C#.
For example:
using (PowerShell powerShellInstance = PowerShell.Create())
{
Collection<PSObject> result;
// psScript object is script text loaded from some .ps1 file
powerShellInstance.AddScript(psScript);
//parameters object is list of passed parameters
powerShellInstance.AddParameters(parameters);
result = powerShellInstance.Invoke();
}
Can we get executed script text anywhere in above code so we could just copy it and try to execute it directly in powershell.
EDIT:
My .ps1 script file looks like this:
param($CustomerPrimaryO365Domain, $AdminUsername, $AdminPassword, $Domain)
#####################################################################################################################################################################
function Get-CustomerDomain()
#####################################################################################################################################################################
{
$O365Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AdminUsername,(ConvertTo-SecureString -AsPlainText -Force -String $AdminPassword)
Connect-MsolService -Credential $O365Cred
$tenID=(Get-MSOLPartnerContract -Domain $CustomerPrimaryO365Domain).tenantId.guid
Get-MsolDomain -DomainName $Domain -TenantId $tenID
}
Import-Module MSOnline
Get-CustomerDomain
But when it is executed it needs to look something like this:
#####################################################################################################################################################################
function Get-CustomerDomain()
#####################################################################################################################################################################
{
$O365Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "MyAdmin#test.test",(ConvertTo-SecureString -AsPlainText -Force -String "testpassword")
Connect-MsolService -Credential $O365Cred
$tenID=(Get-MSOLPartnerContract -Domain "mydomain.onmicrosoft.com").tenantId.guid
Get-MsolDomain -DomainName "testdomain.info" -TenantId $tenID
}
Import-Module MSOnline
Get-CustomerDomain
Is there a way to get "executed" script from powerShellInstance object.

Passing Variables from C# to Powershell

I am working on a C# project that that is supposed to grab a string variable (file path) and pass it to PowerShell script to have further commands done with it. I have been looking around online and through Stack and have not been able to find something that works for me...
Here is my C# code as it stands right now:
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.AddScript(script);
ps.Invoke();
ps.AddCommand("LocalCopy");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine(result);
}
}
Here is my PowerShell script:
Function LocalCopy
{
Get-ChildItem -path "C:\Users\file1\file2\file3\" -Filter *.tib -Recurse |
Copy-Item -Destination "C:\Users\file1\file2\local\"
}
What I want to do is have the first part of the the script: "C:\Users\file1\file2\file3\" replaced with (what i am assuming would be) a variable that I could pass from the C# code to the PowerShell script. I am very new to working with PowerShell and am not quite sure how I would go about doing something like this.
---EDIT---
I am still having issues with my code, but i am not getting any errors. I believe that it is because the variable is still not being passed through...
C# code:
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.AddScript(script);
ps.Invoke();
ps.AddArgument(FilePathVariable);
ps.AddCommand("LocalCopy");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine(result);
}
}
PowerShell code:
Function LocalCopy
{
$path = $args[0]
Get-ChildItem -path $path -Filter *.tib -Recurse |
Copy-Item -Destination "C:\Users\file1\file2\local\"
}
Any help would be much appreciated. Thanks!
I would go the route Anand has shown to pass a path into your script. But to answer the question posed by your title, here's how you pass variable from C#. Well this is really how you set the variable in the PowerShell engine.
ps.Runspace.SessionStateProxy.SetVariable("Path", #"C:\Users\file1\file2\file3\");
Note: in C# for file paths you really want to use verbatim # strings.
Update: based on your comments, try this:
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.AddScript(script, false); // Use false to tell PowerShell to run script in current
// scope otherwise LocalCopy function won't be available
// later when we try to invoke it.
ps.Invoke();
ps.Commands.Clear();
ps.AddCommand("LocalCopy").AddArgument(FilePathVariable);
ps.Invoke();
ps.AddArgument("C:\Users\file1\file2\file3\");
you can use args to fetch the argument in powershell.
$path = $args[0]
MSDN

Categories