How to translate this PowerShell script to C#? - Get-ItemProperty - c#

I can get a list of installed applications by using this PowerShell command:
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName
in C#, it doesn't return the exact list like I see in PowerShell, I need it to show exactly the output from PowerShell.
It shows a totally different list with other programs.
public void conf() {
process p1 = new Process();
ProcessStartInfo psi1 = new ProcessStartInfo("powershell", "Get-ItemProperty HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\* | Select-Object DisplayName");
psi1.RedirectStandardOutput = true;
psi1.CreateNoWindow = true;
p1.StartInfo = psi1;
p1.StartInfo.UseShellExecute = false;
p1.StartInfo.Verb = "runas";
p1.Start();
string output = p1.StandardOutput.ReadToEnd();
Console.WriteLine(output);
p1.WaitForExit(400);
}
What am I doing wrong?
Thanks.

If you are talking about content - if you force C# program to run as x64 in Configuration Manager, you'll get the same output. And by default (Any CPU) it was reading from and x86 registry key. Or if you will run Powershell x86, you'll get the same result, as your original C# program
If you query also HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* key and merge results you'll get the whole list. Make sure your program is x64 in that case
There is some mess with spaces in stdout from PowerShell, so I just removed it.
static void Main(string[] args)
{
var lines = GetSoft("Get-ItemProperty HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*")
.Union(GetSoft("Get-ItemProperty HKLM:\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*"))
.Distinct()
.ToList();
lines.Sort();
foreach (var line in lines)
{
Console.WriteLine(line);
}
Console.WriteLine(lines.Count);
Console.ReadLine();
}
public static IEnumerable<string> GetSoft(string key)
{
Process p1 = new Process();
ProcessStartInfo psi1 = new ProcessStartInfo("powershell",
key + " | Select-Object DisplayName")
{
RedirectStandardOutput = true,
CreateNoWindow = true
};
p1.StartInfo = psi1;
p1.StartInfo.UseShellExecute = false;
p1.StartInfo.Verb = "runas";
p1.Start();
var output = p1.StandardOutput.ReadToEnd();
var result= output.Split('\r', '\n').Select(s => s.Trim()).Where(s => !String.IsNullOrWhiteSpace(s));
p1.WaitForExit(400);
return result;
}
}

Related

How to execute cmds using HTTP Post method in C#

