Powershell Timeout From C# - c#

I want to set a timeout on powershell scripts I have running in c#.
My code to run my scripts is
private void RunPowerShell(string scriptText)
{
string tempFile = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "PinScript.ps1");
var file = new StreamWriter(tempFile);
file.AutoFlush = true;
file.WriteLine(scriptText);
file.Dispose();
string output, errors = string.Empty;
//this is basically a helper method that runs an exe via the command prompt in c#
//I want to keep this as is and either add an argument to powershell.exe or alter the
//.psi scripts themselves
_cmd.Run(#"powershell.exe",
#"-NoProfile -ExecutionPolicy Bypass " + #"& '" + tempFile + "'",
out output,
out errors);
Console.WriteLine("Powershell Output: " + output);
Console.WriteLine("Powershell Errors: " + errors);
File.Delete(tempFile);
}
I see there is code that works to time out a script here but I cannot understand how to ingrate that concept into what I have above.

Related

How can we avoid the gnupg passphrase prompt in C# for Windows?

I am trying to upgrade our legacy code from gnupg1.x to gnupg2.2.4. This is on Windows machine and I installed gnupg for windows gnupg-w32-2.2.4_20171220.exe.
I am stuck as my C# application keeps prompting me to enter the passphrase and time outs and is not able to decrypt the file and the process fails. All this time this application has run without much user intervention and we still want it that way. Is there anyway to avoid the passphrase prompt that comes up every time gnupg tries to decrypt a file?
This is what my current code looks like based on other feedback from this community but I cant figure out what I am doing wrong. It currently creates an empty file and there is no content. Although my encrypted file does have content in it.
I also read about using gpg --preset-passphrase but my release team is discouraging me from using that. Can you please help.
string _commandlineParams = "--home " + gnuHomedir + " --default-key " + "myRealIDKey" + " --batch" + " --passphrase-fd 0" + " --decrypt " + pathAndfile;
string vgpg = "echo " + gphrase + "|gpg ";
string gpgExecutable = Path.Combine(gnuBinDirectory, "gpg");
ProcessStartInfo pInfo = new ProcessStartInfo(gpgExecutable, _commandlineParams);
pInfo.WorkingDirectory = _gnuBinDirectory;
pInfo.CreateNoWindow = true;
pInfo.UseShellExecute = false;
pInfo.RedirectStandardInput = true;
pInfo.RedirectStandardOutput = true;
pInfo.RedirectStandardError = true;
string sCommandLine = vgpg + " " + _commandlineParams;
if (sCommandLine != null)
{
_processObject.StandardInput.WriteLine(sCommandLine);
//_processObject.StandardInput.WriteLine(gphrase); -- tried this too but didnt work
_processObject.StandardInput.Flush();
}
_processObject.StandardInput.Close();
I have also faced the same problem. It was repeatedly asking for Passphrase in a GUI. So after many head hunts found a solution.
Use command text as
gpg --output "decrypted_file_name" --batch --passphrase "passphrase_goes_here" --decrypt "encrypted_file_name"

"You cannot call a method on a null-valued expression" when passing parameters to powershell

