http://www.infini-tec.de/
InfiniTec - Henning Krauses Blog - Development articles
2011-08-13T13:42:07+00:00
Don't adjust your mind - it's reality that is malfunctioning
Henning Krause
BlogEngine.Net Syndication Generator
http://www.infini-tec.de/opml.axd
Henning Krause
Don't adjust your mind - it's reality that is malfunctioning
en-US
InfiniTec - Henning Krauses Blog
0.000000
0.000000
http://www.infini-tec.de/post/2011/08/15/Windbg-Finding-a-specific-instance-of-a-managed-object-in-a-windows-process.aspx
Windbg: Finding a specific instance of a managed object in a windows process
2011-08-15T10:00:00+00:00
hkrause
<p>Todays post is a small detour from the regular Exchange related posts. The other day I was troubleshooting an issue with a program. It did not behave as expected in production and so I fired up <a href="http://msdn.microsoft.com/en-us/windows/hardware/gg463009">WinDbg</a> to inspect the value of some objects. I attached WindDbg to the process in question and load <a href="http://www.microsoft.com/download/en/details.aspx?id=21255">psscor4</a>, a replacement from Microsoft for the standard SOS extension (Note that if you want to use psscor, you need the right version: <a href="http://www.microsoft.com/download/en/details.aspx?id=1073">Psscor2</a> is for .NET 2.0-3.5 software. Psscor4 is only for .NET 4 programs). The WinDbg results I present in this article are not from the process I actually examined. I hacked together a small sample program instead.</p> <p>The sample class creates instances of a class named Person. A Person class has two properties: A name (string) and an age (int). The object instance I’m looking for is named Mallory. The goal is to get a look at the object instance with a call to !DumpObj. So all I need is the memory address of the Person instance named Alice. This should be easy.</p> <p>So here we go. First, load the SOS extension. Since I ‘m examining an x64 process, I ‘m using the X64 version of psscor.</p> <pre class="brush: ps; auto-links: false;">.load C:\temp\Psscor4\amd64\amd64\psscor4.dll</pre>
<p>The first thing to do is to get an overview about the target class. How many instances of the Person class are currently lying around? A call to <a href="http://msdn.microsoft.com/en-us/library/bb190764.aspx">Dumpheap</a> reveals this:</p>
<pre class="brush: ps; auto-links: false;">0:007> !dumpheap -type Person -stat
Loading the heap objects into our cache.
total 21 objects
Statistics:
MT Count TotalSize Change Class Name
000007ff000242b0 1 40 1 System.Collections.Generic.List`1[[DebugTest.Person, DebugTest]]
000007ff00024220 20 640 20 DebugTest.Person</pre>
<p>So, we have one list of Person objects: List<Person> and 20 instances of the Person class itself. Since there are only 20 of them, let’s just dump them to the console:</p>
<pre class="brush: ps; auto-links: false;">Total 21 objects, Total size: 680
0:007> !dumpheap -type Person
Loading the heap objects into our cache.
Address MT Size
00000000027f2588 000007ff000242b0 40 0 System.Collections.Generic.List`1[[DebugTest.Person, DebugTest]]
00000000027f2588 000007ff000242b0 40
00000000027f25d0 000007ff00024220 32 0 DebugTest.Person
00000000027f25d0 000007ff00024220 32
00000000027f2630 000007ff00024220 32 0 DebugTest.Person
00000000027f2630 000007ff00024220 32
00000000027f2650 000007ff00024220 32 0 DebugTest.Person
00000000027f2650 000007ff00024220 32
00000000027f2670 000007ff00024220 32 0 DebugTest.Person
00000000027f2670 000007ff00024220 32
00000000027f2690 000007ff00024220 32 0 DebugTest.Person
00000000027f2690 000007ff00024220 32
00000000027f2710 000007ff00024220 32 0 DebugTest.Person
00000000027f2710 000007ff00024220 32
00000000027f2730 000007ff00024220 32 0 DebugTest.Person
00000000027f2730 000007ff00024220 32
00000000027f2750 000007ff00024220 32 0 DebugTest.Person
00000000027f2750 000007ff00024220 32
00000000027f2770 000007ff00024220 32 0 DebugTest.Person
00000000027f2770 000007ff00024220 32
00000000027f2830 000007ff00024220 32 0 DebugTest.Person
00000000027f2830 000007ff00024220 32
00000000027f2850 000007ff00024220 32 0 DebugTest.Person
00000000027f2850 000007ff00024220 32
00000000027f2870 000007ff00024220 32 0 DebugTest.Person
00000000027f2870 000007ff00024220 32
00000000027f2890 000007ff00024220 32 0 DebugTest.Person
00000000027f2890 000007ff00024220 32
00000000027f28b0 000007ff00024220 32 0 DebugTest.Person
00000000027f28b0 000007ff00024220 32
00000000027f28d0 000007ff00024220 32 0 DebugTest.Person
00000000027f28d0 000007ff00024220 32
00000000027f28f0 000007ff00024220 32 0 DebugTest.Person
00000000027f28f0 000007ff00024220 32
00000000027f2910 000007ff00024220 32 0 DebugTest.Person
00000000027f2910 000007ff00024220 32
00000000027f2a50 000007ff00024220 32 0 DebugTest.Person
00000000027f2a50 000007ff00024220 32
00000000027f2a70 000007ff00024220 32 0 DebugTest.Person
00000000027f2a70 000007ff00024220 32
00000000027f2a90 000007ff00024220 32 0 DebugTest.Person
00000000027f2a90 000007ff00024220 32 </pre>
So, twenty objects. Let’s have a look at one of the instances. This can be achieved using the !DumpObj command, or !do, in short:
<pre class="brush: ps; auto-links: false;">0:007> !do 00000000027f2830
Name: DebugTest.Person
MethodTable: 000007ff00024220
EEClass: 000007ff00132400
Size: 32(0x20) bytes
File: c:\users\hkrause\documents\visual studio 2010\Projects\DebugTest\DebugTest\bin\Debug\DebugTest.exe
Fields:
MT Field Offset Type VT Attr Value Name
000007fef5786870 4000001 8 System.String 0 instance 00000000027f22e8 <Name>k__BackingField
000007fef578c758 4000002 10 System.Int32 1 instance 25 <Age>k__BackingField</pre>
<p>The interesting lines here are the last two. They describe the details and the values of the properties. Since I used auto-properties instead of traditional ones they are named <Name>k__BackingField instead something like _Name. Since the name if of type System.String, the value is a reference. So, the next step is to issue a !DumpObj on the value of that field:</p>
<pre class="brush: ps; auto-links: false;">0:007> !do 00000000027f22e8
Name: System.String
MethodTable: 000007fef5786870
EEClass: 000007fef530ed58
Size: 38(0x26) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: Bob
Fields:
MT Field Offset Type VT Attr Value Name
000007fef578c758 4000103 8 System.Int32 1 instance 6 m_stringLength
000007fef578b298 4000104 c System.Char 1 instance 57 m_firstChar
000007fef5786870 4000105 10 System.String 0 shared static Empty
>> Domain:Value 00000000003ab570:00000000027e1420 <<</pre>
<p>The nice thing about !DumpObj is that it prints string values directly to the console. In this case, the value is Bob. Ok, so this is not the instance I’m searching for. Hmm, just to check one instance for its name, I have to issue two !DumpObj commands and do a lot of copy-and-paste to copy the addresses from the console to the command line. And in this example, there are only 20 instances. In the process I debugged, there were much more. There must be a better way to do this. A colleague of mine jumped to help and together we indeed came up with one. </p>
<p>The idea is the following:</p>
<ul>
<li>Get a list of the addresses of all Person instances. </li>
<li>For each entry
<ul>
<li>Given the address of the Perons instance, get the value of the <Name>k__BackingField </li>
<li>Print out the address of the Person instance along with the string value of the <Name>k__BackingField. </li>
</ul>
</li>
</ul>
<p>The first step is easy: Just execute this line:</p>
<pre class="brush: ps; auto-links: false;">!DumpHeap -type Person -short</pre>
<p>This command will just dump the addresses of each instance to the console. Iterating through this list is also trivial, thanks to the <a href="http://msdn.microsoft.com/en-us/library/ff563124(v=VS.85).aspx">foreach</a> command:</p>
<pre class="brush: ps; auto-links: false;">.foreach(entry {!dumpheap -type Person -short}){.printf "%p:\n", entry;}</pre>
<p>For each entry in the list returned by the command between the first pair curly braces, the variable entry is populated with the value and the command sequence between the second pair of curly braces is executed. The example above just prints out the value itself.</p>
<p>Now comes the harder part. We need to figure out the value of the backing field for the Name property. A closer inspection of the !DumpObj result above reveals that the field is stored at memory offset 8 inside of the object. To read that memory directly, the <a href="http://msdn.microsoft.com/en-us/library/ff542790(v=VS.85).aspx">dq</a> command can be used (dq because I’m debugging a 64bit process. Use dd for a 32bit process). Dq prints the memory at the specified address in the form of 64bit hex values to the screen. Since we are only interested in the 64-bit pointer at offset 8 of that object, we issue this command:</p>
<pre class="brush: ps; auto-links: false;">0:007> dq 00000000027f2830+8 L1
00000000`027f2838 00000000`027f22e8</pre>
<p>The 00000000027f2830+8 specifies the memory address we are interested in. And the L1 specifies that we only want one quad-word. You can see that the result from the dq operation equals the vlaue of the backing field: 00000000027f22e8. We now need a way to dereference that memory address and print the value of the string at that point. At this point it’s good to know how .NET strings are stored in memory: A length indicator (32bit) followed by an unicode-char-array. The result of the DumpObj command on the string instance “Bob” above reveled that the character array starts at offset 0x0c within the string instance. To print the value of the string, the dq command cannot be used because we are interested in the string value itself. For this, the du command can be used. du means: Dump unicode string. To dereference the pointer provided by the dq command, the poi operator can be used. All combined, this resolves to this command:</p>
<pre class="brush: ps; auto-links: false;">0:007> du poi(00000000027f2830+8)+c
00000000`027f22f4 "Walter"</pre>
<p>Nice, exactly what we wanted. Now we can combine this with the foreach command above:</p>
<pre class="brush: ps; auto-links: false;">0:007> .foreach(entry {!dumpheap -type Person -short}){.printf "%p: ", entry; du poi(${entry}+8)+c;.printf "\n"}
00000000027f2588: 00000000`027f293c ""
00000000027f2588: 00000000`027f293c ""
00000000027f25d0: 00000000`027f219c "Alice"
00000000027f25d0: 00000000`027f219c "Alice"
00000000027f2630: 00000000`027f21c4 "Bob"
00000000027f2630: 00000000`027f21c4 "Bob"
00000000027f2650: 00000000`027f21e4 "Carol"
00000000027f2650: 00000000`027f21e4 "Carol"
00000000027f2670: 00000000`027f220c "Chuck"
00000000027f2670: 00000000`027f220c "Chuck"
00000000027f2690: 00000000`027f2234 "Dave"
00000000027f2690: 00000000`027f2234 "Dave"
00000000027f2710: 00000000`027f225c "Eve"
00000000027f2710: 00000000`027f225c "Eve"
00000000027f2730: 00000000`027f227c "Mallory"
00000000027f2730: 00000000`027f227c "Mallory"
00000000027f2750: 00000000`027f22a4 "Peggy"
00000000027f2750: 00000000`027f22a4 "Peggy"
00000000027f2770: 00000000`027f22cc "Victor"
00000000027f2770: 00000000`027f22cc "Victor"
00000000027f2830: 00000000`027f22f4 "Walter"
00000000027f2830: 00000000`027f22f4 "Walter"
00000000027f2850: 00000000`027f231c "Trent"
00000000027f2850: 00000000`027f231c "Trent"
00000000027f2870: 00000000`027f2344 "Charlie"
00000000027f2870: 00000000`027f2344 "Charlie"
00000000027f2890: 00000000`027f236c "Carlos"
00000000027f2890: 00000000`027f236c "Carlos"
00000000027f28b0: 00000000`027f2394 "Arthur"
00000000027f28b0: 00000000`027f2394 "Arthur"
00000000027f28d0: 00000000`027f23bc "Merlin"
00000000027f28d0: 00000000`027f23bc "Merlin"
00000000027f28f0: 00000000`027f23e4 "Paul "
00000000027f28f0: 00000000`027f23e4 "Paul "
00000000027f2910: 00000000`027f2234 "Dave"
00000000027f2910: 00000000`027f2234 "Dave"
00000000027f2a50: 00000000`027f240c "Sue"
00000000027f2a50: 00000000`027f240c "Sue"
00000000027f2a70: 00000000`027f242c "John"
00000000027f2a70: 00000000`027f242c "John"
00000000027f2a90: 00000000`027f2454 "George"
00000000027f2a90: 00000000`027f2454 "George"</pre>
<p>Now we can easily spot the instance named Mallory: It’s located at 00000000027f2730 and we can issue a !DumpObj on that address:</p>
<pre class="brush: ps; auto-links: false;">0:007> !do 00000000027f2730
Name: DebugTest.Person
MethodTable: 000007ff00024220
EEClass: 000007ff00132400
Size: 32(0x20) bytes
File: c:\users\hkrause\documents\visual studio 2010\Projects\DebugTest\DebugTest\bin\Debug\DebugTest.exe
Fields:
MT Field Offset Type VT Attr Value Name
000007fef5786870 4000001 8 System.String 0 instance 00000000027f2270 <Name>k__BackingField
000007fef578c758 4000002 10 System.Int32 1 instance 34 <Age>k__BackingField</pre>
<p>Case closed <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://www.infinitec.de/image.axd?picture=wlEmoticon-smile.png" />.</p>
2011-08-15T10:00:00+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=23e87f3d-3cbf-477c-b367-ff28ebda0d3b
10
http://www.infini-tec.de/trackback.axd?id=23e87f3d-3cbf-477c-b367-ff28ebda0d3b
http://www.infini-tec.de/post/2011/08/15/Windbg-Finding-a-specific-instance-of-a-managed-object-in-a-windows-process.aspx#comment
http://www.infini-tec.de/syndication.axd?post=23e87f3d-3cbf-477c-b367-ff28ebda0d3b
http://www.infini-tec.de/post/2010/12/13/From-ArgumentException-to-CodeContracts-using-Resharper.aspx
From ArgumentException to CodeContracts using Resharper
2010-12-13T22:04:05+00:00
hkrause
<p><a href="http://www.jetbrains.com/resharper/">Resharper</a> (awesome tool btw) makes it really easy to add sanity checks to your code. Just hit Alt+Enter on a method parameter and select “Check parameter for null”:</p> <p><a href="http://www.infinitec.de/image.axd?picture=image_1.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.infinitec.de/image.axd?picture=image_thumb_1.png" width="804" height="429" /></a></p> <p> </p> <p>This inserts this code:</p> <pre class="code"><span style="color: blue">public static void </span><span style="color: #008b8b">Test</span>(<span style="color: #00008b">Frob </span>frob)
{
<span style="color: blue">if </span>(frob == <span style="color: blue">null</span>) <span style="color: blue">throw new </span><span style="color: #00008b">ArgumentNullException</span>(<span style="color: #a31515">"frob"</span>);
}</pre>
<p>This is great, but once you have started working with <a href="http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx">Code Contracts</a> (see <a href="http://www.infinitec.de/post/2010/11/18/Using-Code-Contracts-Visual-Studio-and-with-Resharper.aspx">here</a> for a small tutorial on how to setup Code Contracts) you might want to migrate all those null checks to preconditions. Resharper offers a very powerful feature to to just that: Structural search and replace. It even goes so far that it will highlight parts of code and offers a quick-fix to change conventional argument checking into preconditions. All we need to do is to create a pattern which recognizes an old argument-null check and a replacement pattern:</p>
<ol>
<li>From the main menu, select <strong>ReSharper</strong> –> <strong>Tools</strong>–> <strong>Pattern catalog</strong> </li>
<li>Click <strong>Add pattern</strong> </li>
<li>In the search pattern edit box, add this line:
<br /><strong>if ($parameter$ == null) throw new ArgumentNullException($expression$);</strong> </li>
<li>In the Replace pattern edit box, add this line:
<br /><strong>Contract.Requires($parameter$ != null);</strong> </li>
<li>Click <strong>Add Placeholder</strong> and select <strong>Identifier</strong>. Name the placeholder <strong>parameter</strong>. </li>
<li>Click <strong>Add Placeholder</strong> again and select <strong>Expression</strong>. Name the placeholder <strong>expression</strong> and select <strong>System.String</strong> as the expression type. </li>
<li>Ensure that the<strong> Format after replace</strong> and <strong>Shorten references</strong> options are both checked. </li>
<li>Click <strong>Save</strong> to persist the new pattern. </li>
</ol>
<p>Resharper will immediately recognize traditional argument checking code and offer a replacement:</p>
<p><a href="http://www.infinitec.de/image.axd?picture=image_2.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.infinitec.de/image.axd?picture=image_thumb_2.png" width="804" height="424" /></a></p>
<p>After the quickfix has been applied, the method looks like this:</p>
<pre class="code"><span style="color: blue">public static void </span><span style="color: #008b8b">Test</span>(<span style="color: #00008b">Frob </span>frob)
{
<span style="color: #00008b">Contract</span>.<span style="color: #008b8b">Requires</span>(frob != <span style="color: blue">null</span>);
}</pre>
<p>If you have enabled runtime checking (as per my <a href="http://www.infinitec.de/post/2010/11/18/Using-Code-Contracts-Visual-Studio-and-with-Resharper.aspx">last post</a> about this topic), a ContractException will be thrown then the precondition is not met. Obviously, this differs from the previous behavior, which caused this method to throw an ArgumentNullException. But as <a href="http://blogs.msdn.com/b/ericlippert">Eric Lippert</a> states, ArgumentNullExceptions are boneheaded exceptions, and as such should never be cought – they simply shouldn’t happen in production code:</p>
<blockquote>
<p><strong>Boneheaded</strong> exceptions are <em>your own darn fault</em>, you <em>could have prevented them</em> and therefore <em>they are bugs in your code</em>. You should not catch them; doing so is hiding a bug in your code. Rather, you should write your code so that the exception cannot possibly happen in the first place, and therefore does not need to be caught. That argument is null, that typecast is bad, that index is out of range, you're trying to divide by zero – these are all problems that you could have prevented very easily in the first place, so prevent the mess in the first place rather than trying to clean it up.</p>
</blockquote>
<p>(quoted from <a title="http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx" href="http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx">http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx</a>)</p>
2010-12-13T22:04:05+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=a1867536-5e8c-4825-a01f-3370ee95bae3
2
http://www.infini-tec.de/trackback.axd?id=a1867536-5e8c-4825-a01f-3370ee95bae3
http://www.infini-tec.de/post/2010/12/13/From-ArgumentException-to-CodeContracts-using-Resharper.aspx#comment
http://www.infini-tec.de/syndication.axd?post=a1867536-5e8c-4825-a01f-3370ee95bae3
http://www.infini-tec.de/post/2010/12/05/fun-with-NET-4-expressions-e28093-Light-speed-edition.aspx
fun with .NET 4 expressions – Light speed edition
2010-12-05T20:00:00+00:00
hkrause
<p>A few days ago I posted an article about the new .NET Expression features in .NET 4.0 (<a href="http://www.infinitec.de/post/2010/11/24/Fun-with-NET-4-expressions.aspx">Fun with .NET 4 expressions</a>). A few people commented and wrote the this was a pretty expensive way to synchronize data. Of course it was – performance wasn’t a design consideration. I merely followed the two rules of optimization:</p> <ol> <li>Don’t do it. </li> <li>(For experts only!) Don’t do it now. </li> </ol> <p>And since the synchronization process was fast enough, I didn’t care.</p> <p>However, just for the fun of it, I did some performance optimization and it is pretty amazing. The thing which made the original code rather slow was the fact that the same expressions were compiled over and over again. So an obvious improvement was to cache the compiled expressions and reuse them. So I introduced two dictionaries to hold the compiled expressions:</p> <pre class="code"><span style="color: blue">private static readonly </span><span style="color: #00008b">Dictionary</span><<span style="color: #00008b">Type</span>, <span style="color: blue">object</span>> <span style="color: purple">_SetterCache </span>= <span style="color: blue">new </span><span style="color: #00008b">Dictionary</span><<span style="color: #00008b">Type</span>, <span style="color: blue">object</span>>();
<span style="color: blue">private static readonly </span><span style="color: #00008b">Dictionary</span><<span style="color: #00008b">Type</span>, <span style="color: blue">object</span>> <span style="color: purple">_GetterCache </span>= <span style="color: blue">new </span><span style="color: #00008b">Dictionary</span><<span style="color: #00008b">Type</span>, <span style="color: blue">object</span>>();</pre>
<p>You may wonder why the type of the dictionary is Dictionary<Type, object>. The reason for this is that there is no other common base class for the type Func<TSource, TProperty>. The following this method checks the cache and compiles the expression if required:
<br /></p>
<pre class="code"><span style="color: blue">private static </span><span style="color: #00008b">Func</span><<span style="color: #00008b">TTarget</span>, <span style="color: #00008b">TProperty</span>> <span style="color: #008b8b">GetGetterMethod</span><<span style="color: #00008b">TTarget</span>, <span style="color: #00008b">TProperty</span>>(<span style="color: #00008b">Expression</span><<span style="color: #00008b">Func</span><<span style="color: #00008b">TTarget</span>, <span style="color: #00008b">TProperty</span>>> targetSelector)
{
<span style="color: blue">object </span>getterObject;
<span style="color: #00008b">Func</span><<span style="color: #00008b">TTarget</span>, <span style="color: #00008b">TProperty</span>> getterMethod;
<span style="color: blue">var </span>selectorType = targetSelector.<span style="color: purple">Type</span>;
<span style="color: blue">if </span>(!<span style="color: purple">_GetterCache</span>.<span style="color: #008b8b">TryGetValue</span>(selectorType, <span style="color: blue">out </span>getterObject))
{
getterMethod = targetSelector.<span style="color: #008b8b">Compile</span>();
<span style="color: purple">_GetterCache</span>[selectorType] = getterMethod;
}
<span style="color: blue">else
</span>{
getterMethod = (<span style="color: #00008b">Func</span><<span style="color: #00008b">TTarget</span>, <span style="color: #00008b">TProperty</span>>) getterObject;
}
<span style="color: blue">return </span>getterMethod;
}</pre>
<p>I added a similar method to handle the update expression accordingly.</p>
<p>Finally, I hacked together a small test program which used the <a href="http://msdn.microsoft.com/library/system.diagnostics.stopwatch.aspx">Stopwatch</a> class to measure the synchronization speed. The result is quite impressing. Synchronizing an object with two properties 10,000 times yielded these results:</p>
<p>Elapsed for 10000 rounds (Slow): 00:00:08.0471936
<br />Elapsed for 10000 rounds (Fast): 00:00:00.2009293</p>
<p>That is quite an improvement.</p>
<p>I’ve attached the source code to this post, so you can measure yourself.</p>
<h3></h3>
<h2></h2>
<h3>Downloads</h3>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:dfecdc33-945a-41b1-8cf6-08e6af5cba6a" class="wlWriterEditableSmartContent"><p> <a href="http://www.infinitec.de/file.axd?file=Program.cs" target="_blank">Program.cs</a></p></div>
2010-12-05T20:00:00+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=18846f28-3912-4484-ac13-11c99ae182b8
6
http://www.infini-tec.de/trackback.axd?id=18846f28-3912-4484-ac13-11c99ae182b8
http://www.infini-tec.de/post/2010/12/05/fun-with-NET-4-expressions-e28093-Light-speed-edition.aspx#comment
http://www.infini-tec.de/syndication.axd?post=18846f28-3912-4484-ac13-11c99ae182b8
http://www.infini-tec.de/post/2010/11/30/The-case-of-the-hanging-WCF-service.aspx
The case of the hanging WCF service [Updated]
2010-11-30T18:33:00+00:00
hkrause
<p>Recently a co-worker was complaining about a windows service which took ages to start. Because this exact code runs on a large number of servers I suspected the the fault to be on the machine rather than the code. The task manager yielded no interesting information (memory consumption was ok and so was the CPU usage). So I downloaded and installed the <a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx">Windows Debugging tools</a>, configured the <a href="http://www.microsoft.com/whdc/devtools/debugging/debugstart.mspx#a">symbol server</a> and attached the debugger to the process in question. To enable debugging of managed applications, the SOS extension has to be loaded:</p> <p><strong>.loadby sos mscorwks</strong></p> <p>The next step was to look what all the threads are doing:</p> <p><strong>!eestack –ee</strong></p> <p>The !eestack command lists the stacktraces of all running threads and the –ee option restricts the output to managed methods. This makes the trace much more readable. Anyway, most threads where just sitting around doing nothing, but one got my attention:</p> <div class="csharpcode"> <pre><span class="lnum"> 1: </span>Thread 6 </pre>
<pre><span class="lnum"> 2: </span>*** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v2.0.50727_64\System\65f46521e7fca2cd2d216162175f2fd6\System.ni.dll </pre>
<pre><span class="lnum"> 3: </span>*** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v2.0.50727_64\System.ServiceModel\e000a1cd822ffb6f6483426a67622d75\System.ServiceModel.ni.dll </pre>
<pre><span class="lnum"> 4: </span>*** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v2.0.50727_64\Netatwork.Common\73da8de102292417562adaf43872eec6\Netatwork.Common.ni.dll </pre>
<pre><span class="lnum"> 5: </span>*** ERROR: Module load completed but symbols could not be loaded for C:\Windows\assembly\NativeImages_v2.0.50727_64\Netatwork.Common\73da8de102292417562adaf43872eec6\Netatwork.Common.ni.dll </pre>
<pre><span class="lnum"> 6: </span>Child-SP RetAddr Call Site </pre>
<pre><span class="lnum"> 7: </span>0000000001f9e900 000007fef1b64304 System_ni!DomainBoundILStubClass.IL_STUB(UInt32, System.Security.Cryptography.SafeLocalAllocHandle, System.Security.Cryptography.OidGroup)+0x77 </pre>
<pre><span class="lnum"> 8: </span>0000000001f9ea00 000007fef1b2b402 System_ni!System.Security.Cryptography.CAPI.c(UInt32, System.Security.Cryptography.SafeLocalAllocHandle, System.Security.Cryptography.OidGroup)+0x94 </pre>
<pre><span class="lnum"> 9: </span>0000000001f9eac0 000007fef1b2b28c System_ni!System.Security.Cryptography.X509Certificates.X509Utils.FindOidInfo(UInt32, System.String, System.Security.Cryptography.OidGroup)+0x152 </pre>
<pre><span class="lnum"> 10: </span>0000000001f9eba0 000007fef1b282ec System_ni!System.Security.Cryptography.Oid..ctor(System.String, System.Security.Cryptography.OidGroup, Boolean)+0x2c </pre>
<pre><span class="lnum"> 11: </span>0000000001f9ebe0 000007fef1b27f03 System_ni!System.Security.Cryptography.X509Certificates.X509Certificate2.get_PublicKey()+0x8c </pre>
<pre><span class="lnum"> 12: </span>0000000001f9ec40 000007feee6c5425 System_ni!System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()+0xb3 </pre>
<pre><span class="lnum"> 13: </span>0000000001f9eca0 000007feee6c538d System_ServiceModel_ni!System.ServiceModel.Security.SecurityUtils.EnsureCertificateCanDoKeyExchange(System.Security.Cryptography.X509Certificates.X509Certificate2)+0x55 </pre>
<pre><span class="lnum"> 14: </span>0000000001f9ed20 000007feee6c5349 System_ServiceModel_ni!System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateServerX509TokenProvider()+0x2d </pre>
<pre><span class="lnum"> 15: </span>0000000001f9ed60 000007feee6c52e1 System_ServiceModel_ni!System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateLocalSecurityTokenProvider(System.ServiceModel.Security.Tokens.RecipientServiceModelSecurityTokenRequirement)+0x49 </pre>
<pre><span class="lnum"> 16: </span>0000000001f9edc0 000007feef00fcd9 System_ServiceModel_ni!System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateSecurityTokenProvider(System.IdentityModel.Selectors.SecurityTokenRequirement)+0x41 </pre>
<pre><span class="lnum"> 17: </span>0000000001f9ee10 000007feef010a0f System_ServiceModel_ni!(System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateTlsnegoServerX509TokenProvider(System.ServiceModel.Security.Tokens.RecipientServiceModelSecurityTokenRequirement)+0xd9 </pre>
<pre><span class="lnum"> 18: </span>0000000001f9ee60 000007feee6c5811 System_ServiceModel_ni!System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateTlsnegoSecurityTokenAuthenticator(System.ServiceModel.Security.Tokens.RecipientServiceModelSecurityTokenRequirement, Boolean, System.IdentityModel.Selectors.SecurityTokenResolver ByRef)+0x23f </pre>
<pre><span class="lnum"> 19: </span>0000000001f9eee0 000007feef624a7a System_ServiceModel_ni!System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateSecurityTokenAuthenticator(System.IdentityModel.Selectors.SecurityTokenRequirement, System.IdentityModel.Selectors.SecurityTokenResolver ByRef)+0x2a1 </pre>
<pre><span class="lnum"> 20: </span>0000000001f9ef40 000007feee77dc27 System_ServiceModel_ni!System.ServiceModel.Security.SymmetricSecurityProtocolFactory.OnOpen(System.TimeSpan)+0xe9fc7a </pre>
<pre><span class="lnum"> 21: </span>0000000001f9efb0 000007feee6ebe43 System_ServiceModel_ni!System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(System.TimeSpan)+0x17 </pre>
<pre><span class="lnum"> 22: </span>0000000001f9efe0 000007feef18bf45 System_ServiceModel_ni!System.ServiceModel.Channels.CommunicationObject.Open(System.TimeSpan)+0x233 </pre>
<pre><span class="lnum"> 23: </span>0000000001f9f0d0 000007feef1881cb System_ServiceModel_ni!System.ServiceModel.Security.SecurityListenerSettingsLifetimeManager.Open(System.TimeSpan)+0x65 </pre>
<pre><span class="lnum"> 24: </span>0000000001f9f140 000007feee6ebe43 System_ServiceModel_ni!System.ServiceModel.Channels.SecurityChannelListener`1[[System.__Canon, mscorlib]].OnOpen(System.TimeSpan)+0xcb </pre>
<pre><span class="lnum"> 25: </span>0000000001f9f1b0 000007feee727aa7 System_ServiceModel_ni!System.ServiceModel.Channels.CommunicationObject.Open(System.TimeSpan)+0x233 </pre>
<pre><span class="lnum"> 26: </span>0000000001f9f2a0 000007feee6ebe43 System_ServiceModel_ni!System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(System.TimeSpan)+0x57 </pre>
<pre><span class="lnum"> 27: </span>0000000001f9f2f0 000007feee6b936e System_ServiceModel_ni!System.ServiceModel.Channels.CommunicationObject.Open(System.TimeSpan)+0x233 </pre>
<pre><span class="lnum"> 28: </span>0000000001f9f3e0 000007feee6ebe43 System_ServiceModel_ni!System.ServiceModel.ServiceHostBase.OnOpen(System.TimeSpan)+0x6e </pre>
<pre><span class="lnum"> 29: </span>0000000001f9f450 000007fef09bec81 System_ServiceModel_ni!System.ServiceModel.Channels.CommunicationObject.Open(System.TimeSpan)+0x233 </pre>
<pre><span class="lnum"> 30: </span>… </pre>
</div>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>For administrative reasons, this server exposes a number of encrypted WCF endpoints. During startup the WCF runtime examines the certificate and checks whether it is valid. During this operation, it tries to access the private key and calls the Win32 native function <a href="http://msdn.microsoft.com/en-us/library/aa379938(VS.85).aspx">CryptFindOidInfo</a>. As it turns out, this function may contact a domain controller to fetch certain information. This “feature” can be disabled by passing the CRYPT_OID_DISABLE_SEARCH_DS_FLAG to the function, but the .NET framework doesn’t do this. Apparently, the function had difficulties contacting its domain controller. A common cause for this is an incorrect DNS configuration, so I checked this first. As it turned out, the DNS configuration was quite complicated and a conditional forwarder for the domain the machine was on was missing. Once this was fixed, the startup speed of the service was back to normal.</p>
<h3>Update</h3>
<p>Alex from <a href="http://blogs.msdn.com/b/alejacma">Decrypt my World</a> has an article related to this problem and offers a different solution: <a title="http://blogs.msdn.com/b/alejacma/archive/2010/12/20/big-delay-while-calling-envelopedcms-constructor.aspx" href="http://blogs.msdn.com/b/alejacma/archive/2010/12/20/big-delay-while-calling-envelopedcms-constructor.aspx">http://blogs.msdn.com/b/alejacma/archive/2010/12/20/big-delay-while-calling-envelopedcms-constructor.aspx</a></p>
2010-11-30T18:33:00+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=0c0d7e3f-1acd-419e-9c61-2d00bd5bb86e
1
http://www.infini-tec.de/trackback.axd?id=0c0d7e3f-1acd-419e-9c61-2d00bd5bb86e
http://www.infini-tec.de/post/2010/11/30/The-case-of-the-hanging-WCF-service.aspx#comment
http://www.infini-tec.de/syndication.axd?post=0c0d7e3f-1acd-419e-9c61-2d00bd5bb86e
http://www.infini-tec.de/post/2010/11/24/Fun-with-NET-4-expressions.aspx
Fun with .NET 4 expressions
2010-11-24T15:52:49+00:00
hkrause
<p>The other day I was tasked to write some code to synchronize data between two data stores. The entities were similar but not exactly the same. And I didn’t just want to synchronize all entries every time, but only if the source entity was different than the target entity. To simplify the comparison of each property, I wrote a small function which compared the values of one property of the source entity with the matching property on the target entity and updated it if it was different.</p> <p>Let’s assume we have a simple entity class like this one:</p> <pre class="code"><span style="color: blue">class </span><span style="color: #00008b">Contact
</span>{
<span style="color: blue">public string </span><span style="color: purple">Name </span>{ <span style="color: #008b8b">get</span>; <span style="color: #008b8b">set</span>; }
<span style="color: blue">public int </span><span style="color: purple">Age </span>{ <span style="color: #008b8b">get</span>; <span style="color: #008b8b">set</span>; }
}</pre>
<p>The method I write allows me to write this code to update a target entry with just a few lines of code:</p>
<pre class="code"><span style="color: blue">var </span>source = <span style="color: blue">new </span><span style="color: #00008b">Contact </span>{<span style="color: purple">Name </span>= <span style="color: #a31515">"Alice"</span>, <span style="color: purple">Age </span>= 42};
<span style="color: blue">var </span>target = <span style="color: blue">new </span><span style="color: #00008b">Contact</span>();
<span style="color: blue">if </span>(<span style="color: #008b8b">UpdatePropertyIfChanged</span>(source, target, contact => contact.<span style="color: purple">Name</span>, contact => contact.<span style="color: purple">Name</span>) |
<span style="color: #008b8b">UpdatePropertyIfChanged</span>(source, target, contact => contact.<span style="color: purple">Age</span>, contact => contact.<span style="color: purple">Age</span>))
{
<span style="color: #00008b">Console</span>.<span style="color: purple">Out</span>.<span style="color: #008b8b">WriteLine</span>(<span style="color: #a31515">"Contact updated."</span>);
<span style="color: #00008b">Console</span>.<span style="color: purple">Out</span>.<span style="color: #008b8b">WriteLine</span>(<span style="color: #a31515">"target.Name = {0}"</span>, target.<span style="color: purple">Name</span>);
<span style="color: #00008b">Console</span>.<span style="color: purple">Out</span>.<span style="color: #008b8b">WriteLine</span>(<span style="color: #a31515">"target.Age = {0}"</span>, target.<span style="color: purple">Age</span>);
}</pre>
<p>The important method is the <strong>UpdatePropertyIfChanged</strong> method. It takes two entities, the source and the target instance. The third parameter is a lambda method which selects the property on the source instance and the last parameter selects the destination property on the target instance. To ensure that every property is checked, I used a logical or instead of a conditional or to ensure that every property is checked. If I had used the conditional or operator instead and the first property was different on both objects, the second property would not have been checked and updated.</p>
<p>Here is the body of the UpdatePropertyIfChanged method:</p>
<pre class="code"><span style="color: blue">private static bool </span><span style="color: #008b8b">UpdatePropertyIfChanged</span><<span style="color: #00008b">TSource</span>, <span style="color: #00008b">TProperty</span>, <span style="color: #00008b">TTarget</span>>(<span style="color: #00008b">TSource </span>source, <span style="color: #00008b">TTarget </span>target, <span style="color: #00008b">Func</span><<span style="color: #00008b">TSource</span>, <span style="color: #00008b">TProperty</span>> sourceSelector, <span style="color: #00008b">Expression</span><<span style="color: #00008b">Func</span><<span style="color: #00008b">TTarget</span>, <span style="color: #00008b">TProperty</span>>> targetSelector)
{
<span style="color: blue">var </span>valueA = sourceSelector(source);
<span style="color: blue">var </span>valueB = targetSelector.<span style="color: #008b8b">Compile</span>()(target);
<span style="color: blue">if </span>(<span style="color: #00008b">EqualityComparer</span><<span style="color: #00008b">TProperty</span>>.<span style="color: purple">Default</span>.<span style="color: #008b8b">Equals</span>(valueA, valueB)) <span style="color: blue">return false</span>;
<span style="color: blue">var </span>setterMethod = <span style="color: #008b8b">CreateSetter</span>(targetSelector);
setterMethod(target, valueA);
<span style="color: blue">return true</span>;
}</pre>
<p>It’s pretty straigtforward, except for one details: Instead of a <strong>Func<TSource, TProperty></strong> like the <strong>sourceSelector</strong>, the <strong>targetSelector</strong> is of type <strong>Expression<Func<TTarget, TProperty>></strong>. The main difference is that an expression of type Func is already compiled and ready to be executed. In contrast, an expression of type Expression<Func> can be examined and manipulated at runtime.</p>
<p>The method executes these steps:</p>
<ol>
<li>Read the value of the property from the source entity by execute the <strong>sourceSelector</strong> expression </li>
<li>Read the value of the property from the target entity by compiling and executing the <strong>targetSelector</strong> expression </li>
<li>Compare the two values using the <a href="http://msdn.microsoft.com/library/ms224763.aspx">EqualityComparer<T>.Default</a> comparer. </li>
<li>If the two values are equal, just return false and abort the method. </li>
<li>Convert the expression from the <strong>targetSelector</strong> expression to a setter expression </li>
<li>Call the newly created expression with the value from the <strong>sourceSelector</strong> expression. </li>
</ol>
<p>The ability to compile your own lambda expression has been introduced with .NET 3.5. But they were limited to reading properties and field. This feature has been improved with .NET 4.</p>
<p>Here is the body of the CreateSetter method:</p>
<pre class="code"><span style="color: blue">private static </span><span style="color: #00008b">Action</span><<span style="color: #00008b">TInstance</span>, <span style="color: #00008b">TProperty</span>> <span style="color: #008b8b">CreateSetter</span><<span style="color: #00008b">TInstance</span>, <span style="color: #00008b">TProperty</span>>(<span style="color: #00008b">Expression</span><<span style="color: #00008b">Func</span><<span style="color: #00008b">TInstance</span>, <span style="color: #00008b">TProperty</span>>> getterMethod)
{
<span style="color: blue">var </span>memberExpression = getterMethod.<span style="color: purple">Body </span><span style="color: blue">as </span><span style="color: #00008b">MemberExpression</span>;
<span style="color: blue">if </span>(memberExpression == <span style="color: blue">null</span>) <span style="color: blue">throw new </span><span style="color: #00008b">InvalidOperationException</span>(<span style="color: #a31515">"GetterMethod must be a memberexpression"</span>);
<span style="color: blue">var </span>instance = <span style="color: #00008b">Expression</span>.<span style="color: #008b8b">Parameter</span>(<span style="color: blue">typeof</span>(<span style="color: #00008b">TInstance</span>));
<span style="color: blue">var </span>parameter = <span style="color: #00008b">Expression</span>.<span style="color: #008b8b">Parameter</span>(<span style="color: blue">typeof</span>(<span style="color: #00008b">TProperty</span>));
<span style="color: blue">var </span>expression =
<span style="color: #00008b">Expression</span>.<span style="color: #008b8b">Lambda</span><<span style="color: #00008b">Action</span><<span style="color: #00008b">TInstance</span>, <span style="color: #00008b">TProperty</span>>>(
<span style="color: #00008b">Expression</span>.<span style="color: #008b8b">Assign</span>(
<span style="color: #00008b">Expression</span>.<span style="color: #008b8b">MakeMemberAccess</span>(instance, memberExpression.<span style="color: purple">Member</span>), parameter), <span style="color: blue">new</span>[] { instance, parameter });
<span style="color: blue">return </span>expression.<span style="color: #008b8b">Compile</span>();
}</pre>
This method expects an expression which maps an instance to a property of that instance. Based on this expression, a new expression is created, which sets that property to a specified value. The method returns this new expression in the form of an Action<TInstance, TProperty>.
2010-11-24T15:52:49+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=7d7d05a4-eb1c-4a33-b15b-a39dcc1f8019
7
http://www.infini-tec.de/trackback.axd?id=7d7d05a4-eb1c-4a33-b15b-a39dcc1f8019
http://www.infini-tec.de/post/2010/11/24/Fun-with-NET-4-expressions.aspx#comment
http://www.infini-tec.de/syndication.axd?post=7d7d05a4-eb1c-4a33-b15b-a39dcc1f8019
http://www.infini-tec.de/post/2010/11/22/Setting-the-PIN-of-a-smartcard-programmatically.aspx
Setting the PIN of a smartcard programmatically
2010-11-22T15:17:25+00:00
hkrause
<p>There are certain scenarios where it’s not feasible to require user interaction when accessing the private key of a smartcard. For example, a service does have the ability to provide a user interface. To use a key from a smartcard where a PIN is required, it must be provided to the smartcard using an alternative way. For some operations in .NET, one can use the <a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.cspparameters.aspx">CspParameters</a> class to provide the PIN. But not all APIs which require smartcard access provide a way to use that class. The SSLStream is such a case. Here is a small extension method which sets the PIN for an X509Certificate2 instance:</p> <pre class="code"><span style="color: blue">static class </span><span style="color: #00008b">X509Certificate2Extension
</span>{
<span style="color: blue">public static void </span><span style="color: #008b8b">SetPinForPrivateKey</span>(<span style="color: blue">this </span><span style="color: #00008b">X509Certificate2 </span>certificate, <span style="color: blue">string </span>pin)
{
<span style="color: blue">if </span>(certificate == <span style="color: blue">null</span>) <span style="color: blue">throw new </span><span style="color: #00008b">ArgumentNullException</span>(<span style="color: #a31515">"certificate"</span>);
<span style="color: blue">var </span>key = (<span style="color: #00008b">RSACryptoServiceProvider</span>)certificate.<span style="color: purple">PrivateKey</span>;
<span style="color: blue">var </span>providerHandle = <span style="color: #00008b">IntPtr</span>.<span style="color: purple">Zero</span>;
<span style="color: blue">var </span>pinBuffer = <span style="color: #00008b">Encoding</span>.<span style="color: purple">ASCII</span>.<span style="color: #008b8b">GetBytes</span>(pin);
<span style="color: green">// provider handle is implicitly released when the certificate handle is released.
</span><span style="color: #00008b">SafeNativeMethods</span>.<span style="color: #008b8b">Execute</span>(() => <span style="color: #00008b">SafeNativeMethods</span>.<span style="color: #008b8b">CryptAcquireContext</span>(<span style="color: blue">ref </span>providerHandle, <br /> key.<span style="color: purple">CspKeyContainerInfo</span>.<span style="color: purple">KeyContainerName</span>, <br /> key.<span style="color: purple">CspKeyContainerInfo</span>.<span style="color: purple">ProviderName</span>,<br /> key.<span style="color: purple">CspKeyContainerInfo</span>.<span style="color: purple">ProviderType</span>, <br /> <span style="color: #00008b">SafeNativeMethods</span>.<span style="color: #00008b">CryptContextFlags</span>.<span style="color: purple">Silent</span>));
<span style="color: #00008b">SafeNativeMethods</span>.<span style="color: #008b8b">Execute</span>(() => <span style="color: #00008b">SafeNativeMethods</span>.<span style="color: #008b8b">CryptSetProvParam</span>(providerHandle, <br /> <span style="color: #00008b">SafeNativeMethods</span>.<span style="color: #00008b">CryptParameter</span>.<span style="color: purple">KeyExchangePin</span>, <br /> pinBuffer, 0));
<span style="color: #00008b">SafeNativeMethods</span>.<span style="color: #008b8b">Execute</span>(() => <span style="color: #00008b">SafeNativeMethods</span>.<span style="color: #008b8b">CertSetCertificateContextProperty</span>(<br /> certificate.<span style="color: purple">Handle</span>, <br /> <span style="color: #00008b">SafeNativeMethods</span>.<span style="color: #00008b">CertificateProperty</span>.<span style="color: purple">CryptoProviderHandle</span>, <br /> 0, providerHandle));
}
}
<span style="color: blue">internal static class </span><span style="color: #00008b">SafeNativeMethods
</span>{
<span style="color: blue">internal enum </span><span style="color: #00008b">CryptContextFlags
</span>{
<span style="color: purple">None </span>= 0,
<span style="color: purple">Silent </span>= 0x40
}
<span style="color: blue">internal enum </span><span style="color: #00008b">CertificateProperty
</span>{
<span style="color: purple">None </span>= 0,
<span style="color: purple">CryptoProviderHandle </span>= 0x1
}
<span style="color: blue">internal enum </span><span style="color: #00008b">CryptParameter
</span>{
<span style="color: purple">None </span>= 0,
<span style="color: purple">KeyExchangePin </span>= 0x20
}
[<span style="color: #00008b">DllImport</span>(<span style="color: #a31515">"advapi32.dll"</span>, <span style="color: purple">CharSet </span>= <span style="color: #00008b">CharSet</span>.<span style="color: purple">Auto</span>, <span style="color: purple">SetLastError </span>= <span style="color: blue">true</span>)]
<span style="color: blue">public static extern bool </span><span style="color: #008b8b">CryptAcquireContext</span>(
<span style="color: blue">ref </span><span style="color: #00008b">IntPtr </span>hProv,
<span style="color: blue">string </span>containerName,
<span style="color: blue">string </span>providerName,
<span style="color: blue">int </span>providerType,
<span style="color: #00008b">CryptContextFlags </span>flags
);
[<span style="color: #00008b">DllImport</span>(<span style="color: #a31515">"advapi32.dll"</span>, <span style="color: purple">SetLastError </span>= <span style="color: blue">true</span>, <span style="color: purple">CharSet </span>= <span style="color: #00008b">CharSet</span>.<span style="color: purple">Auto</span>)]
<span style="color: blue">public static extern bool </span><span style="color: #008b8b">CryptSetProvParam</span>(
<span style="color: #00008b">IntPtr </span>hProv,
<span style="color: #00008b">CryptParameter </span>dwParam,
[<span style="color: #00008b">In</span>] <span style="color: blue">byte</span>[] pbData,
<span style="color: blue">uint </span>dwFlags);
[<span style="color: #00008b">DllImport</span>(<span style="color: #a31515">"CRYPT32.DLL"</span>, <span style="color: purple">SetLastError </span>= <span style="color: blue">true</span>)]
<span style="color: blue">internal static extern bool </span><span style="color: #008b8b">CertSetCertificateContextProperty</span>(
<span style="color: #00008b">IntPtr </span>pCertContext,
<span style="color: #00008b">CertificateProperty </span>propertyId,
<span style="color: blue">uint </span>dwFlags,
<span style="color: #00008b">IntPtr </span>pvData
);
<span style="color: blue">public static void </span><span style="color: #008b8b">Execute</span>(<span style="color: #00008b">Func</span><<span style="color: blue">bool</span>> action)
{
<span style="color: blue">if </span>(!action())
{
<span style="color: blue">throw new </span><span style="color: #00008b">Win32Exception</span>(<span style="color: #00008b">Marshal</span>.<span style="color: #008b8b">GetLastWin32Error</span>());
}
}
}</pre>
<p>The interesting piece here is, of course, the SetPinForPrivateKey method. It acquires a Win32 cryptographic context, sets the PIN and associates that pin with the certificate. Once you have an X509Certificate2 instance, you can set the PIN with just one line of code:</p>
<pre class="code"><span style="color: blue">var </span>certificate = <span style="color: #008b8b">GetCertificate</span>();
certificate.<span style="color: #008b8b">SetPinForPrivateKey</span>(<span style="color: #a31515">"123456"</span>);</pre>
<p>The PIN is remembered until the X509Certificate2 instance is open.</p>
<h3>Credits</h3>
<p>This solution is taken from an <a href="http://stackoverflow.com/questions/1234938/ssl-with-private-key-on-an-hsm/3786832#3786832">stackoverflow</a> article. I’ve just made an extension method out of it, converted all those magic numbers to enums and added a little bit of error handling.</p>
2010-11-22T15:17:25+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=7f14bceb-bd4b-4333-bf77-439504cd8394
8
http://www.infini-tec.de/trackback.axd?id=7f14bceb-bd4b-4333-bf77-439504cd8394
http://www.infini-tec.de/post/2010/11/22/Setting-the-PIN-of-a-smartcard-programmatically.aspx#comment
http://www.infini-tec.de/syndication.axd?post=7f14bceb-bd4b-4333-bf77-439504cd8394
http://www.infini-tec.de/post/2010/11/18/Using-Code-Contracts-Visual-Studio-and-with-Resharper.aspx
Using Code Contracts Visual Studio and with Resharper
2010-11-18T16:07:44+00:00
hkrause
<p>CodeContracts are a new feature to write assumptions in .NET programs. A version for .NET 3.5 is available from the <a href="http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx">Microsoft Code Contracts</a>. With .NET 4 they are part of the BCL. Unfortunately, they do nothing out of the box – a binary rewriter is required to enable runtime checking. The rewriter is also available from the Microsoft site specified above.</p> <h3>Enabling Code Contracts</h3> <p>Once the Code Contracts are installed on a machine, they must be enabled in each Visual Studio project by specifying the CONTRACTS_FULL conditional compilation symbol in the properties of a project:</p> <p><a href="http://www.infinitec.de/image.axd?picture=Windows-Live-Writer/Using-CodeContracts-with-Resharper/05970F39/ConditionalSymbol.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="ConditionalSymbol" border="0" alt="ConditionalSymbol" src="http://www.infinitec.de/image.axd?picture=Windows-Live-Writer/Using-CodeContracts-with-Resharper/58A1AC5D/ConditionalSymbol_thumb.png" width="644" height="385" /></a></p> <p>Next, enable the runtime checking on the Code Analysis tab:</p> <p><a href="http://www.infinitec.de/image.axd?picture=Windows-Live-Writer/Using-CodeContracts-with-Resharper/69A5DA40/EnableRuntimeChecking.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="EnableRuntimeChecking" border="0" alt="EnableRuntimeChecking" src="http://www.infinitec.de/image.axd?picture=Windows-Live-Writer/Using-CodeContracts-with-Resharper/07A3E835/EnableRuntimeChecking_thumb.png" width="644" height="385" /></a></p> <p>Now you can use the Code Contracts within the project. Here is a small sample application:</p> <pre class="code"><span style="color: blue">using </span><span style="color: #00008b">System</span>;
<span style="color: blue">using </span><span style="color: #00008b">System</span>.<span style="color: #00008b">Diagnostics</span>.<span style="color: #00008b">Contracts</span>;
<span style="color: blue">namespace </span><span style="color: #00008b">SampleApplication
</span>{
<span style="color: blue">internal class </span><span style="color: #00008b">Program
</span>{
<span style="color: blue">public static int </span><span style="color: #008b8b">Divide</span>(<span style="color: blue">int </span>a, <span style="color: blue">int </span>b)
{
<span style="color: #00008b">Contract</span>.<span style="color: #008b8b">Requires</span>(b != 0);
<span style="color: #00008b">Contract</span>.<span style="color: #008b8b">Ensures</span>(a != 0 ? <span style="color: #00008b">Contract</span>.<span style="color: #008b8b">Result</span><<span style="color: blue">int</span>>() != 0 : <span style="color: #00008b">Contract</span>.<span style="color: #008b8b">Result</span><<span style="color: blue">int</span>>() == 0);
<span style="color: blue">return </span>a/b;
}
<span style="color: blue">private static void </span><span style="color: #008b8b">Main</span>()
{
<span style="color: #00008b">Console</span>.<span style="color: purple">Out</span>.<span style="color: #008b8b">WriteLine</span>(<span style="color: #a31515">"Divide(4, 2) = {0}"</span>, <span style="color: #008b8b">Divide</span>(2, 2));
<span style="color: #00008b">Console</span>.<span style="color: purple">Out</span>.<span style="color: #008b8b">WriteLine</span>(<span style="color: #a31515">"Divide(4, 0) = {0}"</span>, <span style="color: #008b8b">Divide</span>(4, 0));
}
}
}</pre>
<p>It’s just a small division method which has one pre- and one post-condition: The method requires b not to be 0. The post-condition specifies that the result of the method is 0 if a is 0 and not 0 when a is not 0. Very simple. If you run the program, it will throw an exception on the second execution of the Divide method, because b is 0 in this case:</p>
<p><a href="http://www.infinitec.de/image.axd?picture=Windows-Live-Writer/Using-CodeContracts-with-Resharper/788D095A/Precondition-faileed.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Precondition faileed" border="0" alt="Precondition faileed" src="http://www.infinitec.de/image.axd?picture=Windows-Live-Writer/Using-CodeContracts-with-Resharper/2D2D6596/Precondition-faileed_thumb.png" width="798" height="483" /></a></p>
<h3>Integration with Resharper</h3>
<p>If you are using <a href="http://www.jetbrains.com/resharper/">Resharper</a>, you are accustomed to the null-reference checking the tool performs as you type. This is quite handy to spot null-references during design-time vs. run-time. </p>
<p>Here is another method which is annotated with code contracts:</p>
<p> </p>
<a href="http://www.infinitec.de/image.axd?picture=Windows-Live-Writer/Using-CodeContracts-with-Resharper/73AA559E/NullReference.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="NullReference" border="0" alt="NullReference" src="http://www.infinitec.de/image.axd?picture=Windows-Live-Writer/Using-CodeContracts-with-Resharper/33743C24/NullReference_thumb.png" width="488" height="344" /></a>
<p>Notice the squiggles under the name variable and the hint to a System.NullReferenceException. If you would replace the first line of the method with a </p>
<pre class="code"><span style="color: blue">if </span>(<span style="color: blue">string</span>.<span style="color: #008b8b">IsNullOrEmpty</span>(name)) <span style="color: blue">throw new </span><span style="color: #00008b">ArgumentNullException</span>(<span style="color: #a31515">"name"</span>);</pre>
<p>the warning would be gone, because Resharper would sense that the code path with the if-statement is never executed if name is null.</p>
<p>To enabled this feature with Code Contracts, a file with certain annotations must be placed in the directory <strong>C:\Program Files\JetBrains\ReSharper\v5.1\Bin\ExternalAnnotations\mscorlib</strong> (<strong>C:\Program Files (x86)\JetBrains\ReSharper\v5.1\Bin\ExternalAnnotations\mscorlib</strong> on x64 systems). The file is attached at the end of this post. </p>
<h3></h3>
<h3>Visual Studio Editor Code Contracts extension</h3>
<p>A Visual Studio extension is available from the Code Contracts team. It can be downloaded via the Extension Manager. It visualizes code contracts directly in the editor.</p>
<p><a href="http://www.infinitec.de/image.axd?picture=Windows-Live-Writer/Using-CodeContracts-with-Resharper/0C39F2EF/image.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.infinitec.de/image.axd?picture=Windows-Live-Writer/Using-CodeContracts-with-Resharper/37125701/image_thumb.png" width="640" height="323" /></a></p>
<h3>Credits</h3>
<p>The Microsoft.CodeContracts.xml is taken from a Youtrack issue <a title="http://youtrack.jetbrains.net/issue/RSRP-190566" href="http://youtrack.jetbrains.net/issue/RSRP-190566">http://youtrack.jetbrains.net/issue/RSRP-190566</a>. I’ve modified the file to work with .NET 4.0.</p>
<h3>Downloads</h3>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:0feeb39f-011f-4336-b44a-f6acca92d5d0" class="wlWriterEditableSmartContent"><p> <a href="http://www.infinitec.de/file.axd?file=Windows-Live-Writer/Using-CodeContracts-with-Resharper/52B6E2F7/Microsoft.Contracts.xml" target="_blank">Microsoft.Contracts.xml</a></p></div>
2010-11-18T16:07:44+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=77f16be7-fbde-40c6-ba20-0c00bf703cb6
4
http://www.infini-tec.de/trackback.axd?id=77f16be7-fbde-40c6-ba20-0c00bf703cb6
http://www.infini-tec.de/post/2010/11/18/Using-Code-Contracts-Visual-Studio-and-with-Resharper.aspx#comment
http://www.infini-tec.de/syndication.axd?post=77f16be7-fbde-40c6-ba20-0c00bf703cb6
http://www.infini-tec.de/post/2009/10/21/Workflow-Foundation-Part-III-Participating-in-persistence.aspx
Workflow Foundation Part III: Participating in persistence
2009-10-21T19:39:47+00:00
hkrause
<p>This is the third post about the Workflow Foundation 4. The first two posts can be found <a href="http://www.infinitec.de/post/2009/10/19/Persistence-in-Workflow-Foundation-4.aspx">here</a> and <a href="http://www.infinitec.de/post/2009/10/20/Workflow-Foundation-4-e28093-Part-II-NativeActivities-and-Extensions.aspx">here</a>.</p> <p>In the second article I introduced the IncrementExtension which asynchronously increments an integer value and waits one second each time it is called. The activity used bookmarks to stop and resume the workflow while it is running. The problem is this: When the application is forcefully stopped and restarted, the index will start again at zero. This is a shame, since the workflow instance is already persisted to the database between each call.</p> <p>Enter <strong>PersistenceParticipant</strong>. This is a base class for extension that which to persist data to the instance store configured for a workflow application. The <strong>PersistenceParticipant</strong> class has three virtual methods that enable the persistence functionality. Here is the IncrementExtension from the last post extended with the persistence features:</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">using</span> System;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> <span style="color: #0000ff">using</span> System.Activities;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">using</span> System.Activities.Hosting;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> <span style="color: #0000ff">using</span> System.Activities.Persistence;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #0000ff">using</span> System.Collections.Generic;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> <span style="color: #0000ff">using</span> System.Threading;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> <span style="color: #0000ff">using</span> System.Xml.Linq;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> <span style="color: #0000ff">namespace</span> WorkflowConsoleApplication1</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> <span style="color: #0000ff">class</span> IncrementExtension : PersistenceParticipant, IWorkflowInstanceExtension</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> XName PersistencePropertyName = XNamespace.Get(<span style="color: #006080">"urn:example.com:WorkflowDemo/1.0/Increment"</span>).GetName(<span style="color: #006080">"LastValue"</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> <span style="color: #0000ff">int</span> _Index;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span> <span style="color: #0000ff">private</span> WorkflowInstance _Instance;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> Bookmark _Bookmark;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Increment(Bookmark bookmark)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21"> 21:</span> ThreadPool.QueueUserWorkItem(state =></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22"> 22:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23"> 23:</span> Thread.Sleep(1000);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24"> 24:</span> var <span style="color: #0000ff">value</span> = Interlocked.Increment(<span style="color: #0000ff">ref</span> _Index);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25"> 25:</span> _Bookmark = bookmark;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26"> 26:</span> ContinueWorkflow(<span style="color: #0000ff">value</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27"> 27:</span> }, <span style="color: #0000ff">null</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28"> 28:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29"> 29:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30"> 30:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> ContinueWorkflow(<span style="color: #0000ff">int</span> <span style="color: #0000ff">value</span>)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31"> 31:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32"> 32:</span> _Instance.BeginResumeBookmark(_Bookmark, <span style="color: #0000ff">value</span>, CompleteResume, <span style="color: #0000ff">null</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33"> 33:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34"> 34:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35"> 35:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> CompleteResume(IAsyncResult ar)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36"> 36:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37"> 37:</span> var result = _Instance.EndResumeBookmark(ar);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38"> 38:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39"> 39:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40"> 40:</span> IEnumerable<<span style="color: #0000ff">object</span>> IWorkflowInstanceExtension.GetAdditionalExtensions()</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum41"> 41:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum42"> 42:</span> <span style="color: #0000ff">yield</span> <span style="color: #0000ff">break</span>;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum43"> 43:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum44"> 44:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum45"> 45:</span> <span style="color: #0000ff">void</span> IWorkflowInstanceExtension.SetInstance(WorkflowInstance instance)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum46"> 46:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum47"> 47:</span> _Instance = instance;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum48"> 48:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum49"> 49:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum50"> 50:</span> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> CollectValues(<span style="color: #0000ff">out</span> IDictionary<XName, <span style="color: #0000ff">object</span>> readWriteValues, <span style="color: #0000ff">out</span> IDictionary<XName, <span style="color: #0000ff">object</span>> writeOnlyValues)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum51"> 51:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum52"> 52:</span> readWriteValues = <span style="color: #0000ff">new</span> Dictionary<XName, <span style="color: #0000ff">object</span>> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum53"> 53:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum54"> 54:</span> {PersistencePropertyName, <span style="color: #0000ff">new</span> KeyValuePair<Bookmark, <span style="color: #0000ff">int</span>>(_Bookmark, _Index)}</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum55"> 55:</span> };</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum56"> 56:</span> writeOnlyValues = <span style="color: #0000ff">null</span>;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum57"> 57:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum58"> 58:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum59"> 59:</span> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> PublishValues(IDictionary<XName, <span style="color: #0000ff">object</span>> readWriteValues)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum60"> 60:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum61"> 61:</span> var keyvalue = (KeyValuePair<Bookmark, <span style="color: #0000ff">int</span>>)readWriteValues[PersistencePropertyName];</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum62"> 62:</span> _Index = (<span style="color: #0000ff">int</span>)keyvalue.Value;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum63"> 63:</span> _Bookmark = (Bookmark)keyvalue.Key;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum64"> 64:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum65"> 65:</span> ContinueWorkflow(_Index);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum66"> 66:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum67"> 67:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum68"> 68:</span> }</pre>
<!--CRLF--></div>
</div>
<p>To save data to the instance store, a unique id for the the data, represented by an <a href="http://msdn.microsoft.com/library/system.xml.linq.xname.aspx">XName</a> instance. This can be created using the XNamespace class (see line 13). With this unique id, the data of the extension instance can be persisted to the instance store. To save the data the extension needs to override the <strong>CollectValues</strong> method and add the properties to be persisted to the <strong>readWriteValues</strong> (lines 50 to 56). The runtime uses the <a href="http://msdn.microsoft.com/library/system.runtime.serialization.datacontractserializer.aspx">DataContractSerializer</a> to serialize the data. Since .NET 3.5 practically every class that has the SerializableAttribute on its class and/or implements the ISerializable interface can be serialized. At minimum, this method should serialize the bookmark. This is required to continue the workflow when it’s restarted.</p>
<p>When the workflow is restarted the runtime calls the <strong>PublishValues</strong> method on the extension to load the instance data from the store (line 59-66). This method also should check whether to resume any bookmarks to continue the workflow.</p>
<p>That’s all. </p>
2009-10-21T19:39:47+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=de522a3f-b593-4cfc-819a-b7f0ee5fef92
2
http://www.infini-tec.de/trackback.axd?id=de522a3f-b593-4cfc-819a-b7f0ee5fef92
http://www.infini-tec.de/post/2009/10/21/Workflow-Foundation-Part-III-Participating-in-persistence.aspx#comment
http://www.infini-tec.de/syndication.axd?post=de522a3f-b593-4cfc-819a-b7f0ee5fef92
http://www.infini-tec.de/post/2009/10/20/Workflow-Foundation-4-e28093-Part-II-NativeActivities-and-Extensions.aspx
Workflow Foundation 4 – Part II: NativeActivities and Extensions
2009-10-20T11:24:35+00:00
hkrause
<p>This is the second post about Workflow Foundation 4, Beta 2. This time, it’s about native activities and custom extensions. The sample used here is the same as in my last post (<a href="http://www.infinitec.de/post/2009/10/19/Persistence-in-Workflow-Foundation-4.aspx">Persistence in Workflow Foundation 4</a>). In that post, I used a simple workflow which incremented a integer value by one each time it was executed. To make things more interesting, the custom activity does this in an asynchronous manner. </p> <p>The activity is a rather simple one, since it uses an extension to do the actual work:</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">using</span> System.Activities;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">namespace</span> WorkflowConsoleApplication1</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> IncrementActivity : NativeActivity</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> <span style="color: #0000ff">public</span> OutArgument<<span style="color: #0000ff">int</span>> Result { get; set; }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">bool</span> CanInduceIdle { get { <span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span>; } }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Execute(NativeActivityContext context)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> var extension = context.GetExtension<IncrementExtension>();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> var bookmark = context.CreateBookmark(<span style="color: #006080">"test"</span>, IncrementCallback);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span> extension.Increment(bookmark);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> IncrementCallback(NativeActivityContext context, Bookmark bookmark, <span style="color: #0000ff">object</span> <span style="color: #0000ff">value</span>)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21"> 21:</span> Result.Set(context, (<span style="color: #0000ff">int</span>)<span style="color: #0000ff">value</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22"> 22:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23"> 23:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24"> 24:</span> }</pre>
<!--CRLF--></div>
</div>
<p>The action has an out argument, the Result property. The value written to this argument is incremented by one each time the activity is called. The key to enable automatic workflow persistence are bookmarks. A short summary about bookmarks can be found in plenty of blogs (for example <a href="http://blogs.microsoft.co.il/blogs/bursteg/archive/2009/05/19/wf-4-0-long-running-custom-activities-with-bookmarks-and-nativeactivity.aspx">here</a>). But most of them are wrong with their examples: The syntax has changed quite a bit when it comes to how to create bookmarks. When an activity calls the <strong>CreateBookmark</strong> method, the runtime automatically stops the workflow instance at that point and persists it to the instance store, if configured. The bookmark takes a name and a callback. The workflow instance is resumed, when the callback is called. In this example, the callback function sets the ‘Result’ argument to the value it receives from the extension. </p>
<p>Note that the activity needs to return true in the <strong>CanInduceIdle</strong> property. Otherwise, a call to <strong>CreateBookmark</strong> method will throw an exception.</p>
<p>Once the bookmark has been created, it is handed over to the <strong>IncrementExtension</strong>.</p>
<p>The IncrementExtension has one method that actually does something: The Increment method. It takes a Bookmark instance as input and resumes it after waiting for 1 second on a different thread:</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">using</span> System;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> <span style="color: #0000ff">using</span> System.Activities;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">using</span> System.Activities.Hosting;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> <span style="color: #0000ff">using</span> System.Collections.Generic;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #0000ff">using</span> System.Threading;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> <span style="color: #0000ff">namespace</span> WorkflowConsoleApplication1</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> <span style="color: #0000ff">class</span> IncrementExtension : IWorkflowInstanceExtension</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> <span style="color: #0000ff">int</span> _Index;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> <span style="color: #0000ff">private</span> WorkflowInstance _Instance;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> Bookmark _Bookmark;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Increment(Bookmark bookmark)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> ThreadPool.QueueUserWorkItem(state =></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> Thread.Sleep(1000);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span> var <span style="color: #0000ff">value</span> = Interlocked.Increment(<span style="color: #0000ff">ref</span> _Index);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21"> 21:</span> _Bookmark = bookmark;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22"> 22:</span> ContinueWorkflow(<span style="color: #0000ff">value</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23"> 23:</span> }, <span style="color: #0000ff">null</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24"> 24:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25"> 25:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26"> 26:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> ContinueWorkflow(<span style="color: #0000ff">int</span> <span style="color: #0000ff">value</span>)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27"> 27:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28"> 28:</span> _Instance.BeginResumeBookmark(_Bookmark, <span style="color: #0000ff">value</span>, CompleteResume, <span style="color: #0000ff">null</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29"> 29:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30"> 30:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31"> 31:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> CompleteResume(IAsyncResult ar)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32"> 32:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33"> 33:</span> var result = _Instance.EndResumeBookmark(ar);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34"> 34:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35"> 35:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36"> 36:</span> IEnumerable<<span style="color: #0000ff">object</span>> IWorkflowInstanceExtension.GetAdditionalExtensions()</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37"> 37:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum38"> 38:</span> <span style="color: #0000ff">yield</span> break;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum39"> 39:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum40"> 40:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum41"> 41:</span> <span style="color: #0000ff">void</span> IWorkflowInstanceExtension.SetInstance(WorkflowInstance instance)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum42"> 42:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum43"> 43:</span> _Instance = instance;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum44"> 44:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum45"> 45:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum46"> 46:</span> }</pre>
<!--CRLF--></div>
</div>
<p>To resume the workflow instance, the extension needs to know which instance it should resume. By default, it does not have this info. It only has an instance of a Bookmark. To get the workflow instance associated with an instance of an extension instance, the extension needs to implement the <strong>IWorkflowInstanceExtension</strong>. This method is called during the initialization of the extension instance.</p>
<p>Given the instance and the bookmark, the extension can now call the <strong>BeginResumeBookmark</strong> method on the workflow instance.</p>
<p>One question remains: Where does the extension instance come from? Simple, it is provided during the initialization of the workflow:</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">class</span> Program</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> var app = <span style="color: #0000ff">new</span> WorkflowApplication(<span style="color: #0000ff">new</span> Workflow1());</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> <span style="color: #008000">// Specify that the workflow should be persisted everytime it is idle.</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> app.PersistableIdle = e => PersistableIdleAction.Persist;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> <span style="color: #008000">// Add an instance store that is used to persist the workflow.</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> app.InstanceStore = <span style="color: #0000ff">new</span> SqlWorkflowInstanceStore(<span style="color: #006080">"Data Source=(local);Initial Catalog=WorkflowDemo;Integrated Security=True"</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> app.Extensions.Add(() => <span style="color: #0000ff">new</span> IncrementExtension());</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span> app.Load(<span style="color: #0000ff">new</span> Guid(<span style="color: #006080">"1E1A5265-A135-4D42-9D64-2ECCCF22E888"</span>));</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> app.Run();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> Console.WriteLine(<span style="color: #006080">"Current Instance id: {0}"</span>, app.Id);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> Console.ReadLine();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21"> 21:</span> app.Unload();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22"> 22:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23"> 23:</span> }</pre>
<!--CRLF--></div>
</div>
<p>The extension is added to the workflow application in line 13. The app.Extensions.Add method either takes a singleton instance of the extension (which is then used each time the extension is requested) or a factory method which creates a new instance each time the extension is requested.</p>
2009-10-20T11:24:35+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=22ab04a9-e7a7-4077-b15f-79f2c7edb553
3
http://www.infini-tec.de/trackback.axd?id=22ab04a9-e7a7-4077-b15f-79f2c7edb553
http://www.infini-tec.de/post/2009/10/20/Workflow-Foundation-4-e28093-Part-II-NativeActivities-and-Extensions.aspx#comment
http://www.infini-tec.de/syndication.axd?post=22ab04a9-e7a7-4077-b15f-79f2c7edb553
http://www.infini-tec.de/post/2009/10/19/Persistence-in-Workflow-Foundation-4.aspx
Persistence in Workflow Foundation 4 Beta 2
2009-10-19T18:55:48+00:00
hkrause
<p>The Workflow Foundation has changed dramatically since .NET 3.5… and many changes have been made even since Beta one. One of the big changes is related to persistence. In earlier versions, either an SqlWorkflowPersistenceService or the and SQLPersistenceProviderFactory was used. Things have become much easier, though, with the release of the second beta of Visual Studio 2010. A workflow can now easily be persisted with a few lines of code. For this sample, I have created a simple workflow which just counts from zero upwards. Since persistence is primarily useful for long-running workflows, I have come up with this example:</p> <p><a href="http://www.infinitec.de/image.axd?picture=WindowsLiveWriter/PersistenceinWorkflowFoundation4/02BA6B0F/image.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.infinitec.de/image.axd?picture=WindowsLiveWriter/PersistenceinWorkflowFoundation4/42181E9F/image_thumb.png" width="516" height="520" /></a> </p> <p>Obviously, this workflow runs very long… espacially, since the custom IncrementActivity waits one second before incrementing the variable ‘Index’.</p> <p>To execute the workflow, only a few lines of code are required:</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">class</span> Program</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> var app = <span style="color: #0000ff">new</span> WorkflowApplication(<span style="color: #0000ff">new</span> Workflow1());</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> <span style="color: #008000">// Specify that the workflow should be persisted everytime it is idle.</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> app.PersistableIdle = e => PersistableIdleAction.Persist;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> <span style="color: #008000">// Add an instance store that is used to persist the workflow.</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> app.InstanceStore = <span style="color: #0000ff">new</span> SqlWorkflowInstanceStore(<span style="color: #006080">"Data Source=(local);Initial Catalog=WorkflowDemo;Integrated Security=True"</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> app.Run();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> Console.WriteLine(<span style="color: #006080">"Current Instance id: {0}"</span>, app.Id);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span> Console.ReadLine();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span> app.Unload();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span> }</pre>
<!--CRLF--></div>
</div>
<p>Sure, there are simpler ways to execute a workflow but AFAIK only this method support persistence using the SqlWorkflowInstanceStore.</p>
<p>To reload the workflow from the database one line needs to be added to the code (in line 12, just before the app.Run() call):</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> app.Load(<span style="color: #0000ff">new</span> Guid(<span style="color: #006080">"1E1A5265-A135-4D42-9D64-2ECCCF22E888"</span>));</pre>
<!--CRLF--></div>
</div>
<p>Of course, the id needs to be replaced with the instance id of the workflow. Once the workflow is running, the instance id can be retrieved from the app.Id property (as shown in line 15).</p>
<p>That’s all.</p>
<p>To persist workflows to a database, the necessary tables and stored procedures must be created in a database. This can easily be accomplished with two files from the .NET 4 runtime directory under %windir%\Microsoft.NET\Framework\v4.0.21006\SQL\en. The SQL statements from the two files SqlWorkflowInstanceStoreSchema.sql and SqlWorkflowInstanceStoreLogic.sql have to be executed against the target database.</p>
2009-10-19T18:55:48+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=9afb5b90-d7fe-4c75-b567-9707ee24679a
1
http://www.infini-tec.de/trackback.axd?id=9afb5b90-d7fe-4c75-b567-9707ee24679a
http://www.infini-tec.de/post/2009/10/19/Persistence-in-Workflow-Foundation-4.aspx#comment
http://www.infini-tec.de/syndication.axd?post=9afb5b90-d7fe-4c75-b567-9707ee24679a
http://www.infini-tec.de/post/2009/06/13/Developing-Windows-Services-with-NET.aspx
Developing Windows Services with .NET
2009-06-13T10:26:54+00:00
hkrause
<p>Developing Windows services with .NET is not always easy – sure, one can attach a debugger once the service is started (at least when developing on Windows XP / 2003). But this is not exactly an ‘F5’ experience one has with normal programs or even Websites. Another drawback of the “Attach to process” method is that the start of the service cannot be debugged. A common way to circumvent this is to write a <a title="Debugger..::.Break Method " href="http://msdn2.microsoft.com/25xczxa2.aspx">System.Diagnostics.Debugger.Break</a> statement within the first lines. This will bring up the Just-In-Time Debugger window that let’s you choose a debugger. Sadly, this does not work any more with Windows Vista / 2008 because services run on an isolated window station.</p> <p>Luckily, there is a solution: A windows service is nothing more than a console application that is started slightly differently. One can take advantage of this by starting the service as a stand-alone program when started normally (via F5 or starting the service from the command line). But if the program detects if it is started by the Service Control manager, run it as a service. So, how can a program check whether it is started by the Service control manager? It depends on the user account the program runs under. If it’s running as “LocalSystem”, one can safely assume it’s running as a service. In any other case, the user account token has a special group membership: The <a title="WellKnownSidType Enumeration" href="http://msdn2.microsoft.com/6c1t48k5.aspx">System.Security.Principal.WellknownSidType</a>.Service.</p> <p>The default body of a program.cs file of blank service solution looks like this:</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">using</span> System.ServiceProcess;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">namespace</span> WindowsService1</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span> Program</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> <span style="color: #008000">/// <summary></span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> <span style="color: #008000">/// The main entry point for the application.</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> <span style="color: #008000">/// </summary></span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main()</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> var servicesToRun = <span style="color: #0000ff">new</span> ServiceBase[] </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> { </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span> <span style="color: #0000ff">new</span> Service1() </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> };</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span> ServiceBase.Run(servicesToRun);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> }</pre>
<!--CRLF--></div>
</div>
<p>With a few additional lines, a comfortable F5 experience can be gained:</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">using</span> System;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> <span style="color: #0000ff">using</span> System.Linq;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">using</span> System.Security.Principal;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> <span style="color: #0000ff">using</span> System.ServiceProcess;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> <span style="color: #0000ff">namespace</span> WindowsService1</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span> Program</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> <span style="color: #008000">/// <summary></span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> <span style="color: #008000">/// The main entry point for the application.</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> <span style="color: #008000">/// </summary></span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main()</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> var identity = WindowsIdentity.GetCurrent();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span> var principal = <span style="color: #0000ff">new</span> WindowsPrincipal(identity);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> <span style="color: #008000">// Check whether the current user account is the LocalSystem account</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span> var isLocalSystemUser = </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> identity.User == <span style="color: #0000ff">new</span> SecurityIdentifier(WellKnownSidType.LocalSystemSid, <span style="color: #0000ff">null</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21"> 21:</span> <span style="color: #0000ff">if</span> (isLocalSystemUser || principal.IsInRole(<span style="color: #0000ff">new</span> SecurityIdentifier(WellKnownSidType.ServiceSid, <span style="color: #0000ff">null</span>)))</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22"> 22:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum23"> 23:</span> var servicesToRun = <span style="color: #0000ff">new</span> ServiceBase[]</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum24"> 24:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum25"> 25:</span> <span style="color: #0000ff">new</span> Service1()</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum26"> 26:</span> };</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum27"> 27:</span> ServiceBase.Run(servicesToRun);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum28"> 28:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum29"> 29:</span> <span style="color: #0000ff">else</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum30"> 30:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum31"> 31:</span> var service = <span style="color: #0000ff">new</span> Service1();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum32"> 32:</span> service.StartAsApplication();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum33"> 33:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum34"> 34:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum35"> 35:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum36"> 36:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum37"> 37:</span> }</pre>
<!--CRLF--></div>
</div>
<p>I have added a StartAsApplication() method to the Service1 class, because the OnStart() method of the default service template is protected and therefore not accessible. And that is all there is. The service can now be started by just pressing F5. </p>
<h4>Drawbacks</h4>
<p>The gain of the F5 experience does not come without a cost – normally, a Windows service runs under a special account (which is hopefully not LocalSystem): NetworkService, LocalService or a dedicated service account. With this approach, the service runs with the permissions of the currently logged on user. Normally, that user account has far more security permissions than the service account would have. For example, the current user might have the permission to host WCF services on arbitrary ports – something only administrators are allowed to do. A service account would need explicit permission to host that service. Another example are private keys of certificates in the LocalComputer store – not accessible for the NetworkService account by default. But if a service needs to access those keys, it won’t fail unless during development. This should be kept in mind.!</p>
2009-06-13T10:26:54+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=6972eb42-4736-4df6-9f25-a6ce567e74fb
11
http://www.infini-tec.de/trackback.axd?id=6972eb42-4736-4df6-9f25-a6ce567e74fb
http://www.infini-tec.de/post/2009/06/13/Developing-Windows-Services-with-NET.aspx#comment
http://www.infini-tec.de/syndication.axd?post=6972eb42-4736-4df6-9f25-a6ce567e74fb
http://www.infini-tec.de/post/2009/06/06/Getting-the-fullqualified-DNS-name-of-the-current-computer.aspx
Getting the fullqualified DNS name of the current computer
2009-06-06T16:23:34+00:00
hkrause
<p>Under certain circumstances a program needs to determine the name of the computer it’s running on. The first approach to get this name is to use the <a title="Environment..::.MachineName Property " href="http://msdn2.microsoft.com/kd4h3aad.aspx">System.Environment.MachineName</a> property. However, this name only reflects the NETBIOS name of the current machine. But in larger environments a full-qualified name including the DNS domain the computer belongs to. This can be something like computername.contoso.local. One example where this full qualified name might be needed are Exchange Push notification. I’ve published a component to <a href="http://www.codeplex.com/exchangenotification">CodePlex</a> makes it really easy to incorporate them in an application. However, for the notifications to reach the client the component needs to tell the Exchange server a correct callback address. In a very simple network environment, it is sufficient to specify the NETBIOS hostname. But in more complex environments, Exchange might not be able to send a notification because it cannot correctly resolve the unqualified hostname to an IP address.</p> <p>The full qualified domain name of the current host can be resolved with a call tot the <a title="IPGlobalProperties..::.GetIPGlobalProperties Method " href="http://msdn2.microsoft.com/7c7239a3.aspx">System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties</a> method. This method returns, among other things, the required information:</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> <span style="color: #0000ff">string</span> fullQualifiedDomainName;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span> <span style="color: #0000ff">if</span> (!<span style="color: #0000ff">string</span>.IsNullOrEmpty(ipGlobalProperties.DomainName))</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> fullQualifiedDomainName = <span style="color: #0000ff">string</span>.Format(<span style="color: #006080">"{0}.{1}"</span>, ipGlobalProperties.HostName, ipGlobalProperties.DomainName);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> <span style="color: #0000ff">else</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> fullQualifiedDomainName = ipGlobalProperties.HostName;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> }</pre>
<!--CRLF--></div>
</div>
<p>I have updated the PushNotification component to reflect this new behavior. </p>
2009-06-06T16:23:34+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=677502cb-7e91-4273-8cae-8bb3af8a613c
1
http://www.infini-tec.de/trackback.axd?id=677502cb-7e91-4273-8cae-8bb3af8a613c
http://www.infini-tec.de/post/2009/06/06/Getting-the-fullqualified-DNS-name-of-the-current-computer.aspx#comment
http://www.infini-tec.de/syndication.axd?post=677502cb-7e91-4273-8cae-8bb3af8a613c
http://www.infini-tec.de/post/2009/03/29/X509Certificate2-Constructor-Bug.aspx
X509Certificate2 Constructor creates two empty files in the temporary files directory [Update]
2009-03-29T13:13:30+00:00
hkrause
<p>2009-04-18: Microsoft has indeed a knowledgebase article on this topic and there is a hotfix availbe.</p> <p>The .NET Framework has a nice class called <a title="X509Certificate2 Class" href="http://msdn2.microsoft.com/ms148409.aspx">X509Certificate2</a> that simplifies the handling of X.509 certificates. Specifically, it has a constructor that takes a byte array that allows a developer to load a certificate from an arbitrary storage like a database. The class uses some Win32 to parse the byte array, and one of the used functions contain a bug: During the load process, two empty temporary files are created in the temporary files directory of the user running the code. Unfortunately, these files are never cleaned up, so they accumulate over time. What’s worse, they seem to be created by the <a href="http://msdn.microsoft.com/en-us/library/aa364991(VS.85).aspx">GetTempFilename</a> function. This function creates an empty file in a specific directory with a name guaranteed to be unique. These files have a prefix (up to three letters) and a number. The number is generated by the GetTempFilename function in a sequential manner. Since the two files are never deleted by the Win32 function, the call to GetTempFilename takes longer and longer. In my case, I had over 65.000 files in the temporary files directory and the X509Certificate2 constructor took several seconds to complete.</p> <p>Microsoft knows about this bug, but they don’t seem eager to fix it. More details can be found on this connect link: <a title="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=284551" href="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=284551">http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=284551</a>.</p> <p><strike>Since there will be no fix in the near future</strike>, you can use this workaround: Instead of loading the certificate from a byte array, dump it to a file and read it from there. The following snippet demonstrates this workaround:</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> X509Certificate2 LoadCertificate(<span style="color: #0000ff">byte</span>[] buffer)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2"> 2:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff">if</span> (buffer == <span style="color: #0000ff">null</span>) <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ArgumentNullException(<span style="color: #006080">"buffer"</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4"> 4:</span>  </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #0000ff">string</span> filename = Path.GetTempFileName();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6"> 6:</span> <span style="color: #0000ff">try</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7"> 7:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8"> 8:</span> File.WriteAllBytes(filename, buffer);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9"> 9:</span> <span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span> X509Certificate2(filename);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10"> 10:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11"> 11:</span> <span style="color: #0000ff">finally</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12"> 12:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13"> 13:</span> <span style="color: #0000ff">try</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14"> 14:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15"> 15:</span> File.Delete(filename);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16"> 16:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17"> 17:</span> <span style="color: #0000ff">catch</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18"> 18:</span> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19"> 19:</span> <span style="color: #008000">// This is ok - the file is in the temporary files directory. No harm done.</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum20"> 20:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum21"> 21:</span> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum22"> 22:</span> }</pre>
<!--CRLF--></div>
</div>
<h2></h2>
<h3>Hotfix</h3>
<p>The knowledgebase article <a href="http://support.microsoft.com/kb/931908">931908</a> deals with this problem and offers a hotfix. The hot fix can be requested directly from the article.</p>
2009-03-29T13:13:30+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=9887aee2-64f8-4ba1-8dc2-9b1415ce8011
2
http://www.infini-tec.de/trackback.axd?id=9887aee2-64f8-4ba1-8dc2-9b1415ce8011
http://www.infini-tec.de/post/2009/03/29/X509Certificate2-Constructor-Bug.aspx#comment
http://www.infini-tec.de/syndication.axd?post=9887aee2-64f8-4ba1-8dc2-9b1415ce8011
http://www.infini-tec.de/post/2008/05/13/InvalidCastException-Unable-to-cast-object-of-Type-X-to-X.aspx
InvalidCastException: Unable to cast object of Type 'X' to 'X'
2008-05-13T20:23:19+00:00
hkrause
<p>In a recent project, the above exception was thrown when returning from a web service call. Interestingly, the exception was only thrown if the code was running within a web application. It would run fine when executed in an executable or even the Visual Studio development web server. At first I suspected some sort of permission problem but that couldn't really explain that particular error message. Next suspect was the shadow-copy feature of ASP.NET: The runtime does not actually run the assemblies from the path the IIS virtual directory points. Instead it copies all assemblies to the Temporary ASP.NET Files (<strong>C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files</strong> on x86 machines or<strong> C:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files</strong> on x64 machines) and executes them from there. So I added two lines of code right before the exception would be thrown:</p> <div class="csharpcode"> <pre><span class="lnum"> 1: </span>Trace.WriteLine(instance.GetType().Assembly.Location)</pre>
<pre><span class="lnum"> 2: </span>Trace.WriteLine(GetType(MyType).Assembly.Location)</pre>
</div>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Upon execution, the trace output was the following:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span>c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\c88143cc\98574940\assembly\dl3\98dad73b\f3cf1948_ddb4c801\MyAssembly.DLL </pre>
<pre><span class="lnum"> 2: </span>C:\Development\TestApplication\MyAssembly.dll</pre>
</div>
<style type="text/css">
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>This was the problem: One assembly was loaded from two different sources. What was the cause? Turns out that the first assembly was loaded because of an assembly reference. This way it was correctly placed in the Temporary ASP.NET Files. But the second instance of the assembly was loaded via reflection with a call to <a title="Assembly..::.LoadFile Method " href="http://msdn2.microsoft.com/h9dke0yz.aspx">System.Reflection.Assembly.LoadFile</a>. The solution is to use <a title="Assembly..::.LoadFrom Method " href="http://msdn2.microsoft.com/48k1f5te.aspx">System.Reflection.Assembly.LoadFrom</a> instead of the LoadFile method.</p>
<p>Why is this a solution? The main difference between LoadFrom and LoadFile is that LoadFrom goes through the normal Fusion bind process, thus allowing assembly redirection to happen. LoadFile on the other hand, just loads the assembly from the specified location.</p>
<p>For more information on this, see this blog posting from <a href="http://blogs.msdn.com/suzcook/archive/2003/09/19/loadfile-vs-loadfrom.aspx">Suzanne Cooks blog</a>.</p>
2008-05-13T20:23:19+00:00
hkrause
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=131e2545-70ba-408c-b181-66922f195ceb
6
http://www.infini-tec.de/trackback.axd?id=131e2545-70ba-408c-b181-66922f195ceb
http://www.infini-tec.de/post/2008/05/13/InvalidCastException-Unable-to-cast-object-of-Type-X-to-X.aspx#comment
http://www.infini-tec.de/syndication.axd?post=131e2545-70ba-408c-b181-66922f195ceb
http://www.infini-tec.de/post/2007/12/30/Windows-Installer-Xml-30-Extension-for-managed-installers.aspx
Windows Installer Xml 3.0 Extension for managed installers
2007-12-29T23:00:00+00:00
hkrause
<div xmlns="http://www.w3.org/1999/xhtml"><p>The Windows Installer technology unfortunately lacks support for managed custom actions or the <a href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.installer.aspx">System.Configuration.Install.Installer</a> class. Rob Mensching posted an <a href="http://robmensching.com/blog/archive/2007/04/19/Managed-Code-CustomActions-no-support-on-the-way-and-heres.aspx">article</a> on his blog a while back why Microsoft considers custom action in general and managed custom action in particular a bad idea. While he makes some valid points (some technical and some strategic), I think managed custom installers are not a bad thing:</p><ul style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px" type="disc"><li>While they add a dependency on the .NET Framework at setup time, for applications using a windows service written in managed code, the Framework must be installed on the target computer at the setup time because Windows Installer will start the service during setup. And for all other managed applications you'll need the framework right after the application has been installed (to run it). Since the Framework cannot be installed using a Merge module, it must be installed before the actual setup of the application.</li><li>I consider myself a fairly good software developer when it comes to managed code. But my C or C++ knowledge is minimum at best. So I can either write solid managed custom actions (where I have a well-tested BCL at hand) or create spooky and unreliable custom actions in C. I prefer the former option.</li><li>He mentions a problem with managed custom actions using different versions of the CLR. While this may be a problem, you'll mostly write custom actions using .NET 2.0 these days. And .NET 3.0 and 3.5 both use the same CLR as 2.0.</li><li>What remains of his technical problems is the fact that Windows Installer on Windows 2003 will try to load the .NET Framework 1.1 into the deferred-custom action server when it tries to register assemblies into the Global Assembly Cache, which will fail if you force the .NET 2.0 runtime into the process with a managed custom action.</li><li>All those strategic reasons might be ok for the Windows Installer team, but I can't wait a few years until the Windows Installer team bakes all the actions I need into the core of the product. And when they do, you'll need Windows 2015 at the very least…. Not an option.</li></ul><p>Apparently, the Visual Studio Team doesn't consider managed custom actions to be harmful - otherwise they wouldn't give you the option to run managed installers in those Visual Studio deployment projects. But these installers do lack a serious feature: The Windows Installer context. It's not that the installer context isn't propagated to the runtime (You may have wondered what the <a href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.imanagedinstaller.aspx">IManagedInstaller</a> interface is meant for :-) ).</p><p><a href="http://wix.sf.net">Windows Installer Xml</a> also doesn't support managed custom actions out of the box. You have to do this yourself. One option is to decompile a Visual Studio Deployment project and see what Visual Studio does to call a managed custom action. While this will certainly work, you'll end up with a managed installer which has the same limitations as the Visual Studio deployment project: No access to the installer context. Additionally, these installer classes are always called as deferred custom actions. This means that they neither work in the immediate phase of the InstallExecuteSequence nor in the InstallUISequence.</p></div><h2 xmlns="http://www.w3.org/1999/xhtml">Reinventing the wheel…</h2><div xmlns="http://www.w3.org/1999/xhtml"><p><span style="color: #010101;">To call managed code in-process from the Windows Installer process, an intermediate unmanaged DLL must be called which in turn loads the .NET Framework into the process, spawns an AppDomain and finally runs the managed code inside this AppDomain. This is actually what the Visual Studio Deployment Project does.</span></p><p><span style="color: #010101;">The approach I'm using here is based on the article </span><a href="http://www.forestwalk.de/?p=31"><span style="color: #010101;">"WiX - Managed Custom Actions" by ForestWalk</span></a><span style="color: #010101;">, which in turn is based on two other aricles: </span><a href="http://www.codeproject.com/csharp/msiinterop.asp"><span style="color: #010101;">"Wrapping the Windows Installer 2.0 API" by Ian Marino</span></a><span style="color: #010101;"> and </span><a href="http://weblogs.asp.net/cibrax/archive/2005/04/11/399839.aspx"><span style="color: #010101;">“Hosting the CLR within a custom action” by Pablo M. Cibraro (aka Cibrax)</span></a><span style="color: #010101;">. The code in the article make it possible to call managed code in every part of the sequence. But the usage is not very intuitive to use, especially managed installer classes.</span></p><span style="color: #010101;">Since deferred custom actions can only access one property (CustomActionData), all information needed by be managed installer must be placed in this property. And since the CustomActionData is only an unstructured simple string property, some form of serialization is needed to put multiple properties into it. </span><p><span style="color: #010101;">To support all four methods of the managed installer class, you'll have to create and sequence eight custom actions: For each of the four methods (Install, Commit, Rollback, Uninstall) one action for the parameters (CustomActionData) and one action to run it.</span></p><p><span style="color: #010101;">Multiple managed installers will seriously degrade the readability of your Windows Installer XML file. That's why a took the code from the article and put it into a Windows Installer Xml Extension. I also created a small framework to simplify the development of managed installers.</span></p><p><span style="color: #010101;">Here is a simple example setup file:</span></p><div class="clsCode" style="FONT-SIZE: 10pt; BACKGROUND-COLOR: #f0f0f0"><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 1</span> <span style="color: #0000ff;"><?</span><span style="color: #a31515;">xml</span><span style="color: #ff0000;">version</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">1.0</span>"<span style="color: #ff0000;">encoding</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">UTF-8</span>"<span style="color: #0000ff;">?></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 2</span> <span style="color: #0000ff;"><</span><span style="color: #a31515;">Wix</span><span style="color: #ff0000;">xmlns</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">http://schemas.microsoft.com/wix/2006/wi</span>"</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 3</span> <span style="color: #0000ff;"> ></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 4</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">Product</span><span style="color: #ff0000;">Id</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">4ed3ff4f-7b33-4915-9801-a0fdd5515647</span>"</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 5</span> <span style="color: #0000ff;"> </span><span style="color: #ff0000;">UpgradeCode</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">d4bacea3-a59a-4d44-b95b-1e144edfb88b</span>"</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 6</span> <span style="color: #0000ff;"> </span><span style="color: #ff0000;">Name</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">Acme Sample Application</span>"<span style="color: #ff0000;">Language</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">1033</span>"<span style="color: #ff0000;">Version</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">1.0.0.0</span>"</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 7</span> <span style="color: #0000ff;"> </span><span style="color: #ff0000;">Manufacturer</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">Acme Software Ltd.</span>"</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 8</span> <span style="color: #0000ff;"> ></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 9</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">Package</span><span style="color: #ff0000;">InstallerVersion</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">300</span>"<span style="color: #ff0000;">Compressed</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">yes</span>"<span style="color: #0000ff;"> /> </span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 10</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">Media</span><span style="color: #ff0000;">Id</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">1</span>"<span style="color: #ff0000;">Cabinet</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">Sample.cab</span>"<span style="color: #ff0000;">EmbedCab</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">yes</span>"<span style="color: #0000ff;"> /></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 11</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">Directory</span><span style="color: #ff0000;">Id</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">TARGETDIR</span>"<span style="color: #ff0000;">Name</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">SourceDir</span>"<span style="color: #ff0000;">FileSource</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">.\</span>"<span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 12</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">Component</span><span style="color: #ff0000;">Id</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">ProductComponent</span>"<span style="color: #ff0000;">Guid</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">865018ca-dc6f-4987-9766-cffe792cb937</span>"<span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 13</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">File</span><span style="color: #ff0000;">Id</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">f1</span>"<span style="color: #ff0000;">Name</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">ManagedCustomAction.dll</span>"<span style="color: #ff0000;">Source</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">Include\ManagedCustomAction.dll</span>"<span style="color: #0000ff;"> ></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 14</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">ManagedInstaller</span><span style="color: #ff0000;">xmlns</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">http://schemas.infinitec.de/wix/MCAExtension</span>"<span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 15</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">Parameter</span><span style="color: #ff0000;">Name</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">TargetDir</span>"<span style="color: #0000ff;">></span>[TARGETDIR]<span style="color: #0000ff;"></</span><span style="color: #a31515;">Parameter</span><span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 16</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">Parameter</span><span style="color: #ff0000;">Name</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">AssemblyFile</span>"<span style="color: #0000ff;">></span>Assembly is run from [#f1]<span style="color: #0000ff;"></</span><span style="color: #a31515;">Parameter</span><span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 17</span> <span style="color: #0000ff;"> </</span><span style="color: #a31515;">ManagedInstaller</span><span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 18</span> <span style="color: #0000ff;"> </</span><span style="color: #a31515;">File</span><span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 19</span> <span style="color: #0000ff;"> </</span><span style="color: #a31515;">Component</span><span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 20</span> <span style="color: #0000ff;"> </</span><span style="color: #a31515;">Directory</span><span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 21</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">Feature</span><span style="color: #ff0000;">Id</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">ProductFeature</span>"<span style="color: #ff0000;">Title</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">Main Feature</span>"<span style="color: #ff0000;">Level</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">1</span>"<span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 22</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">ComponentRef</span><span style="color: #ff0000;">Id</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">ProductComponent</span>"<span style="color: #0000ff;"> /></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 23</span> <span style="color: #0000ff;"> </</span><span style="color: #a31515;">Feature</span><span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 24</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">UIRef</span><span style="color: #ff0000;">Id</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">WixUI_Minimal</span>"<span style="color: #0000ff;">/></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 25</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">Binary</span><span style="color: #ff0000;">Id</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">ManagedCustomAction</span>"<span style="color: #ff0000;">SourceFile</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">Include\ManagedCustomAction.dll</span>"<span style="color: #0000ff;"> /></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 26</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">ManagedCustomAction</span><span style="color: #ff0000;">Id</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">test</span>"<span style="color: #ff0000;">BinaryKey</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">ManagedCustomAction</span>"<span style="color: #ff0000;">Type</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">ManagedCustomAction.CustomAction</span>"<span style="color: #ff0000;">Execute</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">immediate</span>"<span style="color: #ff0000;">xmlns</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">http://schemas.infinitec.de/wix/MCAExtension</span>"<span style="color: #0000ff;"> /></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 27</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">ManagedActionSequence</span><span style="color: #ff0000;">xmlns</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">http://schemas.infinitec.de/wix/MCAExtension</span>"<span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 28</span> <span style="color: #0000ff;"> <</span><span style="color: #a31515;">Managed</span><span style="color: #ff0000;">Action</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">test</span>"<span style="color: #ff0000;">After</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">CostFinalize</span>"<span style="color: #ff0000;">SequenceTable</span><span style="color: #0000ff;">=</span>"<span style="color: #0000ff;">InstallUISequence</span>"<span style="color: #0000ff;"> /></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 29</span> <span style="color: #0000ff;"> </</span><span style="color: #a31515;">ManagedActionSequence</span><span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 30</span> <span style="color: #0000ff;"> </</span><span style="color: #a31515;">Product</span><span style="color: #0000ff;">></span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 31</span> <span style="color: #0000ff;"></</span><span style="color: #a31515;">Wix</span><span style="color: #0000ff;">></span></span></p></div></div><h2 xmlns="http://www.w3.org/1999/xhtml">Managed Installers</h2><div xmlns="http://www.w3.org/1999/xhtml"><p align="left"><span style="color: #010101;">The extension makes it very easy to call managed installers or managed custom action. </span></p><p align="left"><span style="color: #010101;">Just put the tag <strong>ManagedInstaller </strong>into a File tag and the installer will be called during setup. If you need context information stored in other MSI properties, add a <strong>Parameter </strong>tag into the <strong>ManagedInstaller </strong>tag with an appropiate name and the value. From your managed installer, you can use the <strong>Parameters</strong> dictionary from the </span><a href="http://msdn2.microsoft.com/en-us/library/system.configuration.install.installcontext_members.aspx"><span style="color: #010101;">InstallContext</span></a><span style="color: #010101;"> class. Here is a sample implementation for the Install method of a <strong>System.Configuration.Install.Installer</strong> class:</span></p><div class="clsCode" style="FONT-SIZE: 10pt; BACKGROUND-COLOR: #f0f0f0"><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 1</span> <span style="color: #0000ff;">public</span><span style="color: #0000ff;">override</span><span style="color: #0000ff;">void</span> Install(<span style="color: #2b91af;">IDictionary</span> stateSaver)</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 2</span> {</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 3</span> <span style="color: #0000ff;">string</span> targetDir = Context.Parameters[<span style="color: #a31515;">"TargetDir"</span>];</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 4</span> </span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 5</span> <span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 3 - 1; i >= 0; i--)</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 6</span> {</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 7</span> <span style="color: #2b91af;">InstallerContext</span>.Current.StartAction(<span style="color: #a31515;">"ManagedCustomAction"</span>, <span style="color: #0000ff;">string</span>.Format(<span style="color: #a31515;">"Install: Waiting {0} seconds..."</span>, i), <span style="color: #a31515;">""</span>);</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 8</span> <span style="color: #2b91af;">Thread</span>.Sleep(1000);</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 9</span> }</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 10</span> <span style="color: #0000ff;">base</span>.Install(stateSaver);</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 11</span> }</span></p></div><p align="left"><span style="color: #010101;">In line 5, the property TargetDir is accessed. This property contains the value as specified in line 15 of the Windows Installer XML file. But far more interesting are the lines 7 and 11: These lines access the Windows Installer process and report details about what the custom action is doing. The two function wrap two flavors of the </span><a href="http://msdn2.microsoft.com/en-us/library/aa370354.aspx"><span style="color: #010101;">MsiProcessRecord</span></a><span style="color: #010101;"> function. The StartAction method reports the start of a major action (such as "Copying files" or "Creating registry values"). Additionally, a format string for details is specified, in this case "Waiting [1] more seconds"). The ReportDetails now just take the replacement values for the format string, in this case the number of seconds remaining).</span></p><p align="left"><span style="color: #010101;">Another important method of the InstallerContext class is the LogMessage method which writes directly to the Windows Installer log. Note that you don't have to use this method to log data. You can also use InstallContext.LogMessage or Trace.WriteLine or Console.WriteLine. The output of all those methods is captured and written to the log.</span></p><p align="left"><span style="color: #010101;">All unhandled exceptions from an Installer class are catched by the framework and cause an error message to be displayed. Unhandled exceptions in the Install, Commit and Rollback methods cause the installation to be aborted. If an exception occurs in the Uninstall method, an error dialog is displayed, but the uninstall will continue.</span></p><p align="left"><span style="color: #010101;">The four methods are sequence in the InstallExecuteSequence at the following positions:</span></p><ul style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px" type="disc"><li><p align="left"><span style="color: #010101;">Install, Commit, Rollback: Before InstallServices</span></p></li><li><p align="left"><span style="color: #010101;">Uninstall: Before UnpublishComponents</span></p></li></ul><p align="left"><span style="color: #010101;">The installer will only be invoked if the component the file is associated with is installed.</span></p></div><h2 xmlns="http://www.w3.org/1999/xhtml">Managed custom actions</h2><div xmlns="http://www.w3.org/1999/xhtml"><p><span style="color: #010101;">To run a managed custom action, two things have to be done: Create a <strong>ManagedCustomAction </strong>tag under the <strong>Product </strong>tag and fill in the blanks:</span></p><ul style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px" type="disc"><li><span style="color: #010101;">Id: The name of the custom action </span></li><li><span style="color: #010101;">BinaryKey: If you want to run the custom action in the immediate sequence or in the <strong>InstallUISequence </strong>table, add the assembly to the binary table (via the <strong>Binary </strong>tag) and enter its key here. </span></li><li><span style="color: #010101;">FileKey: If you want to run this custom in the deferred sequence, add the assembly to the file table (via the <strong>File </strong>tag) and enter its key here. </span></li><li><span style="color: #010101;">Type: Name full qualified name of the type you want to run (Namespace + type name) </span></li><li><span style="color: #010101;">Execute: Either commit, deferred, firstSequence, immediate, oncePerProcess, rollback or secondSequence. These are the same options you have with normal Custom actions (<strong>Cutom</strong> tag) </span></li><li><span style="color: #010101;">Impersonate: Yes to run the custom action in the security context of the logged on user. False otherwise. The default is true. Only valid for deferred custom actions. </span></li><li><span style="color: #010101;">Return: asyncNoWait, asyncWait, check or ignore. These are the same options you have with normal Custom actions (<strong>Cutom</strong> tag)</span></li></ul><p><span style="color: #010101;">Unfortunately Windows Installer XML does not allow extensions in the sequence tables, so I had to create my own: ManagedActionSequence. Add a Managed tag for each custom action you want to schedule. The Managed tag has these attributes:</span></p><ul style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px" type="disc"><li><span style="color: #010101;">Action: The name of the managed custom action to run. </span></li><li><span style="color: #010101;">After: The name of the action the managed custom action should be executed after. </span></li><li><span style="color: #010101;">Before: The name of the action the managed custom action should be execute before. </span></li><li><span style="color: #010101;">Sequence: The absolute sequence where the managed custom action should run. </span></li><li><span style="color: #010101;">SequenceTable: The name of the sequence table where the managed custom action should be scheduled: Either InstallUISequence, InstallExecuteSequence, AdminUISequence, AdminExecuteSequence.</span></li></ul><p><span style="color: #010101;">The managed custom action must be a class which implements the InfiniTec.Configuration.Install.ICustomAction interface, like in this example:</span></p><div class="clsCode" style="FONT-SIZE: 10pt; BACKGROUND-COLOR: #f0f0f0"><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 1</span> <span style="color: #0000ff;">public</span><span style="color: #0000ff;">class</span><span style="color: #2b91af;">CustomAction</span>: <span style="color: #2b91af;">ICustomAction</span></span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 2</span> {</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 3</span> <span style="color: #0000ff;">public</span><span style="color: #0000ff;">void</span> Execute()</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 4</span> {</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 5</span> <span style="color: #0000ff;">string</span> targetDir = <span style="color: #2b91af;">InstallerContext</span>.Current.GetProperty(<span style="color: #a31515;">"TARGETDIR"</span>);</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 6</span> </span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 7</span> <span style="color: #2b91af;">InstallerContext</span>.Current.StartAction(<span style="color: #a31515;">"ManagedCustomAction"</span>, <span style="color: #a31515;">"Running custom action..."</span>, <span style="color: #a31515;">"Waiting [1] seconds..."</span>);</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 8</span> <span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 3 - 1; i >= 0; i--)</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 9</span> {</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 10</span> <span style="color: #2b91af;">InstallerContext</span>.Current.ReportDetails(i.ToString());</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 11</span> <span style="color: #2b91af;">Thread</span>.Sleep(1000);</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 12</span> }</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 13</span> </span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 14</span> </span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 15</span> }</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 16</span> }</span></p></div><p><span style="color: #010101;">This implementation has full access to the MSI properties (see line 5, if scheduled as immediate action) and of course access to the Installer log via InstallerContext.Current.LogMessage.</span></p></div><h2 xmlns="http://www.w3.org/1999/xhtml">Other useful classes</h2><div xmlns="http://www.w3.org/1999/xhtml"><p><span style="color: #010101;">Since the custom actions can be executed in the immediate sequence of the install process, it has full access to all properties and tables of the installer. The rows of a view can be accessed via the View class:</span></p><div class="clsCode" style="FONT-SIZE: 10pt; BACKGROUND-COLOR: #f0f0f0"><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 1</span> <span style="color: #0000ff;">using</span> (<span style="color: #2b91af;">View</span> view = <span style="color: #2b91af;">InstallerContext</span>.Current.OpenView(<span style="color: #a31515;">"SELECT * FROM Binary"</span>))</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 2</span> <span style="color: #0000ff;">using</span> (<span style="color: #2b91af;">RecordCollection</span> records = view.Execute())</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 3</span> {</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 4</span> <span style="color: #0000ff;">foreach</span> (<span style="color: #2b91af;">Record</span> record <span style="color: #0000ff;">in</span> records)</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 5</span> {</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 6</span> <span style="color: #0000ff;">string</span> name = record[1].GetString();</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 7</span> }</span></p><p style="PADDING-RIGHT: 0px; MARGIN-TOP: 0px; PADDING-LEFT: 2cm; MARGIN-BOTTOM: 0px; TEXT-INDENT: -2cm"><span style="font-family: Courier New;"><span style="color: #2b91af;"> 8</span> }</span></p></div><p><span style="color: #010101;">The view returns a RecordCollection which in turn provides access to it's Record instances. Each record consists of one or more fields. Note that if you create a record with the Record.Create(int columnCount) method, the resulting record will have columnCount+1 fields - 0 to the specified value.</span></p></div><h2 xmlns="http://www.w3.org/1999/xhtml">Modifications to the original source code</h2><div xmlns="http://www.w3.org/1999/xhtml"><p><span style="color: #010101;">Apart from the newly added code, I made significant changes to the existing code:</span></p><p><span style="color: #010101;">To load the .NET runtime into the process I use the CLRHosting project from the article mentioned above. I have replaced all dangerous API calls (strcat, sprintf) with secure ones. But my C and C++ knowledge is VERY limited. I would appreciate it if someone with more knowledge could take a look at the code….</span></p><p><span style="color: #010101;">I have also made significant changes to the managed part of the solution. Mainly, I have encapsulated all unmanaged MSI handles in a custom SafeHandle class.</span></p></div><h2 xmlns="http://www.w3.org/1999/xhtml">Open issues</h2><div xmlns="http://www.w3.org/1999/xhtml"><ul style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px" type="disc"><li><span style="color: #010101;">Deferred custom actions with assemblies in the Binary table are not yet supported</span></li><li><span style="color: #010101;">Immediate custom actions with assemblies in the File table are not supported (And I don't see how this could work)</span></li><li><span style="color: #010101;">Managed installers do not have an immediate part</span></li><li><span style="color: #010101;">Managed custom actions and managed installer classes don't add ticks to the progress bar.</span></li><li><span style="color: #010101;">A much cleaner approach is to call the custom action in a separate process and provide access to the Windows Installer context via remoting. This approach is dicussed in more detail in the article <a href="http://blog.deploymentengineering.com/2006/03/new-approach-to-managed-custom-actions.html">A New Approach to Managed Custom Actions</a> by Christopher Painter. Unfortunately he didn't release any source code and I'm lacking the necessary C and C++ skills right now.</span></li></ul></div><h2 xmlns="http://www.w3.org/1999/xhtml">Installation</h2><div xmlns="http://www.w3.org/1999/xhtml"><span style="color: #010101;">Just copy the zip file to a directory and decompress it. In your WIX Project add a reference to the ManagedInstallerWixExtension.dll. In your setup file add the namespace </span><a href="http://schemas.infinitec.de/wix/MCAExtension"><span style="color: #010101;">http://schemas.infinitec.de/wix/MCAExtension</span></a><span style="color: #010101;"> to the list of namespace definitions. </span></div><h2 xmlns="http://www.w3.org/1999/xhtml">Requirements</h2><div xmlns="http://www.w3.org/1999/xhtml"><span style="color: #010101;">The extension is compiled against WIX 3.0.361 (build from December 21, 2007) using .NET 2.0.</span></div><h2 xmlns="http://www.w3.org/1999/xhtml">License</h2><div xmlns="http://www.w3.org/1999/xhtml"><span style="color: #010101;">The authors of the original articles haven't lost a word about the license, so I assume it's freely available. To keep this stuff freely available I publish this work under the </span><a href="http://www-128.ibm.com/developerworks/library/os-cpl.html"><span style="color: #010101;">Common Public License</span></a><span style="color: #010101;">, the same license Windows Installer XML is published under.</span></div><h2 xmlns="http://www.w3.org/1999/xhtml">Downloads</h2><table xmlns="http://www.w3.org/1999/xhtml"><tr><td><img style="border:none; vertical-align: middle;" src=file.axd?file=wixmanagedcustomactionextension/zip.gif /></td><td><a href=file.axd?file=wixmanagedcustomactionextension/ManagedInstallerWixExtension.zip>ManagedInstallerWixExtension.zip</a> (637,678 Bytes)<br />Source files and binaries</td></tr></table>
2007-12-29T23:00:00+00:00
hkrause
The Windows Installer technology unfortunately lacks support for managed custom actions or the System.Configuration.Install.Installer class. Rob Mensching posted an article on his blog a while back why Microsoft considers custom action in general and managed custom action in particular a bad idea. While he makes some valid points (some technical and some strategic), I think managed custom installers are not a bad thing:While they add a dependency on the .NET Framework at setup time, for applications using a windows service written in managed code, the Framework must be installed on the target computer at the setup time because Windows Installer will start the service during setup. And for all other managed applications you'll need the framework right after the application has been installed (to run it). Since the Framework cannot be installed using a Merge module, it must be installed before the actual setup of the application.I consider myself a fairly good software developer when it comes to managed code. But my C or C++ knowledge is minimum at best. So I can either write solid managed custom actions (where I have a well-tested BCL at hand) or create spooky and unreliable custom actions in C. I prefer the former option.He mentions a problem with managed custom actions using different versions of the CLR. While this may be a problem, you'll mostly write custom actions using .NET 2.0 these days. And .NET 3.0 and 3.5 both use the same CLR as 2.0.What remains of his technical problems is the fact that Windows Installer on Windows 2003 will try to load the .NET Framework 1.1 into the deferred-custom action server when it tries to register assemblies into the Global Assembly Cache, which will fail if you force the .NET 2.0 runtime into the process with a managed custom action.All those strategic reasons might be ok for the Windows Installer team, but I can't wait a few years until the Windows Installer team bakes all the actions I need into the core of the product. And when they do, you'll need Windows 2015 at the very least…. Not an option.Apparently, the Visual Studio Team doesn't consider managed custom actions to be harmful - otherwise they wouldn't give you the option to run managed installers in those Visual Studio deployment projects. But these installers do lack a serious feature: The Windows Installer context. It's not that the installer context isn't propagated to the runtime (You may have wondered what the IManagedInstaller interface is meant for :-) ).Windows Installer Xml also doesn't support managed custom actions out of the box. You have to do this yourself. One option is to decompile a Visual Studio Deployment project and see what Visual Studio does to call a managed custom action. While this will certainly work, you'll end up with a managed installer which has the same limitations as the Visual Studio deployment project: No access to the installer context. Additionally, these installer classes are always called as deferred custom actions. This means that they neither work in the immediate phase of the InstallExecuteSequence nor in the InstallUISequence.
http://www.infini-tec.de/pingback.axd
http://www.infini-tec.de/post.aspx?id=a4a08006-d5db-45c4-b473-3653b85d365b
8
http://www.infini-tec.de/trackback.axd?id=a4a08006-d5db-45c4-b473-3653b85d365b
http://www.infini-tec.de/post/2007/12/30/Windows-Installer-Xml-30-Extension-for-managed-installers.aspx#comment
http://www.infini-tec.de/syndication.axd?post=a4a08006-d5db-45c4-b473-3653b85d365b