How to input parameters without using command-line parameters - c#

I need to launch program jphide (https://github.com/h3xx/jphs) many times in the cycle
Example:
jphide input-jpeg-file output-jpeg-file file-to-be-hidden
I tryed to use command line to transmit the parameters to program
public static void Hide(string imagePath, string passWord)
{
Collection<PSObject> results;
string fullPath = System.IO.Path.GetFullPath(imagePath);
string pathToOutFile = ".\\outImages\\" + imagePath;
pathToOutFile = System.IO.Path.GetFullPath(pathToOutFile);
System.IO.File.WriteAllLines("test.txt", new string[] { passWord });
string hiddenFile = System.IO.Path.GetFullPath(#".\test.txt");
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
Pipeline pipeline = runspace.CreatePipeline();
//Here's how you add a new script with arguments
Command myCommand = new Command(#".\script.bat");
CommandParameter pathParameter = new CommandParameter(fullPath);
CommandParameter passWordParameter = new CommandParameter(passWord);
CommandParameter pathToOutputFileParameter = new CommandParameter(pathToOutFile);
CommandParameter pathToHiddenFileParameter = new CommandParameter(hiddenFile);
myCommand.Parameters.Add(pathParameter);
myCommand.Parameters.Add(passWordParameter);
myCommand.Parameters.Add(pathToOutputFileParameter);
myCommand.Parameters.Add(pathToHiddenFileParameter);
pipeline.Commands.Add(myCommand);
// Execute PowerShell script
results = pipeline.Invoke();
}
script.bat
jphide "%1" "%3" "%4"
%2
%2
But in doesn't work. This program after executing
jphide input-jpeg-file output-jpeg-file file-to-be-hidden
ask me Passphrase 2 times
C:\Users\Kostyaj\Downloads\JpegTest\JpegTest\JpegTest\bin\Debug>jphide 067.jpg 068.jpg test.txt
Welcome to jphide Rev 0.51 (c) 1998 Allan Latham <alatham#flexsys-group.com>
This program is freeware.
No charge is made for its use.
Use at your own risk. No liability accepted whatever happens.
Contains cryptogaphy which may be subject to local laws.
Passphrase:
Re-enter :
which i need to input manually
How i can write script or change C# code to automate input Passphrase and Re-enter?
UPD
This code
var info = new ProcessStartInfo("cmd.exe");
info.UseShellExecute = false;
info.RedirectStandardInput = true;
var process = Process.Start(info);
Thread.Sleep(1000);
process.StandardInput.WriteLine("jphide \"" + pathParameter.Name + "\" \"" + pathToOutputFileParameter.Name +
"\" \"" + pathToHiddenFileParameter.Name + "\"");
process.StandardInput.WriteLine("echo " + passWord);
creates this output in the command line:
jphide "C:\Users\Kostyaj\Downloads\JpegTest\JpegTest\JpegTest\bin\Debug\067.jpg" "C:\Users\Kostyaj\Downloads\JpegTest\JpegTest\JpegTest\bin\Debug\outImages\067.jpg" "C:\Users\Kostyaj\Downloads\JpegTest\JpegTest\JpegTest\bin\Debug\test.txt" || echo aaa
Welcome to jphide Rev 0.51 (c) 1998 Allan Latham <alatham#flexsys-group.com>
This program is freeware.
No charge is made for its use.
Use at your own risk. No liability accepted whatever happens.
Contains cryptogaphy which may be subject to local laws.
Passphrase:
Re-enter :
C:\Users\Kostyaj\Downloads\JpegTest\JpegTest\JpegTest\bin\Debug>echo 1234
1234
But the program had been stopped to wait input of PassPhrase. I typed it and the execution went on
I need to input "1234" automatically in the program jphide

If you redirect the standard input you can then write to the standard input to fill in the passphrase, for example:
var info = new ProcessStartInfo("cmd.exe");
info.UseShellExecute = false;
info.RedirectStandardInput = true;
var process = Process.Start(info);
Thread.Sleep(1000);
process.StandardInput.WriteLine("echo Hello World");

Related

Calling powershell script with C# - passing in string array as argument in powershell

I am writing C# code to execute a powershell script.
The powershell script has two arguments:
subscriptionId of type string
resourceGroupNames of type string[]
Problem:
When running the C# program, the resourceGroupNames that is passed a is not being read by the powershell script.
Additionally, when running the C# program, powershell prompts me a message "Do you want to run this script?" Is there anyway to suppress this alert and have the powershell script to run automatically?
Here is my code:
Note that chefRepo is the path of the powershell script.
public void DoDeploymentRTM(string chefRepo, string subscriptionId, string[] resourceGroupNames)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = #"powershell.exe";
startInfo.Arguments = String.Format(#"& '{0}\AzurePowerShellScripts\azureVMStatusFetch.ps1' -subscriptionId {1} -resourceGroupNames {2}", chefRepo, subscriptionId, resourceGroupNames);
startInfo.Verb = "runas";
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
}
For passing an array as powershell argument you need to separate it's values by commas i.e. for integers you would pass e.g 1,2,3.
For string you need additional quotation marks (in case some items contain space) e.g.'first string','second string','third'.
In C# you would do this by
string.Join(',', resourceGroupNames.Select(x => "'" + x + "'"))
In order to make this approach work when calling by ProcessStartInfo you need to use powershell option -Command so that the array would be parsed correctly (see more details in question).
Concerning your second problem use powershell commandline option -ExecutionPolicy UnRestricted
Finally you just need to change your Arguments like this:
startInfo.Arguments = String.Format("-ExecutionPolicy UnRestricted -Command &\"'{0}\\AzurePowerShellScripts\\azureVMStatusFetch.ps1' - subscriptionId {1} -resourceGroupNames {2}\"", chefRepo, subscriptionId, string.Join(',', resourceGroupNames.Select(x => "'" + x + "'")));
or easier (for C# 7.0 or higher)
startInfo.Arguments = $"-ExecutionPolicy UnRestricted -Command &\"'{chefRepo}\\AzurePowerShellScripts\\azureVMStatusFetch.ps1' - subscriptionId {subscriptionId} -resourceGroupNames {string.Join(',', resourceGroupNames.Select(x => $"'{x}'"))}\"";

How to call Powershell script using web API (cs or asp.net)

Below is the function to keep server in SCOM maintenance mode and I would like to call this function through cs or asp.net as API call by passing variables.
function set-scomderegister {
param(
[Parameter( Mandatory = $True, ValueFromPipeline = $true)][string]
$SCOMServer,
[Parameter( Mandatory = $True, ValueFromPipeline = $true)]
$Computername
)
ForEach($Comp in $Computername)
{
New-SCManagementGroupConnection -ComputerName $SCOMServer
$numberOfMin = 100
$ReasonComment = "Server got docomissioned "
$Instance = Get-SCOMClassInstance -Name $Comp
$Time = ((Get-Date).AddMinutes($numberOfMin))
Start-SCOMMaintenanceMode -Instance $Instance -EndTime $Time -Comment $ReasonComment -Reason PlannedOther;
}
}
System.Management.Automation namespace would be useful for you.
You can install a nuget package "System.Management.Automation".
Once this is installed you will have this namespace available.
You can invoke a script with parameter as shown below:
public void RunWithParameters()
{
// create empty pipeline
PowerShell ps = PowerShell.Create();
// add command
ps.AddCommand("test-path").AddParameter("Path", Environment.CurrentDirectory); ;
var obj = ps.Invoke();
}
private string RunScript(string scriptText)
{
// create Powershell runspace
Runspace runspace = RunspaceFactory.CreateRunspace();
// open it
runspace.Open();
// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
// add an extra command to transform the script
// output objects into nicely formatted strings
// remove this line to get the actual objects
// that the script returns. For example, the script
// "Get-Process" returns a collection
// of System.Diagnostics.Process instances.
pipeline.Commands.Add("Out-String");
// execute the script
Collection<psobject /> results = pipeline.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();
}
There is another option to use Process.Start to start the powershell prompt. Then pass the file path to the process.
public static int RunPowershellScript(string ps)
{
int errorLevel;
ProcessStartInfo processInfo;
Process process;
processInfo = new ProcessStartInfo("powershell.exe", "-File " + ps);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
process = Process.Start(processInfo);
process.WaitForExit();
errorLevel = process.ExitCode;
process.Close();
return errorLevel;
}
Hope this helps.

Passing C# Parameter to Powershell Script - Cannot validate argument on parameter 'Identity'

I am trying to write a Windows Form App in C# that outputs AD Attributes for a specified user. The way I want it to work is that the user inputs a value (username) into a text box, which is passed as a parameter to the Powershell script and the output is displayed in the form.
My C# code for creating the parameter and invoking the script is as follows:
private string RunScript(string scriptText)
{
// create Powershell runspace
Runspace runspace = RunspaceFactory.CreateRunspace();
// open it
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
pipeline.Commands.Add(new Command("Set-ExecutionPolicy Unrestricted -Scope Process", true));
// "Get-Process" returns a collection of System.Diagnostics.Process instances.
pipeline.Commands.Add("Out-String");
//Create parameter and pass value to script
String username = textBox3.Text;
String scriptfile = #"c:\\scripts\\getpasswordexpirydate.ps1";
Command myCommand = new Command(scriptfile, false);
CommandParameter testParam = new CommandParameter("username", username);
myCommand.Parameters.Add(testParam);
pipeline.Commands.Add(myCommand);
// execute the script
Collection<PSObject> results = pipeline.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 the results of the script that has
// now been converted to text
return stringBuilder.ToString();
}
My PowerShell script is as follows:
param([string]$username)
function Get-XADUserPasswordExpirationDate() {
Param ([Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="Identity of the Account")]
[Object] $accountIdentity)
PROCESS {
$accountObj = Get-ADUser $accountIdentity -properties PasswordExpired, PasswordNeverExpires, PasswordLastSet
if ($accountObj.PasswordExpired) {
echo ("Password of account: " + $accountObj.Name + " already expired!")
} else {
if ($accountObj.PasswordNeverExpires) {
echo ("Password of account: " + $accountObj.Name + " is set to never expires!")
} else {
$passwordSetDate = $accountObj.PasswordLastSet
if ($passwordSetDate -eq $null) {
echo ("Password of account: " + $accountObj.Name + " has never been set!")
} else {
$maxPasswordAgeTimeSpan = $null
$dfl = (get-addomain).DomainMode
if ($dfl -ge 3) {
## Greater than Windows2008 domain functional level
$accountFGPP = Get-ADUserResultantPasswordPolicy $accountObj
if ($accountFGPP -ne $null) {
$maxPasswordAgeTimeSpan = $accountFGPP.MaxPasswordAge
} else {
$maxPasswordAgeTimeSpan = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge
}
} else {
$maxPasswordAgeTimeSpan = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge
}
if ($maxPasswordAgeTimeSpan -eq $null -or $maxPasswordAgeTimeSpan.TotalMilliseconds -eq 0) {
echo ("MaxPasswordAge is not set for the domain or is set to zero!")
} else {
echo ("Password of account: " + $accountObj.Name + " expires on: " + ($passwordSetDate + $maxPasswordAgeTimeSpan))
}
}
}
}
}
}
Get-XADUserPasswordExpirationDate $username
Get-ADUser $username -Properties * | Select-Object DisplayName,LockedOut,LastLogonDate,kPMG-User-GOAccountType,kPMG-User-GOCompanyGroup,kPMG-User-GOFunction,kPMG-User-GOGrade,kPMG-User-GOManagementLevel,kPMG-User-GOMemberFirmGroup,kPMG-User-GPID,kPMG-User-GOMailDisclaimer,kPMG-User-GOMailSync
If I run the script in PowerShell e.g. .\script.ps1 jsmith with 'jsmith' as the parameter it works, however when using the C# parameter it does not accept the parameter and spits out a "Cannot validate argument on parameter 'Identity'" error every time.
Is there something I have done wrong in my C# code that is causing this parameter to not pass to the script and accept it as input?
Thanks
A few thoughts:
The parameter name in the C# code is username
The parameter name in the script is accountIdentity
The error message references parameter Identity
I would think all 3 should be the same.
If that's not the problem then a possible way to debug the problem is to turn your C# code into a PS script. For me, at least, I'd feel more comfortable debugging a PS script where I can rapidly change things (like where you build myCommand) and inspect them (with get-member and select-object *) than you might with C#.
Also for debugging you might also try combining all the individual PS commands so that you end with a single invocation of AddScript(), instead of various AddCommand()s along with the AddScript(). I vaguely remember problems with mixing the two when I wrote somewhat similar code many years ago.

wraping powershell script from C#

i'm trying to wrap an already made powershell script with C# GUI client.
the script acts according to inputs from the user, and it has also outputs according to them.
i would like to get the powershell outputs, display them to my C# client and
and then to enter the input according to his choice.
this is my script, and the code below is what i came up to but it doesn't work.
(i can only get the output at the end, and only if i don't have Read-Host in my powershell script). hope that it helps some how.
Write-Host
Write-Host 'Hello World!'
Write-Host "Good-bye World! `n"
$option = Read-Host "Please enter your number"
switch ($option){
"1"
{
Write-Host "jack"
}
"2"
{
Write-Host "john"
}
"3"
{
Write-Host "joe"
}
}
public void WrapPowerShell()
{
string directory = Directory.GetCurrentDirectory();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = #"powershell.exe";
startInfo.Arguments = string.Format(#"& '{0}'", directory + #"\hello.ps1");
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = false;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
string output = process.StandardOutput.ReadToEnd();
// Assert.IsTrue(output.Contains("StringToBeVerifiedInAUnitTest"));
string errors = process.StandardError.ReadToEnd();
}
Big Thanks in advance For your answers!!
This is a helper class that I wrote to help me create an ASP.NET web app that allowed people to run powershell scripts.
PSHelper.cs
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Text;
namespace admin_scripts {
public class PSHelper {
// See the _ps_user_lookup method for demonstration of using this method
public static Runspace new_runspace() {
InitialSessionState init_state = InitialSessionState.CreateDefault();
init_state.ThreadOptions = PSThreadOptions.UseCurrentThread;
init_state.ImportPSModule(new[] { "ActiveDirectory", "C:\\ps_modules\\disable_user.psm1" });
// Custom PS module containing functions related
// to disabling AD accounts at work.
// You would use your own module here, obviously.
return RunspaceFactory.CreateRunspace(init_state);
}
// This method is for dead-simple scripts that you only want text output from
// Not as flexible as the previous method, but it's good for the really simple cases
public static string run_simple_script( string body ) {
Runspace runspace = new_runspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(body);
pipeline.Commands.Add("Out-String");
Collection<PSObject> output = pipeline.Invoke();
runspace.Close();
StringBuilder sb = new StringBuilder();
foreach( PSObject line in output ) {
sb.AppendLine(line.ToString());
}
return sb.ToString();
}
}
}
I would invoke a script from an ASP.NET handler like so:
private PSObject _ps_user_lookup( string id_param ) {
Runspace runspace = PSHelper.new_runspace();
runspace.Open();
using( Pipeline pipe = runspace.CreatePipeline() ) {
Command cmd = new Command("Get-ADUser");
cmd.Parameters.Add(new CommandParameter("Identity", id_param));
cmd.Parameters.Add(new CommandParameter("Properties", "*"));
cmd.Parameters.Add(new CommandParameter("Server", "REDACTED"));
pipe.Commands.Add(cmd);
return pipe.Invoke().FirstOrDefault();
}
}
The real beauty of this arrangement is that the web application would run the script using the credentials of the web user's domain account. I hope you find it useful.

Execute Powershell script in C# without UserName and Password

How I will execute the Powershell script in C# without use of UserName and Password?
Powershell Script:
#Script:This Script generate the Package (Zip file) dynamically for unittest
#DirectoryName is Out Directory of Unittest execution
#location is Out\Resource Directory
#locationdetail is Array of files Directory for generate the Package
#FileName is name of Package generated through this script
#option is use for switch case implementation,currently not implemented
param(
[string]$DirectoryName="."
, [string]$location=""
, [string]$FileName="Test.zip"
, [int] $option
)
[System.Reflection.Assembly]::LoadFrom($DirectoryName+"\\"+"Ionic.Zip.dll");
$locationdetail = "Package\\Resource", "Package\\ResourceBad", "Package\\ResourceEmptymetada","Package\\ResourceEmptydatafile","Package\\EmptyTest"
$directoryToZip=""
foreach ($element in $locationdetail)
{
If($element -eq "Package\\Resource")
{
$directoryToZip= $location+"\\"+"Package\\Resource"
$FileName ="Package (Good Data).zip"
}
If($element -eq "Package\\ResourceBad")
{
$directoryToZip= $location+"\\"+"Package\\ResourceBad"
$FileName ="Package (Bad Data).zip"
}
If($element -eq "Package\\ResourceEmptymetada")
{
$directoryToZip= $location+"\\"+"Package\\ResourceEmptymetada"
$FileName ="Package (Bad with ManifestEmpty).zip"
}
If($element -eq "Package\\ResourceEmptydatafile")
{
$directoryToZip= $location+"\\"+"Package\\ResourceEmptydatafile"
$FileName ="Package (Bad with Datafile Empty).zip"
}
If($element -eq "Package\\EmptyTest")
{
$directoryToZip= $location+"\\"+"Package\\EmptyTest"
$FileName ="EmptyTest.zip"
}
$zipfile = new-object Ionic.Zip.ZipFile
$e= $zipfile.AddDirectory($directoryToZip)
$zipfile.Save( $location+"\\"+$FileName)
$zipfile.Dispose()
$directoryToZip=""
}
and My C# code
private static void StartPowerShell(string args,string TempScript)
{
string powerShellPath ="C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe";
string commandLine = #" -Sta -Command ""& {{ try {{ {0} }} catch {{throw}} }} """.InvariantCultureFormat(args);
var info = new ProcessStartInfo();
info.FileName = powerShellPath;
info.Arguments = commandLine;
info.WorkingDirectory = Environment.CurrentDirectory;
info.UseShellExecute = false;
info.CreateNoWindow = false;
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
//Pass the Username and Password here in ProcessStartInfo
info.UserName = "Saroop";
string pw = "saroop";
System.Security.SecureString password = new System.Security.SecureString();
foreach (var item in pw)
{
password.AppendChar(item);
}
info.Password = password;
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
Process p = new Process();
p.StartInfo = info;
bool flag = p.Start();
string error = p.StandardError.ReadToEnd();
p.WaitForExit();
}
Please guide me anyone. I try to use runas command to start my Powershell.exe as a User(Administrator) but it's also ask for Username and Password.
I try for System.Management.Automation. dll but it's no more existed in .Net4.0
Reference link :
http://msdn.microsoft.com/en-us/library/system.management.automation(v=vs.85).aspx
Please help me.
What you wrote in the comment will works, but i'd like to give you another direction to run powershell scripts from C# code.
You can use System.Management.Automation.Runspaces namespace which expose really easy and more elegant way to run powershell commands and retrieve the results from C# (and using the returned objects and not just the output textual stream). Try to read about it.
I found the answer of my query .
FOR EXECUTE THE POWERSHELL SCRIPT MUST EXECUTE THE POLICY COMMAND FOR
SYSTEM32
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
AND IF YOUR SYSTEM IS 64BIT THEN ALSO EXECUTE SAME POLICY FOR 64BIT POWERSHELL.EXE TOO.
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\POWERSHELL.EXE
/// COMMAND : `Set-ExecutionPolicy Unrestricted`

Categories

Resources