I'm trying to parse some parameters to a script I'm running in powershell.
But I'm getting errors while executing the script saying they are empty.
Im starting the process like this:
string input1 = "Powershell.exe -File " + Config.Directory + "/ICS.ps1" + " -toggle '" + toggle + "' -par1 '" +
par1 + "' -par2 '" + par2 + "' -connectionInterface '" + connectionInterface + "'";
//(for readability) input1 will look something like this:
//Powershell.exe -File map/to/ICS.ps1 -toggle 'EnableSharing' -par1 '0' -par2 '1' -connectionInterface 'Ethernet'
string[] output = CmdProcess.Exec(input1);
CmdProcess.Exec is a method i created to quickly run a cmd process.
it works like this
public static string[] Exec(params string[] parameters)
{
Process cmd = new Process
{
StartInfo =
{
UseShellExecute = false,
Verb = "runas",
FileName = #"cmd.exe",
RedirectStandardInput = true,
RedirectStandardOutput = true,
CreateNoWindow = true,
}
};
cmd.Start();
foreach (string parameter in parameters)
{
cmd.StandardInput.WriteLine(parameter);
}
cmd.StandardInput.WriteLine("exit");
return Regex.Split(cmd.StandardOutput.ReadToEnd(), "\r\n");
}
the reason i use cmd to execute powershell is because i tried it with a powershell instance* but that crashed for an unknown reason on really fast computers (while it runs normally if you run it manually).
*System.Management.Automation.Powershell
in the script i wrote this: (At the beginning of the script)
Param( [string]$toggle, [string]$par1, [string]$par2, [string]$connectionInterface )
But it gives an error the params are null :
You cannot call a method on a null-valued expression.
At C:\Users\Jeremy\AppData\Roaming\HotspotLauncher\ICS.ps1:10 char:1
+ $config.$toggle($par1)
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
I get error's like this with all the params. not just $toggle or $par1.
I tried running Powershell.exe and -File ..... seperatly but that caused my thread to hang.
Also I'm 100% sure toggle, par1 and the rest (In the C# code) arent null themselves
I also tried adding [CmdletBinding()] before the params in the script but that did nothing :
[CmdletBinding()]Param( [string]$toggle, [string]$par1, [string]$par2, [string]$connectionInterface )
Here is the powershell script:
[CmdletBinding()]Param( [string]$toggle, [string]$par1, [string]$par2, [string]$connectionInterface )
regsvr32 hnetcfg.dll /s
$m = New-Object -ComObject HNetCfg.HNetShare
$m.EnumEveryConnection |% { $m.NetConnectionProps.Invoke($_) }
$c = $m.EnumEveryConnection |? { $m.NetConnectionProps.Invoke($_).Name -eq $connectionInterface }
$config = $m.INetSharingConfigurationForINetConnection.Invoke($c)
Write-Output $config.SharingEnabled
Write-Output $config.SharingConnectionType
$config.$toggle($par1)
$m2 = New-Object -ComObject HNetCfg.HNetShare
$m2.EnumEveryConnection |% { $m2.NetConnectionProps.Invoke($_) }
$c2 = $m2.EnumEveryConnection |? { $m2.NetConnectionProps.Invoke($_).DeviceName -Match 'Microsoft Hosted Network Virtual Adapter' }
$config2 = $m2.INetSharingConfigurationForINetConnection.Invoke($c2)
Write-Output $config2.SharingEnabled
Write-Output $config2.SharingConnectionType
$config2.$toggle($par2)
This script enables/disables Internet sharing for the $connectionInterface which could be something like Ethernet or Wifi, and set it to public ($par1) / or nothing if it has to be disabled.
and does the same for microsoft hostednetwork and set it to private ($par2).
Don't fork a new process with powershell.exe - use the API instead:
using System.Collections.ObjectModel;
using System.IO;
using System.Management.Automation;
//...
using(PowerShell ps = PowerShell.Create())
{
ps.AddScript(Path.Combine(Config.Directory, "ICS.ps1"))
.AddParameter("toggle", toggle)
.AddParameter("par1", par1)
.AddParameter("par2", par2)
.AddParameter("connectionInterface", connectionInterface);
Collection<PSObject> results = ps.Invoke();
}
Remember to add a reference to the System.Management.Automation.dll assembly to your project

SCHTASKS Invalid Syntax in C# but working in CMD