We have a REST endpoint installed as a windows service on a server. This server will be used for test automation. The idea is make a POST request to the endpoint and that endpoint will kick off cypress tests based off the parameters specified in the POST url.
I have an existing powershell script that will do this. Ideally I'd like to call that script and fill in the needed params.
No matter what I do the request returns OK without actually running any of the commands. Is there a way to use a POST request to execute a cmds or a powershell script?? Code below(Note: I'm trying 2 different methods here neither work):
namespace CNet.TestRunner
{
public class AddTestRun : CNetApiEndpoint
{
[HttpPost("Cypress/{testName}/{serverName}")]
public CineNetResult TestRun(string testName, string serverName)
{
string test = testName + ".js";
string testPath = $#"..\EndToEndSpecs\cypress\integration\{test}";
var path = "%PROGRAMFILES%";
var resolvedPath = Environment.ExpandEnvironmentVariables(path);
string cmd = $#"{resolvedPath}\PowerShell\7\pwsh.exe "" '..\EndToEnd.ps1' '-TestPath {testPath}' '-HostToTest {serverName}' """;
Process P = Process.Start($#"{resolvedPath}\PowerShell\7\pwsh.exe", $#""" '..\EndToEnd.ps1' '-TestPath {testPath}' '-HostToTest {serverName}'""");
P.WaitForExit();
int result = P.ExitCode;
string resStr = result.ToString();
var model = new ResponseModel
{
Message = resStr,
DataPassed = $"{testName}|{serverName}"
};
var proc1 = new ProcessStartInfo();
string anyCommand = "yarn install";
proc1.UseShellExecute = true;
proc1.WorkingDirectory = #"C:\Windows\System32";
proc1.FileName = #"C:\Windows\System32\cmd.exe";
proc1.Verb = "runas";
proc1.Arguments = "/c " + anyCommand;
proc1.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(proc1);
return Ok(model);
}
}
}

The property "Redirectstandarderror" on process startinfo used in reflection is not opening the console window

I have a requirement to start a process using reflection.Below is the piece of code I'm trying to execute using reflection.
Process newProcess = new Process();
ProcessStartInfo startInfo =new ProcessStartInfo(filepath);
startInfo.UseShellExecute = false;
startInfo.RedirectStandardError = true;
startInfo.CreateNoWindow=false;
newProcess.StartInfo = startInfo;
newProcess.Start();
newProcess.WaitForExit();
Compilation:(The parameter "codeToExecute" has the class structure with the above piece of code placed in a method)
private static CompilerResults CompileAndGetResult(SnippetInfo snippetInfo, string codeToExecute)
{
CompilerResults result = null;
using (Microsoft.CSharp.CSharpCodeProvider foo =
new Microsoft.CSharp.CSharpCodeProvider())
{
result = foo.CompileAssemblyFromSource(
new CompilerParameters(snippetInfo.References.ToArray())
{
GenerateInMemory = true
},
codeToExecute
);
}
return result;
}
Execution Using Reflection:
var classType = result.CompiledAssembly.GetType(SnippetCodeGenerator.TypeName);
var classobj = Activator.CreateInstance(classType);
MethodInfo methodInfo = classType.GetMethod(SnippetCodeGenerator.MethodName);
object returnValue = methodInfo.Invoke(classobj, parameterArray);
Using this code,my console is not getting opened.If I remove UseShellExecute and RedirectStandardError,I was able to see the console.I tried different ways using allocconsole as well.But nothing seems to be worked out.

Running a PythonScript as a process and reading Standard Output issue

I am trying to run a python script as a process to which I pass a couple of parameters and then read standard output. I have a little console app and a dummy script that works fine, but when I do the same thing in my WebApi project, Standard Output is always blank, and I cannot figure out why. My code follows:
Console App
class Program
{
private static string Foo(string inputString)
{
string result = String.Empty;
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "python";
start.Arguments = string.Format(" {0} {1} {2}", #"*path*\runner.py", #"*path*\test2.py", inputString);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
result = reader.ReadToEnd();
}
}
return result;
}
static void Main(string[] args)
{
var result = Foo("flibble");
Console.Write(result);
Console.ReadKey();
}
}
runner.py (for the console app)
import sys, imp
test = imp.load_source('test',sys.argv[1])
result = test.hello(sys.argv[2])
test2.py (from the console app)
import sys
def hello(inputString):
sys.stdout.write(inputString)
return
That is the end of what I have that works, now onto the code where the issue is:
ApiEndpoint
[HttpPost]
public IHttpActionResult TestEndpoint()
{
string postedJson = ReadRawBuffer().Result;
if (postedJson == null) throw new ArgumentException("Request is null");
var result = _pythonOperations.Foo(postedJson);
// Deal with result
return Ok();
}
_pythonOperations.Foo()
public string Foo(string inputString)
{
string result;
var start = new ProcessStartInfo
{
FileName = _pathToPythonExecutable,
Arguments = string.Format(" {0} {1} {2}", _pathToPythonRunnerScript, _pathToPythonFooScript, inputString),
UseShellExecute = false,
RedirectStandardOutput = true
};
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
result = reader.ReadToEnd();
}
}
return result;
}
pythonRunnerScript
import sys, imp
module = imp.load_source('foo', sys.argv[1])
module.Foo(sys.argv[2])
Foo script
import sys
def Foo(inputString)
outputString = "output"
sys.stdout.write(outputString)
return
This is quite possibly one of the longest posts I have made, so thanks for taking the time to read it, and hopefully I can get a solution to this.
Cheers
Turns out the format I was passing in was wrong. I was using Postman REST Api client, and pasting the huge amounts of data into their request content window truncated it, leaving me with half a line. Once this was sorted, everything ran through ok.

