I'm using this C# code to read my installed programs using PowerShell.
I need it to read both x64 and x86 registry through PowerShell, how am I doing this?
Is there a way to redirect? or maybe run PowerShell in x64 and then x86?
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);
}
The 64-bit version of PowerShell (the one that 64-bit Windows opens by default) is located under: “C:\Windows\SysWOW64\WindowsPowerShell\v1. 0.” To run the program as administrator, right-click on powershell.exe and then choose the “Run as administrator” option.
In File Explorer (or Windows Explorer), right-click the script file name and then select "Run with PowerShell". The "Run with PowerShell" feature starts a PowerShell session that has an execution policy of Bypass, runs the script, and closes the session.
This should do if your process is running in x64 (or it's an x86 process running on an x86 OS).
bool is64 = IntPtr.Size == 8;
var cmdline = "Get-ItemProperty HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\* "
+ (is64 ? ",HKLM:\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*" : "")
+ " | Select-Object DisplayName";
ProcessStartInfo psi1 = new ProcessStartInfo("powershell", cmdline);
This won't work if the process is a 32-bit process running on an x64 OS, but for .NET, it should work with AnyCPU
as long as you don't choose "prefer 32-bit"
If you are only aiming at getting the display names, there might be "display-name duplicates" (in both registry keys)... so you can just remove them from the output. This will remove duplicates and sort:
var result = new StringBuilder();
var resultArr = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToArray();
Array.Sort(resultArr, StringComparer.InvariantCulture);
foreach (string s in resultArr)
result.AppendLine(s);
output = result.ToString();
If you don't want to mangle with processes and capturing output, you can install the System.Management.Automation
nuget package and use powershell directly.
The whole equivalent program would be:
PowerShell ps = PowerShell.Create();
ps.AddCommand("Get-ItemProperty");
var parm = new List<string> {
@"HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*"
};
if(IntPtr.Size == 8)
parm.Add(@"HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*");
var pso = ps.Invoke(parm);
var result = new StringBuilder();
foreach (var ob in pso)
{
if(ob.Members["DisplayName"] != null)
result.AppendLine(ob.Members["DisplayName"].Value.ToString());
}
Console.WriteLine(result.ToString());
This should be better than calling the process :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With