How to Run MsBUILD Command from C# console Application? - c#

I am trying to run msbuild /t:scmclean from my C# console application but failing to. This completely works fine if i run it from my Visual studio command prompt 2017 but fails while executing from my C# console application.
My Target folder where I am running this command is : D:/Git/abc/Build/Tools, this command internally calls csproj file.
What I have tried:
var result = await Cli.Wrap("C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\MSBuild\\15.0\\Bin\\MSBuild.exe")
.WithArguments("/t:scmclean")
.WithWorkingDirectory("D:\\git\\abc\\Build\\Tools")
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdOutCO))
.WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrCO))
.ExecuteBufferedAsync();
var stdOut1 = stdOutCO.ToString();
var stdErr1 = stdErrCO.ToString();
Console.WriteLine("Build Info:");
Console.WriteLine(stdOut1);
Console.WriteLine(stdErr1);
This gives an error access denied, however when I check the user using the command
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
it shows as super user.
Another thing that I tried is running after setting the location to my current directory is
Process.Start("C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\MSBuild\\15.0\\Bin\\MSBuild.exe", "/t:scmclean");
this also seems to be failing. Also I need to know how to write the output of a process in console.
MSBUILD : error MSB1003: Specify a project or solution file. The
current working directory does not contain a project or solution file.

