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!
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).
I have a problem that an instance of an AggregateException causes a TargetInvocationException after a couple of accesses to an Icon resource.
I broke down the problem to the following steps to reproduce (.Net 4.0 full or client profile):
Create a new WinForms application (a console application will not work)
Add an arbitrary icon (.ico file) to the resources
Add the following code to the constructor:
new AggregateException();
for (var i = 0; ; ++i)
{
var icon = Resources.Certificate;
}
You have to change the resource name to the name of your resource.
That's all. Yes I know that this sample doesn't make sense. It's just to illustrate the problem. My working code is much more complex and all of this code is needed.
Without creating this excection the application will work forewer. But if this exception is created the access to the resource will fail with a TargetInvocationException. The InnerException told me that the operation has been finished successfully(?!?!) having a two-line stack trace in System.Drawing.Icon (ctor + Initialize).
What can I do to prevent this problem?
EDIT
It seems to be a problem using Windows 7. A binary which fails on Win 7 will run correctly in Win 8.1.
I found the reason for that problem:
The following system configuration is needed to reproduce the issue:
Windows 7 German Edition
Microsoft .Net Framework 4.5.2 installed (yes I know my binary is compiled against .Net 4.0)
KB2901983 installed
Having a machine which only contains the .Net Framework without KB2901983 the program works fine. After installing KB2901983 the program fails for the same binary (no recompilation required).
I tried to uninstall KB2901983 but it doesn't help. If it was once installed the program will fail. I tested it on a clean Windows 7 German Edition.
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.
My app runs fine on my machine (of course/famous last words). However, when deploying it to another machine on the network, it won't even start up. I ran my EventLog utility on that machine and it told me this:
Type:Error
Source: .NET Runtime
Time Generated: 06/12/2012 15:35:12
Message: Application: duckbilledPlatypus.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.TypeInitialization
Exception
Stack:
at duckbilledPlatypus.PlatypusMainForm..ctor()
at duckbilledPlatypus.Program.Main()
So it's something in my main form's constructor that's the problem, apparently...which, I admit, is a little "busy":
InitializeComponent();
foreach (string arg in Environment.GetCommandLineArgs())
{
if (arg == "-DEBUG")
{
InDebugMode = true;
break;
}
}
SuspendLayout();
tsch = new ToolStripControlHost(dateTimePickerScheduleDate);
toolStripPlatypusMain.Items.Add(tsch);
CreateTableLayoutPanelAndChildren();
LimitPlatypusIDTextBoxesToOneChar();
ShareEventsAmongDynamicTextBoxes();
SetAllPlatypusDataControlsReadOnly();
ResumeLayout();
Does any of this look problematic? (it's all pretty standard stuff, except for the ToolStripControlHost).
Now as to the framework version: does the Event Log report the framework version used to create my app, or the framework version installed on the machine trying to run the app? If the former, and the latter does not have that framework installed, that's a problem, right?
So if that's potentially the problem, how do I determine which version of the .NET runtime is installed on that machine?
UPDATE
I don't know why this is, but I was able to see an err msg after running the app on the remote/deployment only when I right-click and select Run As (and ran as myself, as I don't have any "more special" privileges on that machine). When I did so, I got "Unable to find a version of the runtime to run this application."
If I simply 2-click the app, it dies without a whimper (no err msg).
View the
view the %WINDIR%\Microsoft.NET\Framework directory
to determine which versions of .NET are installed.
http://msdn.microsoft.com/en-us/library/y549e41e.aspx
Try running the Fusion Log Viewer on the problematic machine. It will provide details about binding failures.
http://msdn.microsoft.com/en-us/library/e74a18c4(v=vs.100).aspx
Make sure you run it as administrator. It silently fails if you do not.
UPDATE
Based on your error "Unable to find a version of the runtime to run this application.", I would suggest you don't have the same version of .NET installed on the box that your application targets. Did you verify the installed versions using the steps above?
Also see
.Net framework - "unable to find a version of the runtime to run this application"