Powershell WMI output doesnt match c# WMI output - c#

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.

Related

R.NET works with x86 but not x64

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.

Running C++ app from C# process running on Mono. run-detectors error

I'm currently working on porting a tool to Linux. I'm using mono to to this, and have got the main tool running. However, this tool calls another program, which is written in C++ and compiled natively on Linux with g++. I've had a lot of difficulty porting this over, but have it working and running (runs as expected with ./othertool.exe).
However, when trying to run the original tool on Mono, it fails at launching the other tool, giving a error.
run-detectors: unable to find an interpreter for .../othertool.exe
I'm not sure why this happens, as when testing with a hello world, I managed to get a C++ program running by calling it from C# on Mono. I'm running the other tool using the Process class (see code) which works fine with the hello world example.
var process = new Process
{
StartInfo =
{
FileName = baseDir +
Path.DirectorySeparatorChar +
"tools" +
Path.DirectorySeparatorChar +
"othertool.exe",
Arguments = arguments.ToString(),
UseShellExecute = false
}
};
process.Start();
process.WaitForExit();
Anyone know why this happens? Google does not yield anything so I guess this might not be common. Feel free to ask for more information or clarity, as I've probably left something out.
Ok so turns out that I was somehow using the Windows built version of othertool instead of the Linux one. Who let that happen? Runs 'fine' when using the correct one. – Cameron
Cool, run-detectors/interpreter failures usually (always?) are related to PE executable (.exe) issues (and other non-Linux binaries), assuming you are on a Linux disto (like Ubuntu) that support launching PE format but without something like Wine installed, you will get a failure. IMHO: Naming non-PE/non-CIL files as an .exe is bad-form on Linux...
– SushiHangover

How to get linux distribution info in mono?

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.

Class not registered error from PHP

We've created a C# class library assembly and made it COM visible to be able to call its methods from PHP. This used to work fine, but now we wanted to install it on a Windows Server 2008 server and we keep walking into the error "Class not registered".
To rule out any dependency problems I made a tiny little test class library in C#. The class library is built for Any CPU and it is COM visible (also set COMVisible to true in AssemblyInfo.cs). The test class library only contains one class with one method. The class is called TestLib and the namespace is also called TestLib. The method is called Test and only returns a string.
What we have done is the following:
- built the TestLib.dll
- copied it to the Windows Server 2008 machine
- registered the dll with: regasm /codebase TestLib.dll
- the regasm tool returns a success message
- in PHP we simply try to create a new COM instance:
try
{
$test = new COM("TestLib.TestLib");
}
catch (Exception $e)
{
die($e->getMessage());
}
when we call this test script from either the browser or the commandline (php -f test.php) we get the error "Class not registered" in both cases
I also tried adding TestLib to the GAC by using gacutil -i, but to no avail; still the class not registered error.
Then I tried compiling the testlibrary with .NET 2.0 instead of 4.0 as the target framework, same result. The .NET framework 4.0 is installed on the server by the way.
Any ideas?
Okay, so after some more research I figured it out. The php.exe process is 32 bit. The COM visible assembly is compiled for Any CPU so it should be accessible to both 32 and 64 bit applications.
The problem is that on a 64 bit OS php.exe, and any 32 bit process for that matter, searches in HKEY_CLASSES_ROOT\Wow6432Node\CLSID instead of HKEY_CLASSES_ROOT\CLSID and in HKEY_LOCAL_MACHINE\Software\Classes\Wow6432Node\CLSID instead of HKEY_LOCAL_MACHINE\Software\Classes\CLSID. The registry entries in the Wow6432 keys aren't created by regasm that is shipped with .NET framework v4 on Windows Server 2008. On Windows 7 they are created, don't ask me why.
It also turned out that if I create a little test assembly for .NET v2.0 and register it with regasm that ships with .NET framework v2.0 that it does create the Wow6432Node entries on Windows 2008. Strange.
So my solution is to create a basic registry file on the server using:
regasm /regfile MyClassLib.dll
This creates a file MyClassLib.reg with only the 'normal' 64 bit entries. Then I exported the Wow6432Node keys from a Windows 7 machine and added it to that .reg file. Now when I import that reg file into the registry on Windows 2008 everything works fine.
For more info on the Wow6432Node entries check out: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724072%28v=vs.85%29.aspx
Hope this saves someone else some time and headaches.
If you are trying to call a 32-bit COM DLL on 64-bit Windows, you will need to register it.
Copy your 32-bit DLL to C:\Windows\sysWOW64
Run C:\Windows\sysWOW64\regsvr32.exe your_com_32.dll
A bit more info with screenshots.

PerformanceCounters on .NET 4.0 & Windows 7

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!

Categories