I'm not sure what scmclean is because I couldn't find any information about it. Nevertheless, try the following:
Option 1 (CliWrap)
Download/install NuGet packages:
Microsoft.Build.Locator
CliWrap
Add the following using directives (ex: Form1.cs)
using System.Diagnostics;
using System.IO;
using Microsoft.Build.Locator;
using CliWrap;
using CliWrap.Buffered;
Choose one of the options below (ie: Option A, Option B, Option C, Option D, or Option E):
Option A - ExecuteBufferedAsync:
private async Task RunMSBuild(string solutionFilename, string msBuildPath, string arguments = null)
{
//get tools path for newest Visual Studio version
string msBuildFilename = Path.Combine(msBuildPath, "MSBuild.exe");
if (!File.Exists(msBuildFilename))
throw new Exception($"Error: MSBuild.exe not found ({msBuildFilename})");
var result = await Cli.Wrap(msBuildFilename)
.WithArguments(arguments)
.WithWorkingDirectory(Path.GetDirectoryName(solutionFilename))
.ExecuteBufferedAsync();
Console.WriteLine(result.StandardOutput);
Console.WriteLine(result.StandardError);
}
Option B - ExecuteAsync:
private async Task RunMSBuild(string solutionFilename, string msBuildPath, string arguments = null)
{
var stdOutBuffer = new StringBuilder();
var stdErrBuffer = new StringBuilder();
//get tools path for newest Visual Studio version
string msBuildFilename = Path.Combine(msBuildPath, "MSBuild.exe");
if (!File.Exists(msBuildFilename))
throw new Exception($"Error: MSBuild.exe not found ({msBuildFilename})");
var result = await Cli.Wrap(msBuildFilename)
.WithArguments(arguments)
.WithWorkingDirectory(Path.GetDirectoryName(solutionFilename))
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdOutBuffer))
.WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrBuffer))
.ExecuteAsync();
// Access stdout & stderr buffered in-memory as strings
var stdOut = stdOutBuffer.ToString();
var stdErr = stdErrBuffer.ToString();
Console.WriteLine(stdOut);
Console.WriteLine(stdErr);
}
Option C - ExecuteAsync (Delegate):
Note: This option displays real-time output.
private async Task RunMSBuild(string solutionFilename, string msBuildPath, string arguments = null)
{
//get tools path for newest Visual Studio version
string msBuildFilename = Path.Combine(msBuildPath, "MSBuild.exe");
if (!File.Exists(msBuildFilename))
throw new Exception($"Error: MSBuild.exe not found ({msBuildFilename})");
var result = await Cli.Wrap(msBuildFilename)
.WithArguments(arguments)
.WithWorkingDirectory(Path.GetDirectoryName(solutionFilename))
.WithStandardOutputPipe(PipeTarget.ToDelegate(delegate (string msg)
{
Console.WriteLine(msg);
}))
.WithStandardErrorPipe(PipeTarget.ToDelegate(delegate (string msg)
{
Console.WriteLine(msg);
}))
.ExecuteAsync();
}
Option D - ExecuteAsync (Action/Delegate):
Note: This option displays real-time output.
private async Task RunMSBuild(string solutionFilename, string msBuildPath, string arguments = null)
{
//get tools path for newest Visual Studio version
string msBuildFilename = Path.Combine(msBuildPath, "MSBuild.exe");
if (!File.Exists(msBuildFilename))
throw new Exception($"Error: MSBuild.exe not found ({msBuildFilename})");
Action<string> handleStdOut = delegate (string msg)
{
Console.WriteLine(msg);
};
Action<string> handleStdErr = delegate (string msg)
{
Console.WriteLine(msg);
};
var result = await Cli.Wrap(msBuildFilename)
.WithArguments(arguments)
.WithWorkingDirectory(Path.GetDirectoryName(solutionFilename))
.WithStandardOutputPipe(PipeTarget.ToDelegate(handleStdOut))
.WithStandardErrorPipe(PipeTarget.ToDelegate(handleStdErr))
.ExecuteAsync();
}
Option E - ExecuteAsync (EventStream):
Note: This option displays real-time output.
Download/install NuGet package: System.Reactive.Linq
Add using directives:
using CliWrap.EventStream;
using System.Reactive.Linq;
private async Task RunMSBuild(string solutionFilename, string msBuildPath, string arguments = null)
{
//get tools path for newest Visual Studio version
string msBuildFilename = Path.Combine(msBuildPath, "MSBuild.exe");
if (!File.Exists(msBuildFilename))
throw new Exception($"Error: MSBuild.exe not found ({msBuildFilename})");
Command cmd = Cli.Wrap(msBuildFilename)
.WithArguments(arguments)
.WithWorkingDirectory(Path.GetDirectoryName(solutionFilename));
await cmd.Observe().ForEachAsync(cmdEvent =>
{
switch (cmdEvent)
{
case StartedCommandEvent started:
Console.WriteLine($"Process started; ID: {started.ProcessId}");
break;
case StandardOutputCommandEvent stdOut:
Console.WriteLine($"{stdOut.Text}");
break;
case StandardErrorCommandEvent stdErr:
Console.WriteLine($"{stdErr.Text}");
break;
case ExitedCommandEvent exited:
Console.WriteLine($"Process exited; Code: {exited.ExitCode}");
break;
}
});
}
(Optional) Add the following method overloads:
public enum VSVersionType
{
Latest,
Oldest
}
private async Task RunMSBuild(string solutionFilename, int vsVersionYear, string arguments = null)
{
//get Visual Studio instances
List<VisualStudioInstance> vsInstances = MSBuildLocator.QueryVisualStudioInstances().OrderBy(x => x.Version).ToList();
if (vsInstances != null && vsInstances.Count > 0)
{
//get MSBuild path
var msBuildPath = vsInstances.Where(x => x.Name.EndsWith(vsVersionYear.ToString())).Select(x => x.MSBuildPath).FirstOrDefault();
await RunMSBuild(solutionFilename, msBuildPath, arguments);
}
}
private async Task RunMSBuild(string solutionFilename, VSVersionType vsVersion, string arguments = null)
{
//get Visual Studio instances
List<VisualStudioInstance> vsInstances = MSBuildLocator.QueryVisualStudioInstances().OrderBy(x => x.Version).ToList();
if (vsInstances != null && vsInstances.Count > 0)
{
string msBuildPath = string.Empty;
if (vsVersion == VSVersionType.Latest)
msBuildPath = vsInstances[vsInstances.Count - 1].MSBuildPath;
else if (vsVersion == VSVersionType.Oldest)
msBuildPath = vsInstances[0].MSBuildPath;
await RunMSBuild(solutionFilename, msBuildPath, arguments);
}
}
Usage 1:
string solutionFilename = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.MyDocuments), "Visual Studio 2017", "Projects", "MyAmazingApp", "MyAmazingApp.sln"));
await RunMSBuild(solutionFilename, 2017);
Usage 2:
string solutionFilename = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.MyDocuments), "Visual Studio 2017", "Projects", "MyAmazingApp", "MyAmazingApp.sln"));
await RunMSBuild(solutionFilename, 2017, "-t:Clean;Compile");
Usage 3:
string solutionFilename = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.MyDocuments), "Visual Studio 2017", "Projects", "MyAmazingApp", "MyAmazingApp.sln"));
await RunMSBuild(solutionFilename, VSVersionType.Oldest);
Usage 4:
string solutionFilename = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.MyDocuments), "Visual Studio 2017", "Projects", "MyAmazingApp", "MyAmazingApp.sln"));
await RunMSBuild(solutionFilename, VSVersionType.Oldest, "-t:Clean;Compile");
Usage 5:
string msBuildPath = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.ProgramFilesX86)), #"Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin");
string solutionFilename = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.MyDocuments), "Visual Studio 2017", "Projects", "MyAmazingApp", "MyAmazingApp.sln"));
await RunMSBuild(solutionFilename, msBuildPath);
Usage 6:
string msBuildPath = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.ProgramFilesX86)), #"Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin");
string solutionFilename = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.MyDocuments), "Visual Studio 2017", "Projects", "MyAmazingApp", "MyAmazingApp.sln"));
await RunMSBuild(solutionFilename, msBuildPath, "-t:Clean;Compile"););
Option 2 (System.Diagnostics.Process)
Download/install NuGet package: Microsoft.Build.Locator
Add the following using directives (ex: Form1.cs)
using System.Diagnostics;
using System.IO;
using Microsoft.Build.Locator;
public enum VSVersionType
{
Latest,
Oldest
}
private void RunMSBuild(string solutionFilename, int vsVersionYear, string arguments = null)
{
//get Visual Studio instances
List<VisualStudioInstance> vsInstances = MSBuildLocator.QueryVisualStudioInstances().OrderBy(x => x.Version).ToList();
if (vsInstances != null && vsInstances.Count > 0)
{
//get MSBuild path
var msBuildPath = vsInstances.Where(x => x.Name.EndsWith(vsVersionYear.ToString())).Select(x => x.MSBuildPath).FirstOrDefault();
RunMSBuild(solutionFilename, msBuildPath, arguments);
}
}
private void RunMSBuild(string solutionFilename, VSVersionType vsVersion, string arguments = null)
{
//get Visual Studio instances
List<VisualStudioInstance> vsInstances = MSBuildLocator.QueryVisualStudioInstances().OrderBy(x => x.Version).ToList();
if (vsInstances != null && vsInstances.Count > 0)
{
string msBuildPath = string.Empty;
if (vsVersion == VSVersionType.Latest)
msBuildPath = vsInstances[vsInstances.Count - 1].MSBuildPath;
else if (vsVersion == VSVersionType.Oldest)
msBuildPath = vsInstances[0].MSBuildPath;
RunMSBuild(solutionFilename, msBuildPath, arguments);
}
}
private void RunMSBuild(string solutionFilename, string msBuildPath, string arguments = null)
{
//get tools path for newest Visual Studio version
string msBuildFilename = Path.Combine(msBuildPath, "MSBuild.exe");
if (!File.Exists(msBuildFilename))
throw new Exception($"Error: MSBuild.exe not found ({msBuildFilename})");
ProcessStartInfo startInfo = new ProcessStartInfo(msBuildFilename)
{
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden
};
//set value
startInfo.Arguments = arguments;
if (!String.IsNullOrEmpty(arguments))
{
if (!arguments.Contains(Path.GetFileNameWithoutExtension(solutionFilename)))
{
arguments += $" \"{solutionFilename}\"";
}
}
else
{
arguments = $" \"{solutionFilename}\"";
}
Debug.WriteLine($"arguments: {arguments}");
//set value
startInfo.WorkingDirectory = Path.GetDirectoryName(solutionFilename);
using (Process p = new Process() { StartInfo = startInfo, EnableRaisingEvents = true })
{
//subscribe to event and add event handler code
p.ErrorDataReceived += (sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
//ToDo: add desired code
Debug.WriteLine("Error: " + e.Data);
}
};
//subscribe to event and add event handler code
p.OutputDataReceived += (sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
//ToDo: add desired code
Debug.WriteLine("Output: " + e.Data);
}
};
//start
p.Start();
p.BeginErrorReadLine(); //begin async reading for standard error
p.BeginOutputReadLine(); //begin async reading for standard output
//waits until the process is finished before continuing
p.WaitForExit();
p.CancelErrorRead(); //cancel async reading for standard error
p.CancelOutputRead(); //cancel async reading for standard output
}
}
Usage 1:
string solutionFilename = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.MyDocuments), "Visual Studio 2017", "Projects", "MyAmazingApp", "MyAmazingApp.sln"));
RunMSBuild(solutionFilename, 2017);
Usage 2:
string solutionFilename = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.MyDocuments), "Visual Studio 2017", "Projects", "MyAmazingApp", "MyAmazingApp.sln"));
RunMSBuild(solutionFilename, 2017, "-t:Clean;Compile");
Usage 3:
string solutionFilename = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.MyDocuments), "Visual Studio 2017", "Projects", "MyAmazingApp", "MyAmazingApp.sln"));
RunMSBuild(solutionFilename, VSVersionType.Oldest);
Usage 4:
string solutionFilename = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.MyDocuments), "Visual Studio 2017", "Projects", "MyAmazingApp", "MyAmazingApp.sln"));
RunMSBuild(solutionFilename, VSVersionType.Oldest, "-t:Clean;Compile");
Usage 5:
string msBuildPath = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.ProgramFilesX86)), #"Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin");
string solutionFilename = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.MyDocuments), "Visual Studio 2017", "Projects", "MyAmazingApp", "MyAmazingApp.sln"));
RunMSBuild(solutionFilename, msBuildPath);
Usage 6:
string msBuildPath = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.ProgramFilesX86)), #"Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin");
string solutionFilename = Path.Combine(Path.Combine(GetFolderPath(SpecialFolder.MyDocuments), "Visual Studio 2017", "Projects", "MyAmazingApp", "MyAmazingApp.sln"));
RunMSBuild(solutionFilename, msBuildPath, "-t:Clean;Compile"););
Note: When using the Developer Command Prompt, a batch file ("VsDevCmd.bat") is used to set environment variables. One can see this by:
Click Windows Start menu
Right-click Developer Command Prompt...
Select More
Select Open file location
In the folder that opens:
Right-click Developer Command Prompt... link.
Select Properties
Select Shortcut tab
Look at value of Target which shows the batch file that is used to set the environment variables.
Resources:
System.Diagnostics.Process
Find and use a version of MSBuild
Sort List by Property in the Object in .NET
CliWrap
CliWrap — Execute Shell Commands with Extensive Support for Piping
Getting lines written to StdOut in 4 conceptually different ways (using CliWrap)
Additional Resources:
ProcessStartInfo.EnvironmentVariables Property
MSBuild command-line reference
MSBuild reference
How to: Clean a build

