<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Michael Entin's notebook</title><link>http://blogs.msdn.com/michen/default.aspx</link><description>Michael Entin's notebook</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>When jokes become reality</title><link>http://blogs.msdn.com/michen/archive/2008/12/11/when-jokes-becomes-reality.aspx</link><pubDate>Thu, 11 Dec 2008 23:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9198050</guid><dc:creator>michen</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/michen/comments/9198050.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=9198050</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=9198050</wfw:comment><description>&lt;P&gt;Couple years ago Charles Petzold wrote about &lt;A href="http://www.charlespetzold.com/etc/CSAML.html" mce_href="http://www.charlespetzold.com/etc/CSAML.html"&gt;C# Application Markup Language&lt;/A&gt; - XML syntax for C#. Go read it if you've not seen it yet.&lt;/P&gt;
&lt;P&gt;Well, it was a fool day's joke of course (the publishing date at the bottom hints about it).&lt;/P&gt;
&lt;P&gt;But yesterday, when playing with Windows Workflow Foundation rules, I've looked at the ruleset file, and discovered exactly that - huge XML file that looked familiar :), very close to Charles joke. This is how WWF internally stores the simple one-line rules that one types in the editor. Luckily for us, we don't have to type this XML, and WWF convert the human-readable C# into this monstrosity itself, so it is more an internal details than a language humans would ever use.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9198050" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/wwf/default.aspx">wwf</category><category domain="http://blogs.msdn.com/michen/archive/tags/humor/default.aspx">humor</category></item><item><title>The way NOT to write HTTPS server</title><link>http://blogs.msdn.com/michen/archive/2008/12/04/the-way-not-to-write-https-server.aspx</link><pubDate>Fri, 05 Dec 2008 10:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9179082</guid><dc:creator>michen</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/michen/comments/9179082.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=9179082</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=9179082</wfw:comment><description>&lt;P&gt;Note: posted under &lt;STRONG&gt;rant&lt;/STRONG&gt; tag, so you are warned ;)&lt;/P&gt;
&lt;P&gt;I've just got a new wi-fi router, DIR-655 from DLink. Seems like a nice router, but at least one feature is just plain horrible broken. And it is security feature, which makes me wonder how secure the rest of the code is.&lt;/P&gt;
&lt;P&gt;The router can be accessed and managed using HTTP server, like most any other one. It also has an option to enable HTTPS server, which was probably supposed to make management more secure. This is not very important if you connect from local network, but very important if you do remote management from the internet.&lt;/P&gt;
&lt;P&gt;So I decided to enable it and connect using HTTPS. Internet explorer immediately complained that there are problems with certificate and advised me against proceeding :). IE&amp;nbsp;warned me that (1) the certificate cannot be validated, (2) the certificate has expired, and (3) the certificate was issued to incorrect site. I proceeded nevertheless, checked the certificate, and indeed - it is self-signed, expired in&amp;nbsp;September 2008, and issued to site &lt;A href="http://www.dlink.com/" mce_href="http://www.dlink.com/"&gt;www.dlink.com&lt;/A&gt;, which is obviously different from 192.168.0.1 :). Worse, I asked other guys with same router to compare certificate hash - it turned out all the routers are shipped with the same certificate!&lt;/P&gt;
&lt;P&gt;I can understand the self-signing nature of the certificate - obviously DLink cannot put real certificate to the router. But why has it expired, shared by all routers, and most bizzar - why it indicates &lt;A href="http://www.dlink.com/" mce_href="http://www.dlink.com/"&gt;www.dlink.com&lt;/A&gt; as site name?&lt;/P&gt;
&lt;P&gt;They could have&amp;nbsp;easily generated an individual certificate for each router, issued to correct internal IP address&amp;nbsp;for internal-facing server and to DynDNS name for internet-facing server. It does not add any hardware cost; the software could just generate a random self-signed certificate the very first time the router boots with a new configuration. User could then configure his browser to trust this particular certificate, and know he connects to his own router, not any of the thousands other routers with same certificate.&lt;/P&gt;
&lt;P&gt;The way they did this feature, it is totally broken and makes no sense at all.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9179082" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/Rant/default.aspx">Rant</category><category domain="http://blogs.msdn.com/michen/archive/tags/non-secure/default.aspx">non-secure</category></item><item><title>Does buffer.NextRow() skips the first row in a buffer?</title><link>http://blogs.msdn.com/michen/archive/2008/10/19/does-buffer-nextrow-skips-the-first-row-in-a-buffer.aspx</link><pubDate>Sun, 19 Oct 2008 10:33:40 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9006104</guid><dc:creator>michen</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/michen/comments/9006104.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=9006104</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=9006104</wfw:comment><description>&lt;p&gt;I got a follow up question to &lt;a href="http://blogs.msdn.com/michen/archive/2007/08/31/Buffer.EndOfRowset.aspx" target="_blank" mce_href="http://blogs.msdn.com/michen/archive/2007/08/31/Buffer.EndOfRowset.aspx"&gt;my old post regarding enumerating rows in SSIS buffer&lt;/a&gt;, that suggested using following code to process rows in custom SSIS transform:&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;&lt;font color="#0000ff"&gt;while &lt;/font&gt;&lt;font color="#000000"&gt;(buffer.NextRow())        &lt;br /&gt;{         &lt;br /&gt;&amp;#160; &lt;/font&gt;&lt;font color="#008000"&gt;// do something with the row        &lt;br /&gt;&lt;/font&gt;&lt;font color="#000000"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Here is the question:&lt;/p&gt;  &lt;blockquote class="Q"&gt;buffer.NextRow() moves the pointer forward, so following your code to the letter will make you skip the first row. &lt;/blockquote&gt;  &lt;p&gt;Does it? Actually, no. It behaves like many other enumeration interfaces, e.g. COM's IEnumVariant and .NET's IEnumerator, so I'll quote documentation from &lt;a class="" href="http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.movenext.aspx" target="_blank" mce_href="http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.movenext.aspx"&gt;IEnumerator::MoveNext&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;After an enumerator is created or after the &lt;span sdata="cer" target="M:System.Collections.IEnumerator.Reset"&gt;&lt;a id="ctl00_rs1_mainContentContainer_ctl33" onclick="javascript:Track(&amp;#39;ctl00_rs1_mainContentContainer_cpe691486_c|ctl00_rs1_mainContentContainer_ctl33&amp;#39;,this);" href="http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.reset.aspx"&gt;&lt;font color="#0033cc"&gt;Reset&lt;/font&gt;&lt;/a&gt;&lt;/span&gt; method is called, an enumerator is positioned before the first element of the collection, and the first call to the &lt;span sdata="cer" target="M:System.Collections.IEnumerator.MoveNext"&gt;&lt;span class="selflink"&gt;&lt;strong&gt;MoveNext&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt; method moves the enumerator over the first element of the collection. &lt;/em&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Can you guess why it was designed this way? Let's think what would happen, if the enumerator was positioned on the first element (row in SSIS case) initially. How would we know if the first element exists at all? The enumerator would have to provide another property, like EndOfCollection - making everything more complicated. Note that as explained in my linked post, buffer.EndOfRowset() is not such an indicator. It does not tell you that enumerator finished enumerating rows in current buffer, it tells you that current buffer is the very last buffer you will receive. &lt;/p&gt;  &lt;p&gt;With enumerator initially positioned before first row, you call NextRow() which will immediately return false if the collection is empty, and position iterator to first row if it exists. So the code is correct.&lt;/p&gt;  &lt;p&gt;A note regarding my original post: the SSIS team found that this change caused too many problems for the users, so the final release of SSIS 2008 reverted back to the SSIS 2005 behavior. Interestingly, it was not a simple undo of code change, as the data flow engine has been substantially rewritten, but a new code to simulate the old behavior. Thus the &amp;quot;wrong&amp;quot; code will keep working in 2008. I still recommend changing it according to my previous blog - I think my loop just looks cleaner :).&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9006104" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/SSIS/default.aspx">SSIS</category><category domain="http://blogs.msdn.com/michen/archive/tags/SSIS+Programming/default.aspx">SSIS Programming</category></item><item><title>It's Not Easy Being BI</title><link>http://blogs.msdn.com/michen/archive/2008/06/18/it-s-not-easy-being-bi.aspx</link><pubDate>Wed, 18 Jun 2008 22:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8618039</guid><dc:creator>michen</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/michen/comments/8618039.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=8618039</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=8618039</wfw:comment><description>&lt;P&gt;A very&amp;nbsp;funny post by Matthew Roche, for everybody working in Business Intelligence:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://bi-polar23.blogspot.com/2008/06/it-not-easy-being-bi.html"&gt;http://bi-polar23.blogspot.com/2008/06/it-not-easy-being-bi.html&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8618039" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/BI/default.aspx">BI</category></item><item><title>Lookup multiple rows?</title><link>http://blogs.msdn.com/michen/archive/2008/06/07/lookup-multiple-rows.aspx</link><pubDate>Sat, 07 Jun 2008 11:37:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8579759</guid><dc:creator>michen</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/michen/comments/8579759.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=8579759</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=8579759</wfw:comment><description>&lt;P&gt;Can SSIS Lookup do what this user wants it to do? 
&lt;BLOCKQUOTE class=Q&gt;
&lt;P&gt;I have a problem with a lookup output, I get this warning: The Lookup transformation encountered duplicate reference key values when caching reference data. I know what it is, but I don't like to avoid this warning, I'd like to get all the rows (two in this case) that the lookup output provides me.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Unfortunately, no - the reason is that Lookup transform is &lt;A class="" href="http://msdn.microsoft.com/en-us/library/ms136027.aspx" target=_blank mce_href="http://msdn.microsoft.com/en-us/library/ms136027.aspx"&gt;synchronous&lt;/A&gt;, i.e. it does not add new rows or remove rows*, it just modifies the values - i.e. it can't produce two output rows for&amp;nbsp;one input&amp;nbsp;row.&lt;/P&gt;
&lt;P&gt;It would of course be possible to make an asynchronous Lookup, or provide an option, but the current Lookup is complex enough, that I think more options would kill it :)&lt;/P&gt;
&lt;P&gt;If you need this functionality, you can use Merge Join transform.&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Notes&lt;/U&gt;&lt;BR&gt;*What happens with the rows that are redirected to "not found" output in SSIS 2008? They are not deleted from the buffer (synchronous transform can't do it), they are just marked as belonging to the other path, and the components on the main path do not see them.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8579759" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/SSIS/default.aspx">SSIS</category><category domain="http://blogs.msdn.com/michen/archive/tags/SSIS+Lookup/default.aspx">SSIS Lookup</category></item><item><title>Application termination when user logs off</title><link>http://blogs.msdn.com/michen/archive/2008/04/04/Application-termination-when-user-logs-off.aspx</link><pubDate>Sat, 05 Apr 2008 03:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8359007</guid><dc:creator>michen</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/michen/comments/8359007.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=8359007</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=8359007</wfw:comment><description>&lt;P&gt;Do you know how windows terminates all the applications when user logs off? I did not think too much about this, and assumed that it is a normal process - after all the WM_QUERYENDSESSION and WM_ENDSESSION processing, the application main window closes, posts WM_QUIT and the application quits in a regular way.&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;But a recent bug reported for one of my GUI applications caused me to look deeper. The application settings, normally saved at application's exit,&amp;nbsp;were&amp;nbsp;not saves&amp;nbsp;if user logged off, and this made me look closer at what happens at logoff.&lt;/P&gt;
&lt;P&gt;This was a managed application with related code in Main() function that looked like this:&lt;/P&gt;&lt;PRE&gt;static void Main()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LoadPreferences();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Application.Run(new MainForm());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SavePreferences();&lt;BR&gt;}&lt;/PRE&gt;
&lt;P&gt;This works great when the application is closed normally. But if user logs off, the application closes, but the preferences are not saved - the code following Application.Run is never called at all. &lt;/P&gt;
&lt;P&gt;What happens? Does Application.Run throw any exception that causes the following code to be bypassed? This was ruled out rather quickly by debugger. I then assumed something in Windows Forms calls ExitProcess in response to WM_ENDSESSION, or maybe default message handler does this - but that was proved wrong too. A repro with unmanaged ATL code showed it is not related to managed libraries at all.&lt;/P&gt;
&lt;P&gt;Finally my colleguae debugged this issue a little deeper, and found that CSRSS is blatantly terminating the process after it processed the WM_ENDSESSION event. Here are the outlines of the whole sequence (for non-console applications).&lt;/P&gt;
&lt;P&gt;The user selects Start/Log off and then selects “OK” in the confirmation dialog. This calls ExitWindowsEx(EWX_LOGOFF); if during the OK button click, the CTRL key was down, it also adds the EWX_FORCE flag which makes it ignore the result of the WM_QUERYENDSESSION message (as if the applications always returned TRUE). ExitWindowsEx(EWX_LOGOFF) causes roughly the following activity to occur in the logon session’s instance of CSRSS:&lt;/P&gt;
&lt;P&gt;For each process in the session&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; For each UI thread in the process&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; For each top-level window in the thread&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Send WM_QUERYENDSESSION and get back the result&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Wait with a short timeout and show an “End program” dialog if it takes too long; if the user says “kill”, call TerminateProcess on the process and continue the “for process” loop&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If EWX_FORCE was not specified and WM_QUERYENDSESSION returned FALSE, break (and continue "UI thread loop");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Note that even if one window in one thread returned FALSE to WM_QUERYENDSESSION, windows in the other threads in the same process are still sent WM_QUERYENDSESSION&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool bDoShutdown = (all threads agreed (i.e., all windows returned TRUE to WM_QUERYENDSESSION)) or EWX_FORCE&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; For each UI thread in the process&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; For each top-level window in the thread&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Send WM_ENDSESSION(bDoShutdown);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If (bDoShutdown) wait for return (wait with a short timeout and show an “End program” dialog if it takes too long; whatever the user says, consider that the return from WM_QUERYENDSESSION)&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; If (bDoShutdown)&amp;nbsp;TerminateProcess on the process&lt;BR&gt;}&lt;BR&gt;I have omitted some details, in particular related to no-UI and console processes, but the general picture should be clear. Probably the Windows guys decided that graceful cleanup is not needed when user logs off, and all the application are closed.&lt;/P&gt;
&lt;P&gt;Since the application is forecefully terminated, the application should not rely on being able to execute any code after the message loop. Even classes like SafeHandle are not finalized.&amp;nbsp;All really important cleanup and termination code should be executed when the main form closes, or by providing a handler for the WM_ENDSESSION message . Another option (although I did not try it) is to catch WM_ENDSESSION message and terminate the message loop, then exit the application&amp;nbsp;gracefully - although this goes contrary to Windows design of killing applications fast to ensure quick log off.&lt;/P&gt;
&lt;P&gt;Update: Raymond Chen described the reasons for this behavior:&lt;BR&gt;&lt;A href="http://blogs.msdn.com/oldnewthing/archive/2008/04/21/8413175.aspx"&gt;http://blogs.msdn.com/oldnewthing/archive/2008/04/21/8413175.aspx&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8359007" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/Win32/default.aspx">Win32</category></item><item><title>Configuring .NET for running SSIS packages from custom applications</title><link>http://blogs.msdn.com/michen/archive/2008/03/14/configuring-net-for-running-ssis-packages-from-custom-applications.aspx</link><pubDate>Sat, 15 Mar 2008 01:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8212671</guid><dc:creator>michen</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/michen/comments/8212671.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=8212671</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=8212671</wfw:comment><description>&lt;P&gt;If you&amp;nbsp;&lt;A class="" href="http://blogs.msdn.com/michen/archive/2007/03/22/running-ssis-package-programmatically.aspx" mce_href="http://blogs.msdn.com/michen/archive/2007/03/22/running-ssis-package-programmatically.aspx"&gt;execute SSIS packages&lt;/A&gt; from custom applications, you own the application and thus you are responsible for configuring .NET runtime properly to get the maximum performance.&lt;/P&gt;
&lt;P&gt;.NET configuration is usually performed using .exe.config files, so it is a just matter of providing good config file. How do you know what is good? The simplest way is to look at the config file that SSIS provides, and copy the appropriate settings. Now let's take a look at DTExec.exe.config provided with SQL Server 2008 and discuss the choices made by SSIS team.&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;configuration&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;startup&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;requiredRuntime&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;&lt;FONT color=#ff0000 size=2&gt;version&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;v2.0.50727&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;lt;/&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;startup&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;runtime&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;gcServer&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;&lt;FONT color=#ff0000 size=2&gt;enabled&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;disableCommitThreadStack&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;&lt;FONT color=#ff0000 size=2&gt;enabled&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;generatePublisherEvidence&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;&lt;FONT color=#ff0000 size=2&gt;enabled&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;false&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;lt;/&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;runtime&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;configuration&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT color=#a31515&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/a5dzwzc9.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/a5dzwzc9.aspx"&gt;&lt;STRONG&gt;requiredRuntime&lt;/STRONG&gt;&lt;/A&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;- this line simply tells which version of .NET you want to use. 2.0 or above should be good.&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#a31515&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms229357.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/ms229357.aspx"&gt;&lt;STRONG&gt;gcServer&lt;/STRONG&gt;&lt;/A&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;- DTEXEC uses the "server" version of garbage collector. Server GC performs better for typical SSIS load, especially&amp;nbsp;on multiprocess machines. This is important if your SSIS package uses managed transforms (e.g. ADO.NET source, script transform, or custom transform written in .NET).&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#a31515&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/bb882564.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/bb882564.aspx"&gt;&lt;STRONG&gt;disableCommitThreadStack&lt;/STRONG&gt;&lt;/A&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;- by default .NET commits the thread stacks (i.e. reserves memory for stacks&amp;nbsp;- usually from page file). But SSIS creates a lot of threads, while typically uses little stack space, so it performs better if stack memory is not immediately committed when the thread is created. With&amp;nbsp;this option&amp;nbsp;your application&amp;nbsp;might perform a bit better and require smaller page file (note that anyway, the page file&amp;nbsp;is not really used until needed). The drawback of this choice is that application might fail if Windows is totally out of memory, and application&amp;nbsp;can't extend its stack. But in this situation something has already gone bad, and it is probably better to fail fast in this case anyway.&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#a31515&gt;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/bb629393.aspx" target=_blank mce_href="http://msdn2.microsoft.com/en-us/library/bb629393.aspx"&gt;&lt;STRONG&gt;generatePublisherEvidence&lt;/STRONG&gt;&lt;/A&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;/FONT&gt;- this tells .NET runtime the DTEXEC does not use Publisher evidence, and thus .NET does not&amp;nbsp;have to verify authenticode signatures. This increases the startup performance a little bit, but mainly prevents &lt;A class="" href="http://support.microsoft.com/kb/918644" target=_blank mce_href="http://support.microsoft.com/kb/918644"&gt;problems that may occur&amp;nbsp;when authenticode checks certificate revocation list&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Now that you know these options made by SSIS team, you may test and decide whether they are appropriate for your application as well, and copy them to your application's config file if needed.&lt;/P&gt;
&lt;P&gt;P.S. Also make sure you create SSIS package using MTA thread, see Matt's blog for details:&lt;BR&gt;&lt;A href="http://blogs.msdn.com/mattm/archive/2007/09/14/running-packages-from-custom-applications.aspx"&gt;http://blogs.msdn.com/mattm/archive/2007/09/14/running-packages-from-custom-applications.aspx&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8212671" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/SSIS/default.aspx">SSIS</category><category domain="http://blogs.msdn.com/michen/archive/tags/SSIS+Programming/default.aspx">SSIS Programming</category></item><item><title>Random() is only random if you are using it right</title><link>http://blogs.msdn.com/michen/archive/2008/02/05/Random_28002900_-is-only-random-if-you-are-using-it-right.aspx</link><pubDate>Tue, 05 Feb 2008 11:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7460700</guid><dc:creator>michen</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/michen/comments/7460700.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=7460700</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=7460700</wfw:comment><description>&lt;P&gt;I like the quote "With great power comes great responsibility" when used in regards to .NET - .NET gives one great powers, but use it wisely and know how this stuff works. &lt;/P&gt;
&lt;P&gt;Recently I saw code (it was written by a guy interviewing to our team) that demonstrated interesting problem with incorrect usage of Random class. The code generated a random position for an object, tested if it satisfied some condition; if it did not work - generated another random position, tested the new position and so on until it generated something that did work. The code to generate each position was pretty simple: create new instance of Random class, use it to generate 4 random integers. The percentage of failed position was not very big (but noticeable), the code to test the position was rather fast, and&amp;nbsp;we needed just 10 good positions to create complete configuration (all this was about a&amp;nbsp;variant of &lt;A class="" title="Battleship game on Wikipedia" href="http://en.wikipedia.org/wiki/Battleship_game" target=_blank mce_href="http://en.wikipedia.org/wiki/Battleship_game"&gt;Battleship game&lt;/A&gt;).&lt;/P&gt;
&lt;P&gt;But it took very long to generate the whole configuration - about a second on average.&lt;/P&gt;
&lt;P&gt;Playing with this code, I suddenly found that moving Random object to a member variable, so it is re-used, rather than creating new Random object&amp;nbsp;for each position, made the code 10000 times faster! Well, obviously I expected some savings since&amp;nbsp;it creates less objects, but ten thousand times? My first reaction - is the Random really such a heavy object?&lt;/P&gt;
&lt;P&gt;It turned out the problem was more interesting, and caused by the usage of default constructor. As MSDN puts it, if you use default constructor the "seed is initialized to a value based on the current time."&amp;nbsp;It actually uses GetTickCount() as the seed. Can you now spot the problem? The Random() constructor was very quick, but during the period of time when GetTickCount()&amp;nbsp;returns the same value (which is about 20ms for most chipsets),&amp;nbsp;all the Random&amp;nbsp;objects created this way&amp;nbsp;will have the same seed and generate the same &lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-ansi-language: EN-US; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;positions&lt;/SPAN&gt;! Instead of&amp;nbsp;trying new positions, the code tried the same position again and again until the GetTickCount() returned a new value. So don't generate too many Random instances - just one will behave much better in most cases.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7460700" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/.NET/default.aspx">.NET</category></item><item><title>SSIS event handler threading</title><link>http://blogs.msdn.com/michen/archive/2008/02/01/event-handler-threading.aspx</link><pubDate>Fri, 01 Feb 2008 23:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7379625</guid><dc:creator>michen</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/michen/comments/7379625.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=7379625</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=7379625</wfw:comment><description>&lt;P&gt;I've got an interesting question/statement about event handlers:&lt;/P&gt;
&lt;BLOCKQUOTE class=Q&gt;Tasks fire the same EH at the same time. My understanding is all EHs fire at the same time (Parallel).&lt;/BLOCKQUOTE&gt;
&lt;P&gt;If I understand the question correctly,&amp;nbsp;the&amp;nbsp;package has an &lt;STRONG&gt;event handler&lt;/STRONG&gt; that can&amp;nbsp;handle multiple &lt;STRONG&gt;events&lt;/STRONG&gt;, and these events fire at about the same time. What happens?&lt;/P&gt;
&lt;P&gt;Well, I did not work much with event handlers, so let's experiment and test how it works. This is really simple. I've create a package with two dummy script tasks A and B (not connected with any precedence constraints) that fail (by returning failure) and OnError event handler on the Package. The event handler contains a simple script task that prints the name of the event source:&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;MsgBox(Dts.Variables(&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;"SourceName"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;).Value, MsgBoxStyle.Information, &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;"Event Handler"&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;What will be the result of executing this? Will we get two message boxes at the same time, or sequentially two message boxes? &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;The answer is - two message boxes popup sequentially one after another, but never at the same time. Ssometimes A is the first, sometimes B. The event handler (like any other task) is not reentrable and only a single instance of an event handler can be running at a time, thus the second event has to wait for the event handler to finish processing the first event before processing the next one.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7379625" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/SSIS/default.aspx">SSIS</category></item><item><title>Functional sort in C#</title><link>http://blogs.msdn.com/michen/archive/2007/12/11/functional-sort-in-c.aspx</link><pubDate>Tue, 11 Dec 2007 22:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6738041</guid><dc:creator>michen</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/michen/comments/6738041.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=6738041</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=6738041</wfw:comment><description>&lt;P&gt;On an internal mailing list, we were discussing functional languages, and this Haskell sort code:&lt;/P&gt;
&lt;P&gt;&lt;SPAN lang=EN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN"&gt;qsort []&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = []&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN lang=EN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN"&gt;qsort (x:xs) = qsort (&lt;A href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:filter"&gt;&lt;SPAN style="BORDER-RIGHT: windowtext 1pt; PADDING-RIGHT: 0in; BORDER-TOP: windowtext 1pt; PADDING-LEFT: 0in; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt; COLOR: #006600; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt; TEXT-DECORATION: none; text-underline: none; mso-border-alt: none windowtext 0in"&gt;filter&lt;/SPAN&gt;&lt;/A&gt; (&lt;/SPAN&gt;&lt;SPAN lang=EN style="FONT-SIZE: 10pt; COLOR: #006600; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN lang=EN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN"&gt; x) xs) &lt;A href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:."&gt;&lt;SPAN style="BORDER-RIGHT: windowtext 1pt; PADDING-RIGHT: 0in; BORDER-TOP: windowtext 1pt; PADDING-LEFT: 0in; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt; COLOR: #006600; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt; TEXT-DECORATION: none; text-underline: none; mso-border-alt: none windowtext 0in"&gt;++&lt;/SPAN&gt;&lt;/A&gt; [x] &lt;A href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:."&gt;&lt;SPAN style="BORDER-RIGHT: windowtext 1pt; PADDING-RIGHT: 0in; BORDER-TOP: windowtext 1pt; PADDING-LEFT: 0in; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt; COLOR: #006600; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt; TEXT-DECORATION: none; text-underline: none; mso-border-alt: none windowtext 0in"&gt;++&lt;/SPAN&gt;&lt;/A&gt; qsort (&lt;A href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:filter"&gt;&lt;SPAN style="BORDER-RIGHT: windowtext 1pt; PADDING-RIGHT: 0in; BORDER-TOP: windowtext 1pt; PADDING-LEFT: 0in; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt; COLOR: #006600; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt; TEXT-DECORATION: none; text-underline: none; mso-border-alt: none windowtext 0in"&gt;filter&lt;/SPAN&gt;&lt;/A&gt; (&lt;A href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:&amp;amp;gt;="&gt;&lt;SPAN style="BORDER-RIGHT: windowtext 1pt; PADDING-RIGHT: 0in; BORDER-TOP: windowtext 1pt; PADDING-LEFT: 0in; PADDING-BOTTOM: 0in; BORDER-LEFT: windowtext 1pt; COLOR: #006600; PADDING-TOP: 0in; BORDER-BOTTOM: windowtext 1pt; TEXT-DECORATION: none; text-underline: none; mso-border-alt: none windowtext 0in"&gt;&amp;gt;=&lt;/SPAN&gt;&lt;/A&gt; x) xs)&lt;/SPAN&gt;&lt;SPAN lang=RU style="mso-ansi-language: RU"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;While trying to explain how this code works (which is very different from what it looks like&amp;nbsp;to C++/C# programmers due to &lt;A class="" href="http://en.wikipedia.org/wiki/Lazy_evaluation" target=_blank mce_href="http://en.wikipedia.org/wiki/Lazy_evaluation"&gt;lazy evaluation&lt;/A&gt;) I've come up with following C#&amp;nbsp;code (with Linq) that is logically similar to Haskell version. Obviously, Haskell code is much nicer though.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: Consolas"&gt;static&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt; &lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;T&amp;gt; Qsort&amp;lt;T&amp;gt;(&lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;T&amp;gt; s) &lt;SPAN style="COLOR: blue"&gt;where&lt;/SPAN&gt; T : &lt;SPAN style="COLOR: #2b91af"&gt;IComparable&lt;/SPAN&gt;&amp;lt;T&amp;gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: #2b91af"&gt;IEnumerator&lt;/SPAN&gt;&amp;lt;T&amp;gt; e = s.GetEnumerator();&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (e.MoveNext())&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T x = e.Current;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;foreach&lt;/SPAN&gt; (T t &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; Qsort(s.Skip(1).Where(y =&amp;gt; y.CompareTo(x) &amp;lt; 0)))&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;yield&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; t;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;yield&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; x;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;foreach&lt;/SPAN&gt; (T t &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; Qsort(s.Skip(1).Where(y =&amp;gt; y.CompareTo(x) &amp;gt;= 0)))&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;yield&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; t;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Consolas"&gt;&lt;FONT face=Arial&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6738041" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.msdn.com/michen/archive/tags/Functional/default.aspx">Functional</category></item><item><title>SQL 2008 &amp; VS 2008</title><link>http://blogs.msdn.com/michen/archive/2007/12/04/SQL-2008-and-VS-2008.aspx</link><pubDate>Wed, 05 Dec 2007 09:42:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6663107</guid><dc:creator>michen</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/michen/comments/6663107.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=6663107</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=6663107</wfw:comment><description>Currently SQL Business Intelligence Development Studio (BIDS) and all the project types (AS, IS and RS) live in Visual Studio 2005. So don't try to open a solution that contains IS project in VS 2008 yet. What about final SQL 2008 - now that Visual Studio 2008 is released - what are the plans for BIDS and support of BI projects VS 2008?...(&lt;a href="http://blogs.msdn.com/michen/archive/2007/12/04/SQL-2008-and-VS-2008.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6663107" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/SSIS/default.aspx">SSIS</category><category domain="http://blogs.msdn.com/michen/archive/tags/Katmai/default.aspx">Katmai</category></item><item><title>VALVe/Steam horrors</title><link>http://blogs.msdn.com/michen/archive/2007/11/23/Steam.aspx</link><pubDate>Sat, 24 Nov 2007 02:20:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6492442</guid><dc:creator>michen</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/michen/comments/6492442.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=6492442</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=6492442</wfw:comment><description>&lt;P&gt;(Update: VALVe has removed the worst recommendations that I described below.&amp;nbsp;I don't know if my article&amp;nbsp;had any influence on this. They still want to run the Steam as a service though).&lt;/P&gt;
&lt;P&gt;I originally planned to use this blog for work-related stuff only, but the VALVe drove me mad, so I decided to write this.&lt;/P&gt;
&lt;P&gt;I run Vista on my home PC (and at work too, actually), and all of us run as non-admins (not Vista's protected admin, but real non-admin). My son plays Counter Strike, and thus has to run&amp;nbsp;&lt;A class="" title=Evil href="http://www.steampowered.com/" target=_blank mce_href="http://www.steampowered.com"&gt;Steam&lt;/A&gt;. It worked mostly fine, until recently it started to ask to install Steam as a service. Well, a service for internet-facing software seems not good. Before installing, I decided to find out more about it, and the finding are much worse than I've ever expected. Here is an official FAQ from VALVe that I've found:&lt;/P&gt;
&lt;P&gt;&lt;A class="" title="Evil FAQ" href="http://support.steampowered.com/cgi-bin/steampowered.cfg/php/enduser/std_adp.php?p_faqid=460" target=_blank mce_href="http://support.steampowered.com/cgi-bin/steampowered.cfg/php/enduser/std_adp.php?p_faqid=460"&gt;http://support.steampowered.com/cgi-bin/steampowered.cfg/php/enduser/std_adp.php?p_faqid=460&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Here are some of the recommendations from this FAQ:&lt;/P&gt;
&lt;BLOCKQUOTE class=QR&gt;
&lt;UL&gt;
&lt;LI&gt;Go to: Start &amp;gt; Run and type in: cmd &lt;/LI&gt;
&lt;LI&gt;Type in the following:&lt;BR&gt;net localgroup Administrators /add Local service &lt;/LI&gt;
&lt;LI&gt;Restart your computer. &lt;/LI&gt;&lt;/UL&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;To put it simply, they ask to add Local service account to Administrators group! Apparently, they did not bother to find out the list of specific permissions they need, but simply figured out that administrator permissions "fix" the problem. That alone would be pretty bad, but&amp;nbsp;they did even worse.&amp;nbsp;Instead of creating special account for Steam or using some account that already has administrative permissions,&amp;nbsp;they want to add account &lt;STRONG&gt;shared&lt;/STRONG&gt; by multiple services to Administrators group, thus making not only their service, but &lt;STRONG&gt;all the services&lt;/STRONG&gt; running on the machine much more dangerous and less secure.&lt;/P&gt;
&lt;P&gt;Then VALVe gives even stranger recommendation:&lt;/P&gt;
&lt;BLOCKQUOTE class=QR&gt;
&lt;P&gt;If during this process you receive the error: &lt;SPAN class=bold&gt;System error 5 has occurred. Access is denied&lt;/SPAN&gt; Please follow these instructions and then try the above steps again:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Go to &lt;SPAN class=bold&gt;Start &amp;gt; Control Panel &amp;gt; System &amp;amp; Maintenance &amp;gt; Administrative Tools &amp;gt; Local Security Policy&lt;/SPAN&gt;. &lt;/LI&gt;
&lt;LI&gt;In the left pane, expand &lt;SPAN class=bold&gt;Local Policies &amp;gt; Security Options&lt;/SPAN&gt;.&lt;/LI&gt;
&lt;LI&gt;Double-click &lt;SPAN class=bold&gt;Network Security LAN Manager Authentication Level&lt;/SPAN&gt;.&lt;/LI&gt;
&lt;LI&gt;In the drop down list, change the default setting (NTLMv2 only) to &lt;SPAN class=bold&gt;Send LM &amp;amp; NTLM - use NTLMv2 session if negotiated&lt;/SPAN&gt;.&lt;/LI&gt;&lt;/OL&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Changing LanMan level for Vista Home users to completely unsecure level? Maybe I'm missing something, but I can't see any reason to do this. This setting affects authentication to remove computers (mostly affects NT &lt;STRONG&gt;domain&lt;/STRONG&gt;, should be of no concern to internet game), it would not help&amp;nbsp;one to&amp;nbsp;avoid &lt;STRONG&gt;local &lt;/STRONG&gt;Access Denied&amp;nbsp;while performing the steps above. It is not only completely unsecure, but IMO it also does not make any sense at all.&lt;/P&gt;
&lt;P&gt;So these guys &lt;BR&gt;1) don't understand anything about security, &lt;BR&gt;2) can't write software that does not require administrative privileges,&lt;BR&gt;3) don't even try to use the specific minimum list of permissions,&lt;BR&gt;4) ask user to make completely unreasonable and unsecure configuration changes to OS configuration, that affect not just Steam service, but the whole machine,&lt;BR&gt;5) want to run network-facing service with admin rights.&lt;/P&gt;
&lt;P&gt;Now would you trust the guys who are clueless about security, obviously can't write secure code, and apparently don't care about YOUR machine security at all, to run network-facing service with admin rights on your machine? I don't. I think I'll try stay away from them from now on.&lt;/P&gt;
&lt;P&gt;P.S. As with everything else in this blog, this post represents my personal opinion, and does not represent the view of my employer.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6492442" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/Rant/default.aspx">Rant</category><category domain="http://blogs.msdn.com/michen/archive/tags/non-secure/default.aspx">non-secure</category></item><item><title>SQL Server ETL Survey: Win a Zune!</title><link>http://blogs.msdn.com/michen/archive/2007/11/20/ETL-Survey.aspx</link><pubDate>Wed, 21 Nov 2007 02:11:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6445882</guid><dc:creator>michen</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/michen/comments/6445882.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=6445882</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=6445882</wfw:comment><description>&lt;P&gt;Improve SSIS and win a Zune:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://mscuillume.smdisp.net/Collector/Survey.ashx?Name=SqlETLSurvey2"&gt;https://mscuillume.smdisp.net/Collector/Survey.ashx?Name=SqlETLSurvey2&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6445882" width="1" height="1"&gt;</description></item><item><title>SQL 2008 November CTP is available</title><link>http://blogs.msdn.com/michen/archive/2007/11/19/November_5F00_CTP.aspx</link><pubDate>Mon, 19 Nov 2007 20:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6405966</guid><dc:creator>michen</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/michen/comments/6405966.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=6405966</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=6405966</wfw:comment><description>&lt;P&gt;Get it from &lt;A href="https://connect.microsoft.com/SQLServer"&gt;https://connect.microsoft.com/SQLServer&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;One of the improvements in this build is the ability to persist Lookup&amp;nbsp;reference data&amp;nbsp;and use non-OLEDB sources for Lookup.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6405966" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/SSIS+Lookup/default.aspx">SSIS Lookup</category><category domain="http://blogs.msdn.com/michen/archive/tags/Katmai/default.aspx">Katmai</category></item><item><title>Deploying packages</title><link>http://blogs.msdn.com/michen/archive/2007/11/07/deploying-packages.aspx</link><pubDate>Wed, 07 Nov 2007 12:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5955354</guid><dc:creator>michen</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/michen/comments/5955354.aspx</comments><wfw:commentRss>http://blogs.msdn.com/michen/commentrss.aspx?PostID=5955354</wfw:commentRss><wfw:comment>http://blogs.msdn.com/michen/rsscomments.aspx?PostID=5955354</wfw:comment><description>&lt;P mce_keep="true"&gt;How can one deploy packages programmatically? Here is the original question - &lt;/P&gt;
&lt;BLOCKQUOTE class=Q&gt;
&lt;P mce_keep="true"&gt;Is it possible to deploy a package programmatically? We have an application which has a work flow for approval of object. If the object (ssis package) is approved by the concerned authority it has to be deployed to sql server. How can this code be integrated into the application?&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;First, what does it mean to deploy a package? The package is simply a document (DTSX file). SSIS&amp;nbsp;utilities (DTEXEC, DTUTIL and other)&amp;nbsp;natively support three locations for&amp;nbsp;such files:&amp;nbsp;the actual file in the OS file system, a row in SQL table, or virtualized file in SSIS storage (which wraps the previous two). If you use custom application to run your packages, you can store them anywhere you want (e.g. application resources) - and use &lt;A class="" href="http://technet.microsoft.com/en-us/library/microsoft.sqlserver.dts.runtime.package.loadfromxml.aspx" target=_blank mce_href="http://technet.microsoft.com/en-us/library/microsoft.sqlserver.dts.runtime.package.loadfromxml.aspx"&gt;LoadFromXML&lt;/A&gt; to load it.&lt;/P&gt;
&lt;P&gt;Since package is just a file, in most cases simply copying a file to destination directory location, or to SQL table is all it takes to deploy a package. One can use SSIS API&amp;nbsp;(like &lt;A class="" href="http://blogs.msdn.com/controlpanel/blogs/is%20it%20possivle%20to%20deploy%20a%20package%20programmatically? we have an application which have a work flow for approval of object. if the object(ssis package) is approved by the concerned authority it has to be deployed to sql server. How can this code be integrated into the application?" target=_blank mce_href="http://blogs.msdn.com/controlpanel/blogs/is it possivle to deploy a package programmatically? we have an application which have a work flow for approval of object. if the object(ssis package) is approved by the concerned authority it has to be deployed to sql server. How can this code be integrated into the application?"&gt;SaveToSqlServer&lt;/A&gt;) to do this, run DTUTIL, or copy file using Win32 or .NET APIs.&lt;/P&gt;
&lt;P&gt;In some cases it is necessary to make some adjustments to the package, e.g. if you have multiple packages calling each other - modify the parent package to correctly reference new location of child package(s). This can be done using SSIS API as well, but it is easier and usually better for maintainability to do this using SSIS configurations - edit the configuration values instead of the package itself.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5955354" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/michen/archive/tags/SSIS/default.aspx">SSIS</category></item></channel></rss>