Debugging - A Journeyhttp://blogs.msdn.com/b/hmahrt/Useful bits and pieces I pick up in my daily life as a professional debuggeren-USTelligent Evolution Platform Developer Build (Build: 5.6.50428.7875)My experience with .NET Native Previewhttp://blogs.msdn.com/b/hmahrt/archive/2014/05/21/my-experience-with-net-native-preview.aspxWed, 21 May 2014 15:31:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10523785Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10523785http://blogs.msdn.com/b/hmahrt/archive/2014/05/21/my-experience-with-net-native-preview.aspx#comments<p>Hello everyone,</p>
<p>I just published this new post on our team blog over here: <a href="http://aka.ms/Oz6rgn">http://aka.ms/Oz6rgn</a></p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10523785" width="1" height="1">windows store appWindows 8.1performance hubVisual Studio 2013XAML UI Responsiveness toolSurface RTFailed the WACK Test – How do I get more information?http://blogs.msdn.com/b/hmahrt/archive/2013/04/11/failed-the-wack-test-how-do-i-get-more-information.aspxThu, 11 Apr 2013 16:37:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10410361Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10410361http://blogs.msdn.com/b/hmahrt/archive/2013/04/11/failed-the-wack-test-how-do-i-get-more-information.aspx#comments<pre class="code">&nbsp;</pre>
<p>Hello everyone,</p>
<p>So you finished your Windows Store app and are eager to get it into the Store &ndash; but it failed the Windows App Certification Kit (WACK) test and the results do not provide sufficient information about the reason of the failure. What can you do to get more details?</p>
<p>The first thing to look at are the internal logs of WACK. You can find them in the following folder: <strong>C:\Users\&lt;user&gt;\AppData\Local\Microsoft\AppCertKit </strong>(Especially interesting are the .txt files. Look out for the name of the test that your app failed.)</p>
<p>If you need to review the content of the <strong>xperfTemp.txt</strong> file, e.g. for the performance launch test, you may find that it is empty, or that its content does not reflect the output from the test anymore. That is because it is a temporary file and gets overwritten by different tests. In this case, you have two options:</p>
<ol>
<li>You can run exactly the same command that is listed in the (internal) log file, which WACK used to extract the timing information from the .ETL file</li>
<li>You can run the test that failed manually, and only that test</li>
</ol>
<p>To run a single test manually, you can use the following command: <strong>Appcert.exe test -apptype windowsstoreapp -packagefullname <em>&lt;full package id&gt; </em>-reportoutputpath c:\temp\testpackage.xml &ndash;testid <em>&lt;test id&gt;</em></strong></p>
<p>You can look up the test id here: <strong>C:\Program Files (x86)\Windows Kits\8.0\App Certification Kit\configuration.xml</strong> (E.g. the index for the <em>Performance Launch</em> test is 43)</p>
<p>I hope this helps, should your app ever fail a test in WACK and you don&rsquo;t know why.</p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10410361" width="1" height="1">windows store appWACKWindows App Certification KitAsynchronous Programming in .NET 4.5 – in Spanishhttp://blogs.msdn.com/b/hmahrt/archive/2013/02/22/asynchronous-programming-in-net-4-5-in-spanish.aspxFri, 22 Feb 2013 14:51:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10396203Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10396203http://blogs.msdn.com/b/hmahrt/archive/2013/02/22/asynchronous-programming-in-net-4-5-in-spanish.aspx#comments<p>Hello everyone,</p>
<p>My colleague Jos&eacute; Ortega and I just published some articles about the new .NET 4.5 keywords <span style="color: #0000ff;"><a href="http://msdn.microsoft.com/en-us/library/vstudio/hh156528.aspx">await</a> </span>and <span style="color: #0000ff;"><a href="http://msdn.microsoft.com/en-us/library/vstudio/hh156513.aspx">async</a></span>, and about the <a href="http://msdn.microsoft.com/en-us/library/dd460717.aspx">Task Parallel Library (TPL)</a>. As they are in Spanish we put them on his blog. If you are interested, please have a look here: <a title="http://blogs.msdn.com/b/desarrolloweb/archive/2013/02/22/asincronia-en-net-4-5.aspx" href="http://blogs.msdn.com/b/desarrolloweb/archive/2013/02/22/asincronia-en-net-4-5.aspx">http://blogs.msdn.com/b/desarrolloweb/archive/2013/02/22/asincronia-en-net-4-5.aspx</a></p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10396203" width="1" height="1">.net 4.5asyncawaitTask Parallel LibraryTPLSpanishBe careful when making DataTransferManager.DataRequested an async functionhttp://blogs.msdn.com/b/hmahrt/archive/2012/11/20/don-t-make-datatransfermanager-datarequested-an-async-function.aspxTue, 20 Nov 2012 16:02:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10370247Helge Mahrt1http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10370247http://blogs.msdn.com/b/hmahrt/archive/2012/11/20/don-t-make-datatransfermanager-datarequested-an-async-function.aspx#comments<p>Hello everyone,</p>
<p>Update: Thanks to Nigel Sampson for correcting my post. :)</p>
<p>As you probably already know, .NET Framework 4.5 introduced two new keywords: <a href="http://msdn.microsoft.com/en-us/library/hh156513.aspx">async</a> and <a href="http://msdn.microsoft.com/en-us/library/hh156528.aspx">await</a>. (Look <a href="http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx">here</a> for information about how to use them.)</p>
<p>If you are adding the possibility to <a href="http://msdn.microsoft.com/en-us/library/windows/apps/xaml/Hh871368(v=win.10).aspx">share content of your Windows Store application</a>, you will have to implement the <a href="http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.applicationmodel.datatransfer.datatransfermanager.datarequested.aspx">DataTransferManager.DataRequested</a> callback. From the MSDN documentation:</p>
<blockquote>
<p>This event is fired when a sharing operation starts&mdash;typically when the user taps the Share charm, although it is also fired if your app starts a share operation programmatically.</p>
</blockquote>
<p>As with the callbacks on the App class (<a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.application.onlaunched.aspx">OnLaunched</a>, <a href="http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.application.onactivated.aspx">OnActivated</a> etc.), you can just convert this function into an asynchronous one. However, take the following sample implementation:</p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td>
<pre class="scroll"><code class="csharp">async void App_DataRequested(DataTransferManager sender, DataRequestedEventArgs args) <br />{<br />&nbsp;&nbsp;&nbsp;&nbsp; DataRequest req = args.Request;<br />&nbsp;&nbsp;&nbsp;&nbsp; await Task.Delay(500);<br />&nbsp;&nbsp;&nbsp;&nbsp; req.Data.Properties.Title = "Test";<br />&nbsp;&nbsp;&nbsp;&nbsp; req.Data.SetText("Hello World!");<br />&nbsp;&nbsp;&nbsp;&nbsp; req.GetDeferral().Complete(); <br />}</code></pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>If you use this code, when you are sharing data from your application, you will get a message like one of the following:</p>
<p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88-metablogapi/4263.image_5F00_55373D06.png"><img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88-metablogapi/5153.image_5F00_thumb_5F00_33D7976A.png" alt="image" width="244" height="121" border="0" /></a><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88-metablogapi/0044.image_5F00_32FF3180.png"><img style="margin: 0px; display: inline; background-image: none;" title="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88-metablogapi/3000.image_5F00_thumb_5F00_40654486.png" alt="image" width="244" height="128" border="0" /></a></p>
<p>&nbsp;</p>
<p>&ldquo;What happened?&rdquo;, you may ask. Well, there is a trick to making this callback asynchronous.</p>
<p>If we think about <a href="http://msdn.microsoft.com/en-us/magazine/hh456403.aspx">the consequences of using async and await</a>, and about the nature of the share operation, we can explain this behavior easily: Once the call to <strong>DataRequested</strong> returns, it expects the <strong>DataRequest</strong> to contain the information we want to share. However, if our callback is marked with <strong>async</strong> and we add a call using <strong>await</strong>, it will cause the execution flow to leave the function until we are notified by the awaiter that we can continue. <strong>DataTransferManager</strong>, however, does not know about this and will assume that we have completed the request correctly.</p>
<p>Fortunately, there is a way to tell <strong>DataTransferManager</strong> to wait for us: using the <a href="http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.applicationmodel.datatransfer.datarequest.getdeferral.aspx">GetReferral</a> method. Before, we only called it at the end of our callback, to mark the DataRequest as complete. However, if we call it at the beginning we will be able to call asynchronous methods:</p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td>
<pre class="scroll"><code class="csharp">async void App_DataRequested(DataTransferManager sender, DataRequestedEventArgs args) <br />{&nbsp;&nbsp;&nbsp;&nbsp; DataRequest req = args.Request;&nbsp;&nbsp;&nbsp;&nbsp; DataRequestDeferral deferral = req.GetDeferral();&nbsp;&nbsp;&nbsp;&nbsp; await Task.Delay(500);&nbsp;&nbsp;&nbsp;&nbsp; req.Data.Properties.Title = "Test";&nbsp;&nbsp;&nbsp;&nbsp; req.Data.SetText("Hello World!");&nbsp;&nbsp;&nbsp;&nbsp; deferral.Complete(); <br />}</code></pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Please note that if the asynchronous operations will take more than 200ms you have to <a href="http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.applicationmodel.datatransfer.datapackage.setdataprovider.aspx">use a DataProviderHandler</a> to prevent the operation from timing out.</p>
<p>I hope this helps you.</p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10370247" width="1" height="1">Windows 8.net 4.5asyncwindows store appshare contentawaitHow to avoid “The directory data type cannot be converted to/from a native DS data type” (0x8000500C) in managed codehttp://blogs.msdn.com/b/hmahrt/archive/2012/08/01/how-to-avoid-the-directory-data-type-cannot-be-converted-to-from-a-native-ds-data-type-0x8000500c-in-managed-code.aspxWed, 01 Aug 2012 16:56:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10335697Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10335697http://blogs.msdn.com/b/hmahrt/archive/2012/08/01/how-to-avoid-the-directory-data-type-cannot-be-converted-to-from-a-native-ds-data-type-0x8000500c-in-managed-code.aspx#comments<p>Hello everyone,</p>
<p>We may find ourselves in the situation where we need to access custom properties that have been defined for objects in our Active Directory. However, using the managed class <code class="csharp"><a href="http://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry.aspx"> DirectoryEntry</a></code> we may receive an exception with the error code <b>0x8000500CL</b> when accessing the custom property the following way:</p>
<p><code class="csharp">myDirectoryEntry.Properties["myProperty"]</code></p>
<p>As the error text indicates, the cause for this issue is the lack of information about how to convert the value of our custom property into a managed object. <code class="csharp">DirectoryEntry</code> does not offer the possibility to specify this meta information, so how can we access our custom properties?</p>
<p>Luckily there is COM library, <b>ActiveDS</b>, which exposes (amongst others) the following two functions:</p>
<ul>
<li><code class="csharp"><a href="http://msdn.microsoft.com/en-us/library/aa706103(VS.85).aspx">IADsPropertyList::GetPropertyItem</a></code></li>
<li><code class="csharp"><a href="http://msdn.microsoft.com/en-us/library/aa706108(v=VS.85).aspx">IADsPropertyList::PutPropertyItem</a></code></li>
</ul>
<p>Once we add a reference to the library to our Visual Studio project, selecting it from the COM tab (it appears as "<b>Active DS Type Library</b>"), we can implement a wrapper like the following:</p>
<p></p>
<p><code class="csharp">class PropertyHelper<br /> {<br /> &nbsp;&nbsp;&nbsp;&nbsp;public static List<object> GetProperty(DirectoryEntry entry, String propertyName, ADSTYPEENUM adsType)<br /> &nbsp;&nbsp;&nbsp;&nbsp;{<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// make sure to get the properties from the DC<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.RefreshCache(new String[] { propertyName });<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// get the property list from the underlying native object<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IADsPropertyList propList = (IADsPropertyList)entry.NativeObject;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// return values<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List<object> values = new List<object>();<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// get the native property object<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IADsPropertyEntry propEntry = (IADsPropertyEntry)propList.GetPropertyItem(propertyName, (int)adsType);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// iterate over the values set for the property<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach (IADsPropertyValue propValue in propEntry.Values)<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch (adsType)<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case ADSTYPEENUM.ADSTYPE_CASE_IGNORE_STRING:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values.Add(propValue.CaseIgnoreString);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case ADSTYPEENUM.ADSTYPE_CASE_EXACT_STRING:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values.Add(propValue.CaseExactString);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case ADSTYPEENUM.ADSTYPE_DN_STRING:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values.Add(propValue.DNString);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case ADSTYPEENUM.ADSTYPE_INTEGER:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values.Add(propValue.Integer);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case ADSTYPEENUM.ADSTYPE_BOOLEAN:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values.Add(propValue.Boolean);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case ADSTYPEENUM.ADSTYPE_LARGE_INTEGER:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values.Add(propValue.LargeInteger);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case ADSTYPEENUM.ADSTYPE_OCTET_STRING:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values.Add(propValue.OctetString);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new System.NotImplementedException("Handling of this ADSTYPE is not implemented");<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return values;<br /> &nbsp;&nbsp;&nbsp;&nbsp;}<br /> }<br /> </object></object></object></code></p>
<p>We can then access our custom property using the following call:</p>
<p><code class="csharp">var sReturnValues = PropertyHelper.GetProperty(entry, "sAttribute", ADSTYPEENUM.ADSTYPE_CASE_IGNORE_STRING);</code></p>
<p>Implementing a similar wrapper for setting the values of our custom property should be straightforward from here. I hope this helps.</p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10335697" width="1" height="1">Active DirectoryDirectoryEntryDirectoryEntry.Properties0x8000500Ccustom propertydata type conversionCOM wrapperHow to listen for Printer Connections?http://blogs.msdn.com/b/hmahrt/archive/2012/04/09/how-to-listen-for-printer-connections.aspxMon, 09 Apr 2012 11:41:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10291857Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10291857http://blogs.msdn.com/b/hmahrt/archive/2012/04/09/how-to-listen-for-printer-connections.aspx#comments<p>Hello everyone,</p>
<p>The other day, a customer wanted to listen (in C++) for newly added printers. He was trying to use <code class="csharp"><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd162722(v=vs.85).aspx"> FindFirstPrinterChangeNotification</a></code> but was never notified.</p>
<p>It turned out that he was adding network printers, which belonged to a different print server (effectively creating a &ldquo;Printer Connection&rdquo;) and that <code class="csharp">FindFirstPrinterChangeNotification</code> only works for printers belonging to the local print server (i.e. to the local machine):</p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td>The <strong>FindFirstPrinterChangeNotification</strong> function creates a change notification object and returns a handle to the object. You can then use this handle in a call to one of the wait functions to monitor changes to the printer or print server.</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>There is no equivalent to <code class="csharp">FindFirstPrinterChangeNotification</code>, which listens for new/changed Printer Connections &ndash; and a polling mechanism was not an option. However, there is another way, using WMI.</p>
<p>First of all, here is an overview of the necessary steps. I will explain the <b>why</b> and the <b>how</b> in more detail later.</p>
<ol>
<li>To begin, we scan for all existing printer connections.</li>
<li>Then we have to retrieve the current user&rsquo;s SID.</li>
<li>We start listening for changes to the registry key under which printer connections are stored. (We need to know the SID for this.)</li>
<li>Whenever we are notified, we do another scan and compare the result with the previous scan. The differences are the changes made to the printer connections.</li>
</ol>
<p>&nbsp;</p>
<h1>Scanning for current Printer Connections</h1>
<p>Using the function <code class="csharp"><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd162692(v=vs.85).aspx"> EnumPrinters</a></code>, supplying the <b>PRINTER_ENUM_CONNECTIONS</b> constant, we can get a list of all currently connected printers and their details.</p>
<p>&nbsp;</p>
<h1>Getting the current user&rsquo;s SID</h1>
<p>Please refer to the following article to see how to get the SID of the currently logged in user: <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa446670(v=vs.85).aspx"> Getting the Logon SID in C++</a></p>
<p>&nbsp;</p>
<h1>Listen for changes made to a registry key</h1>
<p>The following article describes how to receive WMI event notifications: <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa390425(v=vs.85).aspx"> Example: Receiving Event Notifications Through WMI</a></p>
<p>By using the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa393040(v=vs.85).aspx"> <code class="csharp">RegistryKeyChangeEvent</code> class</a> we can apply this to our problem. For each Printer Connection, a new registry key is created below <b>HKEY_CURRENT_USER\Printers\Connections</b>. However, due to the following limitation we cannot use this path, but have to use <b>HKEY_USERS\<i>&lt;SID&gt;</i>\Printers\Connetions</b>instead:</p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td>Changes to the <strong>HKEY_CLASSES_ROOT</strong> and <strong>HKEY_CURRENT_USER</strong> hives are not supported by <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa393039(v=vs.85).aspx"> <strong xmlns="http://www.w3.org/1999/xhtml">RegistryEvent</strong></a> or classes derived from it, such as <strong>RegistryKeyChangeEvent</strong>.</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>The WQL query to use in this case would look like this:</p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td><code class="csharp">"SELECT * FROM RegistryKeyChangeEvent WHERE KeyPath='&lt;SID&gt;\\\\Printers\\\\Connections' AND Hive='HKEY_USERS'"</code></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Unfortunately, we cannot use the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa393042(v=vs.85).aspx"> <code class="csharp">RegistryValueChangeEvent</code></a> (because the scope of the query would be too big (we&rsquo;d receive an error message), so we can only know <b>when</b> something changed below the <b>Printers\Connections</b> key, but not <b>what.</b> This is why we have to rely on <b>EnumPrinters</b>.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>I hope this information helps you to implement your own notification mechanism for Printer Connections.</p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10291857" width="1" height="1">WMIregistrywmi eventsprinter connectionlistenProblem running decoupled WMI providers simultaneouslyhttp://blogs.msdn.com/b/hmahrt/archive/2012/02/21/problem-running-decoupled-wmi-providers-simultaneously.aspxTue, 21 Feb 2012 16:46:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10270578Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10270578http://blogs.msdn.com/b/hmahrt/archive/2012/02/21/problem-running-decoupled-wmi-providers-simultaneously.aspx#comments<p>Hello everyone,</p>
<p>The other day, I had a customer who implemented a decoupled WMI provider in her application. She was running two instances simultaneously and when calling a function of the WMI provider, one of the two instances would crash with the following error message:</p>
<p><b>Non-static method requires a target.</b></p>
<p>The process that crashed would always be the one that was started first.</p>
<p>&nbsp;</p>
<h1>What happened?</h1>
<p>The error we were seeing originated from a <b>System.Reflection.TargetException</b>, which was thrown because a call to</p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td><code class="csharp">mscorlib_ni!System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, Boolean)</code></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>was made, providing <b>null</b> as the first parameter. This value was returned when looking up the value <code class="csharp"><b>id=<i>a5f6c650-836b-4597-8831-11b8a80c310e</i></b></code> in a hashtable that is unique to each instance.</p>
<p>I checked the customer&rsquo;s code and saw that she registered a <a href="http://msdn.microsoft.com/en-us/library/system.management.instrumentation.managementkeyattribute.aspx"> ManagementKey</a> "id" and assigned a <a href="http://msdn.microsoft.com/en-us/library/system.guid.aspx"> Guid</a> to it. The values that assigned during this particular run were:</p>
<ul>
<li><code class="csharp">b3d731d4-a5c4-4184-87b4-e2ac35ee1c54</code> for the instance that was launched first</li>
<li><code class="csharp"><b><i>a5f6c650-836b-4597-8831-11b8a80c310e</i></b></code> for the second one</li>
</ul>
<p><i>WMI was trying to look up the WMI provider in the first instance, using the management key registered by the second instance.</i></p>
<p>&nbsp;</p>
<h1>Why it happened</h1>
<p>Long story short: The behavior of having two decoupled providers of the same class running simultaneously is not well defined in .NET and therefore this scenario is not supported.</p>
<p>The WMI core tries to aggregate the instances coming from the same class. The WMI Provider Subsystem will forward the request to the both instances, which results in one instance returning successfully while the other one will fail.</p>
<p>&nbsp;</p>
<h1>Conclusion</h1>
<p>WMI was not designed to implement distributed, per-instance "health check"-like mechanisms. Rather, there should be one single provider which is responsible for probing each instance.</p>
<p>&nbsp;</p>
<p>I hope this proved helpful to you.</p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10270578" width="1" height="1">WMI providerdecoupled WMI providerWMISystem.Reflection.TargetExceptionTFS 2010: An error occurred while validating. HRESULT = '8000000A'http://blogs.msdn.com/b/hmahrt/archive/2012/02/10/tfs-2010-an-error-occurred-while-validating-hresult-8000000a.aspxFri, 10 Feb 2012 13:51:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10266527Helge Mahrt1http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10266527http://blogs.msdn.com/b/hmahrt/archive/2012/02/10/tfs-2010-an-error-occurred-while-validating-hresult-8000000a.aspx#comments<p>Hello everyone,</p>
<p>I&rsquo;ve had a few cases already, where our customers came across a rare problem: They were building Visual Studio Installer projects with Team Build of Team Foundation Server 2010 and the build failed with the error: &ldquo;<b>An error occurred while validating.&nbsp;HRESULT = '8000000A'</b>&rdquo;. When running the build process again, it usually succeeded.</p>
<p>The problem was almost impossible to reproduce and unpredictable in its manner: The customers had several setup projects in their solution and the error appeared seemingly random during the compilation of each of them.</p>
<p>If you ever experience this issue, here is what may be&nbsp;happening and what you can do to work around it:</p>
<p>The error code you are seeing was introduced with this KB: <a href="http://support.microsoft.com/kb/2444922">http://support.microsoft.com/kb/2444922</a></p>
<p>There is a race condition that sometimes used to cause hangs when building setup projects on the command line. It turned out to be an issue that was very risky to tackle, so the decision was made to return this error code (<b>8000000A</b>) instead.</p>
<p>Considering the high risk of solving&nbsp;the problem, and the fact that Visual Studio Installer projects have been deprecated in Visual Studio 2010 (see &ldquo;<b>Visual Studio Setup and Deployment Projects</b>&rdquo;: <a href="http://msdn.microsoft.com/en-us/library/ee721500.aspx">http://msdn.microsoft.com/en-us/library/ee721500.aspx</a>, it is very unlikely that this issue will be fixed.</p>
<p>Instead, there are a few recommendations on how to work around the problem:</p>
<ul>
<li>Script the build process to check for this particular error message. If it appears, rebuild the setup project.</li>
<li>Attempt to automate Visual Studio to load and build the project in the IDE and not from the command line. (This one is more difficult to implement.)</li>
</ul>
<p>&nbsp;</p>
<p>I hope this saves you a headache or two, while trying to figure out where this error code is coming from.</p>
<p>&nbsp;</p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10266527" width="1" height="1">VS2010Team BuildVisual Studio InstallerTFSTFS2010Setup Project8000000AWPF ignoring BiDi control charactershttp://blogs.msdn.com/b/hmahrt/archive/2011/12/15/wpf-ignoring-bidi-control-characters.aspxThu, 15 Dec 2011 16:15:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10248161Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10248161http://blogs.msdn.com/b/hmahrt/archive/2011/12/15/wpf-ignoring-bidi-control-characters.aspx#comments<div>
<p>Hello everyone,</p>
<p>Have you ever tried using the following <b>BiDirectional </b>(<i>Disclaimer: The content linked here is not from Microsoft:</i> <a href="http://en.wikipedia.org/wiki/Bi-directional_text">http://en.wikipedia.org/wiki/Bi-directional_text</a> <a href="http://unicode.org/reports/tr9/">http://unicode.org/reports/tr9/</a>) control characters in WPF?</p>
</div>
<ul>
<li><b>LRM</b> (U+200E, Left-To-Right Mark)</li>
<li><b>LRE </b>(U+202A, Left-To-Right Embedding)</li>
<li><b>LRO</b> (U+202D, Left-To-Right Override)</li>
<li><b>PDF</b> (U+202C, Pop Directional Formatting)</li>
</ul>
<p>If the answer is yes, you will have noticed that WPF is completely ignoring them. (That is: It is ignoring all <b>except</b> for the <b>LRM</b> mark, which only works when the <i>Language</i> is set to "<b>en-US</b>"!) <br /> Silverlight, on the other hand, does regard them and renders the affected text correctly.</p>
<p>Here is a comparison, first in WPF and then in Silverlight:</p>
<p><img border="0" alt="Windows Presentation Foundation" src="http://blogs.msdn.com/resized-image.ashx/__size/253x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88/0474.WPF.jpg" /> <img border="0" alt="Silverlight" src="http://blogs.msdn.com/resized-image.ashx/__size/287x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88/8345.Silverlight.jpg" /></p>
<p>&nbsp;</p>
<p>I used exactly the same code for both examples. (Please note that I replaced the real BiDi control characters with bold text (e.g. <b>[LRM]</b>), to avoid confusion and compatibility issues.)</p>
<p></p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td>
<pre class="scroll"><code class="csharp">&lt;StackPanel FlowDirection="RightToLeft" Language="fa-IR"&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;StackPanel Margin="10"&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock&nbsp; FlowDirection="LeftToRight"&gt;LRM&lt;/TextBlock&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock&gt;<b>[LRM]</b>0 <b>[LRM]</b>1 <b>[LRM]</b>2 <b>[LRM]</b>3 <b>[LRM]</b>4 <b>[LRM]</b>5 <b>[LRM]</b>6 <b>[LRM]</b>7 <b>[LRM]</b>8 <b>[LRM]</b>9&lt;/TextBlock&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;/StackPanel&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;StackPanel Margin="10"&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock FlowDirection="LeftToRight"&gt;LRE &amp; PDF&lt;/TextBlock&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock&gt;<b>[arabic text][LRE]</b><span style="font-family: Calibri; font-size: small;" face="Calibri" size="3">?</span>0 1 2 3 4 5 6 7 8 9<b>[</b><b>PDF][arabic text]</b>&lt;/TextBlock&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;/StackPanel&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;StackPanel Margin="10"&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock FlowDirection="LeftToRight"&gt;LRO&lt;/TextBlock&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock&gt;<b>[LRO]</b>0 1 2 3 4 5 6 7 8 9&lt;/TextBlock&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;/StackPanel&gt;<br /> &lt;/StackPanel&gt; </code></pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Note how WPF does change the way it treats the LRM character when you set the <i>Language</i> attribute to <b>en-US</b>:</p>
<p><img border="0" alt="Windows Presentation Foundation" src="http://blogs.msdn.com/resized-image.ashx/__size/266x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88/4137.WPFenUS.jpg" /></p>
<p>&nbsp;</p>
<p>However curious this may seem: <b>This is</b> <b>actually not a bug, but desired behavior!</b></p>
<p>The reason for the difference is that WPF offers a different, higher-level way of implementing bidirectional text, to enable the implementation of RichText controls. (See here for a detailed guide on BiDi in WPF: <a href="http://msdn.microsoft.com/en-us/library/aa350685.aspx">http://msdn.microsoft.com/en-us/library/aa350685.aspx</a></p>
<p>The correct implementation (in WPF) for the example above would look like this:</p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td>
<pre class="scroll"><code class="csharp">&lt;StackPanel FlowDirection="RightToLeft" Language="fa-IR"&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;StackPanel Margin="10"&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock &nbsp;FlowDirection="LeftToRight"&gt;LRM&lt;/TextBlock&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock&gt;&lt;Span FlowDirection="LeftToRight"&gt;0 1 2 3 4 5 6 7 8 9&lt;/Span&gt;&lt;/TextBlock&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;/StackPanel&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;StackPanel Margin="10"&gt;<br /> &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;TextBlock FlowDirection="LeftToRight"&gt;LRE &amp; PDF&lt;/TextBlock&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock&gt;[arabic text]&lt;Run FlowDirection="LeftToRight"&gt;0 1 2 3 4 5 6 7 8 9&lt;/Run&gt;[arabic text]&lt;/TextBlock&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;/StackPanel&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;StackPanel Margin="10"&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock FlowDirection="LeftToRight"&gt;LRO&lt;/TextBlock&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;TextBlock&gt;&lt;Run FlowDirection="LeftToRight"&gt;0 1 2 3 4 5 6 7 8 9&lt;/Run&gt;&lt;/TextBlock&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;/StackPanel&gt;<br /> &lt;/StackPanel&gt;<br /> </code>
</pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>I hope this was helpful!</p>
<p>Cheers,<br />Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10248161" width="1" height="1">WPFBiDirectionLRMLREPDFLROBiDiBy DesignFlowDirectionSilverlightFile Server Resource Manager: Creating a custom classification module - Running the Classification Modulehttp://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-running-the-classification-module.aspxTue, 18 Oct 2011 15:03:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10227002Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10227002http://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-running-the-classification-module.aspx#comments<p>Hello everyone,</p>
<p>This is the final part of my mini-series on how to create a custom file classification module that can be run by the File Server Resource Manager which ships with Windows Server 2008 R2. (If you missed the other parts, you can <a title="return to the index by clicking here" href="http://blogs.msdn.com/b/hmahrt/archive/2011/10/03/creating-a-classification-module-for-file-server-resource-manager.aspx">return to the index by clicking here</a>)</p>
<p>&nbsp;</p>
<h2>Running the module</h2>
<p>To execute our classification module we need at least one classification property and one classification rule.</p>
<p>First I created two example properties in the management console of the FSRM:</p>
<p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88/2465.fsrm_5F00_properties.png"><img border="0" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88/2465.fsrm_5F00_properties.png" /></a><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88/7380.fsrm_5F00_properties.png"></a></p>
<p>&nbsp;</p>
<p>Only if there are properties defined we can create rules. I created a rule for the &ldquo;File Name&rdquo; property and selected our module:</p>
<p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88/7268.file_5F00_name_5F00_classifier.png"><img border="0" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/464x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88/7268.file_5F00_name_5F00_classifier.png" /></a></p>
<p>Please note that the field &ldquo;Property value to be assigned&rdquo; is disabled. This is because our module is going to supply the value.</p>
<p>&nbsp;</p>
<p>Finally I scheduled the FSRM to run a classification on C:\temp tomorrow:</p>
<p><a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88/4111.schedule.png"><img border="0" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-47-88/4111.schedule.png" /></a></p>
<p>Optionally, instead of scheduling the classification to a later point in time, you can decide to run it right now.</p>
<p>&nbsp;</p>
<p>That concludes my mini-series on creating a custom classification module. I hope it proved to be useful for you!</p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10227002" width="1" height="1">ClassificationWindows Server 2008 R2File Server Resource ManagerClassification ModuleFSRMFile Server Resource Manager: Creating a custom classification module - Registrationhttp://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-registration.aspxTue, 18 Oct 2011 14:56:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10226997Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10226997http://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-registration.aspx#comments<p>Hello everyone,</p>
<p>This is part 3 of my mini-series on how to create a custom file classification module that can be run by the File Server Resource Manager which ships with Windows Server 2008 R2. (If you missed the other parts, you can <a title="return to the index by clicking here" href="http://blogs.msdn.com/b/hmahrt/archive/2011/10/03/creating-a-classification-module-for-file-server-resource-manager.aspx">return to the index by clicking here</a>)</p>
<p>&nbsp;</p>
<h2>Registering the Classification Module</h2>
<p>The registration is done in three steps:</p>
<ol>
<li>Register the class library in the Global Assembly Cache</li>
<li>Register the class library as a COM server</li>
<li>Register the class COM server as a classification module with the FSRM</li>
</ol>
<p><b>Very important:</b> The FSRM is a 64bit service. Please make sure you execute the following commands from the 64bit version of the Visual Studio command line.</p>
<p>&nbsp;</p>
<p><strong>Register with the Global Assembly Cache</strong></p>
<p>To register our class library with the GAC we just need to execute the following command:</p>
<p>"<code class="csharp">gacutil /I &lt;class library&gt; /f</code>" (Replace &lt;class library&gt; with the path + filename of your class library)</p>
<p>To add an assembly to the GAC it needs to be signed with a strong name. During development this can be quite bothersome. You can skip this by using the Strong Name Tool (<a href="http://msdn.microsoft.com/en-us/library/k5b5tt23(v=VS.71).aspx)">http://msdn.microsoft.com/en-us/library/k5b5tt23(v=VS.71).aspx)</a>&nbsp;(<b>CAUTION</b> Use this option only during development. Adding an assembly to the skip verification list creates a security vulnerability. A malicious assembly could use the fully specified assembly name (assembly name, version, culture, and public key token) of the assembly added to the skip verification list to fake its identity. This would allow the malicious assembly to also skip verification.)</p>
<p>&nbsp;</p>
<p><strong>Register as COM server</strong></p>
<p>Registering our class library as a COM server is even simpler:</p>
<p>&ldquo;<code class="csharp">regasm &lt;class library&gt;</code>&rdquo; (Replace &lt;class library&gt; with the path + filename of your class library)</p>
<p>&nbsp;</p>
<p><strong>Register with the File Server Resource Manager</strong></p>
<p>Finally we need to tell the FSRM about the existence of your module. The easiest way is to save the following code in a *.vbs file and to execute this file from an elevated command prompt.</p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td><code class="csharp"> Dim classMan<br /> Dim parameters(0)<br /> Dim module<br /> set classMan = CreateObject( "Fsrm.FsrmClassificationManager")<br /> parameters(0) = "StaticModuleName=File Name Classifier"<br /> set module = classMan.CreateModuleDefinition(2)<br /> module.ModuleClsid = "B99FC137-4934-40C5-BB31-04C04B201479" <br /> module.Name = "File Name Classifier"<br /> module.Enabled = true<br /> module.Account = 3<br /> module.NeedsExplicitValue = false<br /> module.Parameters = parameters<br /> module.Commit()</code></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Please pay special attention to the following lines:</p>
<ul>
<li><code class="csharp">module.ModuleClsid = "B99FC137-4934-40C5-BB31-04C04B201479"</code></li>
<ul>
<li>This has to correspond to the GUID attribute that we defined for our class</li>
</ul>
<li><code class="csharp">module.NeedsExplicitValue = false</code></li>
<ul>
<li>This defines which of the following two functions is called: <code class="csharp">DoesPropertyValueApply</code> or <code class="csharp">GetPropertyValueToApply</code></li>
</ul>
</ul>
<p>&nbsp;</p>
<p>In the final part of this mini-series I will show you <a title="how to execute our custom classification module" href="http://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-running-the-classification-module.aspx">how to execute our custom classification module</a>.</p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10226997" width="1" height="1">ClassificationWindows Server 2008 R2File Server Resource ManagerClassification ModuleFSRMFile Server Resource Manager: Creating a custom classification module - Implementationhttp://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-implementation.aspxTue, 18 Oct 2011 14:47:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10226993Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10226993http://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-implementation.aspx#comments<p>Hello everyone,</p>
<p>This is part 3 of my mini-series on how to create a custom file classification module that can be run by the File Server Resource Manager which ships with Windows Server 2008 R2. (If you missed the other parts, you can <a title="return to the index by clicking here" href="http://blogs.msdn.com/b/hmahrt/archive/2011/10/03/creating-a-classification-module-for-file-server-resource-manager.aspx">return to the index by clicking here</a>)</p>
<h2>The Implementation</h2>
<p>To create a custom classification module you need to implement the IFsrmClassifierModuleImplementation interface. (See here for a description of the interface's members: <a href="http://msdn.microsoft.com/en-us/library/dd878721(VS.85).aspx">http://msdn.microsoft.com/en-us/library/dd878721(VS.85).aspx)</a> For that you will need to add a reference to the srmlib.dll to your project. (The DLL can be found in the system32 folder of Windows Server 2008 R2 or, alternatively, it comes with the Windows SDK.)</p>
<p>Here is a very simple implementation code:</p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td>
<pre class="scroll"><code class="csharp">using System;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Text;<br />using System.Runtime.InteropServices;<br />using Microsoft.Storage;<br /><br />namespace FileServerClassificationModules<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;/// All classification modules are COM servers.<br />&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;[ComVisible(true), Guid("B99FC137-4934-40C5-BB31-04C04B201479")]<br />&nbsp;&nbsp;&nbsp;&nbsp;public class FileNameClassifier : IFsrmClassifierModuleImplementation<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private DateTime _lastModified;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;summary&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// The file's name.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/// &lt;/summary&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private String _name;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void DoesPropertyValueApply(string property, string Value, out bool applyValue, Guid idRule, Guid idPropDef)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// This will never be called if the module is registered correctly, but<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// it needs to be implemented anyway.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;applyValue = false;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void GetPropertyValueToApply(string property, out string Value, Guid idRule, Guid idPropDef)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// I am not checking for the property. To improve performance I create 1 classification<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// module per property type - to avoid having to do costly string comparisons.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// In this case I would call the module "File Name Module". I would use it for every property<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// that I'd want to set to the file's name.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value = _name;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public object LastModified<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get { return _lastModified; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void OnBeginFile(IFsrmPropertyBag propertyBag, object[] arrayRuleIds)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_name = propertyBag.Name;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void OnEndFile() { }<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void OnLoad(IFsrmPipelineModuleDefinition moduleDefinition, out FsrmPipelineModuleConnector moduleConnector)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_lastModified = DateTime.Now;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// bind this module to the module definition<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;moduleConnector = new FsrmPipelineModuleConnector();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;moduleConnector.Bind(moduleDefinition, this);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void OnUnload() { }<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void UseRulesAndDefinitions(IFsrmCollection Rules, IFsrmCollection propertyDefinitions) { }<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></code>
</pre>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>In the next chapter I will show you <a title="how to register the class library so that the File Server Resource Manager recognizes it as a classification module" href="http://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-registration.aspx">how to register the class library so that the File Server Resource Manager recognizes it as a classification module</a>.</p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10226993" width="1" height="1">File Server Resource Manager: Creating a custom classification module - Introductionhttp://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-introduction.aspxTue, 18 Oct 2011 14:35:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10226991Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10226991http://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-introduction.aspx#comments<p>Hello everyone,</p>
<p>This is the first part of my mini-series on how to create a custom file classification module that can be run by the File Server Resource Manager which ships with Windows Server 2008 R2. (If you missed the other parts, you can <a title="return to the index by clicking here" href="http://blogs.msdn.com/b/hmahrt/archive/2011/10/03/creating-a-classification-module-for-file-server-resource-manager.aspx">return to the index by clicking here</a>)</p>
<p>&nbsp;</p>
<h2>Introduction</h2>
<p>What is the File Resource Manager?</p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td>Quoted from <a href="http://technet.microsoft.com/en-us/library/dd758765(WS.10).aspx">http://technet.microsoft.com/en-us/library/dd758765(WS.10).aspx</a></td>
</tr>
<tr>
<td>
<p>Most applications manage files based on the directory they are contained in. This leads to complicated file layouts that require much attention from administrators and lead to frustration for users.</p>
<p>To reduce the cost and risk associated with this type of data management, the File Classification Infrastructure uses a platform that allows administrators to classify files and apply policies based on that classification. The storage layout is unaffected by data management requirements and the organization can adapt more easily to a changing business and regulatory environment.</p>
Files can be classified in a variety of ways - today, classification is commonly performed manually. The File Classification Infrastructure in Windows Server 2008 R2 allows organizations to convert these manual processes into automated policies. Administrators can specify file management policies, based on a file&rsquo;s classification, and automatically apply corporate requirements for managing data, based on business value. They can easily modify the policies and use tools that support classification to manage their files.</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>To get a better overview on how FSRM works, I recommend having a look at the following PowerPoint presentation: <a href="http://ecn.channel9.msdn.com/o9/pdc09/ppt/SVR02.pptx">http://ecn.channel9.msdn.com/o9/pdc09/ppt/SVR02.pptx</a></p>
<p>Here is the information important for us:</p>
<ul>
<li>There are two ways to classify documents</li>
<ol>
<li>Get/Set Property API (this is what the customer used)</li>
<li>File Classification Infrastructure Extensions</li>
</ol></ul>
<ol></ol>
<p>Windows Server 2008 R2 already comes with two FCI extensions:</p>
<ol>
<li>Folder Classifier<ol>
<li>assigns properties according to file location</li>
</ol></li>
<li>Content Classifier<ol>
<li>assigns properties according to string / regex matching in the file's content</li>
</ol></li>
</ol>
<p>They allow assigning static values only. This is a problem e.g. if you want to use the name of the file that you are classifying as the value of a property. Luckily, there is the possibility to implement your own extension.</p>
<p>For that, first of all we have to implement the module itself. Classification modules are COM servers, so I created a class library in .NET using C#. (Windows Server 2008 R2 comes with .NET 3.5, but if you installed the .NET 4.0 Framework you can use that as well.)</p>
<p>Once done, we need to register the library as a COM server and additionally tell the File Server Resource Manager about its existence.</p>
<p>&nbsp;</p>
<div>
<h2>The Classification Flow</h2>
</div>
<p>To create a custom classification module you need to implement the <code class="csharp">IFsrmClassifierModuleImplementation</code> interface. (See here for a description of the interface's members: <a href="http://msdn.microsoft.com/en-us/library/dd878721(VS.85).aspx">http://msdn.microsoft.com/en-us/library/dd878721(VS.85).aspx</a>)</p>
<p>The call flow of the interface during the classification process is the following:</p>
<ol>
<li><code class="csharp">UseRulesAndDefinitions</code> - Called at the start of a classification session. (Later on there will be used only Guids to refer to rules. Should you need information about them at a later point, this is a good moment to cache it.)</li>
<li>For each file:</li>
<ol>
<li><code class="csharp">OnBeginFile</code> - Here is where you are handed the property bag with information about the file that is currently being classified. (This is where you obtain dynamic information that you can use to set the properties' values.) It will be called once per file.</li>
<li>For each rule:</li>
<ol>
<li><code class="csharp">DoesPropertyValueApply</code> - This will only be called when <code class="csharp">IFsrmClassifierModuleDefinition.NeedsExplicitValue</code> is <code class="csharp">false</code>. In this case you can only decide whether the static value that was set when the rule was created applies to this file or not.</li>
<li><code class="csharp">GetPropertyValueToApply</code> - This will only be called when <code class="csharp">IFsrmClassifierModuleDefinition.NeedsExplicitValue</code> is <code class="csharp">true</code>. In this case you can return any value you would like to assign to the property.</li>
</ol>
<li><code class="csharp">OnEndFile</code> - This will be called once per file and allows you to execute clean-up code, should it be necessary.</li>
</ol>
<li><code class="csharp">OnUnload</code> - Called when the classification finished and the module is unloaded.</li>
</ol>
<p>&nbsp;</p>
<p>In the next chapter I will show you <a title="a simple implementation of this interface" href="http://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-implementation.aspx">a simple implementation of this interface</a>.</p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10226991" width="1" height="1">ClassificationWindows Server 2008 R2File Server Resource ManagerClassification ModuleFSRMFile Server Resource Manager: Creating a custom classification module - Indexhttp://blogs.msdn.com/b/hmahrt/archive/2011/10/03/creating-a-classification-module-for-file-server-resource-manager.aspxMon, 03 Oct 2011 16:22:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10219212Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10219212http://blogs.msdn.com/b/hmahrt/archive/2011/10/03/creating-a-classification-module-for-file-server-resource-manager.aspx#comments<p>Hello everyone,</p>
<p>The other day a customer wanted to classify his documents using the File Resource Manager of Windows Server 2008 R2. He needed to classify a huge amount of files with dynamic values in a short amount of time. He found that opening the files programmatically, one by one, writing their classification properties and closing the file again was pretty slow. ("Between 2 and 6 seconds per file" slow.)</p>
<p>The recommended and faster way is to implement your own classification module. In the following mini-series I will explain how to do this.</p>
<h1>Index</h1>
<hr style="width: 100%;" width="100%" /><ol>
<li><a title="Introduction" href="http://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-introduction.aspx">Introduction</a></li>
<li><a title="Implementation" href="http://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-implementation.aspx">Implementation of the class library</a></li>
<li><a title="Registration" href="http://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-registration.aspx">Registration of the class library</a></li>
<li><a title="Running the Classification Module" href="http://blogs.msdn.com/b/hmahrt/archive/2011/10/18/file-server-resource-manager-creating-a-custom-classification-module-running-the-classification-module.aspx">Running the Classification&nbsp;Module</a></li>
</ol>
<p></p>
<hr style="width: 100%;" width="100%" />
<p></p>
<p>I hope this tutorial proves to be&nbsp;useful to you!</p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10219212" width="1" height="1">ClassificationWindows Server 2008 R2File Server Resource ManagerClassification ModuleFSRMCommunication between Windows Services and Applications in Windows Vista and higherhttp://blogs.msdn.com/b/hmahrt/archive/2011/09/15/communication-between-windows-services-and-applications-in-windows-vista-and-higher.aspxThu, 15 Sep 2011 11:54:00 GMT91d46819-8472-40ad-a661-2c78acb4018c:10211596Helge Mahrt0http://blogs.msdn.com/b/hmahrt/rsscomments.aspx?WeblogPostID=10211596http://blogs.msdn.com/b/hmahrt/archive/2011/09/15/communication-between-windows-services-and-applications-in-windows-vista-and-higher.aspx#comments<p>Hello everyone,</p>
<p>If you are trying to migrate a Windows service that communicates with other applications via window messages to Windows Vista or higher (Vista, Server 2008 (+ R2),&nbsp;7),&nbsp;or if you are implementing a new service, please remember: <strong>Windows Vista introduced a new concept called "Session 0 Isolation"!</strong></p>
<p></p>
<p>Have a look at the following quote from the paper published here:&nbsp;<a href="http://msdn.microsoft.com/en-us/windows/hardware/gg463353">http://msdn.microsoft.com/en-us/windows/hardware/gg463353</a></p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td>
<p><span style="font-size: small;" size="3"><span style="font-family: Calibri;" face="Calibri">In Windows&reg; XP, Windows Server&reg; 2003, and earlier versions of the Windows operating system, all services run in the same session as the first user who logs on to the console. This session is called Session 0. Running services and user applications together in Session 0 poses a security risk because services run at elevated privilege and therefore are targets for malicious agents who are looking for a way to elevate their own privilege level.</span></span></p>
<p><span style="font-size: small;" size="3"><span style="font-family: Calibri;" face="Calibri">In Windows Vista&reg;, Windows Server 2008, and later versions of Windows, the operating system mitigates this security risk by isolating services in Session 0 and making Session 0 noninteractive. Only system processes and services run in Session 0. The first user logs on to Session 1, and subsequent users log on to subsequent sessions. This means that services never run in the same session as users&rsquo; applications and are therefore protected from attacks that originate in application code.</span></span></p>
</td>
</tr>
</tbody>
</table>
<p><span style="font-size: small;" size="3"><span style="font-family: Calibri;" face="Calibri"></span></span>&nbsp;&nbsp;</p>
<p>This has the following&nbsp;consequence:</p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td>
<p><span style="font-size: small;" size="3"><span style="font-family: Calibri;" face="Calibri">A service tries to use window message functions such as <strong>SendMessage</strong> and <strong>PostMessage</strong> to communicate with an application. This does not work because the application is running in a different session and therefore has a different message queue. The messages never arrive at their destination. The same is true for applications that try to communicate with services through window messages.</span></span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong>Starting from Windows Vista, services are not able to communicate with applications via window messages anymore!</strong></p>
<p>The paper also suggests alternatives to window messages:</p>
<table style="background-color: #dcdcdc;" border="0">
<tbody>
<tr>
<td>
<p><span style="font-size: small;" size="3"><span style="font-family: Calibri;" face="Calibri">Use a client/server mechanism such as remote procedure call (RPC) or named pipes rather than window messages to communicate with applications.</span></span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>I hope this was useful to anyone. Many people are not aware of the session 0 isolation and don't expect this behavior.</p>
<p>Cheers,</p>
<p>Helge Mahrt</p><div style="clear:both;"></div><img src="http://blogs.msdn.com/aggbug.aspx?PostID=10211596" width="1" height="1">windows 7window messagessession0 isolationwindows vistasession0windows serviceWindows Server 2008 R2windows server 2008