Related

C# Topshelf fails to execute a powershell file

After installing the service (.exe) and starting it, the powershell file in the code will be executed. There are also no error messages.
My Steps:
cd C:\Users\USER_XY\source\repos\ServiceApp\ServiceApp\bin\Debug\net6.0
.\ScriptAsService.exe install -servicename "MyService123" -displayname "My Service123" -description "This is my service123."
start the service (right click, start)
the start.txt and stop.txt will be generated but the powershell script will not be executed.
Here the c# code:
using Topshelf;
public class App
{
static void Main(string[] args)
{
var exitCode = HostFactory.Run(x =>
{
x.Service<ScriptAsService>(s =>
{
s.ConstructUsing(service => new ScriptAsService());
s.WhenStarted(service => service.Start());
s.WhenStopped(service => service.Stop());
});
x.RunAsLocalSystem();
});
}
}
public class ScriptAsService
{
private String _scriptfile = #"C:\Users\USER_XY\source\repos\ServiceApp\ServiceApp\bin\Debug\net6.0\myscript.ps1";
public void Start()
{
File.WriteAllText("start.txt", "service started --> start scriptfile=" + _scriptfile);
ProcessStartInfo process_start_info = new ProcessStartInfo();
process_start_info.FileName = "powershell.exe";
process_start_info.Arguments = this._scriptfile;
Process process = new Process();
process.StartInfo = process_start_info;
process.Start();
process.WaitForExit();
}
public void Stop()
{
File.WriteAllText("stop.txt", "service stopped");
}
}
And here the powershell code (myscript.ps1):
$counter = 0
while (1)
{
Add-Content info22.txt -Value "content = $counter"
$counter++
Start-Sleep -s 15
}
I except the info22.txt file. This file will be created by the powershell script.

