|
| |
Saturday, July 05, 2008
| |
Gama System eArchive accredited (Development | .NET | Personal | Software)
Gama System eArchive, one of the two products in our document product line, received accreditation from the Archives of the Republic of Slovenia last week. This acknowledgement by our national body means that any document stored in Gama System eArchive is automatically legally valid. This is important for both our company and other companies looking for a long term electronic document storage solution. Our product is the first service oriented solution to receive the accreditation. Congratulations to everyone involved in the product. Well done!
7/5/2008 9:37:14 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Tuesday, April 29, 2008
| |
Old ActiveX controls under .NET 2.0 SP1 (Development | .NET | Vista)
A .NET application in the company I work for recently started crashing under Windows Vista when trying to open a window implemented in an ActiveX DLL. Investigations showed that they were caused by an AccessViolationException "Attempted to read or write protected memory. This is often an indication that other memory is corrupt.". The cause was one of the ActiveX controls in the window. When instantited directly in a .NET Form the exception above was contained in a TargetInvocationException "Unable to get the window handle for the '<control name>' control. Windowless ActiveX controls are not supported.". Knowing that the control didn't suddenly turn windowless we dug deeper. It turned out that the problem appeared with .NET Framework 2.0 Service Pack 1. Apparently it caused the C# compiler in Visual Studio 2005 and later to set the NXCOMPAT bit for all build targets without an option to turn this new behavior off. For those who don't know, this means that DEP (data execution prevention) will kick in unless it is turned off completely in the operating system. This wouldn't be a big deal unless ATL before Visual Studio 2005 didn't have a bug which caused the heap allocated memory not to be flagged as executable, which under the new circumstances results as the already mentioned exception. Windows XP has DEP turned off by default therefore everything still works but in Windows Vista it is turned on and prevents such application from functioning properly. The best solution would of course be to recompile the ActiveX controls in Visual Studio 2005 or later but this might not be possible if they are supplied by a third party. In this case the most obvious approach to dealing with the situation is to disable DEP in Vista. There is a Data Execution Prevention tab in the Performance Options which open when you click the Settings button in the Performance frame of the Advanced tab in the System Properties dialog but it only allows switching between DEP for all processes with defined exceptions and DEP for essential Windows programs and services, i.e. executables flagged with the NXCOMPAT bit. The only way to turn DEP completely off is executing the following command with administrative privileges: bcdedit.exe /set {current} nx AlwaysOff After restart DEP will be turned off and problematic binaries will work once again. To restore the previous (default) state replace AlwaysOff with OptIn. The AlwaysOn option enables DEP for all processes and might cause additional problems (e.g. Google Calendar Sync in its current version 0.9.3.2 doesn't work in this mode). Unfortunately, this solution would require all your Vista using customers to disable DEP as well which really isn't an option for commercial software. Fortunately, there is another solution. Although there is no compiler option to turn keep the NXCOMPAT bit unset, you can still do this after compilation using the editbin.exe which comes with C++ compiler for Visual Studio 2005 and later: editbin.exe /NXCOMPAT:NO <filename.exe> This command removes the NXCOMPAT bit and restores the behavior before .NET 2.0 SP1. If your assembly was signed it also invalidates the signature so you'll have to resign it: sn.exe -R <filename.exe> <keyfile.snk> You can automate this by putting the two commands in the Post-build event command line for the project: editbin.exe /NXCOMPAT:NO "$(TargetPath)" sn.exe -R "$(TargetPath)" "$(ProjectDir)<keyfile.snk>" You might need to call vcvars32.bat before that to put the required executables in path and enable editbin.exe dependencies to be resolved. Note that in a completely automated build scenario using MSBuild you'll have to specify full path for the vcvars32.bat because $(DevEnvDir) resolves to *Undefined* outside Visual Studio 2005. Also your strong name key should be in a snk file instead of a password protected pfx file because sn.exe doesn't allow the password to be read from a redirected standard input.
4/29/2008 2:29:08 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Monday, April 14, 2008
| |
MonthCalendar BoldedDates in Windows Vista (Development | .NET | Vista)
The MonthCalendar control's BoldedDates functionality doesn't appear to work properly on Windows Vista. The dates added to any of the BoldedDates, MonthlyBoldedDates and AnnuallyBoldedDates collections are rendered just the same as those not added to any of the collections. The same code works just fine on Windows XP and causes those dates to be rendered bold. The only workaround i've managed to find is disabling visual styles in the application, i.e. commenting out the first line in the Program.Main() method of a new Windows Application: Application.EnableVisualStyles();
4/14/2008 8:54:58 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Saturday, November 24, 2007
| |
Notes about RSACryptoServiceProvider (Development | .NET)
In my opinion RSACryptoServiceProvider class is seriously under-documented in MSDN. Since there is also no abundance of examples on the web, I spent more time than I should figuring out how to use it correctly. For future reference I'm listing below the solution to two problems I had. The maximum byte array length for encrypting without OAEP padding is Modulus size - 11 which is written somewhere in the Encrypt() method documentation. If you pass it a larger array it will return a not so informative Unspecified error. To encrypt a larger chunk of data you have to split it in smaller parts, encrypt them individually and concatenate them back together. You have to do the same when decrypting the data, with the only difference that each part has the size of Modulus in stead of Modulus - 11. To get the modulus size you can use the following piece of code (rsa is an instance of RSACryptoServiceProvider):
Each time you instantiate RSACryptoServiceProvider it generates a new pair of keys. If you want to use existing ones, you can import them by calling:
The key parameter is a string with the XML representation of the keys. You can get it by calling the ToXmlString() method once and storing its results. It's only parameter specifies whether to also export the private key. I guess I don't have to remind you that you need the private key only for decryption and that you should always keep it private for the encryption to make any sense at all.
11/24/2007 5:31:53 PM (Central Europe Standard Time, UTC+01:00)
Always close DeflateStream before reading results (Development | .NET)
Is the code below correct? Will inputString and outputString be equal?
As it turns out, they won't. The reason for it being that compressionStream.Close() was not called before reading from stream started. Calling compressionStream.Flush() is not enough in this case. I haven't managed to find this documented anywhere but the example in the DeflateStream documentation does it correctly. You can find the fixed code below. Notice the additional last parameter in the first call to the DeflateStream constructor. Without it stream will also be closed when compressionStream gets closed.
Thanks once again to my coworker for suggesting this when I was already running out of ideas.
11/24/2007 4:44:37 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Tuesday, July 24, 2007
| |
Loop over files in directory from a batch file (Development | Batch)
Figuring this out took me much longer than it should. The following line in a batch file will execute a command for each file in a directory:
I had to overcome two obstacles to make this work:
- When including the command in a batch file the % characters must be duplicated in comparison to the syntax for executing the command directly from the command line.
- The ~nx prefix to the variable name causes only the filename with extension to be used instead of the complete path.
7/24/2007 3:19:03 PM (Central Europe Standard Time, UTC+01:00)
Creating custom tasks for CruiseControl.NET (Development | .NET)
Once you start putting CruiseControl.NET to production use you'll sooner or later encounter the need for custom build tasks. There's only a limited set of them in the package and Executable Task can only do so much. Unfortunately there is not much information available on development of custom tasks. Your best sources will be: Apart from that I feel obliged to mention a few of the most important points I've come across during the development of a few custom tasks: - ThoughtWorks.CruiseControl.Core.Util.ProcessExecutor is a nice little wrapper around System.Diagnostics.Process class you'll end up using quite a lot.
- You can add your own information to the build log by calling AddTaskResult on the IIntegrationResult instance passed to your ITask.Run method. There are two overloads available: one accepting a System.String and another one accepting ITaskResult to which you can pass a new FileTaskResult instance to quickly include a complete file.
- If you're doing any checkins to your source control system as a part of the build you should call the MarkStartTime method of your IIntegrationResult instance afterwards to prevent triggering another build of the same project by setting the last build start time after the last checkin time.
- Make sure you use a unique ReflectorType name for your task. The service will just silently fail to start in case of a duplicate value.
This information should make your first attempts at making your own custom task a little easier.
7/24/2007 12:57:26 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Sunday, July 22, 2007
| |
MSBuild.xsl problem in CruiseControl.NET 1.3 (Development | .NET | Downloads | Sources) msbuild.zip (1.33 KB)
The 1.3.0.2918 build of CruiseControl.NET has an error in msbuild.xsl file which causes an XslLoadException to be thrown when trying to view the MSBuild output in the web dashboard. One of the users was nice enough to describe the changes to the file necessary to fix the problem. Unfortunately even the latest version of the file on the CruiseControl.NET Live site doesn't include the changes therefore I'm attaching the file to this post as convenience.
7/22/2007 12:24:07 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Saturday, June 02, 2007
| |
OCR with Microsoft Office Document Imaging (Development | .NET)
If you need cheap and simple OCR functionality Microsoft Office Document Imaging Type Library (MODI) is a nice option if its requirements (Microsoft Office 2003 or later) and limitations (limited language support) don't bother you. Here is a simple C# function that does OCR on the image with the specified path:
However, there is another Microsoft Office object model related problem. For Office 2003 users to be able to use your application, the MODI 11.0 (2003 version) must be referenced in the project and the release version of the application must be compiled on a machine with Office 2003 installed. In such a case VB6 still managed to compile the project on a machine with a newer version of Office installed, since the newer version of the type library was automatically used (MODI 12.0 for Office 2007 in this case). On the other hand strong type checking at compile time prevents that in C#.
If you want to keep using Office 2007 and be able to compile such a project, the only solution is to install Microsoft Office Document Imaging as the only component of Office 2003 along the existing Office 2007 installation. Unfortunately this overwrites the Microsoft Office Document Image Writer printer driver from 2007 with the older version, therefore you'll have to start a lengthy process of repairing the Office 2007 installation afterwards. And don't forget to apply all the service packs and updates for Office 2003 before that since this will also overwrite the printer driver and you'll have to repair Office 2007 once again. I learned that the hard way.
6/2/2007 9:39:34 AM (Central Europe Standard Time, UTC+01:00)
| |
| |
Saturday, May 19, 2007
| |
Worker Process Group in IIS 6 (Development | Web)
This is nothing new and it has probably been written about hundreds (if not thousands) of times already, but since I’m only encountering the issue every few months or even more seldom, it always slips my mind and I end up wondering what’s wrong.
I’m talking about the fact that any custom identity being used for an application pool in Internet Information Services 6.0 must be a member of the IIS_WPG group which grants it all the necessary privileges. Unfortunately otherwise IIS reports only Service Unavailable when the site gets accessed without any additional information which makes it kind of difficult to determine the cause of the problem.
Hopefully this post will help reminding me of this fact when I need it the next time.
5/19/2007 6:25:23 AM (Central Europe Standard Time, UTC+01:00)
| |
| |
Sunday, March 25, 2007
| |
Persist Security Info default value changed in Windows Vista (Development | VB6)
In Windows Vista the default value for the Persist Security Info parameter of an ADO connection string has changed from True to False.
You should be aware of this because it can prevent your legacy code from working properly under Windows Vista. If its value is set to False the Server, Database, Trusted_Connection and Password parameters will be removed from the ConnectionString property of the Connection object once the connection has been opened. If you’re creating new connections by just copying the ConnectionString property from an existing and already opened connection to the new one, your code will break under Vista.
The problem can easily be fixed by explicitly setting Persist Security Info to True in your original connection string but it should be mentioned that this can be a potential security risk if untrusted code gets access to your Connection object. Even more so in case you’re not using integrated security and the connection string actually contains the user’s password for accessing the database. It’s a much better practice to have the actual connection string stored separately and use it directly to create new connections.
On a side note, SqlClient in ADO.NET works much more consistently. The Persist Security Info parameter always defaults to False. It also only removes the Password parameter from the ConnectionString property which makes changing its value to True completely unnecessary unless you really feel a strong urge to share your user’s password.
3/25/2007 8:48:05 AM (Central Europe Standard Time, UTC+01:00)
| |
| |
Monday, December 25, 2006
| |
MCP Exam 70-536 Experiences (Development | .NET | Personal | Education)
I’ve recently passed the MCP exam 70-536: TS: Microsoft .NET Framework 2.0 – Application Development Foundation. My overall experience has been very positive. Although there are a few not so relevant topics I think that most of them are a must-know if you’re a .NET developer. I found the exam quite easy with only a few really nitpicking questions. Maybe I was just lucky but it was a pleasant surprise for me.
I used the Microsoft Self-Paced Training Kit as the study guide. In spite of the mistakes it contains (see errata) I still find it a useful overview of the topics covered by the exam. I even think of it as a great overview of .NET framework for every developer even if he’s not considering taking the exam. On the other hand it really shouldn’t be your only resource, more of a starting point to direct you to the topics you realize you don’t know enough about. MSDN or a more specialized book can help you from there on.
If you’re interested, I’m selling my own copy of the book at a reduced price. It is in mint condition, I’ve even left the 15% off voucher unused. On a side note: here you can always see the list of items I am selling. The link is listed among my other sites in the left column of this page.
12/25/2006 9:49:24 AM (Central Europe Standard Time, UTC+01:00)
| |
| |
Monday, December 11, 2006
| |
More Sidebar Gadgets available (Development | Vista | Personal | Software)
I you haven't checked out our Vista site recently, now is the right time to do it. Since my last posting two new gadgets have been released:
An update for Slovenian Radio has also been released in the meantime. Apart from bug fixes the list of radio stations has been extended.
Try them out if you're using Windows Vista and haven't done so already.
12/11/2006 12:58:18 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Friday, December 01, 2006
| |
Our first Sidebar Gadget released (Development | Vista | Personal | Software)
We have just released our first Sidebar Gadget – Slovenian Radio.
The gadget features a centralized list of radio stations (retrieved from our server) and basic controls for selecting the station and adjusting the volume. Everything is packaged in a nice and simple GUI.
Try it out. It really is the most convenient way of listening to Slovenian radio stations online. You can download it for free here. Spread the word if you like it.
12/1/2006 8:23:14 AM (Central Europe Standard Time, UTC+01:00)
| |
| |
Sunday, October 29, 2006
| |
Running Windows Sidebar gadgets directly in IE7 (Development | Vista | Web)
Since gadgets are HTML applications and the Windows Sidebar uses Internet Explorer 7 to render them, I prefer running their code directly in IE7 during development. It makes debugging easier and allows me to develop them in Windows XP on my primary development machine with all the tools properly setup.
While this works great in early development stages, it becomes a problem later on when you start using the Windows Sidebar object model (to implement settings, visibility changes handlers etc.). This specific code understandably can only be debugged while running in Windows Sidebar but the unfortunate side effect is that the calls to objects which don’t exist in IE7 break the scripts and effectively prevent running the would-be gadget in IE7 even without this functionality.
The following function can help you keep the gadget running directly in IE7 even after the gadget specific functionalities are already implemented:
function isGadget() { try { var dummy = System; return true; } catch (err) { return false; } }
Just check if the application is running in Windows Sidebar at gadget startup and make sure to use the object model only when this is true. You can also add alternative initialization for running directly in IE7 to provide default values for settings and any other gadget specific variables. By doing this you can still test new features directly in IE7 if they are not gadget specific.
10/29/2006 2:11:59 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Sunday, October 22, 2006
| |
A sample Windows Sidebar gadget (Development | Vista | Web | Downloads | Sources | Windows) HelloWorld.zip (3.99 KB)
The whitepaper sample code doesn’t exactly follow the guidelines for web development therefore I wrote my own sample with clearly separated HTML structure, CSS styles and JavaScript code. I decided to make it publicly available in case anyone else finds it useful. A few things are worth mentioning.
- Empty XHTML tags. For some reason the XHTML style empty tags don’t work as expected when they are filled from JavaScript code. It seems as if the engine would parse them as opened tags without the corresponding closing tag. Therefore you should always use the long form <span id=”mySpan”></span> instead of the short one <span id=”mySpan” />. This problem seems to be specific for gadgets. The same code runs just fine in IE7.
- Localization. I haven’t managed to get the localization to work at all. I suppose the engine uses the files from the locale directory corresponding to the current display language not the locale settings. This does make sense but with only English language available in Vista there’s no way to check that the current file organization in my sample gadget is really ok. I kept it in the sample since I’m pretty convinced that it is.
- Deployment. If you double click a file with a .gadget extension in Vista, you will automatically start the gadget installation process. The file needs to be a zip or cab archive containing the actual gadget directory structure. Vista behaves as if an application setup was started. This means that you should sign the file to increase the end user trust. You can use the Sign Tool to do that but in this case you need to make a cab file since zip files can’t be signed with it. I tried to make the cab file using a CAB Project template in Visual Studio 2005 but I couldn’t make the correct directory structure. I ended up using Cabarc. After all, I only had to run the following line in the gadget directory to build the cab file correctly.
cabarc –p –r N ..\HelloWorld.gadget *
10/22/2006 1:14:03 PM (Central Europe Standard Time, UTC+01:00)
Writing your first Windows Sidebar gadget (Development | Vista | Web)
This whitepaper should definitely be your first source of information when starting with gadget development. Unfortunately I didn’t find it as helpful as it could be. Find below a few issues that could be covered better since I’ve been struggling with them for some time before I get everything to work as expected.
- The style definition for body in both pages is missing the unit – px. Without it the definition is invalid and the gadget shows up with minimum size. The correct style definition would be in the likes of:
body { width: 130px; height: 50px; }
- The settingsUI property is a member of System.Gadget not System.Gadget.Settings. This time the error is in the reference not the whitepaper.
- If you’re only replacing the files in the C:\Users\<username>\AppData\Local\Microsoft\Windows Sidebar\Gadgets directory to update the gadget you might have some problems with caching even if you close all gadget instances as the whitepaper suggests. In my case the old image files and gadget.xml file were still used although they have been replaced. Restarting Windows Sidebar should help.
- Don’t forget that gadget settings are stored with a particular gadget instance. This makes it possible to display two instances of the gadget with different settings. The side effect is that they get lost every time you remove the gadget from the sidebar and put it back on. It works like that by design and if you need persistent common settings for all instances you’ll have to use a different solution.
10/22/2006 12:48:31 PM (Central Europe Standard Time, UTC+01:00)
Resources for Windows Sidebar gadget development (Development | Vista | Web)
I though I’d gather in one place all the useful links I found with information on development of Windows Sidebar gadgets.
- Gadget Development Overview whitepaper should be you first stop. It’s a short article explaining the basics of gadget development.
- Windows Sidebar Reference is the only documentation that is currently available. It’s not very detailed, neither always accurate but it should still serve you well.
- Gadget Corner is a blog maintained by the Windows Sidebar team. It contains a few articles with information that can’t be found anywhere else.
- Sidebar Gadgets Forum is the only forum dedicated to gadget development. On top of that the Windows Sidebar team members have the habit of answering the posted questions.
Last but not least, don't underestimate the gadgets that come with Windows Vista. Since it’s all HTML, CSS and JavaScript, all the source code is available and can be a good learning material when trying to determine how some functionality has been achieved. You can find them in C:\Program Files\Windows Sidebar\Gadgets directory.
10/22/2006 12:40:45 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Friday, October 20, 2006
| |
Application roles and connection pooling (Development | .NET | SQL)
One would have thought this to be a well known fact but since one of our developers stumbled upon it yesterday I thought it might be useful to someone else.
As soon as a pooled connection with enabled application role gets reused an exception gets thrown and its description is not really helpful if you’re not aware of the problem: General Network Error. This happens because the security context of the connection doesn’t get properly reset when it is closed. To work around the problem you can either avoid using application roles or disable connection pooling (by adding Pooling=False to the connection string). You can find more details in this knowledge base article.
It might be worth mentioning that the above is completely accurate only for SQL Server 2000. SQL Server 2005 comes with a new stored procedure sp_unsetapprole which can be used to reset the security context. I haven’t tried it but by calling it before closing the connection you should be able to make application roles work together with connection pooling.
10/20/2006 3:09:17 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Tuesday, September 19, 2006
| |
Configuration.Save requires Full Control access to a file (Development | .NET)
Don’t use Configuration.Save in scenarios where users might only have read and write permissions for the configuration file as UnauthorizedAccessException will be thrown if full control is not granted. More details are available in the following MSDN Forum posting.
9/19/2006 10:32:34 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Sunday, September 17, 2006
| |
Mapping URLs in ASP.NET (Development | .NET)
ASP.NET offers several ways of mapping nice public URLs to cryptic internal URLs matching the actual implementation.
The simplest way is to match each public URL to its internal value. You can do this by either creating dummy pages which do the redirecting or by adding them to the urlMappings section of the web.config file (brought by framework 2.0). The latter solution is preferable because of simpler maintenance but both of them have the downside of being completely static (an entry is necessary for each mapped page).
A better solution is to implement an IHttpHandler or IHttpModule and do the mapping by calling HttpContext.RewritePath(). You could also change the requested page by using Server.Transfer() or maybe even Response.Redirect() but they have their disadvantages when used for URL mapping.
To avoid having to recompile your IHttpHandler implementation every time the mapping logic changes or extends you could configure it through a custom section in the web.config file. Regular expressions are a nice tool for defining such mappings as demonstrated by here (also check the comments) or implemented in dasBlog sources (check newtelligence.DasBlog.Web.Core.UrlMapperModule). You could even use UrlRewritingNet.UrlRewrite if you don’t like reinventing the wheel.
9/17/2006 12:33:22 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Thursday, September 07, 2006
| |
Last modification time of a web page (Development | .NET)
The following code returns the time when a web resource was last modified:
static DateTime GetModificationTime(string url) { WebRequest request = WebRequest.Create(url); HttpWebResponse response = (HttpWebResponse) request.GetResponse(); DateTime lastModified = response.LastModified; response.Close(); return lastModified; }
It’s quite a simple piece of code actually and very similar to a sample in MSDN. But maybe it will be useful to someone since a member of my developer team was convinced that there is just no way to get this information in .NET.
9/7/2006 10:41:34 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Saturday, August 05, 2006
| |
Display and input of Unicode characters in legacy VB6 applications (Development | VB6)
Although in Visual Basic 6 all string variables are inherently Unicode, the same is not true for the components that come with it – they aren’t capable of displaying (or accepting input of, for that matter) Unicode characters. The same goes for most of the popular third party ActiveX controls that are available on the market.
Unless you’re deciding to move the form (or even the complete application) to .NET, the best solution is to use the components from the Microsoft Forms 2.0 Object Library. There are a few downsides though:
- They come with Microsoft Office and aren’t freely redistributable. But even if your clients don’t have Microsoft Office, they can legally obtain the components by installing the free Microsoft ActiveX Control Pad which contains them.
- The use of these components outside Microsoft Office isn’t officially supported. Still this shouldn’t be a problem as long as everything works. After all, even Microsoft recommends using these components in such a situation.
- The set of the components is not really complete and it might not be enough if you have a bit more complex needs. In this case there’s still UniToolbox available. I haven’t tried it but it looks a promising collection of Unicode components for Visual Basic 6. Might be worth a look.
8/5/2006 1:57:00 PM (Central Europe Standard Time, UTC+01:00)
Too many projects in a solution slows down Visual Studio 2005 (Development | .NET)
Once the number of projects in a solution comes up to thirty or more, most of the project related operations become really slow: setting the default project, building a project starting and stopping a debug session etc. There are no noticeable slowdowns with up to twenty projects in a solution though.
Although usually no solution with real projects should reach such numbers (I stumbled upon it by just adding sample projects to the same solution), it is something to have in mind when deciding how to group projects in solutions.
8/5/2006 1:16:42 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Saturday, June 10, 2006
| |
Downloading template files from web server (Development | Web | Personal | Website)
Be careful when hosting your web site based on DasBlog from a Windows XP machine. While IIS 6 in Windows 2003 prevents the download of files with unknown extensions by default, the IIS 5.1 in Windows XP allows downloading such files. In the case of DasBlog all *.blogtemplate files are at risk. There are a few sites out there where these files can be downloaded. Although this probably isn’t a big security risk it might be something you want to prevent. Probably the easiest way to do that is by modifying the web.config file. You should add the following line at the end of the <httpHandlers> section:
<add verb="*" path="*.snippet" type="System.Web.HttpForbiddenHandler" />
6/10/2006 10:56:44 PM (Central Europe Standard Time, UTC+01:00)
DasBlog macro development (Development | .NET | Web | Personal | Website)
DasBlog – the weblog engine this site is running on – allows extensibility through macros. You’ll need to use them as soon as you want any additional dynamic content on your site. (The ads you can see at the bottom of the right side bar are an example of a macro which I’ve recently updated to make the ad selection a little more advanced.) The documentation doesn’t mention their development at all therefore the following post by Vasanth Dharmaraj is probably the best source of information available on it. It actually discusses everything you need to know to get going. Make sure you read it before trying to write your first macro.
6/10/2006 10:42:10 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Friday, June 09, 2006
| |
Writing to EventLog (Development | .NET)
Before using EventLog.WriteEntry for adding events to event log you should consider calling EventLog.CreateEventSource to make your application a valid source of events. Keep in mind though that you need administrative privileges for it succeed, therefore it is best to call it at installation time. So, if you want to write to the application event log by calling:
EventLog.WriteEntry("MyApplicationName", "My event text");
don’t forget doing this first:
if (!EventLog.SourceExists("MyApplicationName")) EventLog.CreateEventSource("MyApplicationName", "Application");
6/9/2006 4:34:50 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Sunday, June 04, 2006
| |
Implementing plug-ins with late binding (Development | .NET)
Essentially everything you need to implement plug-ins in your application is some way to dynamically instantiate classes at runtime. As long as they all implement the same interface, you just use it to access its properties and methods.
In COM world this was achieved by calling the CreateObject function. In the managed world you should use AppDomain.CreateInstanceAndUnwrap as demonstrated by the following example:
IBind pluginInstance = (IBind)AppDomain.CurrentDomain.CreateInstanceAndUnwrap("MCPP", "DamirsCorner.Samples.LateBinding.MCPP");
Everything you need to know at runtime is the full class name (including the namespace) and the containing assembly. To get those you can either require their previous registration within the application or you can dynamically discover them by loading assemblies from a predefined location (Assembly.Load or Assembly.LoadFrom) and enumerating their classes (Assembly.GetTypes) whichever suits you situation best.
6/4/2006 10:22:32 AM (Central Europe Standard Time, UTC+01:00)
| |
| |
Saturday, June 03, 2006
| |
Problems with SetForegroundWindow calls (Development | Personal | Software | Win32)
Either as a user or as a developer you have certainly noticed that sometimes the application just flashes in the taskbar instead of actually coming to the foreground when the SetForegroundWindow function is called. What you might not know is why and when this happens.
As far as the why goes the Application Compatibility Toolkit’s Compatibility Administrator puts it very nicely in the GiveupForeground compatibility fix description: In Windows XP the foreground semantics have been changed to stop foreground focus stealing by one application if another application is active.
Further investigation reveals that this is related to the ForegroundLockTimeout value. It defines how much time must pass since the last user input to allow another process to force its window into the foreground. Before that time such a window only flashes in the task bar. The default value is 200000 milliseconds. The setting is stored in the registry:
HKEY_CURRENT_USER\Control Panel\Desktop\ForegroundLockTimeout
The value can be programmatically changed by calling the SystemParametersInfo function as follows:
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
The downside is that the call only succeeds when the calling thread has permission to change the foreground window which usually isn’t the case.
To make the long story short: you should never depend on being able to bring your application window to the foreground and this will certainly only get more restrictive in the future. If the flashing in the taskbar is not enough, you should consider using tray balloon pop-ups as the alternative way of notifying the user.
6/3/2006 1:18:29 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Sunday, May 28, 2006
| |
Marshalling System.String to char* and vice-versa (Development | .NET | C++)
By switching from C# with P/Invoke calls to Managed C++ when implementing a managed wrapper for the ANSI C style library I stumbled upon, I wanted to avoid the tedious and error-prone task of writing the P/Invoke signatures for function calls and user-defined types for the structures they used. As a side result I also managed to avoid most of the advanced marshalling issues with complex data structures.
With simple value types not needing any explicit marshalling only strings need special attention since char* and System::String can’t be implicitly converted between. The Marshal class implements the methods necessary for doing this as demonstrated in the following snippet:
String^ MCPP::Together(String^ first, String^ second) { // marshal managed strings to unamanged memory IntPtr firstPtr = Marshal::StringToHGlobalAnsi(first); IntPtr secondPtr = Marshal::StringToHGlobalAnsi(second);
// cast unmanaged buffer to a characer array char* firstNative = static_cast<char*>(firstPtr.ToPointer()); char* secondNative = static_cast<char*>(secondPtr.ToPointer());
// perform some unmanaged calls int bufferSize = strlen(firstNative) + strlen(secondNative) + 4; char* resultBuffer = new char[bufferSize]; sprintf_s(resultBuffer, bufferSize, "%s + %s", firstNative, secondNative); // marshal unmanaged character array to managed string String^ result = Marshal::PtrToStringAnsi(static_cast<IntPtr>(resultBuffer)); // free all unmanaged buffers delete[] resultBuffer; Marshal::FreeHGlobal(firstPtr); Marshal::FreeHGlobal(secondPtr); // return managed string return result; }
It should be noted that it wouldn’t make any sense switching to unmanaged code to do some string operations only as shown above. This is for demonstration purposes only and you would usually call some unmanaged libraries or the like instead of it. But it is a nice demonstration how cumbersome string operations were in C. If you were doing this once, the sprintf_s function call might have caught your attention. It’s a safe implementation of sprintf which prevents buffer overflows.
Another point worth mentioning is that you have to take care of allocated memory for the conversion since your character array is now allocated on the unmanaged heap. Make sure you use the FreeHGlobal method to do it, not the free (used for freeing memory allocated by *alloc calls – ANSI C style) or delete (used for freeing memory allocated by new calls – C++ style) functions.
To reduce the code overhead of string conversions between managed and unmanaged world you might consider wrapping it into a helper class. This should also help preventing unwanted memory leaks during the conversions.
5/28/2006 1:41:03 PM (Central Europe Standard Time, UTC+01:00)
| |
| |
Sunday, May 14, 2006
| |
Implementing a managed interface in C++ (Development | .NET | C++)
Less than a month ago I was certain I’d never have to write managed code in C++. With such a set of mind I didn’t really care about the new features being added and improvements being made to managed C++ since the first Visual Studio .NET. Luckily there were people thinking otherwise and as a result this – often overlooked – member of the .NET family got better with every release and is actually quite nice in the 2005 version. Don’t get me wrong – it still is C++ and you probably wouldn’t want to use it if you could get away with C# or VB. But if platform invoke is giving you too many headaches you might want to take a look at it. It could be the easiest way to solve your problem.
To make this a little bit easier for those of you who haven’t used C++ for some time and didn’t bother to check managed C++ at all, I’ll provide a small sample to help out with the beginner’s problems I had when starting out.
In a situation like mine you’ll usually want to write a class library to wrap the unmanaged calls for undisturbed use within you managed project. In my case I’ll be implementing an interface but writing a standalone class is not much different.
Let’s start with the header file. You might remember that C++ requires the separation of class declaration from method definition, the former being done in a header (*.h) file and the latter in a code (*.cpp) file. I admit being a little bit spoiled by not having to do that any more in C#. Let’s name our header MCPP.h (fell free to guess what it stands for):
using namespace System;
namespace DamirsCorner { namespace Samples { namespace LateBinding { public ref class MCPP : IBind { public: virtual String^ Together(String^ first, String^ second); }; } } }
It looks like a hybrid between C++ and C# and one could argue that’s what it actually is. I’d like to point out the following:
- The using directive has an additional keyword namespace. Also a double colon (static separator in C++) would be used to separate nested namespaces instead of a dot. You’ll see this in the code file which follows.
- To put your own code into a nested namespace, you’ll have to actually nest the namespace declarations. Separating several of them with double colons won’t work.
- To declare a managed class, use the additional keyword ref.
- Don’t forget the different use of the public keyword for the members in C++ compared to C#.
- The ^ character denotes a reference to a managed object (stored on the managed heap), separating it from unmanaged pointers (* character).
- Notice the interface IBind being implemented by the class. A standalone class wouldn’t need this of course. The virtual keyword in the method declaration would also be skipped in this case.
This is it for the header file. Let’s look at the code file now:
#include "MCPP.h"
using namespace System; using namespace DamirsCorner::Samples::LateBinding;
String^ MCPP::Together(String^ first, String^ second) { return String::Empty; }
It’s pretty obvious the method doesn’t really do anything but it’s the skeleton we’re focusing on at the moment. You should turn your attention to the following:
- The code file must include the header file it implements (i.e. defines its methods). To refresh your C++ knowledge: it’s a good habit to use quotes for internal project header files and pointy brackets for external library header files. The compiler looks in the project directory first for the former and in the include directories first for the latter. It checks the other location if it doesn’t find the file but it will work faster if you use the right one (not to mention that by doing it you’re avoiding the problem of locating the wrong include with the same name).
- You can notice the double colons as namespace separators as I mentioned before.
- The methods you’re implementing are not within the class declaration any more. You already declared the class in the header file therefore you only set the method class membership here by prefixing its name with the class name and a colon, just like you were calling a static method.
There’s a reason I used String for parameter and return value type. While value types can be directly used in unmanaged code, reference types have to be correctly marshaled. But that’s a complex enough topic to justify a separate posting. The only thing left for this one is to make the code above compile. Just start a new Class Library project in C++ (you’ll find it in the CLR group) and paste the code to the right files. After you reference the assembly containing the interface used (similar to doing it in C#) the code should build successfully.
5/14/2006 6:11:27 PM (Central Europe Standard Time, UTC+01:00)
C++ project build from network share fails in VS2005 (Development | C++)
Trying to build a C++ project opened from a network share in Visual Studio 2005 might fail with a strange error: Command line error D8022 : cannot open '$(OutDir)\RSP00000115642624.rsp'. Double clicking it in the Error List window crashes the Visual Studio. The issue is reported in the |
|