Comments, how-to's, examples, tools, techniques and other material regarding .NET and related technologies.
Tuesday, January 13, 2009
Unit Testing for Silverlight
Tuesday, June 24, 2008
Watch Out: Window.ObjectKind is UPPER CASE!
string guidpos = "{426E8D27-3D33-4fc8-B3E9-9883AADC679F}";
string guidpos = "{426E8D27-3D33-4FC8-B3E9-9883AADC679F}";
=====
I've highlighted the important bit with red color, bold, and a larger font. In addition I have underlined it. I think you got the idea.
Why is this change important? Assume you iterate over the collection as follows:
foreach(Window2 toolWin in toolWins) {
string toolWinKind = toolWin.ObjectKind;
if( toolWinKind.Equals(guidString) ) {
_toolWindow = toolWin;
break;
}
}The Equals() call may always result in 'false' even if you think you are looking at the correct tool window. The reason is that ObjectKind returns the guid all upper case. The example code has two lower case characters in the guidpos variable.
The same can also happen when you use "Create GUID" from the "Tools" menu in Visual Studio. It may generate a guid for you with one or more lower case digits ('a' through 'f') as well.
It's unfortunate that the online documentation doesn't mention that some time between calling CreateToolWindow2() and calling ObjectKind everything is made upper case. The example code leads to potentially incorrect behavior of your addin as well. This post gives you the heads-up.
It took me quite some time to spot this little difference. In my case it was 'f' versus 'F' and only when Equals() insisted on returning false I took a closer look. Maybe this helps you saving some development time.
And maybe someone from Microsoft is reading this. I tried to add it as Community Content at MSDN. It wasn't possible. So I rated the article and left a comment adding the suggestions for improvement. This would have been ideal for "Community Content". MSFT, you mind updating the online material? Thank you!
Thursday, June 19, 2008
csUnit: What's Next?
Saturday, June 14, 2008
Vista: Finding Encrypted Files
- Open a command prompt and switch to a directory in which you have write permissions.
- Run the command: "cypher /s:c:\ /N /U > filelist.txt" and wait until finished (this example searches the entire volume c:
- When finished open the file filelist.txt. It contains a list of all files that are encrypted.
- In the Explorer window navigate to each file and though "Properties" -> "Advanced..." goto to the "Advanced Attributes" page and remove the checkmark from "Encrypt contents to secure data"
Tuesday, June 10, 2008
Addin Command Names
Saturday, May 31, 2008
Custom Installer Creating Folder, Setting Permissions
The first thing to know is that an installer typically runs with elevated rights as the discussion on Chris Jackson's blog indicates. This means that your installer has sufficient rights to create directories but also to set appropriate permissions.
And here is the code for creating a directory and setting permissions:
public static void CreateWithReadAccess(string targetDirectory) {
try {
if(!Directory.Exists(targetDirectory)) {
Directory.CreateDirectory(targetDirectory);
}
DirectoryInfo info = new DirectoryInfo(targetDirectory);
SecurityIdentifier allUsersSid =
new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid,
null);
DirectorySecurity security = info.GetAccessControl();
security.AddAccessRule(
new FileSystemAccessRule(allUsersSid,
FileSystemRights.Read,
AccessControlType.Allow));
info.SetAccessControl(security);
}
catch(Exception ex) {
Debug.WriteLine(ex.ToString());
}
}This code checks for existence of the directory first. If the directory doesn't exist yet it is created. Then the security settings are applied. In this case the Read permissions are granted to all members of the group BUILTIN\Users.
By selecting another member of the WellKnownSidType enumeration you can grant permissions to a different group. Alternatively, if you'd like to grant permissions to a specific user, have a look at the NTAccount class. An instance of it can be passed into the FileSystemAccessRule constructor as a first parameter as well.
Tuesday, May 27, 2008
ReSharper 3.1 and Empty Constructor
#pragma warning disable EmptyConstructorThe compiler now complains about 'EmptyConstrutor' not being a valid number. Fair enough it is not.
So I removed the pragma since any other pragma would get ReSharper complaining again. To keep ReSharper quiet the constructor now looks as follows:
public class Foo() {
// ... the XML markup for documentation
public Foo() {
; // to shut up ReSharper
}
}Now both, the compiler and ReSharper, are happy! :-)
No big issue but the better solution would have been if ReSharper would modify the code only in such a way that it doesn't cause additional warnings.
Update
This applies to essentially all such pragma's ReSharper inserts, including but not limited to:
- UnusedMemberInPrivateClass
- PossibleNullReferenceException
As stated before: Best option would be if the code inserted by ReSharper would not cause additional warnings from the C# compiler. Or in other words: The added code should be "compatible" with the compiler. One option could be to use comments instead. The compiler ignores them.
The C# preprocessor is not as powerful and flexible as the C/C++ one. The latter allows your extensions by ignoring unknown ones. The C# version does not have that "back door" but checks them for validity as well. In essence you can't define your own. (Or at least you shouldn't if you don't want to cause compiler warnings.)
Thursday, May 15, 2008
Outlining/collapsing Comments in VS2005/VS2008
Tuesday, May 13, 2008
SerializationException - "The constructor to deserialize an object of type 'foo' was not found."
- Add the SerializableAttribute to the class.
- Have the class implement the ISerializable interface.
- Request sufficient privileges for your GetObjectData() implementation.
In essence you are rolling custom serialization. And here is how Foo would look like with all these in place:
using System.Runtime.Serialization;
using System.Security.Permissions;
...
[Serializable]
public class Foo : ISerializable {
protected Foo(SerializationInfo info,
StreamingContext context) {
_barString = info.GetString("_barString");
_barInteger = info.GetInt32("_barInteger");
}
[SecurityPermissionAttribute(
SecurityAction.Demand,
SerializationFormatter = true)]
public virtual void GetObjectData(SerializationInfo info,
StreamingContext context) {
info.AddValue("_barString", _barString);
info.AddValue("_barInteger", _barInteger);
}
private string _barString;
private int _barInteger;
}Note that the constructor is protected. This way it cannot be called except from the serialization code within .NET. It is however accessible by code in subclasses.
If your class is derived from a class that implements ISerializable, then you need to call the base class in both the constructor and the GetObjectData() implementation as follows:
[Serializable]
public class Foo : Base { // Base implements ISerializable
protected Foo(SerializationInfo info,
StreamingContext context)
: base(info, context) {
// your deserialization code
}
[SecurityPermissionAttribute(
SecurityAction.Demand,
SerializationFormatter = true)]
public virtual void GetObjectData(SerializationInfo info,
StreamingContext context) {
base.GetObjectData(info, context);
// your serialization code
}
}For more information please check MSFT's web site here.
Sunday, May 11, 2008
Weakness in VS Debugger
public class ProjectElement {
...
public override bool Equals(object obj) {
if( obj != null
&& obj.GetType().Equals(GetType())) {
ProjectElement otherObject =
(ProjecElement)obj;
return _assemblyPathName.Equals(
otherObject._assemblyPathName);
}
}
...
}
During a debugging session you can use the QuickWatch as a convenient way to examine variables.
However, be aware of the following. When you use QuickWatch on '_assemblyPathName' in the above example then QuickWatch does not consider the context. E.g. even if you hover over the '_assemblyPathName' part of the expression 'otherObject._assemblyPathName' QuickWatch will just use the member variable of 'this', which not in all cases will have the same value.
If you want to be on the safe side then select the entire expression you would like to inspect, e.g. all of 'otherObject._assemblyPathName'. After that select QuickWatch.
I think this is a shortcoming of the QuickWatch feature since it displays the content of a variable that you didn't want to look at, and you might not even notice that you are looking at something different of a similar name.
If one of you Microsofties are reading this maybe you could consider this as an improvement for the next release of Visual Studio? Thank you!
Thursday, May 08, 2008
Implementing Properties: Basic Considerations
public class Foo { private string _bar; }Now we want to add an accessor aka the getter:
public class Foo { public string Bar { get { return _bar; } private string _bar; }This has been the easy part. There is not really a lot that can go wrong.
It starts to become more interesting when you add a modifier aka a setter. In it's most simple form you could write:
public class Foo { public string Bar { get { return _bar; } set { _bar = value; } private string _bar; }Easy you think. But hang on. There is more to it. You may want to decide whether it is acceptable to pass in a null reference or not. Whether you allow for null or not is a decision that should be made based on a number of factors. One way to find out is to look at all the places in your code where the getter is used. What would happen to that code if null would be returned? For example:
Foo foo = new Foo(); ... if( foo.Bar.Length > 25 ) { ... } ...In that case if null was returned this piece of code would crash. You could fix this issue by checking for nullness:
Foo foo = new Foo(); ... if( foo.Bar != null && foo.Bar.Length > 25 ) { ... } ...This certainly work but you pay the price of a slightly less readable code. In addition you may have to have this in a lot of places. So in essence you may decide that the property Foo.Bar doesn't allow for null values. The code for class Foo would then look as this:
public class Foo { public string Bar { get { return _bar; } set { if( value != null ) { _bar = value; } } private string _bar; }This clearly provides the benefit of Foo.Bar never being null since upon initialization _bar will be initialized with string.Empty or "".
But again this comes at a price. The setter simply swallows the attempt to set Foo.Bar to null. This might be desirable. I personally prefer that a class doesn't swallow incorrect things but instead fails fast. In this particular case I would want my code to indicated the error by throwing an exception:
public class Foo { public string Bar { get { return _bar; } set { if( value != null ) { _bar = value; } else { throw new ArgumentNullException("value"); } } private string _bar; }You see that although this is a simple property implementation it can already require quite a few decisions to be made and aspects to be considered.
To close off this particular post, I'd like to also bring performance considerations into the picture. What if the setter needs to validate any new value against a remote system such as a service? Let's look at the possible code:
public class Foo { public string Bar { get { return _bar; } set { if( value != null ) { if( _validationService.IsPermitted(value) ) { _bar = value; } else { throw new ArgumentOutOfRangeException("value"); } } else { throw new ArgumentNullException("value"); } } private string _bar; private ValidationService _validationService = new ValidationService(...); }Calling IsPermitted() can be quite expensive. So how to avoid this? Here is one possible solution:
public class Foo { public string Bar { get { return _bar; } set { if( _bar != value ) { if( value != null ) { if( _validationService.IsPermitted(value) ) { _bar = value; } else { throw new ArgumentOutOfRangeException("value"); } } else { throw new ArgumentNullException("value"); } } } private string _bar; private ValidationService _validationService = new ValidationService(...); }With this implementation the validation service is called only if the value has actually changed. Certainly if the set of permitted values is dynamic this implementation would not make the cut. With this post I want to demonstrate that even property that looks like an easy thing to do already requires a lot of considerations. We even touched performance briefly. It is important that we are aware of all of these aspects when implementing and testing such a property. There are more aspects to this but I think I've made my point. Even with simple things like properties there are already a quite a few aspects to consider.
Sunday, April 27, 2008
Codeplex, IE, and Firefox
Saturday, April 26, 2008
Accessing Installation Properties in Custom Actions
/TargetDir="[TARGETDIR]\"Please note the trailing backslash, which you only need to use when you surround the property in double quotes. However, as a safety measure I suggest making it a habit to always add the double quotes and the backslash. Remember paths can and will contain spaces! In some examples on the internet the backslash may be mentiond in the text but not be included in the code sample. If you leave the backslash out you'll see a message box containing "error code 2869". However, this article makes it clear that you must add the trailing backslash if you use the double quotes. Also, if you want to pass more than one property separate them by a single space, e.g.
/TargetDir="[TARGETDIR]\" /UserDir="[PersonalFolder]\"Then in your custom action implementation - a class derived from System.Configuration.Install.Installer - you can access it in the following way (C# here, but similar in other .NET languages):
string targetDir = Context.Parameters["TargetDir"];That's all.