Execute dotnet command with Process in C#

I have following C# lines of code where open process and run dotnet command to open my console application (created with .net standard/core)
var args = new Dictionary<string, string> {
{ "-p", "title"},
{ "-l", "games"},
...
};
var arguments = string.Join(" ", args.Select((k) => string.Format("{0} {1}", k.Key, "\"" + k.Value + "\"")));
var dllPath = #"C:\Users\xyz\Documents\Visual Studio 2017\myConsole\bin\Debug\netcoreapp2.1\myConsole.dll";
ProcessStartInfo procStartInfo = new ProcessStartInfo();
procStartInfo.FileName = "C:\....\cmd.exe";
procStartInfo.Arguments = $"dotnet \"{dllPath}\" {arguments}";
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = false;
procStartInfo.RedirectStandardOutput = true;
procStartInfo.RedirectStandardError = true;
StringBuilder sb = new StringBuilder();
Process pr = new Process();
pr.StartInfo = procStartInfo;
pr.OutputDataReceived += (s, ev) =>
{
if (string.IsNullOrWhiteSpace(ev.Data))
{
return;
}
string[] split = ev.Data.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
int.TryParse(split[split.Length - 1], out output);
};
pr.ErrorDataReceived += (s, err) =>
{
// do stuff here
};
pr.EnableRaisingEvents = true;
pr.Start();
pr.BeginOutputReadLine();
pr.BeginErrorReadLine();
pr.WaitForExit();
The command Arguments result is:
dotnet "C:\Users\xyz\Documents\Visual Studio 2017\myConsole\bin\Debug\netcoreapp2.1\myConsole.dll" -p "title" -l "games" -s "" -r "none" -k "0" -d "/path/" -f ""
But for ev.Data from OutputDataReceived event looks like:
Microsoft Windows [Version 10.0.16299.665]
(c) 2017 Microsoft Corporation. All rights reserved.
and that's all...
I expected to run dotnet command to dll.
If I run manually the result command dotnet .... above, works fine. But not from my C# code. Why ?
Because cmd returns:
Microsoft Windows [Version 10.0.16299.665]
(c) 2017 Microsoft Corporation. All rights reserved.
You need to call
procStartInfo.FileName = "dotnet"