I am having trouble comparing two lists. The purpose of the program is to perform offline patch installation

The problem comes in the looping. It seems to perform the comparison between the wmi qfe list and the KB list. The issue I run into is taking and searching the contents of the .msu file name list for the KB and then installing it. I have made a similar program in python and was mimicking a similar construct in the C# code. Any guidance on how to make this function properly would be greatly appreciated. The code is as follows:
static void Server08r2Patches()
{
var IE9 = from a in IAVA.Worksheet<IE9>("IE9") select a;
var Server08r2 = from a in IAVA.Worksheet<Server08r2>("Server08r2") select a;
var KBlist = Server08r2.Select(s=>new {KB = s.KB}).ToList();
var ExeList = Server08r2.Select(s=>new {Executable = s.Executable}).ToList();
string path = (Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)+#"\x64\");
foreach (var item in KBlist)
{
if (OsPatches.Contains(item.KB))
{
Console.WriteLine(item.KB+" is already installed.");
}
else
{
Console.WriteLine(item.KB+" will now be installed.");
foreach (var inst in ExeList)
{
do
{
var kb_inst = new ProcessStartInfo()
{
CreateNoWindow = true,
UseShellExecute = true,
FileName =path+inst.Executable,
WindowStyle = ProcessWindowStyle.Hidden,
Arguments = (#" /quiet /norestart"),
};
try
{
Process update = new Process();
update.StartInfo = kb_inst;
update.Start();
update.WaitForExit();
Console.WriteLine(inst.Executable+" was successfully installed");
}
catch (Exception Ex)
{
Console.WriteLine(Ex.Message+" "+inst.Executable);
}
}
while (inst.Executable.Contains(item.KB) == true);
}
}
}
}

mass .net update in iis6

We have about 200 web sites (on 3 separate servers, so 600 total) that we're going to have to update to run on .net 4 framework. They're currently set to run on .net 2. Does anyone know if there's a way to do this with a c# console program? Thanks!
Edit: I found a tool called IIS Metabase Explorer. Using that along with some code I had found a while ago for setting up a site in IIS 6, I came up with the following code. Hopefully it will be of help to others.
I would call it like
UpdateSiteToDotNet4("mytestsite", "mywebserver", #"D:\inetpub\wwwroot\", "DotNet4");
private void UpdateSiteToDotNet4(string siteName, string server, string serverPath, string newAppPoolId)
{
var service = new DirectoryEntry("IIS://" + server + "/W3SVC");
DirectoryEntries sites = service.Children;
bool found = false;
foreach (DirectoryEntry siteEntry in sites)
{
var siteId = siteEntry.Name;
DirectoryEntries siteSettings = siteEntry.Children; //Root
foreach (DirectoryEntry siteSetting in
from DirectoryEntry siteSetting in siteSettings
where siteSetting.SchemaClassName == "IIsWebVirtualDir"
let siteRoot = siteSetting.Properties["Path"][0].ToString()
where siteRoot.ToLower().Trim() == (serverPath + siteName).ToLower().Trim()
select siteSetting)
{
siteSetting.Properties["AppPoolId"].Value = newAppPoolId;
siteSetting.CommitChanges();
//Update to version v4.0.30319
var aspnet = string.Format(#"{0}\Microsoft.NET\Framework\v{1}\aspnet_regiis.exe", Environment.GetEnvironmentVariable("windir"), "4.0.30319");
var startInfo = new ProcessStartInfo(aspnet)
{
Arguments = string.Format("-sn \"{0}\"", "W3SVC/" + siteId + "/Root"),
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
CreateNoWindow = true
};
var process = new Process { StartInfo = startInfo };
process.Start();
process.WaitForExit();
process.Dispose();
found = true;
break;
}
if (found) break;
}
}

Categories