I've got a command I'm trying to run through C# to get a list of tasks in CSV format from a bunch of computers.
To do this, I am using the SCHTASKS command with command redirection to a CSV. So I wrote this code in C# to do this for me:
string commandGetStatus = "schtasks";
string argumentsGetStatus = "/s:" + CompName +
" /fo:csv" +
" > \"" + #"\\BIG\OL\UNC\PATH\"+CompName+".csv" + "\"";
getLatestTaskStatus.StartInfo.FileName = commandGetStatus;
getLatestTaskStatus.StartInfo.Arguments = argumentsGetStatus;
getLatestTaskStatus.StartInfo.CreateNoWindow = true;
getLatestTaskStatus.StartInfo.RedirectStandardOutput = true;
getLatestTaskStatus.StartInfo.RedirectStandardInput = true;
getLatestTaskStatus.StartInfo.RedirectStandardError = true;
getLatestTaskStatus.StartInfo.UseShellExecute = false;
getLatestTaskStatus.Start();
It returns the output:
ERROR: Invalid syntax.
Type "SCHTASKS /?" for usage.
So I used StartInfo.FileName + " " + StartInfo.Arguments to print out the exact command that should be being executed. From there, I copy and pasted the command into CMD. Where it worked without a problem. This was the command + args:
schtasks /s:COMPUTERNAME /fo:csv > "\\BIG\OL\UNC\PATH\COMPUTERNAME.csv"
I'm not sure what the problem is at this point.
My Solution
Luaan was absolutely correct about the problem. The command prompt redirection operator,>, is not available without using Command Prompt. Fortunately, the solution was quote simple and easy to implement. I reduced the argument variable to:
"/s:" + CompName + " /fo:csv"
And with standard output being redirected, I simply used:
string output = process.StandardOuptut.ReadToEnd();
File.WriteAllText(#"\\UNC\File\Path\" + myfile + ".csv", output);
You explicitly disabled UseShellExecute - > is a shell operator, not something inherent to processes. It definitely isn't an argument. You need to read the output and write it out manually :)

Process.Start not executing command

I am using ImageMagick C# tool to convert PDF to JPG by calling the executable from C#. I believe I set up the command correctly but it does not execute; it just passes through Process.Start(startInfo) without executing it. I do see the command prompt popping up but nothing happens.
string PNGPath = Path.ChangeExtension(Loan_list[f], ".png");
string PDFfile = '"' + Loan_list[f] + '"';
string PNGfile = '"' + PNGPath + '"';
string arguments = string.Format("{0} {1}", PDFfile, PNGfile);
ProcessStartInfo startInfo = new ProcessStartInfo(#"C:\Program Files\ImageMagick-6.9.2-Q16\convert.exe");
startInfo.Arguments = arguments;
Process.Start(startInfo);
I wasn't sure if it was because of the double quotes I added to each argument before hand but after commenting it out and running it again, it still skipped over. Any thoughts?
Edit: To add some clarity, I am expecting a JPG files from a PDF but I see no output file from this part of code. I ran the following in my command prompt to convert PDF to JPG
"C:\Program Files\ImageMagick-6.9.2-Q16\convert.exe" "C:\Users\rwong\Desktop\RoundPoint\1000965275\1000965275_157_Credit File_10.PDF" "C:\Users\rwong\Desktop\RoundPoint\1000965275\1000965275_157_Credit File_10.png"
I explicitly called the convert.exe for clarity sake in my code. The command works fine in command prompt but when coping the structure over to C# it doesn't do anything. I see the code step into it but it continues without an error.
Edit2: Upon request below is the code and output for a Process Exit code
string PNGPath = Path.ChangeExtension(Loan_list[f], ".png");
string PDFfile = '"' + Loan_list[f] + '"';
string PNGfile = '"' + PNGPath + '"';
try
{
Process myprocess = null;
string[] arguments = { PDFfile, PNGfile };
myprocess=Process.Start(#"C:\ProgramFiles\ImageMagick6.9.2Q16\convert.exe", String.Join(" ", arguments));
Console.WriteLine("Process exit code: {0}", myprocess.ExitCode);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Process exit code: 1
Assuming that you are right and there was a problem (rather than the process just executed very quickly and exited), you can check the return code as follows:
if (Process.Start(startInfo) == null)
{
int lastError = Marshal.GetLastWin32Error();
}
You then go here to look up the error code:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
Hopefully, that vendor actually sets an error code on failure (they may or may not).

Issue when passing multiple arguments to an external exe program using c#

I have an exe file in which I am trying to pass arguments through c#. the code is as follows
class Class1
{
static void Main()
{
string[] arg;
arg = new string[3];
Process p = new Process();
p.StartInfo.FileName = #"D:\xxx.exe";
for (int i = 0; i < 3; i++)
{
arg[i] = Console.ReadLine();
}
p.StartInfo.Arguments = arg[0] + " " + arg[1] + " " + arg[2];
p.Start();
}
}
I open up a console and then write the arguments there. As soon as I am finished typing 3 arguments, I make a string out of the 3 arguments and then call Process.Start() with the arguments in the p.StartInfo.Arguments string. The exe file loads but it does not generate any output. The strange thing is that if I open the exe file from my computer and then write
Arg1.txt Arg2.txt Arg3.txt
and press enter the exe file generates the output. However the same arguments in the same style are currently being passed through C# code and it is not generating any output. I donot understand what I am doing wrong. There are multiple questions on StackOverflow about this, I know that, however they all suggest the same procedure as what I have done here. I have also tried giving arguments as
p.StartInfo.Arguments = "\"arg[0]\"\"arg[1]\"\"arg[2]\"";
but this also has not worked.
Try this:
p.StartInfo.Arguments = "\"" + arg[0] + " " + arg[1] + " " + arg[2] + "\"";
p.Start();
It is recomended to use "" when you use several parameters between gaps.
EDIT: No "\" have to be included if you type it ok. It is the escape character. See picture below.

Categories