need output from vsDiffMerge.exe

I am automating the file compare feature using vsDiffMerge.exe to compare the file using c#.net code that works fine but I need output information from vsDiffMerge.exe to c#.net variable when files are identical, I am using following code to compare the two files using c#.net code and vsDiffMerge.exe from following Visual Studio location C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\vsDiffMerge.exe
private void CompareFile()
{
bool isFileIdentical=false;
string exe = "C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\vsDiffMerge.exe";
string orignalSourceFile = _lstFiles[_selectedRowIndex - 1].SourceFilePath;
string orignalTargetFile = _lstFiles[_selectedRowIndex - 1].TargetFilePath;
string command = string.Format(#"""{0}"" ""{1}"" ""Source: {2}"" ""Target : {3}""{4}", sourceFile, targetFile,
orignalSourceFile,
orignalTargetFile,
chkOnlyOne.Checked ? "" : " /t");
var attr = File.GetAttributes(sourceFile);
File.SetAttributes(sourceFile, attr & ~FileAttributes.ReadOnly);
var attr2 = File.GetAttributes(targetFile);
File.SetAttributes(targetFile, attr2 & ~FileAttributes.ReadOnly);
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.FileName = exe;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = command;
try
{
using (Process exeProcess = Process.Start(startInfo))
{
//string output = exeProcess.StandardOutput.ReadToEnd();
//isFileIdentical = exeProcess. ?
// I need output from exeProcess if both the files are identical
exeProcess.WaitForExit();
}
}
catch (Exception ex)
{
string e = ex.Message;
}
}

