9

Is there any where to get the CLR ID at runtime for the current application? I am monitoring my system using Performance Monitors and the name used for the instance is:

ApplicationName.exe_p4952_r15_ad1

I can get all other parameters programmatically but not the r15 which is the runtime ID of the common language runtime (instance) that executes your code. I noticed it is always 15, but it is best to get it dynamically to avoid complications.

M.Babcock
  • 18,753
  • 6
  • 54
  • 84
TheGateKeeper
  • 4,420
  • 19
  • 66
  • 101
  • Does using Process.GetProcesses help you out? http://msdn.microsoft.com/en-us/library/system.diagnostics.process.getprocesses.aspx – Kris Krause Apr 17 '12 at 18:16
  • Doesn't seem to have what I am looking for. – TheGateKeeper Apr 17 '12 at 18:27
  • That's novel. What does "p4952" and "ad1" mean then? Is this your own counter? Then post the code you used to create it. – Hans Passant Apr 17 '12 at 18:56
  • You think I made this up? Here `http://msdn.microsoft.com/en-us/library/dd537616.aspx` the `p` is the application ID and the `ad` is the application domain. I juts need a way to get the `r` programmatically. – TheGateKeeper Apr 17 '12 at 19:28
  • Have you tried `Thread.CurrentThread.ManagedThreadId`? – Joseph Yaduvanshi Apr 20 '12 at 21:16
  • Didn't return the correct number. It returned 9 while the counter is still using the number 15. – TheGateKeeper Apr 21 '12 at 15:27
  • 1
    I have a feeling this may be an internal identifier only intended to be used in Profiler contexts, because I took my own shot at finding info on it and I've found zilch *excepting* profiling side-by-side application instances. – David W Apr 24 '12 at 15:07
  • So there is no way to get this info programmatically? Will it always be 15? It always is 15 on my machine but I wonder if it is the same on who ever else will use it... – TheGateKeeper Apr 24 '12 at 18:36
  • Why not enumerate over the instances and parse the name to your liking (ignoring whatever you don't need)? – Allon Guralnek Apr 24 '12 at 19:48
  • I would rather not do that, althou it is a solution. What if there are 2 counters using the same name? It wouldn't work. Why is it so hard to get the runtime Id?? – TheGateKeeper Apr 25 '12 at 14:54

3 Answers3

5

You can get the whole "suffix", i.e. the part after Application.exe using the same infrastructure that the .NET framework (e.g. the peformance counters) does.

There is the method System.Runtime.Versioning.VersioningHelper.MakeVersionSafeName, which can do that. Note that the method is described as being "Infrastructure" and "This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.", but nevertheless is public. I don't think there is any "better supported" way to get the information you want. At least it is more robust and resilient to future changes, then reverse engineering the information based on documentation.

string suffix = System.Runtime.Versioning.VersioningHelper.MakeVersionSafeName("",                         
    System.Runtime.Versioning.ResourceScope.Machine,
    System.Runtime.Versioning.ResourceScope.AppDomain));

This returns _p4472_r16_ad1, for example.

Of course, you could also directly pass the basename of the performance counter to directly get the full name. The usage of the empty string above is only a trick to just get the "suffix".

string str = VersioningHelper.MakeVersionSafeName("Application.exe",
    ResourceScope.Machine, ResourceScope.AppDomain);

// str -> "Application.exe_p4472_r16_ad1".

The class VersioningHelpers also has the private method GetRuntimeId(), but given the above, I don't think it is neccessary to use reflection on that achieve what you need.

Christian.K
  • 47,778
  • 10
  • 99
  • 143
  • Thanks so much man! I knew there was a way to get this information. This method is perfect. I dumped my old "piece by piece" builder and used this instead, which returns the full string on it's own. Also since this is what the performace counter uses, I can be sure it will work on 99% of the machines this runs on :) – TheGateKeeper May 03 '12 at 12:17
  • To get "Application.exe", use the filename of the current process: `Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName)` – Daniel Rose Aug 03 '18 at 12:40
1

As far as I can see there is no way to predict what that value will be - here is a quote from the MSDN page you linked (emphasis mine)

runtimeID is a common language runtime identifier.

The article is slightly confusing as it gives an example whereby an application myapp.exe hosts two CLR runtimes however in the example the two instances appear to have different process IDs but the same CLR runtime ID.

The article however definitely doesn't give any promises about what the value of the CLR runtime ID will be or how to find it (it doesn't even state that its a number), which implies to me that its an internal thing and you shouldn't rely on being able to work out what it is.

My approach would probably be to enumerate through all Perfmon counters and monitor any of them that match your PID. If there is more than one (which will happen if you are using any .Net 2.0 components) then you will just have to monitor both.

Can you give any more information about what it is you are trying to do?

Justin
  • 84,773
  • 49
  • 224
  • 367
  • I am monitoring net in/out of my application. Why did microsoft include this "unkown" variable in the equation? Before it was just appname[appID] and was so simple to use... now it is really confusing. I know I can enumerate thru all the instances and find my application name, but I would rather not do that. I will keep looking for a solution. – TheGateKeeper Apr 25 '12 at 16:22
  • @TheGateKeeper In that can you not just monitor both and sum the value? – Justin Apr 25 '12 at 16:28
  • I know I can isolate the instance name from all the instances running in perfmon, but that is not the ideal solution to me. There must be some way to get this variable, it's impossible it's hidden if they included it in an identifier. – TheGateKeeper Apr 25 '12 at 16:33
0

You can find it easily by splitting the string you get :

This function split the instance name , and search for the only part that begins with "r" and does not end with ".exe". Once the right part of the string has been found , just delete the first letter "r" and just keep the number to convert it into an integer number and return it. If the CLR ID is not found , just return "-1" to let the parent function notice this.

    int getClrID(string instance_name)
    {
        string[] instance_name_parts = instance_name.Split('_');
        string clr_id = "";

        for (int i = 0; i < instance_name_parts.Length; i++)
        {
            if (instance_name_parts[i].StartsWith("r") && !instance_name_parts[i].EndsWith(".exe"))
            {
                clr_id = instance_name_parts[i];
                break;
            }
        }

        if (clr_id == "") // An error occured ...
            return -1;
        else 
            return Convert.ToInt32(clr_id.Substring(1));
    }

I hope I helped you.

Sywesk
  • 21
  • 2
  • Hi, thanks for the effort but this is useless. If I somehow had the full string in my code, I wouldn't need to split it to get the CLR Id, I would just use it as it is. I need a way to get the CLR ID from code. – TheGateKeeper Apr 25 '12 at 15:38