Getting the CLR ID - c#

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.

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.

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?

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.

Related

Is it a programmatic way to get SQL keywords (reserved words)

I need to validate the Name of a SQL column, which is created programmatically...
There whould be 2 validation rules:
The Name shouldn't be a C# keyword
The Name shouldn't be a SQL keyword (SQL Server 2008 R2)
The solution for 1st rule it's nice:
The CSharpCodeProvider class has the IsValidIdentifier method which makes the implementation of validation easy.
(ex:
string myColumnName = "blabla";
var isValid = _cSharpCodeProvider.IsValidIdentifier(myColumnName);
)
The solution for 2nd rule it's a litle verbose:
The only way I found doing google searches is to take the keywords from MSDN - Reserved Keywords (Transact-SQL) SQL Server 2008 R2
To build a string[] property which will return all these keywords...
(ex:
public static class SqlReservedKeywords {
public static string[] SqlServerReservedKeywords {
get { return SqlServerKeywords; }
}
private static readonly string[] SqlServerKeywords = new[] {
"ADD","EXISTS","PRECISION",
//. . .
"EXEC","PIVOT","WITH",
"EXECUTE","PLAN","WRITETEXT"
};
}
//External code
var isValid = SqlReservedKeywords.SqlServerReservedKeywords.Contains(myColumnName);
)
Can you advice me about implementantion of 2nd validation rule.
Is it a good practice?
Maybe it exist another way to implement which i didn't found by googling...
Reserved words are a moving target. If the dbms doesn't expose them through a public interface, there isn't usually a good programmatic way to get to them.
If you don't want to guard them with brackets, you risk incorporating symbols that are not reserved in your currently used version of SQL Server, but are reserved in some future version.
I think your best bet is to use the quoting mechanism your dbms provides, since it's designed to deal with exactly this problem. For SQL Server, that means square brackets.
Since there is a function you can call for C#, the real question is how to do the lookup for SQL Reserved words. The way you implemented look up here is NOT the most efficient C#. You should use a HashSet -- quick untested code example follows:
public static class SqlReservedKeywords {
public bool isReserved(string in)
{
return SqlServerKeywords.Contains(in.ToUpper());
}
private static HashSet<string> SqlServerKeywords = new HashSet<string>();
static SqlReservedKeywords()
{
SqlServerKeywords.Add("ADD");
SqlServerKeywords.Add("EXISTS");
SqlServerKeywords.Add("PRECISION");
//. . .
SqlServerKeywords.Add("EXEC");
SqlServerKeywords.Add("PIVOT");
SqlServerKeywords.Add("WITH");
SqlServerKeywords.Add("EXECUTE");
SqlServerKeywords.Add("PLAN");
SqlServerKeywords.Add("WRITETEXT");
}
}
Here is a nice article (by #theburningmonk) showing how fast HashSet is when using Contains
(For those that don't want to click, HashSet is zero)
http://theburningmonk.com/2011/03/hashset-vs-list-vs-dictionary/
Generally, the approach looks correct. Getting keywords for any given language involves a (hopefully small) bit of trial and error due to anything undocumented but the main source is always the language specification itself. I don't know of any languages that come with their own validators but that's not to say they don't exist.
Visual Studio itself has a set of xml files that help it do the validation for any given language. If you were developing an IDE, you might have a table that looked something like;
Keyword | MatchWithRegEx | Color
------------+----------------+---------
for | \wfor | #FF0000
...you get the idea. In your case, you just want to filter out possible problem keywords so that they don't throw an exception. Allowing an exception to be thrown and catching and handling it specifically is a valid methodology albeit not a very clean one.
As for your case, the only real tweak I'd make is not having the list of keywords buried into the program at compile time but instead store the list in an external file which is loaded at your application's starting point. This allows some flexibility if you forget anything or need to support later versions of a language without requiring a rebuild of your application.

Is there a programatic way to identify c# reserved words?

I'm looking for a function like
public bool IsAReservedWord(string TestWord)
I know I could roll my own by grabbing a reserve word list from MSDN. However I was hoping there was something built into either the language or .NET reflection that could be relied upon so I wouldn't have to revisit the function when I move to newer versions of C#/.NET.
The reason I'm looking for this is I'm looking for a safeguard in .tt file code generation.
CSharpCodeProvider cs = new CSharpCodeProvider();
var test = cs.IsValidIdentifier("new"); // returns false
var test2 = cs.IsValidIdentifier("new1"); // returns true
The Microsoft.CSharp.CSharpCodeGenerator has an IsKeyword(string) method that does exactly that. However, the class is internal, so you have to use reflection to access it and there's no guarantee it will be available in future versions of the .NET framework. Please note that IsKeyword doesn't take care of different versions of C#.
The public method System.CodeDom.Compiler.ICodeGenerator.IsValidIdentifier(string) rejects keywords as well. The drawback is this method does some other validations as well, so other non-keyword strings are also rejected.
Update: If you just need to produce a valid identifier rather than decide if a particular string is a keyword, you can use ICodeGenerator.CreateValidIdentifier(string). This method takes care of strings with two leading underscores as well by prefixing them with one more underscore. The same holds for keywords. Note that ICodeGenerator.CreateEscapedIdentifier(string) prefixes such strings with the # sign.
Identifiers startings with two leading underscores are reserved for the implementation (i.e. the C# compiler and associated code generators etc.), so avoiding such identifiers from your code is generally a good idea.
Update 2: The reason to prefer ICodeGenerator.CreateValidIdentifier over ICodeGenerator.CreateEscapedIdentifier is that __x and #__x are essentially the same identifier. The following won't compile:
int __x = 10;
int #__x = 20;
In case the compiler would generate and use a __x identifier, and the user would use #__x as a result to a call to CreateEscapedIdentifier, a compilation error would occur. When using CreateValidIdentifier this situation is prevented, because the custom identifier is turned into ___x (three underscores).
However I was hoping there was something built into either the language or .NET reflection that could be relied upon so I wouldn't have to revisit the function when I move to newer versions of C#/.NET.
Note that C# has never added a new reserved keyword since v1.0. Every new keyword has been an unreserved contextual keyword.
Though it is of course possible that we might add a new reserved keyword in the future, we have tried hard to avoid doing so.
For a list of all the reserved and contextual keywords up to C# 5, see
http://ericlippert.com/2009/05/11/reserved-and-contextual-keywords/
static System.CodeDom.Compiler.CodeDomProvider CSprovider =
Microsoft.CSharp.CSharpCodeProvider.CreateProvider("C#");
public static string QuoteName(string name)
{
return CSprovider.CreateEscapedIdentifier(name);
}
public static bool IsAReservedWord(string TestWord)
{
return QuoteName(TestWord) != TestWord;
}
Since the definition of CreateEscapedIdentifier is:
public string CreateEscapedIdentifier(string name)
{
if (!IsKeyword(name) && !IsPrefixTwoUnderscore(name))
{
return name;
}
return ("#" + name);
}
it will properly identify __ identifiers as reserved.

Converting C# Data Types from unknown sources

There seems to be a lot of confusion around converting strings (usually) to their appropriate datatype, whilst validating it on the fly as well. Wherever I look - blogs, articles, code samples, forums.. a few people seem to have a preferred way of dealing with these scenarios.
The case is usually a string/object that comes from an unknown source, such as QueryString, Session/Viewstate, WebService, and so on...
I've seen many different examples:
Say we're trying to get the id= Query String and use it in our code as an integer. But someone tampered with our URL and changed it to
http://www.example.com/page.aspx?id=sometextvalue
One way
int id = Convert.ToInt32(Request["id"]);
// "Input string was not in a correct format"
Another way
int id = (int)Request["id"];
// "Input string was not in a correct format"
Yet another way
int id = int.Parse(Request["id"]);
// "Input string was not in a correct format"
I have ever seen this (And it kind of makes sense to throw an exception and notify the user)
int id = 0;
try {
id = Convert.ToInt32(Request["id"]);
}
catch(Exception ex) {
lblError.Text = ex.Message;
}
if(id > 0) { ... }
Lastly, and the one I personally use
int id = 0;
int.TryParse(Request["id"], out id);
// make sure it's not 0
if(id > 0) { // live a happy life }
This goes for all the other types, bool, double, decimal and so on..
Please help me understand what the correct way is, as I find myself using this on a day-to-day basis.
Well, for starters you should be using:
int id;
if(!int.TryParse(Request["id"], out id)
//notify the user, or handle it someother way
instead of checking for id > 0. int.TryParse(string, out int) returns true if the parse succeeded, false otherwise.
MSDN Documentation for int.TryParse(string, out int)
The System.ComponentModel namespace contains a well-designed framework for doing exactly these types of conversions.
Inspect the namespace for yourself, but this will get you going for starters:
targetType newValue = (targetType) System.ComponentModel.TypeDescriptor.GetDescriptor(typeof(sourceType))
.ConvertTo((object)value, typeof(targetType))
You get the basic type conversions for free in one centralized type-agnostic place rather than having to search through the unfortunately inconsistent X.Parse or X.TryParse methods found on the primitive types.
On top of the basics, you get an extensible framework where you can write your own type converters among other things. The ASP.NET MVC framework makes use of this namespace heavily to handle its type conversions for things like query-string value conversions to method parameters.
I don't think any of these would actually be considered "Correct". I like to use Convert.ToInt32() because I can get some specific exceptions that I can check for to see if its valid input.
Correct: Answer is, it depends. You should learn the difference between typecasting, parsing. Use them appropriately.

Is there .net magic to get parameter values by name in console application?

I've been developing .net console applications using C# and have always just dictated what order parameters must be inserted in so that args[0] is always start date and args[1] is always end date, for example.
however I would like to move over to using named parameters so that any combination of parameters can be sent in any order, such as the typical "-sd" would prefix a start date.
I know I could parse through the args[] looking for "-" and then read the name and look the next position for the accompanying value, but before doing that wanted to see if there was any kind of baked in handling for this rather standard practice.
is there something like this out there already that could do as such:
DateTime startDate = (DateTime)((ConsoleParameters)args[])["sd"]
I'm using C# and .Net 4
There is nothing built into the core framework.
A lot of people think NDesk.Options is useful for this sort of thing. Check out this example (taken directly from the provided link):
string data = null;
bool help = false;
int verbose = 0;
var p = new OptionSet () {
{ "file=", v => data = v },
{ "v|verbose", v => { ++verbose } },
{ "h|?|help", v => help = v != null },
};
List<string> extra = p.Parse (args);
Yes, the "magic" is that this is a common problem and it has been adequately solved. So I recommend using an already written library to handle parsing command line arguments.
CommandLineParser has been great for me. It is reasonably documented and flexible enough for every type of command line argument I've wanted to handle. Plus, it assists with usage documentation.
I will say that I'm not the biggest fan of making a specific class that has to be adorned with attributes to use this library, but it's a minor point considering that it solves my problem. And in reality forcing that attributed class pushes me to keep that class separate from where my app actually retrieves it's settings from and that always seems to be a better design.
You can use NDesk.Options.
There is no such a thing as named parameters. "-sd" is just a choice for a specific application. It can be "/sd" as well. Or "sd=". Or whatever you want.
Since there are no named parameters, there is nothing inside .NET Framework which let you use the "-sd" syntax.
But you can quite easily build your own method to get a set of "named parameters" for your app.
Edit: or, even better, you can use an existing library, like suggested in other answers.
Edit: reading the answer by #Sander Rijken, I see that I was wrong: there were still an implementation of "-sd" syntax in .NET 4.0 before the release. But since it was dropped before the final release, the only ways are still to create your own method or to use an existing library.

Add Ellipsis to a Path in a WinForms Program without Win32 API call (revisited)

I was searching for a way to insert an ellipsis in a C# path, and found an answer here on stackoverflow: C# Path Ellipsis without Win32 API call
Using the RTM versions of VS2010 and .Net 4.0, I was unable to get the suggested method to work. I searched the 'Net and found example code that uses the same method, but it failed in the same way.
You can see the string I'm trying to shorten in my code below.
After calling the MeasureText method, both the input string (OriginalName) and the output string (ellipsisedName) look like this:
d:\abcd\efgh\ijkl\mnop\qrst\...\test.txt\0F\GHIJ\KLMN\OPQR\STIV\WXYZ\test.txt
Two problems:
1) The resulting string is narfed (the path is truncated as expected, but is followed by what looks like a C-style terminating null and a chunk of the original path).
2) My original string is changed to be identical to the output string.
Am I doing something wrong?
namespace WindowsFormsApplication2 {
public partial class Form1 : Form {
public Form1()
{
InitializeComponent();
string OriginalPath = #"d:\abcd\efgh\ijkl\mnop\qrst\uvwx\yzAB\CDEF\GHIJ\KLMN\OPQR\STIV\WXYZ\test.txt";
string ellipsisedPath = OriginalPath;
Size proposedSize = new Size(label1.Width, label1.Height);
TextRenderer.MeasureText(ellipsisedPath, label1.Font, proposedSize, TextFormatFlags.ModifyString | TextFormatFlags.PathEllipsis);
}
}
}
Holy moly, you've found a whopper of a bug. The P/Invoke used inside the TextRenderer class that calls DrawTextEx() is borked. That API function is writing back into the string, which it is allowed to do since the cchText argument is a LPTSTR, not a LPCTSTR. That destroys the .NET string content for both variables because the string is interned.
The bug isn't specific to .NET 4.0, I see it wrong in the ReferenceSource for .NET 3.5 SP1 as well and can repro it on VS2008. The trouble is in the internal WindowsGraphics.MeasureText function. You can report the bug at connect.microsoft.com.
A possible workaround is to alter the string so it gets copied and can't affect the original:
string ellipsisedPath = OriginalPath + '\0';
But the better workaround in this case is to simply not pass the ModifyString option, it serves no purpose. Which is safer too, there is still a possibility of destroying the garbage collected heap with the first workaround. The fix for Microsoft is similarly simple, it should just mask out the ModifyString option. It is documented to have no effect.
My original string is changed to be identical to the output string.
You've asked for this to happen by specifying TextFormatFlags.ModifyString, which the docs say
Modifies the specified string to match the displayed text. This value has no effect unless EndEllipsis or PathEllipsis is also specified.
This is (to my mind) an unusual way for a .NET Framework call to operate, but it does clearly say it will do this. Both the 'original' string and the 'output' string end up being modified, because string is a reference type (though usually with immutable value semantics) - when you say
string ellipsisedPath = OriginalPath;
you are actually just making ellipsisedPath refer to the same string instance as OriginalPath does. When this instance gets modified by the API call, both the references to it will see the modification.
As for
the path is truncated as expected, but is followed by what looks like a C-style terminating null and a chunk of the original path
my guess would be that the abstraction this managed wrapper provides around the Win32 API call is being somewhat leaky, as abstractions are prone to being - it's not shielding you from the fact that the underlying call works with C-style strings. It might be that you'll have to deal with yourself.

Categories