Open Visual Studio command prompt from C# code

I am trying to open Visual studio Command prompt using C# code.
Here is my code
private void Execute(string vsEnvVar)
{
var vsInstallPath = Environment.GetEnvironmentVariable(vsEnvVar);
// vsEnvVar can be VS100COMNTOOLS, VS120COMNTOOLS, VS140COMNTOOLS
if (Directory.Exists(vsInstallPath))
{
var filePath = vsInstallPath + "vsvars32.bat";
if (File.Exists(filePath))
{
//start vs command process
Process proc = new Process();
var command = Environment.GetEnvironmentVariable("ComSpec");
command = #"" + command + #"";
var batfile = #"E:\Test\vstest.bat";
var args = string.Format("/K \"{0}\" \"{1}\"" ,filePath, batfile);
proc.StartInfo.FileName = command;
proc.StartInfo.Arguments = args;
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.UseShellExecute = false;
proc.Start();
}
else
{
Console.WriteLine("File Does not exists " + filePath);
}
}
}
But the args string is not getting properly formatted.
I am getting below formatted string
"/K \"C:\\Program Files\\Microsoft Visual Studio 10.0\\Common7\\Tools\\vsvars32.bat\" \"E:\\Test\\vstest.bat\""
extra "\" is getting added.
Please point out what I am missing.
Thanks
The string is being formatted as you asked, but you have asked for the wrong thing. "E:\Test\VStest.bat" is being passed as an argument to VCVars.bat, but I suspect you want it to be executed after it.
Try this:
var args = string.Format("/S/K \" \"{0}\" && \"{1}\" \"" ,filePath, batFile);
This should produce:
"/S/K \" \"C:\\Program Files\\Microsoft Visual Studio 10.0\\Common7\\Tools\\vsvars32.bat\" && \"E:\\Test\\vstest.bat\" \" \"
Which as a string is:
/S/K " "C:\Program Files\Microsoft Visual Studio 10.0\Common7\Tools\vsvars32.bat" && "E:\Test\vstest.bat" "

How to check that a jre environment is 32 bit or 64 bit programmatically with C#?

