My problem is to get information about the linux distro what is running the mono code(For example: Linux Mint, Ubuntu, Fedora, etc...)
This is important because my application is used to edit .bash_profile(Ubuntu) or .profile(Linux Mint) or .bashrc(Mac OS) files to easily edit environment variables like Rapid Environment Editor on Windows
Environment.OSVersion.Platform does not give me the necessary details, only Unix in my case(I'm using Linux Mint).
I don't know if there's a .NET API to do this. From the looks of it, it seems you're right, Environment.OSVersion will only tell you you're running Unix.
If that first check indicates you're running Unix, perhaps you can try parsing the /etc/lsb-release file. On my machine that file looks like this:
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=12.04
DISTRIB_CODENAME=precise
DISTRIB_DESCRIPTION="Ubuntu 12.04.4 LTS"
You can test if it exists in other modern distros as well.
Related
I'm trying to build and run the Hello World sample at the tutorial page at R.NET. When I force the program to run in x86 mode, it seems to do OK. However, when I run in x64, it stops very early on with the message, "[program] exited with code-1073740791"
I've installed the latest version of R at The R Project and have ran the troubleshooting steps. The output I've gotten from the troubleshooting program is:
Is this process 64 bits? True
Info: caller provided rPath=null, rHome=null Info: R.NET looked for preset R_HOME env. var. Found null
Info: Found Windows registry key RDotNet.NativeLibrary.WindowsRegistryKey
Info: Found Windows registry key RDotNet.NativeLibrary.WindowsRegistryKey
Info: Found sub-key InstallPath under RDotNet.NativeLibrary.WindowsRegistryKey
Info: InstallPath value of key RDotNet.NativeLibrary.WindowsRegistryKey: C:\Program Files\R\R-4.0.3
Info: R.NET looked for platform-specific way (e.g. win registry). Found C:\Program Files\R\R-4.0.3
Info: R.NET trying to find rPath based on rHome; Deduced C:\Program Files\R\R-4.0.3\bin\x64
C:...\bin\x64\Debug\net5.0\ConsoleNet5R.exe
(process 33500) exited with code -1073740791.
I have verified that there IS a file R.dll where it deduced it should be, "C:\Program Files\R\R-4.0.3\bin\x64". When I step through using my decompiler, it appears that it gets choked up at what is showing up for me as line 400 in REngine.cs, under the function "Initialize" at this.GetFunction<setup_Rmainloop>()(); It doesn't appear to throw an exception, it just stops. I'll be honest--I'm not sure what this line is supposed to be doing...
Any ideas what is going on? I can run in x86 mode if I have to, but I would like to use x64 if possible.
This issue has been reported for a while..
I experienced the same with R-4.0.3 to R-4.0.5.
There is not such issue for R-4.0.2 and former versions (4.0.1, 4.0.0, 3.6, 3.5)
I've done an analysis of this and tracked findings in one of the RDotNet GitHub issues where this was raised (https://github.com/rdotnet/rdotnet/issues/139#issuecomment-898699993).
This appears to be related to the Control Flow Guard security feature enabled in Windows 10. This doesn't happen in the R programs themselves because they are compiled using a different compiler (gcc via mingw) than Microsoft's. However, the CFG feature is enabled for .NET binaries and there is something (sorry, I don't know the actual underlying root cause) in a change within R 4.0.3 in setjmp/longjmp calls that is causing the crash (see: https://github.com/wch/r-source/blob/trunk/src/gnuwin32/fixed/h/psignal.h#L44-L51).
Although you would actually be disabling a security feature, I have had some luck for now in modifying my program after it is compiled (you can set this as a post-build event). You will need to run something like: link /EDIT /GUARD:NO <yourapp>.exe, which disables CFG.
Thanks to https://github.com/dotnet/runtime/issues/11899#issuecomment-502195325 for providing the instructions needed for this workaround, and https://www.trendmicro.com/en_us/research/16/j/control-flow-guard-improvements-windows-10-anniversary-update.html for providing the amazing analysis of CFG that led to an understanding of what was going on.
There are a few questions (and unwanted answers) all over the forums about Microsoft.ACE.OLEDB.12.0 provider not being registered on the local machine, like this one. The gist of the problem, how I understand it, is that the application will look for the provider on the same platform as what the application is running on. So if your computer is 64 bit and the provider 32 bit, then there will be a mismatch if you don't compile the application to run in 32 bit mode.
Most answers effectively deal with this by installing the appropriate data components for the current platform. Other suggestions are to compile for whichever platform the data components are available.
I am developing an app using PCs running Windows 7, 8 and 10, all 64 bit, depending on where I am, but some have older versions of Office and others newer versions. This causes me to have to change the platform for which I compile depending on the PC I currently work on. While this is no problem for me, personally, I foresee this causing headaches for the end users not being able to run the program.
Trying to avoid asking users to install other components on their computers; is there a way I can tell the program to check the platform availability of the database provider and then run in that mode? Might it be possible to create 32 bit and 64 bit extensions of the database module and load the appropriate one regardless of the mode the main program is running in?
EDIT:
I just tried to compile my database extensions on different platforms Whichever one that is not the same platform as the application causes an exception when being loaded saying that I am attempting to load an assembly from a different platform. So I guess I'm out of luck with my option 2...
You can use CorFlags utility to modify your executable on target machine, after you will detect which mode it needs to run.
First ensure that your main exe is compiled under any cpu with Prefer 32 bit flag not set. Now when application is started you need to check if we are in 64-bit process or not, and also check your dependencies (this I won't cover - I don't work with OLEDB). If you found mismatch (say you are running in 64-bit process but your dependencies are 32-bit) - you need to run external process to modify your main executable and then restart it. Easiest way to do it is via simple cmd script, like this (in this example my main exe is called ConsoleApplication3.exe):
:start
start /wait "" "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\CorFlags.exe" ConsoleApplication3.exe /32BIT+
if errorlevel 1 (
goto start
)
start "" ConsoleApplication3.exe
Note that this is just example and if something goes wrong it will fall into endless loop, adjust to your requirements. What this script does is just updates your exe using CorFlags tool to run in 32-bit mode, then starts your main exe.
Right after starting your application, you might do the following check:
static void Main() {
if (Environment.Is64BitProcess) {
// here you also check if you have dependency mismatch, and then:
Console.WriteLine("Running in 64-bit mode. Press any key to fix");
Console.ReadKey();
// run script (here we assume script is in the same directory as main executable, and is called fix-mode.cmd
var process = new Process() {
StartInfo = new ProcessStartInfo("cmd.exe", "/c call fix-mode.cmd")
};
process.Start();
// here you should exit your application immediatly, so that CorFlags can update it (since it cannot do that while it is running)
}
else {
// after restart by our script - we will get here
Console.WriteLine("Running in 32bit mode");
}
}
Note that this tool (CorFlags) is available only with Visual Studio so you may want to pack it together with your application (might be not available on remote machine).
First I would like to say thank you for helping me with this issue. I really appreciate your time and efforts.
The title sums it up pretty well however I will provide a few specifics. Basically if I pull my OS version using C# it returns the result 6.2 which is for Windows 8 even though my system is 8.1 which should return 6.3. After my research I found that this was a documented limitation inside of the System.Enviroment class, ... gotta love those "features".
I have found a way to deal with this by going into the reg and comparing my 6.2 result with the current version key under HKLM\SOFTWARE\Microsoft\WindowsNT\CurrentVersion however, this is a very risky operation as the reg info could change without notice.
It all got screwy on me when I tried to poll WMI though Powershell. I can't remember why I did a WMI search though Powershell, I guess its not just cats that get curious :)
C# Code:
string version = Environment.OSVersion.ToString();
MessageBox.Show(version);
//Output "Microsoft Windows NT 6.2.9200.0"
Powershell Code:
[System.Environment]::OSVersion | Select-Object -Property VersionString
//OUtput "Microsoft Windows NT 6.3.9600.0"
I have tried both x86 and x64 builds of my C# program as well as running the Powershell both x86 and x64. The discrepancies did not change.
This raises several questions for me but the basic one is where does Powershell get the correct info from? Does Powershell use the reg like I had planned to fix its output? Since my build targets .Net 3.5 does Powershell pull .Net 4.5 (changed my build and this changed nothing).
From my understanding [System.Environment]::OSVersion pulls info the same as System.Environment.OSVersion.
How the heck does Powershell work and C# fails??
:)
Thanks again!
As far as I can tell only the Environment.Version call in a C# program is incorrect (6.2). In PowerShell it is correct (6.3). In WMI called via PowerShell or C# it is correct. In fact, C# compiled from source in PowerShell using Add-Type returns 6.3.
Looking into the article here (thanks Booga Roo) it indicates that unless your application specifically says it targets Windows 8.1 via a manifest file, you get the old version (6.2).
You can make a C# application return the correct version by adding an application manifest file and declaring 8.1 support by uncommenting the line
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
It seems safe to assume that the writers of PowerShell at Microsoft included an application manifest with powershell.exe that declares Windows 8.1 support.
I have two applications running on W2k8 R2 x64, one is compiled as 64bit and the other one as 32bit as it has COM dependencies.
In both I'm trying to call:
Process p = Process.Start("telnet.exe", string.Format("{0} {1}", address, port));
In the x64 it works perfectly fine, however in the 32bit one I get a System.ComponentModel.Win32Exception ("The system cannot find the file specified")?
Any idea what's going on here? Even if I call
Process.Start(#"C:\Windows\System32\telnet.exe")
I get the same exception?
Thanks,
Tom
To launch a system32 located 64bit app from a 32bit app (at least on Vista,2k8,7, doesn't work on x64 XP or 2k3) run it from the sysnative directory, i.e. "C:\windows\sysnative\telnet.exe" (alternatively disable Wow64 but that is generally a bad idea).
This drove me crazy... had one project that would find "telnet.exe" without the full path and one that refused to find it (even with the path, or never figured it out). My dev machine is 64-bit.
The problem was the target platform in build.
If it's set to x86 it will not find telnet.
set it to Any CPU it will find telnet.
sometimes you need to set it to x86, this allows your applications to see 32-bit drivers (such as odbc drivers) on 64-bit platforms
Windows Server 2008 does not have a 32 bit telnet.exe client. It only installs a 64bit version in the windows\system32 folder.
\live.sysinternals.com\tools\procmon.exe and/or procexp always has the answer.
Have you looked at the path environment variable in the context of your process? Can you prefix it with the System\SysWow64 path to make it work?
copy telnet.exe to SysWow64 folder
I have a program that works fine on VS2008 and Vista, but I'm trying it on Windows 7 and VS2010 / .NET Framework 4.0 and it's not working. Ultimately the problem is that System.Diagnostics.PerformanceCounterCategory.GetCategories() (and other PerformanceCounterCategory methods) is not working. I'm getting a System.InvalidOperationException with the message "Cannot load Counter Name data because an invalid index '' was read from the registry."
I can reproduce this with the very simple program shown below:
class Program
{
static void Main(string[] args)
{
foreach (var pc in System.Diagnostics.PerformanceCounterCategory.GetCategories())
{
Console.WriteLine(pc.CategoryName);
}
}
}
I did make sure I'm running the program as an admin. It doesn't matter if I run it with VS/Debugger attached or not. I don't have another machine with Windows 7 or VS2010 to test it on, so I'm not sure which is complicating things here (or both?). It is Windows 7 x64 and I've tried forcing the app to run in both x32 and x64 but get the same results.
It seems performance counters were corrupted on my system. Although I didn't follow this post exactly, it led me to the solution. Here is what I did:
In an command prompt with administrator/elevate privileges typed the following:
lodctr /?
Useful stuff in there...
Then typed:
lodctr /R
According to the docs from the prior step, this gets windows to rebuild the perf registry strings and info from scratch based on the current registry settings and backup INI files. I have a feeling this is what did the magic. However, next I noticed the .NET performance counters were not there anymore so based on this I typed the following to reload them:
lodctr "C:\Windows\Microsoft.NET\Framework64\v4.0.20506\corperfmonsymbols.ini"
Note that this path is for .NET Framework 4.0 on x64. You can imagine the path for other variations of the framework/platform. I'm guessing you should always load the counters from the highest version of the .NET framework that you have installed, but that is just a guess.
I hope this helps someone else someday!