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();
Related
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.
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.
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
I am new to PowerShell. I am trying to execute PowerShell script from C#. PS Script that I have written transfer xml file from host computer (running PS script) to a remote computer. Script is as follows
$Username = "User"
$Password = "Pass"
$SecurePass = ConvertTo-SecureString -AsPlainText $Password -Force"
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$SecurePass"
$contents = [IO.File]::ReadAllBytes("D:\MyFile.xml")
Invoke-Command -ComputerName ComputerName -Credential $Cred {[IO.File]::WriteAllBytes("D:\MyFile.xml",$using:contents)}
I store username and password of remote computer, to which I want to transfer my file, in variables. Convert password to secure string and create a credential object containing username and password. Use credential to copy the contents of file from my computer to remote computer.
This code works fine if I execute these commands one by one from my powershell or by running these lines from a .ps1 powershell script from my computer.
I used following code in C# to execute above script and transfer the file.
Runspace runSpace = RunspaceFactory.CreateRunspace();
Pipeline pipeline = runSpace.CreatePipeline();
runSpace.Open();
string script = "";
script = "$Username = \"User\"\n";
script = script + "$Password = \"Pass\"\n";
script = script + "$SecurePass = ConvertTo-SecureString -AsPlainText $Password -Force\n";
script = script + "$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$SecurePass\n";
script = script + "$contents = [IO.File]::ReadAllBytes(\"D:\\MyFile.xml\")\n";
script = script + "Invoke-Command -ComputerName ComputerName -Credential $Cred {[IO.File]::WriteAllBytes(\"D:\\MyFile.xml\",$using:contents)}\n";
// pipeline.Runspace.SessionStateProxy.SetVariable
pipeline.AddScript(script);
Collection<PSObject> results = pipeline.Invoke();
However, it did not transfer the file. So, I thought I need to Add each line in script one by one to the pipeline and then execute it. So I changed it to following.
string[] commands = script.Split('\n');
foreach (string command in commands)
{
pipeline.AddScript(command);
}
Collection<PSObject> results = pipeline.Invoke();
It did not work either. I executed single Invoke-Command from C# code on my computer and it worked fine. Also, if I try to execute other single PS commands they work. So I assessed that setting variable values like this $User = "user" is not working through C#.
I used SessionStateSetProcy.SetVariable to Store variable values in powershell session as follows.
pipeline.Runspace.SessionStateProxy.SetVariable("User", "User");
pipeline.Runspace.SessionStateProxy.SetVariable("Password", "Pass");
var value = pipeline.Runspace.SessionStateProxy.GetVariable("Password");
Console.WriteLine(value);
So, I was able to set value and retrieve as well. But, since I was using Other cmdlets like ConvertTo-SecureString, I realized I need to execute these cmdlets separately in my code.
I finally I came up with following piece of code.
pipeline.Runspace.SessionStateProxy.SetVariable("User", "User");
pipeline.Runspace.SessionStateProxy.SetVariable("Password", "Pass");
Command command = new Command("ConvertTo-SecureString");
string pass_value = pipeline.Runspace.SessionStateProxy.PSVariable.GetValue("Password").ToString();
command.Parameters.Add("AsPlainText",pass_value);
command.Parameters.Add("Force");
pipeline.Runspace.SessionStateProxy.SetVariable("SecurePass",command);
/*Build a command2*/
Command command1 = new Command("New-Object");
string user_name = pipeline.Runspace.SessionStateProxy.PSVariable.GetValue("User").ToString();
command1.Parameters.Add("TypeName", "System.Management.Automation.PSCredential");
string args = user_name + " , "+pass_value;
command1.Parameters.Add("-ArgumentList", args);
pipeline.Runspace.SessionStateProxy.SetVariable("Cred", command1);
byte[] wifiXML = System.IO.File.ReadAllBytes(#"D:\MyFile.xml");
pipeline.Runspace.SessionStateProxy.SetVariable("contents", wifiXML);
Object a = pipeline.Runspace.SessionStateProxy.PSVariable.GetValue("contents");
string script = "Invoke-Command -ComputerName ComputerName -Credential $Cred {[IO.File]::WriteAllBytes(\"D:\MyFile.xml\",$using:contents)}";
pipeline.Commands.AddScript(script);
Collection<PSObject> results = pipeline.Invoke();
It gave some weird error in System.Management.Automation. I know in SetVariable I am doing it wrong by passing command variable.
I have tried PowerShell ps = PowerShell.Create() instead of pipeline as well and tried ps.AddCommand and ps.AddParameters followed by ps.AddArgument as well. But I am not sure that once I run cmdlet ConvertTo-SecureString through ps.AddCommad, ps.AddArgument etc., how should I set it's output value to $Cred variable?
I am aware that solution to this won't be this complicated and someone must have executed multiple line powershell script through C#. All I want to accomplish is execute the .ps1 script lines mentioned in very start from C# code.I have tried bunch of methods including mentioned above to no use, so any help related to it would be much appreciated?
Try in this way
string script = #"
$Username = 'User'
$Password = 'Password'
$SecurePass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$SecurePass
$contents = [IO.File]::ReadAllBytes('D:\MyFile.xml')
Invoke-Command -ComputerName ComputerName -Credential $Cred {[IO.File]::WriteAllBytes('D:\\MyFile.xml',$using:contents)}
";
pipeline.Commands.AddScript(script);
Collection<PSObject> results = pipeline.Invoke();
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