I have a jre folder which is basically java runtime, it is not installed I have copied this folder from somewhere else, now I need to check this jre is 32 bit or 64 bit with manual inspection without writing any code and if code has to be written then it should be c#.
All the example tell system.getproperty("java...model") something for getting the target type of the installed jre, but I dont have this jre installed, rather I have just copied this jre.
so is there any way to know its target type is it 32 bit or 64 bit.
C# Code
// *** Main code
string output = RunExternalExe("java.exe -version");
// Parse output here...
// *** Helper methods
public string RunExternalExe(string filename, string arguments = null)
{
var process = new Process();
process.StartInfo.FileName = filename;
if (!string.IsNullOrEmpty(arguments))
{
process.StartInfo.Arguments = arguments;
}
process.StartInfo.CreateNoWindow = true;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
var stdOutput = new StringBuilder();
process.OutputDataReceived += (sender, args) => stdOutput.Append(args.Data);
string stdError = null;
try
{
process.Start();
process.BeginOutputReadLine();
stdError = process.StandardError.ReadToEnd();
process.WaitForExit();
}
catch (Exception e)
{
throw new Exception("OS error while executing " + Format(filename, arguments)+ ": " + e.Message, e);
}
if (process.ExitCode == 0)
{
return stdOutput.ToString();
}
else
{
var message = new StringBuilder();
if (!string.IsNullOrEmpty(stdError))
{
message.AppendLine(stdError);
}
if (stdOutput.Length != 0)
{
message.AppendLine("Std output:");
message.AppendLine(stdOutput.ToString());
}
throw new Exception(Format(filename, arguments) + " finished with exit code = " + process.ExitCode + ": " + message);
}
}
private string Format(string filename, string arguments)
{
return "'" + filename +
((string.IsNullOrEmpty(arguments)) ? string.Empty : " " + arguments) +
"'";
}
COMMAND sample output
On my box I have a 64bit java version. Here is its output:
C:\Program Files\Java\jdk1.7.0_45\bin>java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
Note the 64-Bit mention. You may find this SO answer useful.
You could use the GNU file utility to check whether or not java.exe is a 64-bit-executable.
See this link for more information about that.
This way, you can avoid starting the unknown java.exe from your code, but instead your program has to start the file utility you have provided yourself.
I know I am late to this, but I wrote these methods in C# so that it can detect both 32/64-bit JRE and JDK because the provided answers don't suffice my need
private string CheckJreJdkVersion()
{
StringBuilder sb = new StringBuilder();
string jre = #"SOFTWARE\JavaSoft\Java Runtime Environment";
string jdk = #"SOFTWARE\JavaSoft\Java Development Kit";
string jreInstallDirValueName = "INSTALLDIR";
string jdkInstallDirValueName = "JavaHome";
// Check 32-bit JRE
GetJreJdkVersion(jre, RegistryView.Registry32, jreInstallDirValueName, ref sb, "JRE", "32");
// Check 64-bit JRE
GetJreJdkVersion(jre, RegistryView.Registry64, jreInstallDirValueName, ref sb, "JRE", "64");
// Check 32-bit JDK
GetJreJdkVersion(jdk, RegistryView.Registry32, jdkInstallDirValueName, ref sb, "JDK", "32");
// Check 64-bit JDK
GetJreJdkVersion(jdk, RegistryView.Registry64, jdkInstallDirValueName, ref sb, "JDK", "64");
string res = sb.ToString();
return res;
}
private void GetJreJdkVersion(string jreJdkPath, RegistryView registryView, string jreJdkInstallDirValueName, ref StringBuilder sb, string jreJdk, string bitVer)
{
RegistryKey key = GetRegistryKeyHKLM(jreJdkPath, registryView);
if (key == null)
return;
List<string> lstVersions = new List<string>();
foreach (var version in key.GetSubKeyNames())
{
lstVersions.Add(version);
}
IEnumerable<string> relevantVersions = GetRelevantVersions(lstVersions);
foreach (var relevantVersion in relevantVersions)
{
string regPath = string.Empty;
if (jreJdk == "JRE")
{
regPath = Path.Combine(jreJdkPath, Path.Combine(relevantVersion, "MSI"));
}
else
{
regPath = Path.Combine(jreJdkPath, relevantVersion);
}
string installDir = GetRegistryValueHKLM(regPath, jreJdkInstallDirValueName, registryView);
sb.Append("Detected " + bitVer + "-bit " + jreJdk + ", install directory: " + installDir + "\n");
}
}
private IEnumerable<string> GetRelevantVersions(List<string> lstVersions)
{
IEnumerable<string> versions = lstVersions.Where(version => version.Contains("_"));
return versions;
}
public RegistryKey GetRegistryKeyHKLM(string keyPath, RegistryView view)
{
RegistryKey localMachineRegistry
= RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, view);
return string.IsNullOrEmpty(keyPath)
? localMachineRegistry
: localMachineRegistry.OpenSubKey(keyPath);
}
public string GetRegistryValueHKLM(string keyPath, string keyName, RegistryView view)
{
RegistryKey registry = GetRegistryKeyHKLM(keyPath, view);
if (registry == null) return null;
string value = string.Empty;
try
{
value = registry.GetValue(keyName).ToString();
}
catch (Exception)
{
}
return value;
}
Sample output:
Detected 32-bit JRE, install directory: C:\Program Files (x86)\Java\jre7\
Detected 32-bit JRE, install directory: C:\Program Files (x86)\Java\jre1.8.0_73\
Detected 32-bit JRE, install directory: C:\New folder\
Detected 64-bit JRE, install directory: C:\Program Files\Java\jre7\
Detected 32-bit JDK, install directory: C:\jdk fol

Categories

Resources