<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Matt Evans's Weblog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/mattev/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/mattev/feed.xml</link>
    <description />
    <lastBuildDate>Tue, 16 Apr 2019 05:18:26 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Analyzing your App Insights Data with the ELK stack</title>
      <link>https://docs.microsoft.com/archive/blogs/mattev/analyzing-your-app-insights-data-with-the-elk-stack</link>
      <pubDate>Thu, 12 Feb 2015 10:02:00 GMT</pubDate>
      <dc:creator><![CDATA[Matt Evans - Visual Studio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mattev/2015/02/12/analyzing-your-app-insights-data-with-the-elk-stack/</guid>
      <description><![CDATA[Application Insights is a telemetry and instrumentation offering that gives you a great out-of-box...]]></description>
      <content:encoded><![CDATA[<p>Application Insights is a telemetry and instrumentation offering that gives you a great out-of-box experience for understanding what is happening with your sites, apps, and mobile apps.&nbsp; The data viewing experience in the new Azure portal extends from high level summary charts of your usage all the way down to viewing individual diagnostic events.&nbsp; The team is adding new capabilities to the portal experience at a rapid cadence, and for most users, most of the time, the portal is the best place to quickly understand what's going on with your code.</p>
<p>One of the great new features the App Insights team has delivered is the ability to export your telemetry data.&nbsp; Enabling and configuring this is described here:</p>
<p><a href="https://azure.microsoft.com/en-us/documentation/articles/app-insights-export-telemetry/">https://azure.microsoft.com/en-us/documentation/articles/app-insights-export-telemetry/</a></p>
<p>Once you can get the raw data out of App Insights, you can import into other analysis or visualization tools.&nbsp; Today I'll talk a little bit about how you might want to do that with the ELK stack.&nbsp; ELK refers to "Elastic Search, Logstash, Kibana", and is a suite of open source technologies designed to build rapid data visualizations of semi-structured text data.&nbsp; ElasticSearch is the indexing system, logstash is an agent for pumping data into elasticsearch, and kibana is a dashboard building tool that works well with ElasticSearch.</p>
<p>For this posting, I'll be talking about the "custom event" event type that AI exposes.&nbsp; A custom event allows you to manually insert telemetry points into your code base.&nbsp; You choose the event name, and you can attach properties or measures to the event as necessary.&nbsp; Your mileage may vary if you work with other event types.</p>
<p>AppInsights custom events are exported as Azure storage blobs into the storage account you configure when you enable exporting.&nbsp; The blob files themselves are organized by application, date, and hour.&nbsp; Within each per-hour directory,&nbsp; one or more blob files with semi-random names will be present.&nbsp; Each blob file will have 1 or more events.&nbsp; Each event will be a separate JSON object, one event per line of text.</p>
<p>If you'd like to do a one-time download of all of your blobs, doing a recursive copy with AzCopy.exe is a great way to get the data onto a local machine.&nbsp; A more elegant solution might be to have a worker role that monitors the storage accounts for new blobs, and retrieves them as needed.</p>
<p>Once you've got a blob, you need to insert its contents into ElasticSearch.&nbsp; You could adapt the code in the article above and have it use ElasticSearch.NET to insert each line of JSON into your ES instance.</p>
<p>Consider the following code:</p>
<pre class="scroll"><code class="csharp">IElasticsearchClient client = new ElasticsearchClient();<br /> <br /> string indexName = "myevents";<br /> string typeName = "aievent";<br /> <br /> foreach(var blob in directoryFullOfBlobs)<br /> {<br /> string s = blob.ReadAllText();<br /> string lowerCaseEventText = "";<br /> foreach (string eventString in s.Split(new[] { '\r', '\n' }))<br /> {<br /> // eventString is a JSON object representing 1 event..<br /> if (eventString != "")<br /> {<br /> lowerCaseEventText = eventString.ToLower();<br /> client.Index(indexName, typeName, lowerCaseEventText);<br /> }<br /> }<br /> }<br /></code><code class="csharp"> </code></pre>
<p><span style="font-family: arial black,avant garde;"><em><strong><code class="csharp">(Warning: Don't run this code and insert your events into ES just yet.&nbsp; Read the whole post to see why)</code></strong></em></span></p>
<p><span style="font-family: arial black,avant garde;"><code class="csharp">Assuming that you have some enumerable of blob files, this code would read them, split each file up into separate events, transform the entire event into lower case, and then insert the event </code><code class="csharp">body into the default ES server, using index "myevents" and object type "aievent".</code></span></p>
<p><span style="font-family: arial black,avant garde;"><code class="csharp"></code><code class="csharp">(The case transformation is optional - in our environment, we've seen some case inconsistencies which break certain reports, so I normalize the JSON to all lower case)</code></span></p>
<p><span style="font-family: arial black,avant garde;"><code class="csharp">Note that we're not using the "L" part of the ELK stack here - you could probably create a Logstash plugin that does the event insertion instead of writing custom code.&nbsp; If you come up with a good one, please let me know.</code></span></p>
<p><span style="font-family: arial black,avant garde;"><code class="csharp">At this point, your AI events should start showing up in kibana.&nbsp; However, if you start looking at the data, you may notice some things aren't showing up quite the way you like.&nbsp; For one thing, the locale field of your users is normally in the form of "languagecode-countrycode", with examples being en-US, fr-FR, or en-GB.&nbsp; The default string tokenizer in ES splits up this field on the dash character.&nbsp; Kibana draws you a pie chart with values like "en", "GB", and "fr".&nbsp; This is not what you want.</code></span></p>
<p><span style="font-family: arial black,avant garde;"><code class="csharp">Similarly, if your event names have any sort of separator characters in them, they'll be tokenized into segments.</code></span></p>
<p><code class="csharp"></code>Finally, when we inserted these events, we didn't specify an ID for them, so ES auto-generated an id for each event we inserted.&nbsp; This is&nbsp;nice, but it means that if we re-insert the same event more than once, it will be duplicated in our ES index and subsequently in any reports we build with kibana.</p>
<p>app insights events&nbsp;already have a durable unique ID, so&nbsp;it would be nice if we could tell ES to simply honor the id that's already present.&nbsp; &nbsp;</p>
<p>It turns out, we can fix all three of these problems by adding an ES <em><strong>mapping</strong></em> to our index before we insert any data into it.&nbsp; The mapping I present here is one that I've been happy with; you can use it as a starting point for your own ES indexes.&nbsp; The mapping does 3 things.&nbsp;</p>
<p>1) it maps the ai internal event ID to&nbsp;be the ES document&nbsp;ID.&nbsp;</p>
<p>2) it adds a 2nd property for the event name that won't be tokenized.&nbsp; This lets you report&nbsp;on the full event name</p>
<p>3) it adds a 2nd property for the locale name that won't be tokenized.&nbsp; This lets you report on the full locale value</p>
<p>&nbsp;</p>
<p>To create this mapping, first create the index</p>
<p>curl -XPUT <a href="https://localhost:9200/indexname/">https://localhost:9200/indexname/</a></p>
<p>the inject the mapping:</p>
<p>curl -XPOST <a href="https://localhost:9200/indexname/aievent/_mapping">https://localhost:9200/indexname/aievent/_mapping</a>&nbsp;</p>
<pre class="scroll"><code class="js">{<br /> "aievent": {<br /> "_id": {<br /> "path": "internal.data.id"<br /> },<br /> "properties": {<br /> "context": {<br /> "properties": {<br /> "device": {<br /> "properties": {<br /> "locale": {<br /> "type": "multi_field",<br /> "fields": {<br /> "locale": { "type": "string" },<br /> "originallocale": { "type": "string", "index": "not_analyzed" }<br /> }<br /> }<br /> }<br /> }<br /> }<br /> },<br /> "event": {<br /> "properties": {<br /> "name": {<br /> "type": "multi_field",<br /> "fields": {<br /> "name": { "type": "string" },<br /> "originalname": { "type": "string", "index": "not_analyzed" }<br /> }<br /> }<br /> }<br /> }<br /> }<br /> }<br /> }<br /> </code></pre>
<p>This mapping adds "event.originalname" and "locale.originallocale" to the list of properties you can visualize in Kibana.</p>
<p>Note that you can add this mapping <em>after</em> you've inserted your data, but the ID assignment and additional fields will only show up for data you insert after the mapping is created.&nbsp; It is best to apply the mapping to an empty index and then insert your AI data afterwards.</p>
<p>If you're interested in seeing your AI telemetry data in kibana,&nbsp;and building custom visualizations above and beyond what the AI portal supports today, hopefully this posting gives you a headstart.&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Working around the Chrome Data Loading Bug in LightSwitch 2012 RC</title>
      <link>https://docs.microsoft.com/archive/blogs/mattev/working-around-the-chrome-data-loading-bug-in-lightswitch-2012-rc</link>
      <pubDate>Mon, 25 Jun 2012 09:30:47 GMT</pubDate>
      <dc:creator><![CDATA[Matt Evans - Visual Studio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mattev/2012/06/25/working-around-the-chrome-data-loading-bug-in-lightswitch-2012-rc/</guid>
      <description><![CDATA[With the RC release of LightSwitch 2012, some users have noticed data load (the &quot;red x&quot;)...]]></description>
      <content:encoded><![CDATA[<p>With the RC release of LightSwitch 2012, some users have noticed data load (the &quot;red x&quot;) problems when using Chrome (and very old versions of Firefox).</p>  <p>The underlying issue is how Chrome asks for data and how the OData libraries that LightSwitch uses respond to those requests.</p>  <p>Chrome appends the &quot;Accept-Charset&quot; HTTP header onto outgoing requests -- even those that come from the Silverlight plugin that hosts the Ligthswitch client.&#160; Specifically, for en-US and English language users, Chrome specifies the iso-8859-1 charset encoding on all outbound requests.</p>  <p>Other browsers have done this in the past; older versions of IE and Firefox also asked for iso-8859-1.&#160; Chrome still does it, and there is an active bug on Chrome to ask them to stop doing it.</p>  <p>(Modern browsers either do not set this header at all, or set it to the value &quot;utf-8&quot;, which has emerged as the de-facto internet standard)</p>  <p>When a request asking for Accept-Charset: iso-8859-1 comes into the LightSwitch server, it dutifully responds by sending a response which has an iso-8859-1 charset encoding.</p>  <p>The problem is that the Silverlight platform, upon which the LightSwitch Silverlight client is based, doesn't support this content encoding.&#160; When the client tries to de-serialize the XML payload, it sees the content-encoding is one that it doesn't support, and it throws a client-side exception.&#160; Thus, the red-x.</p>  <p>Chrome is perfectly capable of dealing with utf-8 formatted data -- in fact, the Accept-Charset header allows you to specify a list of acceptable character sets and the browsers preferences for each.&#160; Chrome actually sends over an Accept-Charset header that specifies iso-8859-1 as 1st choice, and utf-8 as second choice.&#160; So if we can make the server somehow return a utf-8 response, everyone will be happy.</p>  <p>Until the proper fix is available, here is a workaround that can be used to do just that.&#160; We'll use the &quot;URL Rewrite&quot; module in IIS to accomplish this.&#160; Specifically, we'll create an in-bound rule that re-writes all requests so that the &quot;Accept-Charset&quot; header is replaced with &quot;utf-8&quot;.&#160; This will make it seem like Chrome asked for utf-8 to begin with.</p>  <p>First, open the IIS administration console and use Web Platform Installer to get URL Rewrite 2.0    <br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/39/metablogapi/3660.startwebPI_6B5EE3DB.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-39-metablogapi/3660.startwebPI_5F00_6B5EE3DB.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="startwebPI" border="0" alt="startwebPI" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/39/metablogapi/0636.startwebPI_thumb_56012E73.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-39-metablogapi/0636.startwebPI_5F00_thumb_5F00_56012E73.png" width="244" height="154" /></a></p>  <p>After Web PI launches, type &quot;URL Rewrite&quot; in the search box and install it.</p>  <p>Next, navigate to the LightSwitch app you'd like to apply the fix to.&#160; I think you can also apply the URL Rewrite rule at the top level of your IIS server, but that's riskier so I don't recommend it.&#160; <br /><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/39/metablogapi/0624.urlRewrite1_7C6311BE.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-39-metablogapi/0624.urlRewrite1_5F00_7C6311BE.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="urlRewrite1" border="0" alt="urlRewrite1" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/39/metablogapi/2604.urlRewrite1_thumb_350DBBCC.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-39-metablogapi/2604.urlRewrite1_5F00_thumb_5F00_350DBBCC.png" width="244" height="70" /></a></p>  <p>Double click on the &quot;URL Rewrite&quot; icon in the IIS management pane.</p>  <p>The first thing we need to do is enable changing of the Accept-Charset header by URL Rewrite.&#160; To do that, we choose &quot;View Server Variables&quot; and then choose &quot;Add&quot;.&#160; The name of the server variable is &quot;HTTP_ACCEPT_CHARSET&quot;.&#160; The name must be upper case and must have underscores where I've specified them.    <br /></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/39/metablogapi/1682.urlRewrite2_02A9E84D.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-39-metablogapi/1682.urlRewrite2_5F00_02A9E84D.png"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="urlRewrite2" border="0" alt="urlRewrite2" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/39/metablogapi/7065.urlRewrite2_thumb_3B54925A.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-39-metablogapi/7065.urlRewrite2_5F00_thumb_5F00_3B54925A.png" width="244" height="67" /></a></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/39/metablogapi/2781.urlRewrite3_08F0BEDB.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-39-metablogapi/2781.urlRewrite3_5F00_08F0BEDB.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="urlRewrite3" border="0" alt="urlRewrite3" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/39/metablogapi/5327.urlRewrite3_thumb_419B68E8.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-39-metablogapi/5327.urlRewrite3_5F00_thumb_5F00_419B68E8.png" width="244" height="104" /></a></p>  <p>Now that we've allowed rules to manipulate the Accept-Charset header, we can create a rule that does the manipulation.&#160; From the main URL Rewrite screen, choose &quot;Add Rules&quot; and then choose &quot;Blank Rule&quot;</p>  <p>   <br />First, give the rule a name like &quot;rewrite all requests as utf-8&quot;     <br /></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/39/metablogapi/1614.urlRewrite4_335CEFF8.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-39-metablogapi/1614.urlRewrite4_5F00_335CEFF8.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="urlRewrite4" border="0" alt="urlRewrite4" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/37/39/metablogapi/8154.urlRewrite4_thumb_12D5B046.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-37-39-metablogapi/8154.urlRewrite4_5F00_thumb_5F00_12D5B046.png" width="173" height="244" /></a></p>  <p>For the Match URL, choose &quot;Regular Expressions&quot; and specify &quot;.*&quot; for the pattern.&#160; </p>  <p>Under the Server-Variables tab, choose &quot;Add&quot; and then specify &quot;HTTP_ACCEPT_CHARSET&quot; as the name of the variable, and set its value to &quot;utf-8&quot;.&#160; Make sure &quot;Replace&quot; is checked.</p>  <p>Finally, under the &quot;Action&quot; section, choose &quot;Rewrite&quot;.&#160; Specify &quot;{UNENCODED_URL}&quot; as the rewrite target, and MAKE SURE TO UNCHECK &quot;Append Query String&quot;.</p>  <p>Apply/Save the rule and test your app with Chrome.&#160; If things aren't working, look at the traces with fiddler.</p>  <p>Once you get the basic re-write rule working, you can experiment with the “Conditions” tab to try and narrow the applicability of the rule.&#160; For instance, you may want to target only requests that specify iso-8859-1 encoding on the request.</p>]]></content:encoded>
    </item>
    <item>
      <title>Introduction to the Lightswitch Weakly Typed API</title>
      <link>https://docs.microsoft.com/archive/blogs/mattev/introduction-to-the-lightswitch-weakly-typed-api</link>
      <pubDate>Mon, 11 Oct 2010 12:40:00 GMT</pubDate>
      <dc:creator><![CDATA[Matt Evans - Visual Studio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mattev/2010/10/11/introduction-to-the-lightswitch-weakly-typed-api/</guid>
      <description><![CDATA[The typical coding experience in a Lightswitch app revolves around the objects you've created --...]]></description>
      <content:encoded><![CDATA[<p>The typical coding experience in a Lightswitch app revolves around the objects you've created -- your tables, your screens, queries, and so on.&nbsp; When you click "Write Code" in our design experience, there is a rich and strongly typed programming experience for you to use.&nbsp; Your intellisense picker understands that a "Customer" exists and has properties like "LastName".&nbsp; And you can write code that looks like</p>
<pre class="scroll"><code class="csharp">private void Customer_Created()
<br />{
<br />  this.LastName = "Smith";
<br />}</code></pre>
<p>To make this happen, as you are working in the Lightswitch design experience, Lightswitch is generating code on your behalf that defines the Customer class and all of its properties.&nbsp; These objects aren't simple; there are separate concrete implementations of them for client and server, and the magic to make a Customer remote back and forth between Client and Server is all handled for you via code generation.&nbsp; </p>
<p>Lightswitch gives you a programming experience that is suited towards your specific project.&nbsp; Your first app will&nbsp;have "Customer", "Person", Address", "Order", whereas your second app may have objects like "Appointment", "Office", and "Holiday".&nbsp; </p>
<p>But what happens if you want to write some code that works on <em>any</em> entity?&nbsp; What if you won't know its name until runtime?&nbsp; </p>
<p>In addition to the strongly typed, code generated programming experience we expect customers to use, Lightswitch also offers a second programming experience, one that is late bound and weakly typed.</p>
<p>Suppose that like above, you have a table named Customer, with&nbsp;a string property named "LastName".&nbsp; The following code is the weakly typed equivalent to the above code:</p>
<pre class="scroll"><code class="cplusplus">private void Customer_Created() {
<br />  this.Details.Properties["LastName"].Value = "Smith";
<br />}</code></pre>
<p>Why might you want to use this?</p>
<p>Consider the case above: suppose I want to write an extension method that works on any entity.&nbsp; Say that I am writing a logging or auditing framework to include in an LS app.&nbsp; I want to make any entity in the system "describe" itself.&nbsp; </p>
<pre class="scroll"><code class="csharp">        /// &lt;summary&gt;
<br />        /// Given any possible Lightswitch Entity, return a string of key:value pairs that describe its primary key columns and values
<br />        /// &lt;/summary&gt;
<br />        /// &lt;param name="entity"&gt;The entity instance&lt;/param&gt;
<br />        /// &lt;returns&gt;an Id string&lt;/returns&gt;
<br />        public static string GetKeyString(Microsoft.LightSwitch.IEntityObject entity)
<br />        {
<br />            string s = "";
<br />            object propVal = null;
<br />
<br />            foreach (Microsoft.LightSwitch.Model.IKeyPropertyDefinition kp in entity.Details.GetModel().KeyProperties)
<br />            {
<br />                if (!string.IsNullOrEmpty(s))
<br />                    s += ", ";
<br />
<br />                s += kp.Name; s += ":";
<br />                propVal = entity.Details.Properties[kp.Name].Value;
<br />                if (null != propVal)
<br />                    s += propVal.ToString();
<br />                else
<br />                    s += "(null)";
<br />
<br />                IEntityPropertyDefinition nameProp = entity.Details.GetModel().Properties.SingleOrDefault(x =&gt; x.Name == "Name");
<br />                if (null != nameProp)
<br />                {
<br />                    s += ", Name:"; s += entity.Details.Properties["Name"].Value;
<br />                }
<br />            }
<br />            return s;
<br />
<br />        }</code></pre>
<p>There are a few things going on in this code.</p>
<p>1) we're using "IEntityObject".&nbsp; An IEntityObject can hold any LightSwitch entity.&nbsp; If a function asks for an IEntityObject, you can pass it a Customer, an Order -- whatever you like.</p>
<p>2) We're using the <strong>Model</strong> API off of the Details property.&nbsp; A lot of the tricky "goodies" in the Lightswitch programming experience are available off of the "Details" member of any object.&nbsp; The Model retreives the metadata of the object instance.&nbsp; This is how the object describes itself to the Lightswitch runtime.</p>
<p>3) We're using the weakly-typed property access, just like we did above in the "Customer" example.&nbsp; The difference is that we don't know the name of the property we want to access; we're asking the Lightswitch Model what the names of the properties are.</p>
<p>4) Note that the Model API knows the difference between a property and a Key property.&nbsp; This is how we can ask any entity what its primary key columns are.&nbsp; Once we know the&nbsp;appropriate property&nbsp;names, we can use the weakly typed property access to get their values as normal.</p>
<p>Try pasting this code somewhere in your own project.&nbsp; Send it different types of entities and convince yourself that it will work.</p>
<p style="padding-left: 30px;"><strong>Challenge</strong>: Modify this code so that it returns the name of the <em>type</em> of entity, in addition to its key info.&nbsp; For instance, if I pass this routine a "Customer" instance, and Customer's Id column is named "Id", and the customer I pass in is customer id #7, I would expect the output to be:</p>
<p style="padding-left: 30px;">"Customer, Id:7"</p>
<p style="padding-left: 30px;">&nbsp;If you figure it out, wait a day or two before responding with an answer.</p>
<p>Are there other uses you can think of for this?&nbsp; Suppose that you have lots phone number properties on a few different entities in your LS app.&nbsp; Suppose that you want to do phone-number defaulting, for any phone number on any entity in the system.&nbsp; Imagine a routine called "SetPhoneNumbers", and that you called this routine from the _Created event for each of the entities in your system.</p>
<p>Here's what the logic might look like:</p>
<pre class="scroll"><code class="csharp">private static void SetPhoneNumber(IEntityObject e) {
<br /> foreach (var v in e.Details.GetModel().Properties.Where(x =&gt; x.PropertyType.Name == "PhoneNumber"))
<br /> {
<br />   e.Details.Properties[v.Name].Value = "(800)555-1212";
<br /> }
<br />}</code></pre>
<p>Some quick notes: </p>
<p>1) we're doing a LINQ query against the Properties collection in the Model API. We're asking LS to give us any property object who's type is "PhoneNumber".</p>
<p>2) we're using the C# "var" syntax to avoid caring about what the Lightswitch Property object actually is. You will get full intellisense if you type this code in manually. You won't have to worry about Ligthtswitch's Model.IEntityPropertyDefinition </p>
<p>I think it's pretty cool that in 3 lines of code, given any entity of any type from any LS project, we&nbsp;can set any discovered phone number fields on that entity to some default value.&nbsp; Or run any other logic we like.</p>
<p>I hope you've enjoyed this introduction to the weakly typed programming experience.&nbsp; So far, we've only discussed entities and entity properties.&nbsp; We also used the Model API to get the metadata about a runtime entity instance, like it's properties, key properties, and the data types of its properties.&nbsp; These simple techniques let developers write re-usable Lightswitch functionality.&nbsp; </p>]]></content:encoded>
    </item>
    <item>
      <title>WCF Binary Inspector, MS-NBFX, MS-NBFS</title>
      <link>https://docs.microsoft.com/archive/blogs/mattev/wcf-binary-inspector-ms-nbfx-ms-nbfs</link>
      <pubDate>Fri, 05 Mar 2010 14:53:00 GMT</pubDate>
      <dc:creator><![CDATA[Matt Evans - Visual Studio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mattev/2010/03/05/wcf-binary-inspector-ms-nbfx-ms-nbfs/</guid>
      <description><![CDATA[Fiddler&nbsp;is an indispensible tool for troubleshooting client/server communications, especially...]]></description>
      <content:encoded><![CDATA[<P><A href="https://www.fiddler2.com/" mce_href="https://www.fiddler2.com">Fiddler</A>&nbsp;is an indispensible tool for troubleshooting client/server communications, especially when your next best option is running the client under a debugger, or trying to glean info from IIS logs.</P>
<P>The <A title="WCF Binary Inspector Plugin for Fiddler" href="https://code.msdn.microsoft.com/wcfbinaryinspector" mce_href="https://code.msdn.microsoft.com/wcfbinaryinspector">WCF Binary Inspector</A>&nbsp;for fiddler is a great help when you are working with WCF servies using the SOAP messages that have been binary encoded/compressed according to the MS-NBFS standard.&nbsp; </P>
<P>As near as I can tell, MS-NBFS is essentially an implementation of MS-NBFX, which covers the actual binary encoding protocol, with a specified shared dictionary.&nbsp; The NBFX protocol specifies "dictionary lookup" op-codes, both for elements and attributes, but says that both sides of a connection must agree on what the dictionary contents are.&nbsp; MS-NBFS specifies that dictionary, with SOAP messages in mind, so high-probability strings like "mustUnderstand" are&nbsp;entries in the dictionary and messages get a good effective compression ratio.</P>
<P>The Binary inspector plugin uses the WCF message facility for doing its decoding, however, the message must be a valid SOAP message in WCF Binary format.&nbsp; I was recently looking at a system where messages were in MS-NBFX, but without SOAP envelopes.&nbsp; As such, the WCF Binary plugin was blowing up as it was setup to deal with SOAP messages.</P>
<P>It is possible to decode the MS-NBFX directly, by using XmlDictionaryReader.CreateBinaryReader.&nbsp; </P>
<P><A title="This Post" href="https://social.msdn.microsoft.com/Forums/en-US/wcf/thread/e9208540-7877-4318-909d-92eb8490ab58?prof=required" mce_href="https://social.msdn.microsoft.com/Forums/en-US/wcf/thread/e9208540-7877-4318-909d-92eb8490ab58?prof=required">This post</A>&nbsp;has sample code and some other good links.</P>
<P>I've sent over a copy of this code to the author of the fiddler WCF Binary inspector so that Fiddler's MS-NBFS decoder can handle more than just SOAP binary formatted messages.</P>
<P mce_keep="true">&nbsp;</P>]]></content:encoded>
    </item>
    <item>
      <title>Enabling ASLR for memory savings?</title>
      <link>https://docs.microsoft.com/archive/blogs/mattev/enabling-aslr-for-memory-savings</link>
      <pubDate>Tue, 21 Aug 2007 18:38:00 GMT</pubDate>
      <dc:creator><![CDATA[Matt Evans - Visual Studio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mattev/2007/08/21/enabling-aslr-for-memory-savings/</guid>
      <description><![CDATA[There's not a lot of easy-to-come-by-knowledge on how ASLR works or what it does, so to save people...]]></description>
      <content:encoded><![CDATA[<p>There's not a lot of easy-to-come-by-knowledge on how ASLR works or what it does, so to save people some effort, I'll place some links here:</p>
<p><a href="https://www.nynaeve.net/?p=100">https://www.nynaeve.net/?p=100</a></p>
<p><a href="https://www.blackhat.com/presentations/bh-dc-07/Whitehouse/Paper/bh-dc-07-Whitehouse-WP.pdf">https://www.blackhat.com/presentations/bh-dc-07/Whitehouse/Paper/bh-dc-07-Whitehouse-WP.pdf</a></p>
<p>The first link talks about how to turn on ASLR for your dlls.&nbsp; The second is an in depth discussion of the Vista RTM ASLR implementation and some deficiencies from a security perspective.</p>
<p>I'm actually interested in ASLR for an entirely different reason -- performance.</p>
<p>An important scenario for Axapta is hosting multiple instance of the client on a Terminal Server.&nbsp; Obviously the less memory each instance of Ax32.exe uses, the more clients we'll be able to successfully host on a single machine.&nbsp; This means customers save money on hardware and licensing.</p>
<p>Most modern operating systems look for ways to eliminate redundancy w.r.t. memory consumption.&nbsp; One mechanism for doing this is attempting to load a DLL into the same spot in the virtual address space of each process on the system.&nbsp; The short version goes something like this: notepad.exe and explorer.exe both need "shell32.dll" loaded into their own "private" address space.&nbsp; </p>
<p>Windows doesn't use fully relocatable code like the linux ELF format is (that is, in a linux module, virtual addresses in machine instructions reference the program counter or some other well-known base address (like the GOT), so you can load that segment of code essentially anywhere in the flat 32bit address space).</p>
<p>Linux: <a href="https://en.wikipedia.org/wiki/Position-independent_code">https://en.wikipedia.org/wiki/Position-independent_code</a></p>
<p>Windows: <a href="https://en.wikipedia.org/wiki/Portable_Executable">https://en.wikipedia.org/wiki/Portable_Executable</a></p>
<p>Windows DLLs specify a "preferred address" in their PE image, telling the loader where, ideally, that code will be loaded.&nbsp; This is a bit weird - at link time, you specify in the DLL where you'd ideally load your self into a processes address space.</p>
<p>In the event that notepad.exe and explorer.exe can both load shell32.dll into shell32's desired address space, windows can be pretty clever about the backing memory for shell32.&nbsp; Even though each process gets a distinct and seperate logical virtual address space, the pages backing shell32 in each of them can be backed by the same physical memory.&nbsp; Essentially, the VM system is only charged "once" for shell32.&nbsp;</p>
<p>In the event that a DLL cannot load into its preferred spot in memory, the loader must "rebase" the DLL to a new address that is available in the target process.&nbsp; This rebasing disqualifies the VM pages from being re-used across multiple processes.</p>
<p>Obviously in the case of Ax32.exe on terminal&nbsp;servers; we want to avoid rebasing as much as possible, as each instance of the client with a rebased module will consume more memory than is strictly needed, thus limiting capacity.</p>
<p>This is where ASLR comes in.&nbsp; ASLR stands for "Address Space Layout Randomization", and its a <em>security</em> feature in Vista.&nbsp; Read the earlier links on how and why ASLR is used from a security perspective.</p>
<p>The practical upshot of ASLR for us is that the rebasing mechanism has now been moved in-kernel, and is system wide per DLL instead of process-wide.&nbsp; This means that if&nbsp;a rebase <em>does</em> occur in Ax32, it should be shared across all subsequent copies of AX32, leading to less private memory consumption per instance of the client.</p>
<p>Additionally, because the kernel rebaser doesn't leave gaps between loaded modules, there is less memory&nbsp; page fragmentation and fewer pages are used in general.&nbsp; </p>
<p>We're still experimenting with the per-client memory footprint advantages of ASLR, but hopefully they'll be there.&nbsp; We're hoping to see some per-client memory savings due to ASLR on ASLR enabled operating systems like Windows Server 2008.</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Axapta Document Management</title>
      <link>https://docs.microsoft.com/archive/blogs/mattev/axapta-document-management</link>
      <pubDate>Wed, 08 Aug 2007 17:16:00 GMT</pubDate>
      <dc:creator><![CDATA[Matt Evans - Visual Studio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mattev/2007/08/08/axapta-document-management/</guid>
      <description><![CDATA[I've recently become involved in testing the Document Management features in Axapta.&nbsp; This is a...]]></description>
      <content:encoded><![CDATA[<P>I've recently become involved in testing the Document Management features in Axapta.&nbsp; This is a pretty powerful subsystem for integrating external structured and unstructured data and document types with the in built ERP system.</P>
<P>&nbsp;There are two sides of document management... the end-user aspect and the administrator or setup side of it.&nbsp; Ultimately what you want is to give your end users a better experience; I'll mostly be talking about the sorts of documents you can setup using the administration side of things.</P>
<P><STRONG>User Overview of&nbsp;Attaching Documents&nbsp;</STRONG></P>
<P>To get a quick look at doc handling in Axapta, open up AR-&gt;Customers.&nbsp; Next to the big "bell" icon (the Alerts button, if you're using 4.x) there will be an icon that looks like a document.&nbsp; If you mouse-hover (in 4.x, at least) over the button it will say "Document handling"</P>
<P>If you click this button you get the Document Handling form (DocuView).&nbsp; </P>
<P>DocuView is an app-singleton form.&nbsp; That means that you can only have one instance of it open at a time.&nbsp; Since you open DocuView from some other form, you are operating on a linked data source (that is, the DocuView form knows who called it, and restricts its data to the context-appropriate records).&nbsp; In our case, you'll see the documents attached to whatever customer was selected when you hit the doc handling button.</P>
<P>If you're new to doc handling, you'll probably have an empty grid.&nbsp;&nbsp;&nbsp; Off on the right you'll see a "New" button.&nbsp; Axapta has some in-built document types; the most commonly used one is "Note".&nbsp; Select New-&gt;Note.&nbsp; You'll be able to enter a description, and then set the flag "Internal" or "External".&nbsp; Finally, in the window at the bottom of the DocuView form you'll be able to enter free form text.</P>
<P>hit ctrl-S to save the note.&nbsp; You've now attached a document to this customer.</P>
<P><STRONG>Administrator view of Setting up Document Types&nbsp;</STRONG></P>
<P>Now, you may have noticed other options available to you under New-&gt;.&nbsp; On my configuration, one of them is "Letter".&nbsp; </P>
<P>Axapta has the ability to create Word documents for you with data pre-populated.&nbsp; Here we begin to talk about the Setup side of things.</P>
<P>In Basic-&gt;Setup-&gt;Document Management-&gt;Document Types, you'll find the configuration of the document types available in Doc handling.&nbsp; </P>
<P>You can create new records here.&nbsp; Give your new document type a name like "CustLetter".&nbsp; The "Job description" property is most interesting.&nbsp; Here we'll choose from the drop down "Create Word document via COM".</P>
<P mce_keep="true">Switch over to the general tab and make sure to set the "Archive directory".&nbsp; Then click "Options" on the right.</P>
<P mce_keep="true"><STRONG>Mapping Axapta Table Fields to Document Template Bookmarks</STRONG></P>
<P mce_keep="true">The new form that opens is how you bind Axapta data to the document type.&nbsp; Here you'll define what data to export into the Word document, and how it will be mapped into the document.</P>
<P mce_keep="true">Hit Ctrl-N to setup a new table mapping.&nbsp; Choose the table you'd like to pull data from (CustTable is a fine choice).&nbsp; </P>
<P mce_keep="true">Here we're going to use a Word Template.&nbsp; </P>
<P mce_keep="true">Suppose I've got a word document that is a nice form letter I'd like to send customers.&nbsp; It has my company logo on it, some standard legal text, my return address, and so on.&nbsp; I'd like to auto-populate regions of this letter with data like the customers name and address, and then store the resultant letter in the doc management system.</P>
<P mce_keep="true">Here's how we can use Doc handling to automate this (to a degree).</P>
<P mce_keep="true">Create a word document that looks like you'd like the letter to appear.&nbsp; For places where you'd like the customers address or name, you'll insert word Bookmarks.&nbsp; In Word 2007, you can insert a Bookmark right from the ribbon bar... Insert-&gt;Links-&gt;Bookmark.&nbsp; Move the cursor in the document to the position you'd like to insert the customer name, and then insert a bookmark.&nbsp; Name the bookmark "CustName".&nbsp; </P>
<P mce_keep="true">You'll want to save this file as a word <EM>template</EM>, by&nbsp;going to File-&gt;Save As, and changing the type.&nbsp; The template lets you control content and formatting, and is used as a starting point from which to generate new word documents that have the bookmarks filled in with real customer data.</P>
<P mce_keep="true">Back in AX on the Setup form, edit the "Template File" column to point at your newly saved template.</P>
<P mce_keep="true">Now flip over to the "fields" tab on this form.&nbsp; Here you can hit Ctrl-N to add new Field-&gt;Bookmark mappings.&nbsp; Create a mapping from data field "name" on table "CustTable", to the bookmark "CustName".&nbsp; Save your configuration and then save/click OK to all of the setup forms you've got open.&nbsp; </P>
<P mce_keep="true">Now we're ready to try it out!</P>
<P mce_keep="true">If you open up a customer, click doc handling, and then click "New-&gt;CustLetter".&nbsp; Word should fire up, show you a new document named according to the configured number sequence, and the document should have the content of the template you created earlier, with the customer's name filled in where you defined the bookmark.&nbsp; Save the document and you're done!</P>
<P mce_keep="true"><STRONG>Wrap Up</STRONG></P>
<P mce_keep="true">Hopefully you were able to setup a new document type that exported table data to a word doc based on a template without too much trouble.&nbsp; Templates can be reasonably complex, and data can come from multiple tables, but there are some limitations.&nbsp; </P>]]></content:encoded>
    </item>
    <item>
      <title>HoeKey - Exactly what I needed</title>
      <link>https://docs.microsoft.com/archive/blogs/mattev/hoekey-exactly-what-i-needed</link>
      <pubDate>Tue, 01 Nov 2005 14:34:00 GMT</pubDate>
      <dc:creator><![CDATA[Matt Evans - Visual Studio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mattev/2005/11/01/hoekey-exactly-what-i-needed/</guid>
      <description><![CDATA[So&nbsp;I listen to music at work a bunch via headphones (here in Fargo, we've got cubes, not...]]></description>
      <content:encoded><![CDATA[<P>So&nbsp;I listen to music at work a bunch via headphones (here in Fargo, we've got cubes, not individual offices).&nbsp; I use my laptop as my "fluff" machine - that is, i listen to music, read mail, do office stuff, write up bugs, web surf (gasp!), etc from it.&nbsp; </P>
<P>Naturally, this doesn't have the "media" keys of the recently awful MS keyboards.&nbsp; So the common scenario is that a&nbsp;person comes over to talk to me and i have to find media player, restore it, hit pause, then take off my headphones, then turn to talk to the person.</P>
<P>What i wanted was a global "pause" button.</P>
<P>It turns out that somebody has made a tiny (12kb) program that lets you bind arbitrary key sequences (context-free, it seems) to arbitrary actions.&nbsp; This thing fits the bill exactly, and is available from <A href="https://dana.ucc.nau.edu/~tsr22/apps/hoekey.htm">https://dana.ucc.nau.edu/~tsr22/apps/hoekey.htm</A>.&nbsp; It has stuff built-in to send messages to whatever app, so i can bind windowskey-P to send the play/pause command to WMP.&nbsp; Life is good.</P>
<P>As an aside, the default config includes "windowskey-4" as a command which..turns the currently selected window to half alpha-transparency.</P>
<P>&nbsp;</P>]]></content:encoded>
    </item>
    <item>
      <title>iPod - Incompatable by Design.</title>
      <link>https://docs.microsoft.com/archive/blogs/mattev/ipod-incompatable-by-design</link>
      <pubDate>Mon, 19 Sep 2005 14:51:00 GMT</pubDate>
      <dc:creator><![CDATA[Matt Evans - Visual Studio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mattev/2005/09/19/ipod-incompatable-by-design/</guid>
      <description><![CDATA[A coworker here was thinking about getting an iPod Nano.&nbsp; My best friend ordered one the day...]]></description>
      <content:encoded><![CDATA[<P>A coworker here was thinking about getting an iPod Nano.&nbsp; My best friend ordered one the day they were announced and I got to see it a bit this weekend.&nbsp; Side note - we were at a resturant and I was playing with it, and the waitress came over to talk to us about it and was telling us how she just got hers and totally loves it, and wanted to know if i liked mine, to which i sheepishly replied that it belonged to my friend.&nbsp; </P>
<P>In any case, the thing is <EM>tiny</EM>.&nbsp; The display is beautiful, the interface works how you'd expect.&nbsp; It has the ability to store vCards and other cool stuff.</P>
<P>So my co-worker asked "do you need iTunes to sync to it?".&nbsp; I didn't know.&nbsp; My friend figured you didn't, and that it just showed up as a mass storage device.&nbsp; Sweet.&nbsp; But before I told my coworker about this, i figured i had better look into it myself.</P>
<P>So later this weekend i hooked the thing into my XP SP2 machine via USB cable.&nbsp; It showed up as a disk, and when I went to explore that disk, it had folders for eTexts, vCards, and calender appointments.&nbsp; Nothing about music.&nbsp; There is a hidden folder called something like "itunes data" and if you explore it, you find a few index files and album art collections and other stuff, and eventually you get to a folder that contains what appear to be the song files - they have .mp3 and .aac (or whatever they are) extensions on them.</P>
<P>The problem is that these files all have 4 letter names.. there's no effective way to look through this folder and figure out what the songs are.&nbsp; The containing folder heirarchy is also broken down into arbitrary folders.. something like M1 through M6 on this particular unit.&nbsp; </P>
<P>The ipod apparently has a media database that it uses to let you navigate its menus, and as part of putting songs on it, you're updating this database, and during that time, turning the proper filenames into hash names and then recording those hashnames in the database.</P>
<P>While i can understand the design decision to have an offboard index calculator (itunes), it stinks that getting media into or out of this thing is more difficult than it needs to be.</P>
<P>I can think of two or three people that would be more interested in the iPod Nano if they didn't need to use iTunes to deal with it.&nbsp; Not that Apple should worry about what 2 or 3 people want, but I suspect there are more pro-Ipod, anti-iTunes people out there.</P>
<P mce_keep="true">&nbsp;</P>]]></content:encoded>
    </item>
    <item>
      <title>Make SQL Server generate SQL for you using SELECT literals</title>
      <link>https://docs.microsoft.com/archive/blogs/mattev/make-sql-server-generate-sql-for-you-using-select-literals</link>
      <pubDate>Tue, 23 Nov 2004 14:15:00 GMT</pubDate>
      <dc:creator><![CDATA[Matt Evans - Visual Studio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mattev/2004/11/23/make-sql-server-generate-sql-for-you-using-select-literals/</guid>
      <description><![CDATA[Suppose that I've got an instance of SQL server setup for testing, and I've programmatically created...]]></description>
      <content:encoded><![CDATA[<P>Suppose that I've got an instance of SQL server setup for testing, and I've programmatically created databases on this instance, but never cleaned them up.</P>
<P>This can leave you with hundreds of databases that you'll never use again, and there's no reason for them to continue taking up space and cluttering things which you do not wish to be cluttered.</P>
<P>Now, you could use a GUI tool like enterprise manager, and right click on <I>every</I> database and choose "Delete" </P>
<P>Obviously, that stinks.</P>
<P>Alternatively, you could use isqlw (SQL Query Analyzer) and enter the appropriate T-SQL statement to delete a database:</P><PRE>drop database Foo </PRE><PRE>go </PRE>
<P>This also stinks, because thats a lot of typing, once you do it for 100 databases</P>
<P>Fortuneately, you can do better. What you've got, fundamentally, is a problem that computers are good at. You've got a lot of somethings (databases) that you want to do something to. You know what you want to do - drop <EM>a</EM> database. Now you just need to leverage that across a big list of them. </P>
<P>If one wanted to get a list of data in SQL, one would write a a <B>SELECT</B> statement. It turns out that if we're willing to look at the system tables, sql server will <EM>tell us</EM> about the databases installed in this instance. </P><PRE>select name </PRE><PRE>from sysdatabases </PRE><PRE>where sid &lt;&gt; 0x01 </PRE><PRE>and name like 'HW_%' </PRE>
<P>Now, this will give you the name of any databases from this instance which match "HW_%" and which have an sid other than 0x01. The sid &lt;&gt; 0x01 clause is interesting. On the SQL instances I'm looking at, the "system" databases always have sid=0x01. But on one other instance, Northwind also has sid=0x01. User databases always have a long gooofy, non-0x01 value for sid. So you can use this as a hack to do a "reasonable" job of excluding "system" databases from your select list. If you can make a determination based on the dbname, as I have above, you can do even better. </P>
<P>Great, we can get SQL server to tell us the list of user databases installed from this instance. What does that buy me? Well, suppose we change the select list: </P><PRE>select 'drop database ', name </PRE><PRE>from sysdatabases </PRE><PRE>where sid &lt;&gt; 0x01 </PRE><PRE>and name like 'HW_%' </PRE>
<P>If you run this select statement (and you have databases that match the select list) you'll get the following output (at least on my machine - you probably <EM>won't</EM> get this output as your dbnames will be different</P><PRE>drop database HW_North </PRE><PRE>drop database HW_South </PRE><PRE>drop database HW_Enterprise </PRE>
<P>Congratulations, you've just told SQL server to generate SQL for you. Obviously, if you had 100 databases in your select list, you'd get 100 statements generated. Here's where the hack comes in, i don't know of a way to actually <EM>execute</EM> this in one step, but I bet it is possible. Instead, I copy and paste the results (results to grid works fine in ISQLW, results as text will give you a giant column width for the name column), back into a command window, and then execute the batch. </P>
<P>This technique is handy for dropping lots of databases, but its also good in other places. For instance, you can generate INSERT or UPDATE statements this way, which may be desirable if you've got just one or two peices that make doing the job with a single insert/update too difficult. </P>
<P>It is not elegant, not efficient, and probably upsets somebody somewhere, but for a quick and dirty management task, using select literals to generate statements for you is a great technique to keep in mind. </P>]]></content:encoded>
    </item>
    <item>
      <title>Don't trust user supplied data - Real World Example</title>
      <link>https://docs.microsoft.com/archive/blogs/mattev/dont-trust-user-supplied-data-real-world-example</link>
      <pubDate>Thu, 15 Jul 2004 17:39:00 GMT</pubDate>
      <dc:creator><![CDATA[Matt Evans - Visual Studio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/mattev/2004/07/15/dont-trust-user-supplied-data-real-world-example/</guid>
      <description><![CDATA[Suppose I have a notion of a User Account in my application, and I want to allow 3rd parties to tie...]]></description>
      <content:encoded><![CDATA[<P>Suppose I have a notion of a User Account in my application, and I want to allow 3rd parties to tie that user account to one or more objects in an external directory/authentication system.&nbsp; </P>
<P>Let's say, for the sake of argument, that I'm going to use <A href="https://msdn.microsoft.com/library/default.asp?url=/library/en-us/sds/sds/directoryservices_directoryentry.asp">System.DirectoryServices.DirectoryEntry </A>to represent links to external directory objects.&nbsp; </P>
<P>I need to persist the relationship between a DE and my concept of a User.&nbsp; </P>
<P>The way I've chosen to do this is by taking the <A href="https://msdn.microsoft.com/library/default.asp?url=/library/en-us/sds/sds/directoryservices_directoryentry_path.asp">Path Property </A>&nbsp;of the DirectoryEntry and saving that, as a string, into the database.</P>
<P>When I need to re-hydrate my user Account object, I'll back the DirectoryEntry property by using the DirectoryEntry <A href="https://msdn.microsoft.com/library/default.asp?url=/library/en-us/sds/sds/directoryservices_directoryentry_directoryentry_string.asp">constructor</A> which takes the Path as its argument.</P>
<P>Now, this is all well and good, except what it means is that anytime anyone loads an instance of my User Account, and looks at the DirectoryEntry property (say, a user management application), they're going to be running code that&nbsp;I supplied data to.&nbsp; Namely, the constructor code for the DE class.</P>
<P>We're now in a situation where we're running code, and passing it an argument from an untrusted source.&nbsp; </P>
<P>DE is currently a shim on top of the COM based ADSI architecture.&nbsp; ADSI is a scheme with multiple, pluggable providers.&nbsp; The DE Path specifies the provider to use.</P>
<P>This is nice from a programming perspective - if you want to get an Active Directory object corresponding to a user, you might try:</P>
<P>de = new DirectoryEntry(&#8221;LDAP://CN=mattev,DC=microsoft,DC=com&#8221;);</P>
<P>alternatively, if you had an NT4 provider:</P>
<P>de = new DirectoryEntry(&#8221;WinNT://localhost/administrator&#8221;);</P>
<P>You've got the same .NET DirectoryEntry object, and the same ADSI COM interface, but underneath you've got an LDAP provider handling one LDAP object, and a WinNT provider handling the other.</P>
<P>Now, it turns out that there's a 3rd &#8220;standard&#8221; provider -the IIS:// provider.&nbsp; This provider lets you use ADSI to script commands against the IIS metabase.&nbsp; The IIS ADSI interface is extensive - you can create virtual directories, delete them, delete metabase backup copies, and so on.&nbsp; Essentially any IIS admin task can be performed via the IIS ADSI interface.</P>
<P>Note that any of these IIS:// type paths are perfectly valid DirectoryEntry paths - Infact, only the IIS provider can say if an IIS:// path isn't valid.&nbsp; </P>
<P>So I think you can see where this is going.&nbsp; Suppose hypothetically, user &#8220;Evil&#8221; is running our user management system.&nbsp; Evil, for whatever reason, can update the DirectoryEntry property of one of our user objects.&nbsp; Say that Evil does the following:</P>
<P>user.DirectoryEntry = new DirectoryEntry(&#8221;IIS://importantserver/W3SVC/1/ROOT/Important/deleteApplication&#8221;);</P>
<P>Note that I'm not familiar enough with the IIS provider to actually know what the IIS path would be to perform this action, so play along :)</P>
<P>Now, because Evil doesn't have any sort of permissions to administer <A href="https://importantserver">https://importantserver</A> , this property assignment may fail or it may not - it depends on the ADSI provider, frankly.</P>
<P>If the property assignment silently fails, then we persist the above ADSI path into our database.</P>
<P>Now user &#8220;Admin&#8221; comes along and runs the user management application.&nbsp; If the user admin app displays the directoryentries associated with a given user, the DirectoryEntry constructor will be run on the path saved in the database.</P>
<P>Admin <EM>does</EM> have permission to administrate <A href="https://importantserver">https://importantserver</A>.&nbsp; And just the process of the application running the DirectoryEntry constructor is enough to to destroy the IIS application that Evil was targeting.&nbsp; </P>
<P>In reality, there was at least one thing that kept this attack from working.&nbsp; When Evil tried to set the DirectoryEntryPath property, we checked the Schema type of the object indicated by the path.&nbsp; There's nothing in the IIS ADSI space that looks anything like a user or group schema.&nbsp; This marginal validation was just enough to keep the IIS:// path from being a valid DirectoryEntry&nbsp; in the eyes of the application, so it was not persisted.&nbsp; </P>
<P>Secondly, it seems likely that the IIS provider, given a path with a verb, would return a failure code if the verb failed, and thus the DirectoryEntry constructor would throw an exception if its underlying COM call returned the error.&nbsp; </P>
<P>Finally, it's not clear that you can actually construct IIS:// paths that are verbs.</P>
<P>&nbsp;</P>]]></content:encoded>
    </item>
  </channel>
</rss>