<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3120879123043634081</id><updated>2011-10-24T14:41:44.986-07:00</updated><category term='digital certificate'/><category term='text size'/><category term='reflection'/><category term='kernel drivers'/><category term='64-bit'/><category term='SQL'/><category term='CSS'/><category term='VSS'/><category term='catalog file'/><category term='Read Only'/><category term='XP'/><category term='CD backup'/><category term='DataGrid AutoGenerateColumns ItemCommand'/><category term='Model'/><category term='WM_CTLCOLORSTATIC'/><category term='text color'/><category term='SetTextColor'/><category term='padding'/><category term='LOGFONT'/><category term='.NET app.config appSettings'/><category term='C#'/><category term='VISITOR'/><category term='AssemblyInfo'/><category term='IWin32Window'/><category term='signing'/><category term='attributes'/><category term='Win32'/><category term='Visual Source Safe'/><category term='WPF'/><category term='.NET'/><title type='text'>FPL Tech Talk</title><subtitle type='html'>As I spend my day thrashing away in the murky ocean that is Micros*ft's development environment, occasionally I actually figure something out that seems oh-so-profound.  Either that or I'm zonked at the end of the day and the profundity is really just relief at having found an answer. Maybe my travails will help you, too.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-2449357231988771623</id><published>2011-10-24T14:34:00.000-07:00</published><updated>2011-10-24T14:41:45.003-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Computing the viewport size within a WPF Border control</title><content type='html'>Copyright © 2011, Steven E. Houchin. All rights reserved.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;I have a WPF application that renders a photo bitmap&lt;/b&gt; inside a System.Windows.Controls.Image control that is contained within a System.Windows.Controls.Border. If the photo bitmap is too large for the app window (either in the horizontal or vertical direction), I set the Image's corresponding size attribute(s) to 'Auto' (i.e.&amp;nbsp;Double.NaN) within the Image's SizeChanged event handler. If the bitmap is smaller than the app window, I set the Image's size to the actual fixed size of the bitmap, so it doesn't get scaled.&lt;br /&gt;&lt;br /&gt;But, that left a problem when I resized the app window smaller: a fixed-size Image was &lt;i&gt;truncated &lt;/i&gt;by the border when the window shrank smaller than the photo's bitmap size. And, because the Image's width/height weren't set to Auto,&amp;nbsp;its SizeChanged event wasn't firing.&lt;br /&gt;&lt;br /&gt;However, the Border's SizeChanged event &lt;i&gt;was &lt;/i&gt;firing.&amp;nbsp;So, I added that handler for the Border control, planning to set the Image's proper width/height after resize. &amp;nbsp;That left another problem in this new event handler: how to calculate whether or not the Image control's width/height should be Auto or fixed. &amp;nbsp;Put another way, what was the size of the viewport inside the Border control where the Image would be rendered?&lt;br /&gt;&lt;br /&gt;The Border's&amp;nbsp;SizeChanged event handler is passed a&amp;nbsp;SizeChangedEventArgs parameter that provides the new width/height of the Border control. The size available to the Image control inside that will clearly be smaller, but by how much? Here is the algorithm in C# that I came up with (keep in mind that a negative BorderThickness means the border is drawn outside the control's drawing area):&lt;br /&gt;&lt;pre&gt;&lt;span class="Apple-style-span" style="color: #6fa8dc;"&gt;&lt;br /&gt;// Calculate the Border control's new viewport&lt;br /&gt;// size within the drawn border where the Image control&lt;br /&gt;// is rendered (add in any padding and non-negative&lt;br /&gt;// border thickness).&lt;br /&gt;Size viewport = new Size();&lt;br /&gt;viewport.Width = e.NewSize.Width -&lt;br /&gt;    (border.Padding.Left + border.Padding.Right) -&lt;br /&gt;    ((border.BorderThickness.Left &amp;gt; 0) ?&lt;br /&gt;        border.BorderThickness.Left : 0) -&lt;br /&gt;    ((border.BorderThickness.Right &amp;gt; 0) ?&lt;br /&gt;        border.BorderThickness.Right : 0);&lt;br /&gt;viewport.Height = e.NewSize.Height -&lt;br /&gt;    (border.Padding.Top + border.Padding.Bottom) -&lt;br /&gt;    ((border.BorderThickness.Top &amp;gt; 0) ?&lt;br /&gt;        border.BorderThickness.Top : 0) -&lt;br /&gt;    ((border.BorderThickness.Bottom &amp;gt; 0) ?&lt;br /&gt;        border.BorderThickness.Bottom : 0);&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;This viewport variable now holds the size available for the Image control inside the border. Now, all I have to do is determine if the Image needs to be scaled down in the viewport or set to a fixed size. One thing I discovered is that the Image's Margin value must be taken into account, since it is also rendered inside the viewport along with the photo bitmap.  The code to determine the right sizing, in this case for the width is:&lt;br /&gt;&lt;pre&gt;&lt;span class="Apple-style-span" style="color: #6fa8dc;"&gt;&lt;br /&gt;// Calculate the image's real width to determine if&lt;br /&gt;// scaling is needed&lt;br /&gt;double imageWidth = _bitmapActualSize.Width +&lt;br /&gt;    image.Margin.Left + image.Margin.Right;&lt;br /&gt;if (viewport.Width &amp;gt; imageWidth)&lt;br /&gt;{&lt;br /&gt;    // Restrict the Image control's width to the&lt;br /&gt;    // bitmap's actual width&lt;br /&gt;    image.Width = _bitmapActualSize.Width;&lt;br /&gt;}&lt;br /&gt;else if (viewport.Width &amp;lt; imageWidth)&lt;br /&gt;{&lt;br /&gt;    if (Double.NaN != image.Width)&lt;br /&gt;    {&lt;br /&gt;        // Set the Image control's width to 'Auto' so&lt;br /&gt;        // it will scale down to fit&lt;br /&gt;        image.Width = Double.NaN;&lt;br /&gt;    }&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;The same calculation is done for the Image height immediately after. This results in the proper change to the photo bitmap size just at the right time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-2449357231988771623?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/2449357231988771623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=2449357231988771623' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/2449357231988771623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/2449357231988771623'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2011/10/computing-viewport-size-within-wpf.html' title='Computing the viewport size within a WPF Border control'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-6311109538281234195</id><published>2011-08-31T18:31:00.000-07:00</published><updated>2011-08-31T18:33:45.231-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='padding'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><title type='text'>Eliminating Visible Image Borders on Blogger</title><content type='html'>Copyright © 2011, Steven E. Houchin&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Something that has driven me crazy&lt;/strong&gt; for quite awhile about Blogger is its propensity to place a thick white border around any image I added to my postings. Editing the HTML of the img element to include border="0" or a style="border: none;" or anything else like that was simply ignored. What the heck was happening?&lt;br /&gt;&lt;br /&gt;Then, I found a hint on another site, where it referred to Blogger's "template style sheet." After some poking around in Blogger, I stumbled across it. When logged in, navigate to the Dashboard page, then select the Design tab (or link), then click the Edit HTML link along the top. This brings up a screen that allows editing of your blog template, which contains the HTML, CSS, and Javascript that is the basis for every posting. On this template page, it suggests you download your existing template before messing with it, which sounds like good advice. Under the Edit Template heading is the text of the template which you can alter.&lt;br /&gt;&lt;br /&gt;Okay. Now to the nuts and bolts of what I did to eliminate the image border. In my template, there was a CSS directive like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #3d85c6;"&gt;.post-body img,  .post-body .tr-caption-container { &lt;br /&gt;   padding: 8px;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The 8 pixels of padding is the border I saw, because it seems to inherit a white background color from elsewhere. My images are controlled by the ".post-body img" class. So, I deleted that class specification from the above and created a new one that had the padding and background specifications I wanted:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #3d85c6;"&gt;.post-body .tr-caption-container {&lt;br /&gt;  padding: 8px;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.post-body img {&lt;br /&gt;  padding: 8px;&lt;br /&gt;  background: $(post.background.color);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;This keeps the padding (which I like since it provides some separation between the image and the text) and makes the background color for the image's box the same as the post's color. The $(post.background.color) value is, I think, a variable handled by Blogger's XSL processing that is replaced in the final output with the actual color (or "transparent" in my case).&lt;br /&gt;&lt;br /&gt;Once I saved these CSS changes to my template ... &lt;em&gt;voila&lt;/em&gt;! The image borders in all my posts (new and old) vanished. In reality, all I really did was change the background color of the padding for just the images.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-6311109538281234195?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/6311109538281234195/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=6311109538281234195' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/6311109538281234195'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/6311109538281234195'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2011/08/eliminating-visible-image-borders-on.html' title='Eliminating Visible Image Borders on Blogger'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-6036864060548174848</id><published>2011-08-11T16:44:00.000-07:00</published><updated>2011-08-11T16:52:48.031-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><category scheme='http://www.blogger.com/atom/ns#' term='IWin32Window'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Finding IWin32Window in WPF</title><content type='html'>Copyright © 2011, Steven E. Houchin&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;I'm developing a WPF desktop application&lt;/strong&gt; (C# and .NET&amp;nbsp;3.5), and I&amp;nbsp;need to pop up a dialog window that allows the user to browse for a folder.&amp;nbsp; .NET provides a convenient (and bland) dialog that does this: &lt;strong&gt;System.Windows.Forms.FolderBrowserDialog&lt;/strong&gt;. To pop up the dialog in a modal mode, I need to call the &lt;em&gt;ShowDialog&lt;/em&gt; method. I want this dialog to be a child window of my main window, so I have to pass the parent window to ShowDialog, which should be straightforward given the "owner" paremater to the method:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #3d85c6;"&gt;ShowDialog(System.Windows.Forms.IWin32Window owner);&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The problem is, the parent of the dialog is of type &lt;em&gt;System.Window&lt;/em&gt;, so "this.Owner" can't be passed as ShowDialog's "owner" parameter.&amp;nbsp; So, given that I have a WPF System.Window-derived class, where do I obtain an IWin32Window?&lt;br /&gt;&lt;br /&gt;Well, it turns out I have to write a little code for it. Specifically, I have to implement the &lt;em&gt;IWin32Window interface&lt;/em&gt; on the parent window class:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #3d85c6;"&gt;public partial class Main : Window,&lt;br /&gt;    &lt;strong&gt;&lt;span style="color: #e69138;"&gt;System.Windows.Forms.IWin32Window&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;...&lt;br /&gt;   #region IWin32Window implementation&lt;br /&gt;   IntPtr System.Windows.Forms.IWin32Window.Handle&lt;br /&gt;   {&lt;br /&gt;      get&lt;br /&gt;      {&lt;br /&gt;         return ((HwndSource)&lt;br /&gt;             PresentationSource.FromVisual(this)).Handle;&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;   #endregion&lt;br /&gt;...&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;With the &lt;em&gt;IWin32Window.Handle&lt;/em&gt; property now implemented in the parent class, I can simply call ShowDialog(this). Note that you must also include a "using System.Windows.Interop" for this to work.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-6036864060548174848?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/6036864060548174848/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=6036864060548174848' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/6036864060548174848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/6036864060548174848'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2011/08/finding-iwin32window-in-wpf.html' title='Finding IWin32Window in WPF'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-2745059298125930831</id><published>2010-09-22T12:13:00.000-07:00</published><updated>2010-09-22T12:13:05.802-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='catalog file'/><category scheme='http://www.blogger.com/atom/ns#' term='digital certificate'/><category scheme='http://www.blogger.com/atom/ns#' term='kernel drivers'/><category scheme='http://www.blogger.com/atom/ns#' term='signing'/><title type='text'>Kernel Driver Signing - Part III</title><content type='html'>Copyright © 2010, Steven E. Houchin&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;In Parts I and II of this article&lt;/strong&gt;, I discussed the requirement for driver signing, digital signatures,&amp;nbsp;and how to go about testing signed drivers.&lt;br /&gt;&lt;br /&gt;The last step&amp;nbsp;is the actual signing of the binaries that you integrate into the customer product.&amp;nbsp;In order to do this, you must first purchase a digital certificate from a reputable certificate authority (CA). In fact, for kernel mode drivers, you &lt;em&gt;must&lt;/em&gt; purchase your digital certificate from &lt;a href="https://www.verisign.com/code-signing/index.html"&gt;Verisign&lt;/a&gt;. Certificates from other vendors can be used to sign the binaries, and Windows installs them, but it refuses to execute those binaries (as of Windows 7).&lt;br /&gt;&lt;br /&gt;As I've mentioned in the earlier parts of this article, the step-by-step procedures for&amp;nbsp;driver signing are contained in a document at the &lt;a href="http://www.microsoft.com/whdc/driver/install/drvsign/kmsigning.mspx"&gt;Windows WHDC&lt;/a&gt; site, and need not be repeated here.&amp;nbsp;It contains a section titled "The Kernel-Mode Code-Signing Process." The important decision to make is whether to set up the digital signature via a catalog file (specified in the INF file), or to sign the binaries directly. A cartalog is preferable, especially if you are signing multiple files; but that won't work if your binaries start at boot time (see StartType in your INF fle). In that case, signing the binarys themselves is required. Microsoft has another site, titled "&lt;a href="http://msdn.microsoft.com/en-us/library/ff552279(v=VS.85).aspx"&gt;Signing Drivers for Public Release&lt;/a&gt;", that gives more details&amp;nbsp;about the files you may receive from your CA.&lt;br /&gt;&lt;br /&gt;When you distribute your product for the customer to install, the installer package must include, in addition to the binaries, the INF file, signed catalog files (if any), and the public key portion of your digital certificate. The public key digital certificate (.spc or .cer file) must be installed on your customer's system. Your original private key digital certificate (.pvk file) should be locked away, because it is used in the signing process.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-2745059298125930831?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/2745059298125930831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=2745059298125930831' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/2745059298125930831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/2745059298125930831'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2010/09/kernel-driver-signing-part-iii.html' title='Kernel Driver Signing - Part III'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-463359885940789591</id><published>2010-08-09T13:53:00.000-07:00</published><updated>2010-08-09T13:53:09.597-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='catalog file'/><category scheme='http://www.blogger.com/atom/ns#' term='digital certificate'/><category scheme='http://www.blogger.com/atom/ns#' term='64-bit'/><category scheme='http://www.blogger.com/atom/ns#' term='kernel drivers'/><category scheme='http://www.blogger.com/atom/ns#' term='signing'/><title type='text'>Kernel Driver Signing - Part II</title><content type='html'>Copyright © 2010, Steven E. Houchin&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;In Part I of this article&lt;/strong&gt;, I explained that all kernel drivers on 64-bit Windows systems must be digitally signed.&lt;br /&gt;&lt;br /&gt;There are two ways of signing kernel drivers: embed the signature in the driver binaries themselves, or use a signed catalog file. To peform driver signing, you really must have the latest Microsoft WDK installed on your signing system.&lt;br /&gt;&lt;br /&gt;For drivers that start at boot time (see StartType in your INF fle), the binary &lt;i&gt;itself &lt;/i&gt;must be signed.&amp;nbsp; Use of a catalog file is not enough, though is also required if installing the driver package via INF file.&amp;nbsp; For other types of drivers - especially those that contain multiple files - a signed catalog file can be used to identify all the files in a driver package.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Use of a catalog file requires that the driver package be installed via an INF file, because that is where the catalog file is specified.&amp;nbsp;For example, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;ADriver.inf&lt;/span&gt; will have the following line included in its [Version] section:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;CatalogFile=ADriver.cat&lt;/span&gt;&lt;/blockquote&gt;After your driver binaries are all built and copied to a "package" directory (which includes the INF file), a catalog file is created using the WDK's &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Inf2Cat&lt;/span&gt; utility.&amp;nbsp;For example, if your package files are in C:\MyDriverPackage, the catalog file (in this case for Win2K and Win64 systems) is created via:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Inf2Cat /driver:C:\MyDriverPackage\ /os:2000,Server2003_X64&lt;/span&gt;&lt;/blockquote&gt;This utility will scan all INF files in the given directory and create catalog files for each one using the "CatalogFile" line.&lt;br /&gt;&lt;br /&gt;Once the catalog files are created, they must be signed using WDK's &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SignTool&lt;/span&gt; utility and your digital certificate information.&amp;nbsp; The details for catalog file creation and signing, and driver binary signing,&amp;nbsp;are&amp;nbsp;at the&amp;nbsp;&lt;a href="http://www.microsoft.com/whdc/driver/install/drvsign/kmsigning.mspx"&gt;Windows WHDC&lt;/a&gt; site, which&amp;nbsp;contains white paper that has decent step-by-step procedures.&lt;br /&gt;&lt;br /&gt;The catalog file&amp;nbsp;and INF file go together as a pair wherever the signed driver package is to be installed.&amp;nbsp; If your INF file is also used for 32-bit drivers, then your 32-bit installer should comment out the "CatalogFile" line in the [Version] section so that a signing certificate isn't needed on those systems.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-463359885940789591?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/463359885940789591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=463359885940789591' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/463359885940789591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/463359885940789591'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2010/08/kernel-driver-signing-part-ii.html' title='Kernel Driver Signing - Part II'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-5795639956367748958</id><published>2010-07-27T16:46:00.000-07:00</published><updated>2011-08-11T15:12:44.626-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='digital certificate'/><category scheme='http://www.blogger.com/atom/ns#' term='64-bit'/><category scheme='http://www.blogger.com/atom/ns#' term='kernel drivers'/><category scheme='http://www.blogger.com/atom/ns#' term='signing'/><title type='text'>Kernel Driver Signing - Part I</title><content type='html'>Copyright © 2010, Steven E. Houchin&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Back in January of 2006,&lt;/strong&gt; Microsoft announced - much to developers' dismay - that &lt;em&gt;all&lt;/em&gt; kernel drivers on 64-bit Windows systems must be signed. Signing is defined as: &lt;br /&gt;&lt;blockquote&gt;&lt;span style="color: #e69138;"&gt;the process of assigning an encrypted&amp;nbsp;digital signature to executables in&amp;nbsp;order&amp;nbsp;to confirm the software's author and to guarantee that the code has not been altered or corrupted&lt;/span&gt;&lt;/blockquote&gt;Once I ported my client's driver code to 64-bit, I found myself in an "uh-oh" situation: how do I test the changes on my development systems without having my client's digital signing certificate?&amp;nbsp;&amp;nbsp;A digital certificate is:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="color: #e69138;"&gt;a digital signature from a certificate authority (CA) that contains a&amp;nbsp;private key used to sign some&amp;nbsp;software, which must&amp;nbsp;match the public key in the CA's certificate installed on a user's system&lt;/span&gt;&lt;/blockquote&gt;The private key (PK) is necessary for me to sign the driver executables, and is something that the software vendor (my client) must &lt;em&gt;not&lt;/em&gt; pass around to anyone else - including me - lest it fall into the wrong hands and be used for malicious signing. That gets us back to my dilemma: how do I test without the PK?&lt;br /&gt;&lt;br /&gt;The answer provided by MSFT is Test Signing. The &lt;a href="http://www.microsoft.com/whdc/driver/install/drvsign/kmsigning.mspx" target="_blank"&gt;Windows WHDC&lt;/a&gt; site contains a good white paper on this subject that has decent step-by-step procedures. The basic idea is this: a developer can create a Test Certificate, which is used on the development systems to sign and validate executables.&amp;nbsp; The catch is, the executables will only work if the target test system is configured to boot into a special Test Signing mode. This is done on the target system with the BCDEDIT command. Note that, in the past, it was also possible to boot Windows into a "Disable Driver Signature Enforcement" mode, where signatures were ignored. That option, while still visible via F8 boot options, does not actually work anymore.&lt;br /&gt;&lt;br /&gt;Next time: Test Signing using catalog files.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-5795639956367748958?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/5795639956367748958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=5795639956367748958' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/5795639956367748958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/5795639956367748958'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2010/07/kernel-driver-signing-part-i.html' title='Kernel Driver Signing - Part I'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-6567328006403487148</id><published>2009-09-03T16:07:00.000-07:00</published><updated>2009-09-03T16:32:20.145-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Read Only'/><category scheme='http://www.blogger.com/atom/ns#' term='VSS'/><category scheme='http://www.blogger.com/atom/ns#' term='CD backup'/><category scheme='http://www.blogger.com/atom/ns#' term='XP'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Source Safe'/><title type='text'>The Mysterious Missing Attribute</title><content type='html'>Copyright © 2009, Steven E. Houchin&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Something about my XP system&lt;/strong&gt; has been driving me crazy for a long time. I use Visual Source Safe for source control of my development projects on. VSS makes use of Windows’ Read Only file attribute to prevent modification of source-controlled files in a project’s working directory. When a file is checked out of VSS, that attribute is cleared, and the user can then change the file. When checked back in, Read Only is set again.&lt;br /&gt;&lt;br /&gt;So, what was my problem? It’s this: the Read Only attribute on those source-controlled files (and others) would simply disappear periodically. I’d have to go through all my files and reassert Read Only by hand. I looked into a number of causes: that VSS was doing it, or Visual Studio; maybe it was compiling the files over a network share; maybe it was my anti-virus software.&lt;br /&gt;&lt;br /&gt;Then I stumbled across the cause: backing up the files to a CD via Windows Explorer. It seems that somebody in Redmond Land decided it would be a clever idea to clear the Read Only attribute for all files burned to a CD. When I searched the web for others with this problem, I actually saw the opposite complaint: that files &lt;em&gt;retained&lt;/em&gt; their R/O attributes on a CD. Okay, &lt;em&gt;so what&lt;/em&gt;? The CD is … wait for it … wait for it … READ ONLY!&lt;br /&gt;&lt;br /&gt;Maybe there is some obscure Windows setting that will stop this behavior on my system. Let me know if you find one. In the meantime, I now have to first copy my files into a zip file, then back up the zip – a real pain.&lt;br /&gt;&lt;br /&gt;So, call me crazy. This problem has certainly driven me mad.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-6567328006403487148?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/6567328006403487148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=6567328006403487148' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/6567328006403487148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/6567328006403487148'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2009/09/mysterious-missing-attribute.html' title='The Mysterious Missing Attribute'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-8671459219489407975</id><published>2009-04-27T17:55:00.000-07:00</published><updated>2011-08-11T15:22:00.671-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='text size'/><category scheme='http://www.blogger.com/atom/ns#' term='LOGFONT'/><category scheme='http://www.blogger.com/atom/ns#' term='Win32'/><title type='text'>Setting a Win32 Control's Font and Sizing It to Fit the Text</title><content type='html'>Copyright © 2009, Steven E. Houchin&lt;br /&gt;&lt;strong&gt;In my latest application&lt;/strong&gt;, I have a Static control that I use as a label at the top of a rectangular box. I wanted to change the font, then resize the control to fit the text exactly. First, I needed to set the font. This is done by initializing a LOGFONT structure for the desired font family and size. The code below speicifies the minimum LOGFONT fields necessary:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;LOGFONT lf;&lt;br /&gt;ZeroMemory(&amp;amp;lf, sizeof(LOGFONT));&lt;br /&gt;lf.lfHeight = 12;&lt;br /&gt;_tcscpy(lf.lfFaceName, _T("MS Sans Serif"));&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;Now that we have a LOGFONT, a Win32 font object needs to be created and associated with the control:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;// the LOGFONT must have some valid data in it&lt;br /&gt;HFONT hFont = CreateFontIndirect(&amp;amp;lf);&lt;br /&gt;if ((HFONT)0 != hFont)&lt;br /&gt;{&lt;br /&gt;     SetWindowFont(hCtrl, hFont, TRUE);&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;The SetWindowFont call is really a macro that expands into a call to SendMessage that specifies the WM_SETFONT message. At this point, when the control is redrawn, it will use the new font.&lt;br /&gt;Now, we need to resize the control so it fits exactly the text it contains. Let's assume the variable &lt;em&gt;lpszText&lt;/em&gt; points to our null-terminated text string that the Static control already displays. We must call the Win32 GetTextExtentPoint32 function to get the dimensions of the text. This function requires the device context (DC) of the control. And, to make sure we're getting the proper dimensions, our new font must be selected into the device context.&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;HDC hdc = GetDC(hCtrl); // get the static control's DC&lt;br /&gt;HFONT hfOld = reinterpret_cast&amp;lt;hfont&amp;gt;(SelectObject(hdc, hFont));&lt;br /&gt;DeleteObject(hfOld);    // free the old font handle&lt;br /&gt;&lt;br /&gt;// measure the text height and width&lt;br /&gt;size_t iLen = _tcslen(lpszText);&lt;br /&gt;SIZE s;&lt;br /&gt;if (GetTextExtentPoint32(hdc, m_pszLabelText, static_cast&amp;lt;int&amp;gt;(iLen), &amp;amp;s))&lt;br /&gt;{&lt;br /&gt;     // control's x,y position set by CreateWindow&lt;br /&gt;     POINT p = this-&amp;gt;ptControlOrigin;&lt;br /&gt;     MoveWindow(hCtrl, p.x, p.y, s.cx, s.cy,&lt;br /&gt;     FALSE /* no repaint now */);&lt;br /&gt;}&lt;br /&gt;ReleaseDC(hCtrl, hdc); // free the DC&lt;/int&gt;&lt;/hfont&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;That completes the task. We've changed the control's font to 12 point "MS Sans Serif" and have resized the control to fit the control's text string exactly. If the control's text string is changed, then the calls to GetTextExtentPoint32 and MoveWindow must be repeated for the new string's length.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-8671459219489407975?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/8671459219489407975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=8671459219489407975' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/8671459219489407975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/8671459219489407975'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2009/04/setting-win32-controls-font-and-sizing.html' title='Setting a Win32 Control&apos;s Font and Sizing It to Fit the Text'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-5597321911769050926</id><published>2008-08-04T17:50:00.000-07:00</published><updated>2011-08-11T15:29:11.630-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WM_CTLCOLORSTATIC'/><category scheme='http://www.blogger.com/atom/ns#' term='Win32'/><category scheme='http://www.blogger.com/atom/ns#' term='text color'/><category scheme='http://www.blogger.com/atom/ns#' term='SetTextColor'/><title type='text'>Machinations to Set Text Color in Win32</title><content type='html'>Copyright © 2008, Steven E. Houchin&lt;br /&gt;&lt;strong&gt;Recently, I wanted to set the text color&lt;/strong&gt; for a Win32 Static control within a dialog window. I'm a relative novice when it comes to old fashioned Win32 message pump applications, so I had to scrounge around for the right API calls to do this. I assumed there must be a simple one-time call to set the text attributes for a given control. Silly me.&lt;br /&gt;It took some digging to discover that the answer was to handle the WM_CTLCOLORSTATIC message. The M*soft documentation states that this message is sent when "a static control, or an edit control that is read-only or disabled, ... is about to be drawn." In other words, the color is modified right before the text gets drawn. It seems you have to do this each and every time you wish to draw the text, not just as a one-time setup. So I wrote this:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;&lt;br /&gt;case WM_CTLCOLORSTATIC:&lt;br /&gt;{&lt;br /&gt;     HDC hDC = (HDC)wParam;&lt;br /&gt;     ::SetTextColor(hDC, RGB(255,0,0)); // red text&lt;br /&gt;     return TRUE;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Seems simple enough. The result? Plain old black text. It turns out that WM_CTLCOLORSTATIC requires an HBRUSH as its return value. Since TRUE isn't a valid brush, it ignored the whole thing. So, where do I get a brush? The documentation says the brush will be used to paint the control's background. I tried this:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;&lt;br /&gt;return (LRESULT)::GetStockObject(HOLLOW_BRUSH);&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The result was red text with each character on a white background. Plus, the old text wasn't erased when new text was written to the control. I realized that HOLLOW_BRUSH is essentially no brush, so the old text wasn't getting wiped. I needed the brush for the control's plain old gray background. So, I tried this:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;&lt;br /&gt;...&lt;br /&gt;COLORREF bg = ::GetBkColor(hDC);&lt;br /&gt;HBRUSH hb = ::CreateSolidBrush(bg);&lt;br /&gt;return (LRESULT)hb;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Surely this would work. Nice try, but no cigar. This fixes the problem of ghost text hanging around. But it has the side effect of turning the control's background entirely white. In other words, GetBkColor() is returning white, even though the background of the dialog is the usual gray. So, two problems still remain: the character background is white, and now the control's background is white. For the first problem, I discovered this:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;&lt;br /&gt;...&lt;br /&gt;::SetBkMode(hDC, TRANSPARENT);&lt;br /&gt;::SetTextColor(hDC, RGB(255,0,0)); // red text&lt;br /&gt;...&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;By temporarily forcing the returned brush to a stock light gray (using GetStockObject()), I could see that the text backgound was now what I wanted: red text on the control's background color (stock light gray).&lt;br /&gt;So, where could I get the dialog's usual gray background to return as a brush? After lots of searching around, I discovered the answer: send a WM_CTLCOLORDLG message. This message returns the background brush for the dialog box, as long as I'm not handling that message myself in DlgProc() - which could cause a chicken-and-egg problem.&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;&lt;br /&gt;...&lt;br /&gt;HBRUSH hBrush = (HBRUSH)SendMessage(&lt;br /&gt;     hDlg,&lt;br /&gt;     WM_CTLCOLORDLG,&lt;br /&gt;     (WPARAM)hDC,&lt;br /&gt;     lParam /* the control's HWND */);&lt;br /&gt;     return (LRESULT)hBrush;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;I executed this and ... ugh! This set me all the way to black text on the gray background. My previous attempts told me that the problem was an invalid brush. Later, I was moving around the code into separate functions, and it accentally started to work. I had done this:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;&lt;br /&gt;...&lt;br /&gt;HBRUSH hBrush = (HBRUSH)SendMessage(&lt;br /&gt;     hDlg,&lt;br /&gt;     WM_CTLCOLORDLG,&lt;br /&gt;     GetWindowDC((HWND)lParam),&lt;br /&gt;     lParam /* the control's HWND */);&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Voila! A miracle occured. I finally see the result I wanted from the start: red text on the standard gray background. All of that work just to draw RED TEXT!&lt;br /&gt;I'm guessing that the HDC provided via 'wParam' is for the text&lt;br /&gt;glyphs, which is different than the HDC associated with the control's HWND via 'lParam'. Here's the final magic code:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;&lt;br /&gt;DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)&lt;br /&gt;...&lt;br /&gt;case WM_CTLCOLORSTATIC:&lt;br /&gt;{   &lt;br /&gt;     // handle just for my MSG control&lt;br /&gt;     if ((HWND)lParam == GetDlgItem(m_hDlg, IDC_STATIC_MSG))&lt;br /&gt;     {&lt;br /&gt;          HDC hDC = (HDC)wParam;  // use for the text&lt;br /&gt;          ::SetBkMode(hDC, TRANSPARENT);&lt;br /&gt;          ::SetTextColor(hDC, RGB(255,0,0)); // red text&lt;br /&gt;          HBRUSH hb = (HBRUSH)SendMessage(&lt;br /&gt;               hDlg,&lt;br /&gt;               WM_CTLCOLORDLG,&lt;br /&gt;               (WPARAM)GetWindowDC((HWND)lParam),&lt;br /&gt;               lParam /* the control's HWND */);&lt;br /&gt;          return (LRESULT)hb;&lt;br /&gt;     }&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The WM_CTLCOLORDLG also works by using 'hDlg' instead of 'lParam', even though it results in different hDC's. It would also be possible to send a WM_CTLCOLORSTATIC message itself to get an HBRUSH, but that seems like it could result in an infinite loop - sending a message from the same message's handler. I suppose a different target HWND might avoid that. So, it now works, but I don't know all the details under the hood.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-5597321911769050926?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/5597321911769050926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=5597321911769050926' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/5597321911769050926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/5597321911769050926'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2008/08/machinations-to-set-text-color-in-win32.html' title='Machinations to Set Text Color in Win32'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-3827326299400273356</id><published>2008-05-14T16:56:00.000-07:00</published><updated>2011-08-11T15:40:31.956-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='reflection'/><category scheme='http://www.blogger.com/atom/ns#' term='AssemblyInfo'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='attributes'/><title type='text'>Accessing Attributes in AssemblyInfo.cs</title><content type='html'>Copyright © 2008, Steven E. Houchin&lt;br /&gt;&lt;strong&gt;For a new C# .NET application&lt;/strong&gt;, an AssemblyInfo.cs file is automatically created. It contains empty attributes that can be used to describe the assembly. These attributes are queried by Windows when the Properties of an executable are examined from Windows Explorer. They are also useful within the application itself to set the string in the title bar and for populating an About dialog. For example, I set the following values for one of my applications (with names changed to protect confidentiality):&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;&lt;br /&gt;[assembly: AssemblyTitle("My Application")]&lt;br /&gt;[assembly: AssemblyCompany("Forest Park Lab")]&lt;br /&gt;[assembly: AssemblyProduct("My Product")]&lt;br /&gt;[assembly: AssemblyCopyright("Copyright © 2004-2008, Forest Park Lab.")]&lt;br /&gt;[assembly: AssemblyTrademark("My Product ™ is a trademark of Forest Park Lab.")]&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Setting these values doesn't make them automatically available to your application code. In order to access them, I have a piece of boilerplate code I include in the AssemblyInfo.cs file to make these attributes readily accessible. I define an "AssemblyInfo class" as follows:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;&lt;br /&gt;using System.Reflection;&lt;br /&gt;using System.Runtime.CompilerServices;&lt;br /&gt;&lt;br /&gt;public class AssemblyInfo&lt;br /&gt;{&lt;br /&gt;   private AssemblyTitleAttribute  _title = null;&lt;br /&gt;   private AssemblyCopyrightAttribute _copyright = null;&lt;br /&gt;   private AssemblyProductAttribute _product = null;&lt;br /&gt;   private string    _version;&lt;br /&gt;&lt;br /&gt;   public AssemblyInfo()&lt;br /&gt;   {&lt;br /&gt;      System.Reflection.Assembly assembly =&lt;br /&gt;      System.Reflection.Assembly.GetExecutingAssembly();&lt;br /&gt;      // get the version string&lt;br /&gt;      _version = assembly.GetName().Version.ToString();&lt;br /&gt;&lt;br /&gt;      // get other desired attributes&lt;br /&gt;      object[] attributes = assembly.GetCustomAttributes(false);&lt;br /&gt;      for (int i = 0; i &amp;lt; attributes.Length; i ++)&lt;br /&gt;      {&lt;br /&gt;         if (_title == null)&lt;br /&gt;         {&lt;br /&gt;            _title = attributes[i]&lt;br /&gt;               as AssemblyTitleAttribute;&lt;br /&gt;            if (_title != null)&lt;br /&gt;               continue;&lt;br /&gt;         }&lt;br /&gt;         if (_copyright == null)&lt;br /&gt;         {&lt;br /&gt;            _copyright = attributes[i]&lt;br /&gt;               as AssemblyCopyrightAttribute;&lt;br /&gt;            if (_copyright != null)&lt;br /&gt;               continue;&lt;br /&gt;         }&lt;br /&gt;         if (_product == null)&lt;br /&gt;         {&lt;br /&gt;            _product = attributes[i]&lt;br /&gt;               as AssemblyProductAttribute;&lt;br /&gt;            if (_product != null)&lt;br /&gt;               continue;&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;   public string Title  { get { return _title.Title; } }&lt;br /&gt;   public string Product  { get { return _product.Product; } }&lt;br /&gt;   public string Copyright  { get { return _copyright.Copyright; } }&lt;br /&gt;   public string Version  { get { return _version; } }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The way this code works is that it fetches all of the customizable attributes from the assembly (GetCustomAttributes()) into an array of objects. It then loops through each object and attempts to cast it (using the C# "as" operator) to one of the desired attribute types. If the cast fails, the result is null. Otherwise, the object is remembered as a property within the AssemblyInfo class for later access by the application.&lt;br /&gt;To make use of these attributes in the application, simply create an instance of the AssemblyInfo class and access the properties, as follows:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;&lt;br /&gt;AssemblyInfo appInfo = new AssemblyInfo();&lt;br /&gt;// set the title in title bar&lt;br /&gt;this.Text = appInfo.Title;&lt;br /&gt;// set the product name&lt;br /&gt;this.lblProduct.Text = appInfo.Product;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-3827326299400273356?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/3827326299400273356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=3827326299400273356' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/3827326299400273356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/3827326299400273356'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2008/05/accessing-attributes-in-assemblyinfocs.html' title='Accessing Attributes in AssemblyInfo.cs'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-3098682450529751557</id><published>2008-04-15T18:03:00.000-07:00</published><updated>2011-08-11T15:44:41.471-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET app.config appSettings'/><title type='text'>Shared .NET Configuration Files</title><content type='html'>Copyright © 2008, Steven E. Houchin&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;One C# .NET application I’ve been working on&lt;/strong&gt; for a while consists of two executables: a main application and a taskbar tray applet. The two apps needed to share common configuration settings, which I planned to implement via the &lt;em&gt;app.config&lt;/em&gt; file. The way .NET is set up (I’m using .NET 1.1), each .EXE loads its config file based upon the executable’s file name. For example, &lt;em&gt;xyz.exe&lt;/em&gt; loads &lt;em&gt;xyz.exe.config&lt;/em&gt;. This is a problem when &lt;em&gt;abc.exe&lt;/em&gt; needs to access the same config settings. Now, .NET may have some clever API to solve this problem, but I didn’t find one.&lt;br /&gt;&lt;br /&gt;My answer to the situation was to create a file named &lt;em&gt;common.config&lt;/em&gt;, which I placed within the project for a shared library. Inside this config file are the &amp;lt;appSettings&amp;gt; and &amp;lt;/appSettings&amp;gt; tags, with the application’s key, value pairs coded inside:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;&amp;lt;appSettings&amp;gt;&lt;br /&gt;&amp;lt;add key="database_type" value="MSACCESS"/&amp;gt;&lt;br /&gt;&amp;lt;add key="datasource" value="mydatabase.mdb"/&amp;gt;&lt;br /&gt;&amp;lt;add key="default_browser" value="C:\Program Files\Internet Explorer\iexplore.exe"/&amp;gt;&lt;br /&gt;&amp;lt;/appSettings&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Once the &lt;em&gt;common.config&lt;/em&gt; file was created, I needed to reference it from each executable’s &lt;em&gt;app.config&lt;/em&gt; file. I accomplished this using the “file=” parameter of the &amp;lt;appSettings&amp;gt; tag. Below is my entire &lt;em&gt;app.config&lt;/em&gt; file, which I duplicate in the projects for the main application and a taskbar tray applet:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;&amp;lt;appSettings file="common.config"&amp;gt;&lt;br /&gt;&amp;lt;/appSettings&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Note that the above does not include path information for &lt;em&gt;common.config&lt;/em&gt;. The reason for this is that &lt;em&gt;common.config&lt;/em&gt; is installed on a user’s system in a single directory, along with the application executables. Thus, simply using the current directory is appropriate. However, this doesn’t work when using the Visual Studio development environment, where each part of the application is built in a different directory. So, for each executable to find this file during Debug execution, I added a Pre-Build Event to each executable’s project, which first copies &lt;em&gt;common.config&lt;/em&gt; to that project’s directory:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;copy $(SolutionDir)MyCommonDll\common.config $(TargetDir)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;With this done, I now have a configuration file that is shared by each executable in my application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-3098682450529751557?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/3098682450529751557/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=3098682450529751557' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/3098682450529751557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/3098682450529751557'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2008/04/shared-net-configuration-files.html' title='Shared .NET Configuration Files'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-4981865060939855539</id><published>2008-03-31T16:40:00.000-07:00</published><updated>2009-09-03T16:35:14.242-07:00</updated><title type='text'>MSMQ Startup Failure on XP Pro</title><content type='html'>Copyright © 2008, Steven E. Houchin&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Yesterday, I installed an application I'd written&lt;/strong&gt; onto a new machine. It uses Message Queuing for two processes to communicate with each other, so I needed MSMQ installed and running on the new machine (which is XP Pro). Much to my surprise, the MSMQ service refused to start. In Event Viewer, I saw the following cryptic error:&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;Event Type: Error&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;Event Source: MSMQ&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;Event Category: Kernel&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;Event ID: 2047&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;Date: 3/30/2008&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;Time: 1:31:10 PM&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;User: N/A&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;Computer: ********&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;Description:A connection to the Distributed Transaction Coordinator cannot be established. Consequently, transactions cannot be supported.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Uninstalling and reinstalling the MSMQ Windows components (via Add/Remove Programs) still resulted in failure. After hours of fruitless research on the web, trying a half-dozen search keyword combinations, I finally found the answer. The problem -- just as the error message says -- was with the Distributed Transaction Cordinator service (MS DTC). This is apparently a facility that MSMQ uses for routing its messages.&lt;br /&gt;&lt;br /&gt;The problem was apparently that MS DTC service needs to execute under the NETWORK SERVICE user in order to work properly with MSMQ. I didn't have to do this on my other XP system, so something I installed (such as .NET 3.5?) on this newer system seems to have messed up either MSMQ or MS DTC.&lt;br /&gt;&lt;br /&gt;The actual process for the fix is:&lt;br /&gt;&lt;br /&gt;a) Uninstall MSMQ&lt;br /&gt;b) Stop the MS DTC service&lt;br /&gt;c) Change MS DTC's execution user to NETWORK SERVICE&lt;br /&gt;d) Open a Command Prompt and execute "msdtc -resetlog"&lt;br /&gt;e) Restart MS DTC&lt;br /&gt;f) Install MSMQ&lt;br /&gt;&lt;br /&gt;Lots of mystery here, but others on the net have seen this same MSMQ problem. Does anyone out there know more about what's going on?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-4981865060939855539?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/4981865060939855539/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=4981865060939855539' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/4981865060939855539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/4981865060939855539'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2008/03/msmq-startup-failure-on-xp-pro.html' title='MSMQ Startup Failure on XP Pro'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-1990701271699465909</id><published>2008-02-18T14:44:00.000-08:00</published><updated>2011-08-11T15:56:23.548-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Model'/><category scheme='http://www.blogger.com/atom/ns#' term='VISITOR'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>VISITOR Design Pattern</title><content type='html'>Copyright © 2008, Steven E. Houchin&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;I ran into an architectural problem&lt;/strong&gt; after I developed a generic library class, &lt;em&gt;SQLDbConn&lt;/em&gt;, that connects to a SQL database given a connection string. It implements an interface &lt;em&gt;IDbConn &lt;/em&gt;that can also be used to implement a similar class for MS Access or other databases. An instance of &lt;em&gt;SQLDbConn&lt;/em&gt;is created by the application via a Factory function:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;static public IDbConn MakeDatabaseConnFactory&lt;br /&gt;(DatabaseConnType eType)&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;After a databse connection is made through this "Connection" object, the nuts and bolts of accessing the database and retrieving rowsets is done using an &lt;em&gt;application-specific&lt;/em&gt; "Model" object, defined by an &lt;em&gt;IDbModel&lt;/em&gt; interface. For a SQL connection, that would be an instance of the &lt;em&gt;SQLDbModel&lt;/em&gt; class.&lt;br /&gt;&lt;br /&gt;Here's the design problem I encountered: the application shouldn't have any hard-coded knowledge of what kind of database it is using. It only has a reference to its &lt;em&gt;IDbConn&lt;/em&gt;object after calling the Factory function above. So, it needs to instantiate its Model object without knowing it will actually be a &lt;em&gt;SQLDbModel&lt;/em&gt; object. I don't want to put the logic in &lt;em&gt;SQLDbConn&lt;/em&gt;to create it, because that Connection class is &lt;em&gt;generic&lt;/em&gt;, so shouldn't know about the &lt;em&gt;application-specific&lt;/em&gt; Model class. I also don't want to simply create another Factory function - though that would work - because I have already created a database-type aware object - the Connection object - that knows what kind of database is in use. So, how do I get the generic Connection object (&lt;em&gt;SQLDbConn&lt;/em&gt;) to create the specific Model object for me, and still remain application neutral?&lt;br /&gt;&lt;br /&gt;The solution I came up with uses the VISITOR design pattern. I added the VISITOR pattern's &lt;em&gt;accept&lt;/em&gt; method to the &lt;em&gt;IDbConn &lt;/em&gt;interface:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;bool AcceptVisitor(IDbConnVisitor visitor);&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;This allows my application to generically extend the connection object's functionality after its instantiation. The &lt;em&gt;IDbConnVisitor &lt;/em&gt;interface referenced above specifies a &lt;em&gt;visit&lt;/em&gt;method for each type of supported database, but does not dictate what that method does (they could order sandwiches from the deli):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;public interface IDbConnVisitor&lt;br /&gt;{&lt;br /&gt;   bool VisitMsAccess(IDbConn dbConn);&lt;br /&gt;   bool VisitSqlOle(IDbConn dbConn);&lt;br /&gt;   bool VisitSqlDa(IDbConn dbConn);&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Since each instance of a Connection object (like &lt;em&gt;SQLDbConn&lt;/em&gt;) knows what kind of database it is, it can call its appropriate &lt;em&gt;visit &lt;/em&gt;function, without knowing what that function actually does. For the &lt;em&gt;SQLDbConn&lt;/em&gt;class, its &lt;em&gt;accept&lt;/em&gt;function looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;public bool AcceptVisitor(IDbConnVisitor visitor)&lt;br /&gt;{&lt;br /&gt;   try&lt;br /&gt;   {&lt;br /&gt;      return visitor.VisitSqlDa(this);&lt;br /&gt;   }&lt;br /&gt;   catch (System.Exception excp)&lt;br /&gt;   {&lt;br /&gt;      _errorText = excp.Message;&lt;br /&gt;   }&lt;br /&gt;   return false;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;An MS Access Connection object's &lt;em&gt;AcceptVisitor&lt;/em&gt; would similarly call &lt;em&gt;VisitMsAccess&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;My application then defines an implementation of &lt;em&gt;IDbConnVisitor &lt;/em&gt;via a new class, such as &lt;em&gt;CreateDbModelVisitor&lt;/em&gt;, whose job is to provide functions that will instantiate the appropriate Model object for any of the supported database types. Inside, it has a property of type &lt;em&gt;IDbModel&lt;/em&gt; that the &lt;em&gt;visitor&lt;/em&gt; methods instantiate:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;public class CreateDbModelVisitor : IDbConnVisitor&lt;br /&gt;{&lt;br /&gt;   ...&lt;br /&gt;   protected IDbModel _model = null;&lt;br /&gt;   ...&lt;br /&gt;   public bool VisitMsAccess(IDbConn dbConn) { ... }&lt;br /&gt;   public bool VisitSqlOle(IDbConn dbConn) { ... }&lt;br /&gt;   public bool VisitSqlDa(IDbConn dbConn) { ... }&lt;br /&gt;   public IDbModel Model { get { return _model; } }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;For the SQL database, the &lt;em&gt;visit&lt;/em&gt;method implementation within &lt;em&gt;CreateDbModelVisitor&lt;/em&gt;is as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;public bool VisitSqlDa(IDbConn dbConn)&lt;br /&gt;{&lt;br /&gt;   _errorText = "";&lt;br /&gt;   try&lt;br /&gt;   {&lt;br /&gt;      if (dbConn.IsConnected)&lt;br /&gt;      {&lt;br /&gt;         _model = new SqlDbModel(dbConn);&lt;br /&gt;         return true;&lt;br /&gt;      }&lt;br /&gt;      else&lt;br /&gt;      {&lt;br /&gt;         _errorText = "Database has not been connected."&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;   catch (System.Exception excp)&lt;br /&gt;   {&lt;br /&gt;      _errorText = excp.Message;&lt;br /&gt;   }&lt;br /&gt;   return false;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Putting it all together, the application would do the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="color: #e69138;"&gt;IDbConn dbConn = MakeDatabaseConnFactory(config.DbType);&lt;br /&gt;IDbConnVisitor dbVisitor = new CreateDbModelVisitor();&lt;br /&gt;if (dbConn.AcceptVisitor(dbVisitor))&lt;br /&gt;{&lt;br /&gt;   IDbModel model = dbVisitor.Model;&lt;br /&gt;   ...&lt;br /&gt;   // make Model calls here to access database&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that the only thing the application knows of its database type is a value that it picks up from a config file.&lt;br /&gt;&lt;br /&gt;By using a VISITOR design pattern, the database-specific Connection object (&lt;em&gt;IDbConn&lt;/em&gt;), which is supposed to be application neutral, can execute an application-specific function (via &lt;em&gt;AcceptVisitor&lt;/em&gt;) for that particular type of database, without knowing the details of what that function does. It just calls the &lt;em&gt;accept&lt;/em&gt; method, and that's that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-1990701271699465909?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/1990701271699465909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=1990701271699465909' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/1990701271699465909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/1990701271699465909'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2008/02/visitor-design-pattern.html' title='VISITOR Design Pattern'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3120879123043634081.post-9189146724591547277</id><published>2008-02-13T15:43:00.000-08:00</published><updated>2011-08-11T16:03:36.108-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DataGrid AutoGenerateColumns ItemCommand'/><title type='text'>Fun with DataGrids</title><content type='html'>Copyright © 2008, Steven E. Houchin&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Recently, I was implementing&lt;/strong&gt; a &lt;b&gt;DataGrid&lt;/b&gt; for an ASP.NET application. ASP.NET is not usually my forte, so I was once again in learning mode.&lt;br /&gt;&lt;br /&gt;The first obstacle I stumbled onto was that a lot more columns were displayed when the page came up than what I intended. My &lt;i&gt;DataSource&lt;/i&gt; was an ArrayList of objects, which represented information culled from the database. In the page's Page_Load function, I had code that created each column explicitly, using &lt;i&gt;ButtonColumn&lt;/i&gt; and &lt;i&gt;BoundColumn&lt;/i&gt; objects. The extraneous unwanted columns that displayed were duplicates of the &lt;i&gt;DataSource&lt;/i&gt; object's properties.&lt;br /&gt;&lt;br /&gt;I discovered the problem was with the &lt;i&gt;AutoGenerateColumns&lt;/i&gt; property of the DataGrid. Its default value was True, which causes a DataGrid object to automatically create columns (duh!) identical to the &lt;i&gt;DataSource&lt;/i&gt; object's properties ... just what I was seeing. Setting this to False prior to assigning the &lt;i&gt;DataSource&lt;/i&gt; value fixed that.&lt;br /&gt;&lt;br /&gt;The next obstacle was that my &lt;i&gt;ItemCommand&lt;/i&gt; handler wouldn't fire when I clicked on a &lt;i&gt;ButtonColumn&lt;/i&gt; item in the list. Worse, my grid completely disappeared afterward. Searching around on the web revealed many others who also had this problem, but nobody seemed to have a good answer. There were some postings about &lt;i&gt;EnableViewState&lt;/i&gt; related to this, but they didn't help.&lt;br /&gt;&lt;br /&gt;Eventually, I discovered that when the Click event caused a PostBack to the page, the DataGrid reverted back to its initial empty state. My &lt;i&gt;Page_Load&lt;/i&gt; code populated the DataGrid only when the call was &lt;i&gt;not&lt;/i&gt; a PostBack. Armed with this insight, I changed &lt;i&gt;Page_Load&lt;/i&gt; so a PostBack call only decides where to get the data: a database call for non-PostBack versus session variable on PostBack. The code now creates and binds the DataGrid columns each time through &lt;i&gt;Page_Load&lt;/i&gt;, since my columns are created on-the-fly. The fixed code follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size: 85%;"&gt;&lt;br /&gt;&lt;span style="color: #e69138;"&gt;&lt;br /&gt;ArrayList allUsers = null;&lt;br /&gt;if (IsPostBack)&lt;br /&gt;{&lt;br /&gt;   // restore array of all users&lt;br /&gt;   allUsers = controller.GenericPageData as ArrayList;&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;      // get an array of all users as UserProfile objects&lt;br /&gt;      controller.Model_GetAllUserInfo(ref allUsers);&lt;br /&gt;&lt;br /&gt;      // save the user data in the controller&lt;br /&gt;      controller.GenericPageData = allUsers as object;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;if (null != allUsers)&lt;br /&gt;{&lt;br /&gt;   // set the array of users as the data source&lt;br /&gt;   dgUsers.AutoGenerateColumns = false;&lt;br /&gt;   dgUsers.DataSource = allUsers;&lt;br /&gt;&lt;br /&gt;   // configure the columns&lt;br /&gt;   ButtonColumn colName = new ButtonColumn();&lt;br /&gt;   colName.DataTextField = "FullName";&lt;br /&gt;   colName.HeaderStyle.BorderStyle = BorderStyle.Outset;&lt;br /&gt;   colName.HeaderStyle.BackColor = Color.Ivory;&lt;br /&gt;   colName.HeaderText = "Full Name";&lt;br /&gt;   colName.CommandName = "View";&lt;br /&gt;&lt;br /&gt;   BoundColumn colLogin = new BoundColumn();&lt;br /&gt;   colLogin.DataField = "LoginName";&lt;br /&gt;   colLogin.HeaderText = "Login Name";&lt;br /&gt;   colLogin.HeaderStyle.BorderStyle = BorderStyle.Outset;&lt;br /&gt;   colLogin.HeaderStyle.BackColor = Color.Ivory;&lt;br /&gt;&lt;br /&gt;   BoundColumn colId = new BoundColumn();&lt;br /&gt;   colId.DataField = "KeyId";&lt;br /&gt;   colId.HeaderText = "Record Id";&lt;br /&gt;   colId.HeaderStyle.BorderStyle = BorderStyle.Outset;&lt;br /&gt;   colId.HeaderStyle.BackColor = Color.Ivory;&lt;br /&gt;&lt;br /&gt;   // add the columns to the datagrid&lt;br /&gt;   dgUsers.Columns.Add(colId);&lt;br /&gt;   dgUsers.Columns.Add(colName);&lt;br /&gt;   dgUsers.Columns.Add(colLogin);&lt;br /&gt;&lt;br /&gt;   dgUsers.EnableViewState = false;&lt;br /&gt;   dgUsers.DataKeyField = colId.DataField;&lt;br /&gt;   dgUsers.DataBind();&lt;br /&gt;&lt;br /&gt;   // set up the click and edit event callbacks&lt;br /&gt;   dgUsers.ItemCommand +=&lt;br /&gt;      new DataGridCommandEventHandler(this.UsersGrid_OnClick);&lt;br /&gt;   return;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3120879123043634081-9189146724591547277?l=forestparklab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://forestparklab.blogspot.com/feeds/9189146724591547277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3120879123043634081&amp;postID=9189146724591547277' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/9189146724591547277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3120879123043634081/posts/default/9189146724591547277'/><link rel='alternate' type='text/html' href='http://forestparklab.blogspot.com/2008/02/fun-with-datagrids.html' title='Fun with DataGrids'/><author><name>Steven</name><uri>http://www.blogger.com/profile/10214789449479308232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
