<?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>Jerry Dixon's Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/jerrydixon/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/jerrydixon/feed.xml</link>
    <description>JerBear&amp;#039;s Lair - A dumping ground for tips and information about .NET, SQL Server, and technology in general.</description>
    <lastBuildDate>Wed, 17 Apr 2019 04:05:41 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Moving On</title>
      <link>https://docs.microsoft.com/archive/blogs/jerrydixon/moving-on</link>
      <pubDate>Tue, 18 Nov 2014 11:49:47 GMT</pubDate>
      <dc:creator><![CDATA[Jerry Dixon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jerrydixon/2014/11/18/moving-on/</guid>
      <description><![CDATA[I'm moving on to bigger and better things, so this blog has come to an end.&nbsp; If you'd like to...]]></description>
      <content:encoded><![CDATA[<p>I'm moving on to bigger and better things, so this blog has come to an end.&nbsp; If you'd like to follow me on my new journey, you can surf on over to <a href="https://jerryldixon.wordpress.com/">https://jerryldixon.wordpress.com/</a> , where I'll post about any new or interesting things that I come across.</p>]]></content:encoded>
    </item>
    <item>
      <title>Using SignalR to power ASP.NET Dashboards, Part 2</title>
      <link>https://docs.microsoft.com/archive/blogs/jerrydixon/using-signalr-to-power-asp-net-dashboards-part-2</link>
      <pubDate>Sat, 11 Oct 2014 15:42:00 GMT</pubDate>
      <dc:creator><![CDATA[Jerry Dixon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jerrydixon/2014/10/11/using-signalr-to-power-asp-net-dashboards-part-2/</guid>
      <description><![CDATA[In a previous post, I covered how you can use SignalR to provide real-time communications between a...]]></description>
      <content:encoded><![CDATA[<p>In a <a href="https://blogs.msdn.com/b/jerrydixon/archive/2014/08/16/using-signalr-to-power-asp-net-dashboards.aspx">previous post</a>, I covered how you can use <a href="https://www.asp.net/signalr/overview/getting-started/introduction-to-signalr">SignalR</a> to provide real-time communications between a Windows application and a Web page. The idea is that the Windows application could collect different kinds of system health information and provide it to the Web page, which serves as a dashboard. I provided online demos and downloadable source to help get the point across. The dashboard demo was fairly realistic, in that it showed several "servers" with color-coded health indicators. Unfortunately, the Windows application was less so. It consisted of several slider controls that set the "health" values that were communicated to the dashboard.</p>
<p>I have been asked to provide a more-realistic Windows application, and that is the point of this post.</p>
<p>&nbsp;</p>
<p>My new Windows application uses .NET performance-counter classes to collect health information:</p>
<p><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/89/16/metablogapi/7142.101114_2241_UsingSignal1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-89-16-metablogapi/7142.101114_5F00_2241_5F00_UsingSignal1.png" alt="" /></p>
<p>It uses SignalR to send this information to the Web page:</p>
<p><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/89/16/metablogapi/2112.101114_2241_UsingSignal2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-89-16-metablogapi/2112.101114_5F00_2241_5F00_UsingSignal2.png" alt="" /></p>
<p>The application samples its counters once per second and sends the information to the dashboard. The values that determine the system health status are derived from the thresholds defined in the <a href="https://pal.codeplex.com/">PAL</a> tool. (PAL is a great addition to your toolbox, by the way. If you haven't used it, you should go look right away, Go ahead, I'll wait.)</p>
<p>&nbsp;</p>
<p><span style="font-size: large;">Try it out</span></p>
<p>I will describe the new Windows application below. However, if you would like to try this for yourself first, then follow these steps:</p>
<ol>
<li>Navigate to the web page. The URL is <a href="https://signalrdashboard.azurewebsites.net/">https://signalrdashboard.azurewebsites.net/</a> .</li>
<li>Run the new Windows application. It is a ClickOnce-deployed application hosted at <a href="https://signalrdashboard.blob.core.windows.net/wpfclientperf/publish.htm">https://signalrdashboard.blob.core.windows.net/wpfclientperf/publish.htm</a> . (You will probably need to add <a href="https://signalrdashboard.blob.core.windows.net">https://signalrdashboard.blob.core.windows.net</a> to your trusted sites list in order to run the application. It was signed with an untrusted, temporary certificate.)</li>
<li>Copy the "Client ID" value from the web page and paste it into the Windows application. (Because this demo is hosted in the cloud, many people may try to use it at the same time. To keep things simple, each instance of the Windows application will send data only to the client whose ID matches that entered into the application's "Client ID" textbox.)</li>
<li>Sit back and watch the show. New system status values will be set to the dashboard every second. If you get bored with constant "Normal" values, make your machine work harder. For this purpose, I like to make SQL Server Management Studio run "CPU Stress" scripts such as the one described at <a href="https://blog.sqlauthority.com/2013/02/22/sql-server-t-sql-script-to-keep-cpu-busy/">https://blog.sqlauthority.com/2013/02/22/sql-server-t-sql-script-to-keep-cpu-busy/</a> . Choose what you will, but get that CPU util up!</li>
<li>OPTIONAL. You can also run the older Windows application as well. The dashboard will respond to the old "health" sliders as well as to the new performance-based information.</li>
</ol>
<p>&nbsp;</p>
<p><span style="font-size: large;">Read the details</span></p>
<p>The heart of the new application is the <a href="https://msdn.microsoft.com/en-us/library/system.diagnostics.performancecounter(v=vs.110).aspx">System.Diagnostics.PerformanceCounter</a> class. The application uses this class to pull system performance-counter information from the local machine. In fact, most of the code is devoted to this. There are three main classes involved:</p>
<ul>
<li>
<div>SignalRDashboard.Common.PerformanceCounter</div>
<ul>
<li>Abstract class</li>
<li>Provides functionality needed to collect data from any system performance counter</li>
</ul>
</li>
<li>
<div>SignalRDashboard.Common.CPUPerformanceCounter</div>
<ul>
<li>Derived from SignalRDashboard.Common.PerformanceCounter</li>
<li>Contains overrides unique to the "Processor Information\% Processor Time(_Total)" counter</li>
</ul>
</li>
<li>
<div>SignalRDashboard.Common.ProcessorQueueLengthPerformanceCounter</div>
<ul>
<li>Derived from SignalRDashboard.Common.PerformanceCounter</li>
<li>Contains overrides unique to the "Processor Queue Length\Processor Information(Total)" counter</li>
</ul>
</li>
</ul>
<p>&nbsp;</p>
<p>Combined together, these classes provide the information needed to determine the "health" of the monitored system. (For the demo, this is always the local machine. However, in reality, it could include data from remote machines as well.)</p>
<p>The data points used are:</p>
<ul>
<li>The last five counter values</li>
<li>The average of these five values</li>
<li>The peak from these five values</li>
<li>The warning threshold (from PAL)</li>
<li>The critical threshold (from PAL)</li>
</ul>
<p>The classes also contain logic to update their counter values when directed, and to determine a new health status from those values. The code is too long to duplicate here, but it is all very straight forward and is included in the download zip below.</p>
<p>&nbsp;</p>
<p>The SignalRDashboard.Common.PerfStatusCounter class brings everything together. This class holds a collection of PerformanceCounter-derived objects, and performs aggregations across them.</p>
<pre><span style="font-size: medium;"><code><span style="color: blue; font-family: Consolas;">public<span style="color: black;">&nbsp;<span style="color: #2b91af;">ICollection<span style="color: black;">&lt;<span style="color: #2b91af;">PerformanceCounter<span style="color: black;">&gt;&nbsp;Counters&nbsp;{&nbsp;<span style="color: blue;">get<span style="color: black;">;&nbsp;<span style="color: blue;">private<span style="color: black;">&nbsp;<span style="color: blue;">set<span style="color: black;">;&nbsp;} </span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p>&nbsp;</p>
<p>For example, the overall status of the system is the maximum of the status values for all the counters:</p>
<pre><span style="font-size: medium;"><code><span style="color: blue; font-family: Consolas;">public<span style="color: black;">&nbsp;<span style="color: #2b91af;">Status<span style="color: black;">&nbsp;Status <br /></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">get<br /></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return<span style="color: black;">&nbsp;<span style="color: blue;">this<span style="color: black;">.Counters.Max(x&nbsp;=&gt;&nbsp;x.Status); <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">} </span></code></span></pre>
<p>&nbsp;</p>
<p>Similarly, the details of the current status are the concatenation of the details of each counter:</p>
<pre><span style="font-size: medium;"><code><span style="color: blue; font-family: Consolas;">public<span style="color: black;">&nbsp;<span style="color: #2b91af;">ICollection<span style="color: black;">&lt;<span style="color: blue;">string<span style="color: black;">&gt;&nbsp;StatusDetails <br /></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">get<br /></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">var<span style="color: black;">&nbsp;details&nbsp;=&nbsp;<span style="color: blue;">new<span style="color: black;">&nbsp;<span style="color: #2b91af;">Collection<span style="color: black;">&lt;<span style="color: #2b91af;">String<span style="color: black;">&gt;(); <br /></span></span></span></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach<span style="color: black;">&nbsp;(<span style="color: blue;">var<span style="color: black;">&nbsp;c&nbsp;<span style="color: blue;">in<span style="color: black;">&nbsp;<span style="color: blue;">this<span style="color: black;">.Counters) <br /></span></span></span></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach<span style="color: black;">&nbsp;(<span style="color: blue;">var<span style="color: black;">&nbsp;d&nbsp;<span style="color: blue;">in<span style="color: black;">&nbsp;c.StatusDetails) <br /></span></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;details.Add(d); <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return<span style="color: black;">&nbsp;details; <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">} </span></code></span></pre>
<p>&nbsp;</p>
<p>And the individual counters are updated as a batch:</p>
<pre><span style="font-size: medium;"><code><span style="color: blue; font-family: Consolas;">public<span style="color: black;">&nbsp;<span style="color: blue;">void<span style="color: black;">&nbsp;Update() <br /></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">foreach<span style="color: black;">&nbsp;(<span style="color: blue;">var<span style="color: black;">&nbsp;c&nbsp;<span style="color: blue;">in<span style="color: black;">&nbsp;<span style="color: blue;">this<span style="color: black;">.Counters) <br /></span></span></span></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c.Update(); <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if<span style="color: black;">&nbsp;(!<span style="color: #2b91af;">String<span style="color: black;">.IsNullOrWhiteSpace(<span style="color: blue;">this<span style="color: black;">.ClientId)) <br /></span></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">SignalRSupport<span style="color: black;">.Instance.SendPerfStatusUpdate(<span style="color: blue;">this<span style="color: black;">.ClientId, <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">this<span style="color: black;">.CounterName, <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">this<span style="color: black;">.Status.ToString(), <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">this<span style="color: black;">.StatusDetails); <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">this<span style="color: black;">.OnPropertyChanged(<span style="color: #a31515;">"Status"<span style="color: black;">); <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">this<span style="color: black;">.OnPropertyChanged(<span style="color: #a31515;">"StatusDetails"<span style="color: black;">); <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">} </span></code></span></pre>
<p>&nbsp;</p>
<p>Notice the "SendPerfStatusUpdate" method above. This is where SignalR comes in. This method makes a call to the "SendPerfStatusUpdate" method defined in the SignalR hub defined in the Web page.</p>
<p>In Common.SignalRSupport:</p>
<pre><span style="font-size: medium;"><code><span style="color: blue; font-family: Consolas;">public<span style="color: black;">&nbsp;<span style="color: blue;">void<span style="color: black;">&nbsp;SendPerfStatusUpdate(<span style="color: blue;">string<span style="color: black;">&nbsp;clientId,&nbsp;<br /> <span style="color: blue;">string<span style="color: black;">&nbsp;systemName,&nbsp;<br /> <span style="color: blue;">string<span style="color: black;">&nbsp;status,&nbsp;<br /> </span></span></span></span></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: blue; font-family: Consolas;"><span style="color: black;"><span style="color: blue;"><span style="color: black;"><span style="color: blue;"><span style="color: black;"><span style="color: blue;"><span style="color: black;"><span style="color: blue;"><span style="color: black;"><span style="color: #2b91af;">ICollection<span style="color: black;">&lt;<span style="color: blue;">string<span style="color: black;">&gt;&nbsp;statusDetails) <br /></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if<span style="color: black;">&nbsp;(!<span style="color: #2b91af;">String<span style="color: black;">.IsNullOrWhiteSpace(clientId)) <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;invoke&nbsp;the&nbsp;SendStatus&nbsp;method&nbsp;that&nbsp;is&nbsp;defined&nbsp;on&nbsp;the&nbsp;hub.<br /></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;statusHubProxy.Invoke(<span style="color: #a31515;">"SendPerfStatusUpdate"<span style="color: black;">,&nbsp;<br /> clientId,&nbsp;<br /> systemName,&nbsp;<br /> status,&nbsp;<br /> statusDetails); <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">} </span></code></span></pre>
<p>&nbsp;</p>
<p>In StatusHub in the Web project:</p>
<pre><span style="font-size: medium;"><code><span style="color: blue; font-family: Consolas;">public<span style="color: black;">&nbsp;<span style="color: blue;">void<span style="color: black;">&nbsp;SendPerfStatusUpdate(<span style="color: blue;">string<span style="color: black;">&nbsp;connectionId,&nbsp;<br /> <span style="color: blue;">string<span style="color: black;">&nbsp;systemName,&nbsp;<br /> <span style="color: blue;">string<span style="color: black;">&nbsp;status,&nbsp;<br /> <span style="color: #2b91af;">ICollection<span style="color: black;">&lt;<span style="color: blue;">string<span style="color: black;">&gt;&nbsp;statusDetails) <br /></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;Clients.Client(connectionId).ProcessPerfStatusMessage(systemName,&nbsp;<br /> status,&nbsp;<br /> statusDetails); <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">} </span></code></span></pre>
<p>&nbsp;</p>
<p>And in the web page itself:</p>
<pre><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">hub.client.processPerfStatusMessage&nbsp;=&nbsp;<span style="color: blue;">function<span style="color: black;">&nbsp;(systemName,&nbsp;<br /> status,&nbsp;<br /> statusDetails)&nbsp;{ <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;show&nbsp;the&nbsp;row<br /></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;$(<span style="color: #a31515;">"#"<span style="color: black;">&nbsp;+&nbsp;systemName&nbsp;+&nbsp;<span style="color: #a31515;">"Row"<span style="color: black;">).css(<span style="color: #a31515;">"visibility"<span style="color: black;">,&nbsp;<span style="color: #a31515;">"visible"<span style="color: black;">); <br /></span></span></span></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;get&nbsp;appropriate&nbsp;class&nbsp;from&nbsp;status<br /></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">var<span style="color: black;">&nbsp;c&nbsp;=&nbsp;<span style="color: #a31515;">"btn&nbsp;btn-lg"<span style="color: black;">; <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if<span style="color: black;">&nbsp;(status&nbsp;==&nbsp;<span style="color: #a31515;">"Critical"<span style="color: black;">)&nbsp;{ <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;=&nbsp;<span style="color: #a31515;">"btn&nbsp;btn-lg&nbsp;btn-danger"<span style="color: black;">; <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if<span style="color: black;">&nbsp;(status&nbsp;==&nbsp;<span style="color: #a31515;">"Warning"<span style="color: black;">)&nbsp;{ <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;=&nbsp;<span style="color: #a31515;">"btn&nbsp;btn-lg&nbsp;btn-warning"<span style="color: black;">; <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if<span style="color: black;">&nbsp;(status&nbsp;==&nbsp;<span style="color: #a31515;">"Normal"<span style="color: black;">)&nbsp;{ <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;=&nbsp;<span style="color: #a31515;">"btn&nbsp;btn-lg&nbsp;btn-success"<span style="color: black;">; <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;assign&nbsp;the&nbsp;class&nbsp;to&nbsp;the&nbsp;appropriate&nbsp;button<br /></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;$(<span style="color: #a31515;">"#"<span style="color: black;">&nbsp;+&nbsp;systemName).attr(<span style="color: #a31515;">"class"<span style="color: black;">,&nbsp;c); <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;assign&nbsp;details<br /></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">var<span style="color: black;">&nbsp;detailsName&nbsp;=&nbsp;<span style="color: #a31515;">"#"<span style="color: black;">&nbsp;+&nbsp;systemName&nbsp;+&nbsp;<span style="color: #a31515;">"Details"<span style="color: black;">; <br /></span></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;$(detailsName).text(<span style="color: #a31515;">""<span style="color: black;">); <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;$.each(statusDetails,&nbsp;<span style="color: blue;">function<span style="color: black;">&nbsp;(index,&nbsp;value)&nbsp;{ <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(detailsName).append(value); <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(detailsName).append(<span style="color: #a31515;">"&lt;br&nbsp;/&gt;"<span style="color: black;">); <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;}); <br /></span></code></span></pre>
<p>Finally, the Windows application has a dispatcher timer that causes the counter values to be updated once per second. Here is the entire code-behind:</p>
<pre><span style="font-size: medium;"><code><span style="color: blue; font-family: Consolas;">private<span style="color: black;">&nbsp;Common.<span style="color: #2b91af;">PerfStatusCounter<span style="color: black;">&nbsp;_status&nbsp;=&nbsp;<span style="color: blue;">null<span style="color: black;">; <br /></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: blue; font-family: Consolas;">private<span style="color: black;">&nbsp;<span style="color: #2b91af;">DispatcherTimer<span style="color: black;">&nbsp;_timer&nbsp;=&nbsp;<span style="color: blue;">null<span style="color: black;">; <br /></span></span></span></span></span></span></code></span>&nbsp;<br /><span style="font-size: medium;"><code><span style="color: blue; font-family: Consolas;">public<span style="color: black;">&nbsp;MainWindow() <br /></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;InitializeComponent(); <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">var<span style="color: black;">&nbsp;localMachineName&nbsp;=&nbsp;<span style="color: #2b91af;">Environment<span style="color: black;">.MachineName; <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;_status&nbsp;=&nbsp;<span style="color: blue;">new<span style="color: black;">&nbsp;Common.<span style="color: #2b91af;">PerfStatusCounter<span style="color: black;">(); <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;_status.CounterName&nbsp;=&nbsp;<span style="color: #a31515;">"PRD3"<span style="color: black;">; <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;_status.Counters.Add(<br /> <span style="color: blue;">new<span style="color: black;">&nbsp;Common.<span style="color: #2b91af;">CPUPerformanceCounter<span style="color: black;">(localMachineName)<br /> ); <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;_status.Counters.Add(<br /> <span style="color: blue;">new<span style="color: black;">&nbsp;Common.<span style="color: #2b91af;">ProcessorQueueLengthPerformanceCounter<span style="color: black;">(localMachineName)<br /> ); <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">this<span style="color: black;">.DataContext&nbsp;=&nbsp;_status; <br /></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;_timer&nbsp;=&nbsp;<span style="color: blue;">new<span style="color: black;">&nbsp;<span style="color: #2b91af;">DispatcherTimer<span style="color: black;">(); <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;_timer.Interval&nbsp;=&nbsp;<span style="color: blue;">new<span style="color: black;">&nbsp;<span style="color: #2b91af;">TimeSpan<span style="color: black;">(0,0,1); <br /></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;_timer.Tick&nbsp;+=&nbsp;timer_Task; <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;_timer.Start(); <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">} <br /></span></code></span><span style="font-size: medium;"><code><span style="color: blue; font-family: Consolas;"><br />private<span style="color: black;">&nbsp;<span style="color: blue;">void<span style="color: black;">&nbsp;timer_Task(<span style="color: blue;">object<span style="color: black;">&nbsp;sender,&nbsp;<span style="color: #2b91af;">EventArgs<span style="color: black;">&nbsp;e) <br /></span></span></span></span></span></span></span></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">{ <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;_status.Update(); <br /></span></code></span><span style="font-size: medium;"><code><span style="color: black; font-family: Consolas;">} </span></code></span></pre>
<p>&nbsp;</p>
<p>Other than the timer and the performance-counter code, this new demo works in exactly the same way as the previous one does. However, instead of reporting the values of a bunch of sliders, this new application lifts performance data from the local system. It is much more realistic than using sliders.</p>
<p>&nbsp;</p>
<p><span style="font-size: large;">Download the code</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/89/16/7367.SignalRDashboard2.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-89-16/7367.SignalRDashboard2.zip">SignalRDashboard2.zip</a>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Using SignalR to power ASP.NET Dashboards</title>
      <link>https://docs.microsoft.com/archive/blogs/jerrydixon/using-signalr-to-power-asp-net-dashboards</link>
      <pubDate>Sat, 16 Aug 2014 13:36:00 GMT</pubDate>
      <dc:creator><![CDATA[Jerry Dixon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jerrydixon/2014/08/16/using-signalr-to-power-asp-net-dashboards/</guid>
      <description><![CDATA[Edit:&nbsp; This is now part 1 of a series.&nbsp;

This post covers SignalR and how it is used to...]]></description>
      <content:encoded><![CDATA[<p>Edit:&nbsp; This is now part 1 of a series.&nbsp;</p>
<ul>
<li>This post covers SignalR and how it is used to provide real-time "health" updates to a web page.</li>
<li><a href="https://blogs.msdn.com/b/jerrydixon/archive/2014/10/11/using-signalr-to-power-asp-net-dashboards-part-2.aspx">Part 2</a> covers how to use the .NET PerformanceCounter class to pull actual status information and forward it to the dashboard.</li>
</ul>
<p>&nbsp;</p>
<p>Lately, I have received a number of requests for help with simple dashboard applications. Most of the people making these requests have similar requirements. They would like an application that:</p>
<ul>
<li>Runs in a web page</li>
<li>Acquires updated information without page refreshes or post-backs</li>
<li>Is easy to code</li>
<li>Receives data within seconds of that data being generated</li>
</ul>
<p>Some people have additional requirements. Their application must also:</p>
<ul>
<li>Run on different browser brands and versions</li>
<li>Obtain data from non-web sources, such as console or Windows applications</li>
</ul>
<p>&nbsp;</p>
<p>My demo addresses all of these points, and consists of two parts. The first is a web application that displays the health of a fictitious environment that contains six computers. Those computers are divided into three different environments; Development (DEV), User-Acceptance (UAT), and Production (PRD). Each computer name is derived, imaginatively enough, from its environment and ordinal position within that environment. We therefore have DEV1 and DEV2 in the development area, UAT1 and UAT2 in the user-acceptance area, and PRD1 and PRD2 in the production area.</p>
<p><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/89/16/metablogapi/6431.081614_2035_UsingSignal1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-89-16-metablogapi/6431.081614_5F00_2035_5F00_UsingSignal1.png" alt="" /></p>
<p>In this sample, you can quickly see that the computers in the production environment are just fine, but that we have a possible situation in development, and an outright problem in acceptance.</p>
<p>&nbsp;</p>
<p>The second part of the solution is a Windows application that provides the status values for this fictitious environment.</p>
<p><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/89/16/metablogapi/3630.081614_2035_UsingSignal2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-89-16-metablogapi/3630.081614_5F00_2035_5F00_UsingSignal2.png" alt="" /></p>
<p>You can see that there is a slider for each machine, and that the data values here are reflected in the web page. The demo implements a one-way communications channel from the Windows application to the web page. Changes made in this Windows application are quickly transmitted to the web page.</p>
<p>By the way, in a real implementation, this Windows application would be a background task that constantly assesses the health of the environment. It could be any type of application; a console app, a Windows service, or even a PowerShell script. Anything that can communicate using HTTP protocols will work. Here, however, we are concerned about how the data is sent from the source to the web page and not on the data collection itself. Therefore, we have a simple set of sliders.</p>
<h1>Try it out</h1>
<p>I will describe the solution in some detail below. However, if you would like to try this for yourself first, then follow these steps:</p>
<ol>
<li>Navigate to the web page. The URL is <a href="https://signalrdashboard.azurewebsites.net/">https://signalrdashboard.azurewebsites.net/</a> .</li>
<li>Run the Windows application. It is a ClickOnce-deployed application hosted at <a href="https://signalrdashboard.blob.core.windows.net/wpfclient/publish.htm">https://signalrdashboard.blob.core.windows.net/wpfclient/publish.htm</a> . (You will probably need to add <a href="https://signalrdashboard.blob.core.windows.net">https://signalrdashboard.blob.core.windows.net</a> to your trusted sites list in order to run the application. It was signed with an untrusted, temporary certificate.)</li>
<li>Copy the "Client ID" value from the web page and paste it into the Windows application. (Because this demo is hosted in the cloud, many people may try to use it at the same time. To keep things simple, each instance of the Windows application will send data only to the client whose ID matches that entered into the application's "Client ID" textbox.)</li>
<li>Fiddle with the sliders and watch the web page change. (Don't fiddle TOO fast. Again, I'm trying to keep things simple. The demo does not throttle slider-value changes, so it is possible to change the slider values faster than the web page can apply them. In a real application, messages will normally be throttled in an appropriate manner.)</li>
</ol>
<p>&nbsp;</p>
<h1>Read the details</h1>
<p>The demo uses a SignalR <a href="https://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server">Hub</a> to facilitate easy communications. The hub is defined in the web application code-behind, so it runs on the Web server. It is defined in a class called <strong>StatusHub</strong>:</p>
<p style="background: white;"><span style="color: blue; font-family: Consolas; font-size: 10pt;">namespace<span style="color: black;">&nbsp;SignalRDashboard.Web <br /></span></span><span style="color: black; font-family: Consolas; font-size: 10pt;">{&nbsp;<br /></span><span style="color: black; font-family: Consolas; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public<span style="color: black;">&nbsp;<span style="color: blue;">class<span style="color: black;">&nbsp;<span style="color: #2b91af;">StatusHub<span style="color: black;">:&nbsp;<span style="color: #2b91af;">Hub<br /></span></span></span></span></span></span></span></span><span style="color: black; font-family: Consolas; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br /></span><span style="color: black; font-family: Consolas; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">public<span style="color: black;">&nbsp;<span style="color: blue;">void<span style="color: black;">&nbsp;SendStatus(<span style="color: blue;">string<span style="color: black;">&nbsp;connectionId,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">string<span style="color: black;">&nbsp;systemName,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">string<span style="color: black;">&nbsp;value,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">string<span style="color: black;">&nbsp;status)&nbsp;<br /></span></span></span></span></span></span></span></span></span></span></span></span></span><span style="color: black; font-family: Consolas; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br /></span><span style="color: black; font-family: Consolas; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Clients.Client(connectionId).ProcessStatusMessage(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; systemName,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; status);&nbsp;<br /></span><span style="color: black; font-family: Consolas; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br /></span><span style="color: black; font-family: Consolas; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span><span style="color: black; font-family: Consolas; font-size: 10pt;">} </span></p>
<p>&nbsp;</p>
<p>The hub class defines a method (<strong>SendStatus</strong>) that sends a message to a particular client. The command is broken down like this:</p>
<p style="background: white;"><span style="color: black; font-size: 10pt;"><span style="font-family: Consolas;">Clients&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-family: Wingdings;">&szlig;</span><span style="font-family: Consolas;"> returns an IHubCallerConnectionContext that <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; allows access to clients<br />Client(connectionId)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-family: Wingdings;">&szlig;</span><span style="font-family: Consolas;"> returns a connection to the client with <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the specified Id<br />ProcessStatusMessage(...);&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: Wingdings;">&szlig;</span><span style="font-family: Consolas;"> invokes the ProcessStatusMessage function&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defined in the web page </span></span></p>
<p>&nbsp;</p>
<p>The <strong>ProcessStatusMessage</strong> function is defined in the JavaScript in the web page itself:</p>
<pre><code><span style="color: black; font-family: Consolas;">hub.client.processStatusMessage&nbsp;=&nbsp;<span style="color: blue;">function<span style="color: black;">&nbsp;(systemName,&nbsp;value,&nbsp;status)&nbsp;{ <br /></span></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;get&nbsp;appropriate&nbsp;class&nbsp;from&nbsp;status<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">var<span style="color: black;">&nbsp;c&nbsp;=&nbsp;<span style="color: #a31515;">"btn&nbsp;btn-lg"<span style="color: black;">; <br /></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if<span style="color: black;">&nbsp;(status&nbsp;==&nbsp;<span style="color: #a31515;">"Critical"<span style="color: black;">)&nbsp;{ <br /></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;=&nbsp;<span style="color: #a31515;">"btn&nbsp;btn-lg&nbsp;btn-danger"<span style="color: black;">; <br /></span></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if<span style="color: black;">&nbsp;(status&nbsp;==&nbsp;<span style="color: #a31515;">"Warning"<span style="color: black;">)&nbsp;{ <br /></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;=&nbsp;<span style="color: #a31515;">"btn&nbsp;btn-lg&nbsp;btn-warning"<span style="color: black;">; <br /></span></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if<span style="color: black;">&nbsp;(status&nbsp;==&nbsp;<span style="color: #a31515;">"Normal"<span style="color: black;">)&nbsp;{ <br /></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;=&nbsp;<span style="color: #a31515;">"btn&nbsp;btn-lg&nbsp;btn-success"<span style="color: black;">; <br /></span></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;assign&nbsp;the&nbsp;class&nbsp;to&nbsp;the&nbsp;appropriate&nbsp;button<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;$(<span style="color: #a31515;">"#"<span style="color: black;">&nbsp;+&nbsp;systemName).attr(<span style="color: #a31515;">"class"<span style="color: black;">,&nbsp;c); <br /></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;assign&nbsp;name&nbsp;based&nbsp;on&nbsp;value<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;$(<span style="color: #a31515;">"#"<span style="color: black;">&nbsp;+&nbsp;systemName).text(systemName&nbsp;+&nbsp;<span style="color: #a31515;">"&nbsp;("<span style="color: black;">&nbsp;+&nbsp;value&nbsp;+&nbsp;<span style="color: #a31515;">")"<span style="color: black;">) <br /></span></span></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;">} </span></code></pre>
<p>&nbsp;</p>
<p>The cool part is that SignalR wires up the communications between the function in the code-behind on the server (SendStatus) and the function in the JavaScript in the browser (ProcessStatusMessage). It does this based on the capabilities of the specific web server and browser being used. It implements various transport protocols and <a href="https://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/introduction-to-signalr">chooses the most &ndash;appropriate</a> one for the situation. This eliminates a lot of tedious programming.</p>
<p>&nbsp;</p>
<p>Now that we know that the hub can send data to the browser client, we need to know how to send data to the hub. In this demo, the data is generated in the Windows application, so that is where the communication happens as well. In the SignalRSupport class, there are two interesting sections of code.</p>
<p>First, in the constructor:</p>
<pre><code><span style="color: blue; font-family: Consolas;">private<span style="color: black;">&nbsp;SignalRSupport() <br /></span></span></code><code><span style="color: black; font-family: Consolas;">{ <br /></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;create&nbsp;a&nbsp;connection&nbsp;to&nbsp;the&nbsp;hub<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;note&nbsp;that&nbsp;this&nbsp;is&nbsp;a&nbsp;disposable&nbsp;object,&nbsp;but&nbsp;I&nbsp;do&nbsp;not&nbsp;dispose&nbsp;of&nbsp;it&nbsp;here.<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;the&nbsp;connection&nbsp;will&nbsp;be&nbsp;used&nbsp;for&nbsp;the&nbsp;life&nbsp;of&nbsp;the&nbsp;application,&nbsp;so&nbsp;this&nbsp;is&nbsp;acceptable.<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">var<span style="color: black;">&nbsp;hubConnection&nbsp;=&nbsp;<span style="color: blue;">new<span style="color: black;">&nbsp;<span style="color: #2b91af;">HubConnection<span style="color: black;">("<span style="color: #a31515;">https://signalrdashboard.azurewebsites.net/<span style="color: black;">"); <br /></span></span></span></span></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;create&nbsp;a&nbsp;client&nbsp;proxy&nbsp;class&nbsp;to&nbsp;use&nbsp;to&nbsp;communicate&nbsp;with&nbsp;the&nbsp;hub.<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;statusHubProxy&nbsp;=&nbsp;hubConnection.CreateHubProxy(<span style="color: #a31515;">"StatusHub"<span style="color: black;">); <br /></span></span></span></code><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;start&nbsp;the&nbsp;connection&nbsp;and&nbsp;wait&nbsp;for&nbsp;it&nbsp;to&nbsp;complete.<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;without&nbsp;.wait,&nbsp;the&nbsp;code&nbsp;would&nbsp;continue&nbsp;while&nbsp;the&nbsp;connection&nbsp;is&nbsp;made.<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;hubConnection.Start().Wait(); </span></code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><code><span style="color: black; font-family: Consolas;">} </span></code></pre>
<p>&nbsp;</p>
<p>The code creates a connection to the hub via its URL. (Hey! I KNOW that this shouldn't be hard-coded, but this is a demo. Do what I say, not what I do.) It next creates a Hub proxy that will be used to execute the <strong>SendStatus</strong> function mentioned above. Finally, it starts the connection. Note the "<strong>Wait</strong>" method call. The <strong>Start</strong> method is asynchronous. Without <strong>Wait</strong>, the code would continue executing even though the connection hasn't started. In many applications, this is fine. In this demo though, I didn't want to deal with people moving sliders around when the hub connection wasn't ready.</p>
<p>The second interesting section is the <strong>SendStatusUpdate</strong> method:</p>
<pre><code><span style="color: blue; font-family: Consolas;">public<span style="color: black;">&nbsp;<span style="color: blue;">void<span style="color: black;">&nbsp;SendStatusUpdate(<span style="color: blue;">string<span style="color: black;">&nbsp;clientId,&nbsp;<span style="color: blue;">string<span style="color: black;">&nbsp;systemName,&nbsp;<span style="color: blue;">string<span style="color: black;">&nbsp;value,&nbsp;<span style="color: blue;">string<span style="color: black;">&nbsp;status) <br /></span></span></span></span></span></span></span></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;">{ <br /></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;invoke&nbsp;the&nbsp;SendStatus&nbsp;method&nbsp;that&nbsp;is&nbsp;defined&nbsp;on&nbsp;the&nbsp;hub.<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;statusHubProxy.Invoke(<span style="color: #a31515;">"SendStatus"<span style="color: black;">,&nbsp;clientId,&nbsp;systemName,&nbsp;value,&nbsp;status); <br /></span></span></span></code><code><span style="color: black; font-family: Consolas;">} </span></code></pre>
<p>&nbsp;</p>
<p>This code uses the proxy that was create in the constructor to invoke the <strong>SendStatus</strong> method that is defined in the Hub. Once again, SignalR takes care of wiring up the communications between the Windows application and the Web server. (Remember when I said that the Hub class ran on the server?) It negotiates the best protocol and handles the connection automatically. More tedious code that I don't have to write.</p>
<p>&nbsp;</p>
<p>Believe it or not, the SignalR part of the application is complete. The rest of the example is all XAML and data-binding, which is not the point of this post. However, it goes something like this:</p>
<p>The main window has 6 instances of the StatusControl usercontrol, which contains the slider that is used to control a single machine value. Each StatusControl binds to an instance of the StatusCounter class. The StatusCounter value property contains code that initiates the SignalR communications described above:</p>
<pre><code><span style="color: blue; font-family: Consolas;">public<span style="color: black;">&nbsp;<span style="color: blue;">int<span style="color: black;">&nbsp;Value <br /></span></span></span></span></code><code><span style="color: black; font-family: Consolas;">{ <br /></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">get<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;{ <br /></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">return<span style="color: black;">&nbsp;_value; <br /></span></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">set<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;{ <br /></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;has&nbsp;the&nbsp;value&nbsp;changed?<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if<span style="color: black;">&nbsp;(_value&nbsp;!=&nbsp;<span style="color: blue;">value<span style="color: black;">) <br /></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br /></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;the&nbsp;value&nbsp;has&nbsp;changed,&nbsp;so&nbsp;apply&nbsp;it.<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_value&nbsp;=&nbsp;<span style="color: blue;">value<span style="color: black;">; <br /></span></span></span></code><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: green;">//&nbsp;raise&nbsp;propertychanged&nbsp;events&nbsp;so&nbsp;that&nbsp;databinding&nbsp;can&nbsp;work<br /></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">if<span style="color: black;">&nbsp;(PropertyChanged&nbsp;!=&nbsp;<span style="color: blue;">null<span style="color: black;">) <br /></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br /></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PropertyChanged(<span style="color: blue;">this<span style="color: black;">,&nbsp;<span style="color: blue;">new<span style="color: black;">&nbsp;<span style="color: #2b91af;">PropertyChangedEventArgs<span style="color: black;">(<span style="color: #a31515;">"Value"<span style="color: black;">)); <br /></span></span></span></span></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PropertyChanged(<span style="color: blue;">this<span style="color: black;">,&nbsp;<span style="color: blue;">new<span style="color: black;">&nbsp;<span style="color: #2b91af;">PropertyChangedEventArgs<span style="color: black;">(<span style="color: #a31515;">"Status"<span style="color: black;">)); <br /></span></span></span></span></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #2b91af;">SignalRSupport<span style="color: black;">.Instance.SendStatusUpdate(<span style="color: blue;">this<span style="color: black;">.ClientId,&nbsp;<span style="color: blue;">this<span style="color: black;">.CounterName,&nbsp;<span style="color: blue;">this<span style="color: black;">.Value.ToString(),&nbsp;<span style="color: blue;">this<span style="color: black;">.Status.ToString()); <br /></span></span></span></span></span></span></span></span></span></span></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code><code><span style="color: black; font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp;} <br /></span></code><code><span style="color: black; font-family: Consolas;">} </span></code></pre>
<p>&nbsp;</p>
<p>Therefore, when a slider value is changed, data-binding drives the sending of that value to the appropriate machine counter on the correct client. Gotta love data-binding!</p>
<h1>Download the code</h1>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/89/16/3348.SignalRDashboard.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-89-16/3348.SignalRDashboard.zip">&nbsp;SignalRDashboard.zip</a></p>
<h1>Read the references</h1>
<p><a href="https://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/introduction-to-signalr">Introduction to SignalR</a></p>
<p>Please leave a comment if you find this useful.</p>]]></content:encoded>
    </item>
    <item>
      <title>Zipping a single file with PowerShell</title>
      <link>https://docs.microsoft.com/archive/blogs/jerrydixon/zipping-a-single-file-with-powershell</link>
      <pubDate>Fri, 08 Aug 2014 12:46:00 GMT</pubDate>
      <dc:creator><![CDATA[Jerry Dixon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jerrydixon/2014/08/08/zipping-a-single-file-with-powershell/</guid>
      <description><![CDATA[I recently needed to quickly create a PowerShell script that would create a Zip file from a...]]></description>
      <content:encoded><![CDATA[<p>I recently needed to quickly create a PowerShell script that would create a Zip file from a specified input file.&nbsp; A quick Bing search found a <a href="https://stackoverflow.com/questions/1153126/how-to-create-a-zip-archive-with-powershell">popular solution on StackOverflow</a>:</p>
<blockquote>
<p><span style="font-family: Consolas;">function ZipFiles( $zipfilename, $sourcedir )<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Add-Type -Assembly System.IO.Compression.FileSystem&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; $compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal<br />&nbsp;&nbsp;&nbsp;&nbsp; [System.IO.Compression.ZipFile]::CreateFromDirectory($sourcedir,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$zipfilename,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$compressionLevel,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $false) <br />}</span></p>
</blockquote>
<p>Unfortunately, this would not work for me.&nbsp; This script zips everything in a folder, whereas I needed to zip a specific file.&nbsp; I therefore searched some more and found a combination of three blogs that gave me what I needed:</p>
<blockquote>
<p><span style="font-family: Consolas;">[CmdletBinding()]<br />Param(<br />&nbsp;&nbsp;&nbsp;&nbsp; [Parameter(Mandatory=$True)]<br />&nbsp;&nbsp;&nbsp;&nbsp; [ValidateScript({Test-Path -Path $_ -PathType Leaf})]<br />&nbsp;&nbsp;&nbsp;&nbsp; [string]$sourceFile,<br /><br />&nbsp;&nbsp;&nbsp;&nbsp; [Parameter(Mandatory=$True)]<br />&nbsp;&nbsp;&nbsp;&nbsp; [ValidateScript({-not(Test-Path -Path $_ -PathType Leaf)})]<br />&nbsp;&nbsp;&nbsp;&nbsp; [string]$destinationFile<br />) <br /></span></p>
</blockquote>
<blockquote>
<p><span style="font-family: Consolas;">&lt;#<br />&nbsp;&nbsp;&nbsp;&nbsp; .SYNOPSIS<br />&nbsp;&nbsp;&nbsp;&nbsp; Creates a ZIP file that contains the specified innput file. </span></p>
</blockquote>
<blockquote>
<p><span style="font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp; .EXAMPLE<br />&nbsp;&nbsp;&nbsp;&nbsp; FileZipper -sourceFile c:\test\inputfile.txt <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -destinationFile c:\test\outputFile.zip<br />#&gt; <br /></span></p>
</blockquote>
<blockquote>
<p><span style="font-family: Consolas;">function New-Zip<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp; param([string]$zipfilename)<br />&nbsp;&nbsp;&nbsp;&nbsp; set-content $zipfilename <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))<br />&nbsp;&nbsp;&nbsp;&nbsp; (dir $zipfilename).IsReadOnly = $false<br />} </span></p>
</blockquote>
<blockquote>
<p><span style="font-family: Consolas;">function Add-Zip<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp; param([string]$zipfilename) <br /></span></p>
</blockquote>
<blockquote>
<p><span style="font-family: Consolas;">&nbsp;&nbsp;&nbsp;&nbsp; if(-not (test-path($zipfilename)))<br />&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set-content $zipfilename <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (dir $zipfilename).IsReadOnly = $false&nbsp;&nbsp;&nbsp; <br /><br />&nbsp;&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp;&nbsp; $shellApplication = new-object -com shell.application<br />&nbsp;&nbsp;&nbsp;&nbsp; $zipPackage = $shellApplication.NameSpace($zipfilename)<br />&nbsp;&nbsp;&nbsp;&nbsp; <br /><br />&nbsp;&nbsp;&nbsp;&nbsp; foreach($file in $input) <br />&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $zipPackage.CopyHere($file.FullName)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Start-sleep -milliseconds 500</span><span style="font-family: Consolas;"><br />&nbsp;&nbsp;&nbsp;&nbsp; }<br />} </span></p>
</blockquote>
<blockquote>
<p><span style="font-family: Consolas;">dir $sourceFile | Add-Zip $destinationFile</span></p>
</blockquote>
<p>The three posts that helped were:</p>
<ul>
<li><a href="https://blogs.msdn.com/b/daiken/archive/2007/02/12/compress-files-with-windows-powershell-then-package-a-windows-vista-sidebar-gadget.aspx">Compress Files with Windows PowerShell then package a Windows Vista Sidebar Gadget</a></li>
<li><a href="https://blogs.technet.com/b/heyscriptingguy/archive/2011/05/15/simplify-your-powershell-script-with-parameter-validation.aspx">Simplify Your PowerShell Script with Parameter Validation</a></li>
<li><a href="https://blogs.technet.com/b/heyscriptingguy/archive/2010/01/07/hey-scripting-guy-january-7-2010.aspx">Hey, Scripting Guy! How Do I Add Help Information for Windows PowerShell Parameters?</a></li>
</ul>
<p>I hope this saves&nbsp;someone else some time.</p>]]></content:encoded>
    </item>
    <item>
      <title>Visual Studio 2013 Goodies</title>
      <link>https://docs.microsoft.com/archive/blogs/jerrydixon/visual-studio-2013-goodies</link>
      <pubDate>Thu, 07 Aug 2014 12:05:00 GMT</pubDate>
      <dc:creator><![CDATA[Jerry Dixon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jerrydixon/2014/08/07/visual-studio-2013-goodies/</guid>
      <description><![CDATA[Just a quick post to remind everyone that Visual Studio 2013 Update 3 has now been...]]></description>
      <content:encoded><![CDATA[<p>Just a quick post to remind everyone that <a href="https://support.microsoft.com/kb/2933779">Visual Studio 2013 Update 3</a> has now been released.&nbsp;&nbsp;It has too many features to cover in detail here.&nbsp; However, in addition to a number of fixes, it also allows you to get rid of the ALL CAPS menus.</p>
<p>&nbsp;</p>
<p>This:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/89/16/5355.Before.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-89-16/5355.Before.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/89/16/5355.Before.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-89-16/5355.Before.PNG" alt="" border="0" /></a></p>
<p>becomes this:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/89/16/8078.After.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-89-16/8078.After.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/89/16/8078.After.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-89-16/8078.After.PNG" alt="" border="0" /></a></p>
<p>&nbsp;</p>
<p>New goodies include better Web tooling (MVC, WebAPI, JSON, CSS) and vastly-increased debugging capabilities.&nbsp; This is a free update, and it is well worth the download time.&nbsp;</p>
<p>&nbsp;</p>
<p>The REAL reason for this post, however, is to make sure that people know about these add-ins:</p>
<ul>
<li><a href="https://visualstudiogallery.msdn.microsoft.com/dbcb8670-889e-4a54-a226-a48a15e4cace">Productivity Power Tools 2013</a></li>
<li><a href="https://vswebessentials.com/">Web Essentials 2013</a></li>
</ul>
<p>I have been doing more development lately, and these tools are really useful.&nbsp;</p>
<p>&nbsp;</p>
<p><strong>Productivity Power Tools</strong> provides about 25 useful features to general development.&nbsp; My favorites are:</p>
<ul>
<li><strong>Peek Help (Alt + F1)</strong> - invoke context-sensitive help from MSDN and display it in the "Peek Definition" window.</li>
<li><strong>Solution Explorer Errors</strong> - Solution Explorer now places "squiggles" beneath files, folders, projects, and solutions that contain errors.&nbsp; Now it is obvious where my errors lie.&nbsp; Hovering the mouse pointer over a squiggle causes the error messages to pop up in a little window.</li>
<li><strong>Structure Visualizer</strong> - Vertical lines connect the begin and end of block constructs, such as if statements.&nbsp; This is really nice when there are a lot of nested structures or one structure is large than one screen height.</li>
<li><strong>Document Well</strong> - Customize many of the color and behaviors of the tabs in the source editor window.</li>
</ul>
<p>All of the features are configurable, and can be enabled or disabled as you see fit.&nbsp; The full feature list is available on the <a href="https://visualstudiogallery.msdn.microsoft.com/dbcb8670-889e-4a54-a226-a48a15e4cace">Visual Studio Gallery </a>page.</p>
<p>&nbsp;</p>
<p><strong>Web Essentials</strong> adds enhanced support for Web page development, including CSS (more Intellisense), JavaScript (Minification, Auto-complete braces), and more.&nbsp; It also enhances BrowserLink so that it is even more useful than before. Check out the <a href="https://vswebessentials.com/">web site</a> for a full list of features.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br /><br />&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Boot from VHD - What worked for us</title>
      <link>https://docs.microsoft.com/archive/blogs/jerrydixon/boot-from-vhd-what-worked-for-us</link>
      <pubDate>Sun, 29 Jun 2014 11:11:00 GMT</pubDate>
      <dc:creator><![CDATA[Jerry Dixon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jerrydixon/2014/06/29/boot-from-vhd-what-worked-for-us/</guid>
      <description><![CDATA[My son and I spent most of the day yesterday trying to get our laptops to boot from a VHD.&nbsp; We...]]></description>
      <content:encoded><![CDATA[<p>My son and I spent most of the day yesterday trying to get our laptops to boot from a VHD.&nbsp; We found loads of posts on the&nbsp;Internet that showed how it should be done, but we couldn't make it work.&nbsp; When we finally were successful, we found what we believe is an easier process, at least for us.&nbsp;&nbsp;I'm posting those steps here for future reference.</p>
<p>The&nbsp;goal was to run Windows 8.1&nbsp;on&nbsp;a laptop, but to have the option to boot into Windows 7&nbsp;when needed.&nbsp; I used&nbsp;an HP EliteBook 8540w, which is easily able to run Windows 7.&nbsp; (It has Windows 7 drivers available, uses BIOS instead of UEFI, and has no SecureBoot support.)&nbsp; My son used&nbsp;his Dell Inspiron 15 7000 Touch, which does NOT have Windows 7 drivers available.&nbsp;&nbsp;His laptop has all the latest goodies, including UEFI and SecureBoot.&nbsp;</p>
<p>Here is our list of steps:</p>
<ol>
<li>Create a fixed-size hard disk with Hyper-V Manager.&nbsp; You need to use the VHD format, because VHDX only works with Windows 8.x / Widows Server 2012&nbsp;and above.&nbsp;&nbsp;</li>
<li>Create a VM for your VHD, and install Windows 7.&nbsp; I also installed SP1 and all of the updates and patches.</li>
<li>Run SysPrep on the VM, and specify OOBE, Generalize, and Shutdown.</li>
<li>Copy the VHD to the laptop that will use it for boot.&nbsp; (I created the VHD on a new, faster, laptop.)</li>
<li>Mount the VHD with Disk Manager and note the driver letter that is assigned.&nbsp; On my laptop, it was drive G:</li>
<li>Open an Administrative Command Prompt</li>
<li>Run <span style="font-family: courier new,courier; font-size: small;">BCDBoot G:\Windows</span></li>
<li>Run <span style="font-family: courier new,courier; font-size: small;">BCDBoot C:\Windows</span></li>
<li>Reboot the laptop.</li>
</ol>
<p>After following these steps, my laptop could successfully boot into Windows 7.&nbsp;&nbsp; My son's could not.&nbsp; We believe that the only difference was that my laptop has Windows 7 driver support, while his does not.</p>
<p>I believe that this is an easier process, because I did not have to use BCDEdit or&nbsp;ImageX, which were recommended in all of the posts that I found.&nbsp; These steps are&nbsp;very similar to those that I use&nbsp;to create VMs in Hyper-V, so I find them more&nbsp;intuitive.</p>
<p>There are&nbsp;some caveats:</p>
<ul>
<li>If you have enabled Hyper-V one the machine, this this process will disable it.&nbsp; You can re-enable the hypervisor by&nbsp;running this command from and Administrative Command Prompt:</li>
<ul>
<li><span style="font-family: courier new,courier; font-size: small;">BCDEdit /set {current} hypervisorlaunchtype auto</span></li>
</ul>
<li>Your laptop has to be able to run the guest OS in the first place (my son's could not because there are no Windows 7 drivers available)</li>
<li>You need to disable BIOS/UEFI features that are not supported by your guest OS (SecureBoot, for example)</li>
<li>You can only use&nbsp;the VHDX format if your&nbsp;guest OS supports it (Windows 8.x / Windows Server 2012)</li>
<li>Be ready to admit that your son knows more about this than you do.&nbsp;:)</li>
</ul>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Get the name of the current property or method</title>
      <link>https://docs.microsoft.com/archive/blogs/jerrydixon/get-the-name-of-the-current-property-or-method</link>
      <pubDate>Fri, 27 Jun 2014 11:46:00 GMT</pubDate>
      <dc:creator><![CDATA[Jerry Dixon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jerrydixon/2014/06/27/get-the-name-of-the-current-property-or-method/</guid>
      <description><![CDATA[I often need to obtain the name of the current property of method, and I have historically used...]]></description>
      <content:encoded><![CDATA[<p>I often need to obtain the name of the current property of method, and I have historically used reflection for this.&nbsp; However, I recently ran across the <a title="CallerMemberName" href="https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute(v=vs.110).aspx">CallerMemberName</a> attribute. This lead me to create the following utility function:</p>
<pre style="background: white; color: black; font-family: Consolas;"><span style="color: blue;">Public</span>&nbsp;<span style="color: blue;">Shared</span>&nbsp;<span style="color: blue;">Function</span>&nbsp;GetMethodOrPropertyName(<br />			&lt;<span style="color: #2b91af;">CallerMemberName</span>&gt;&nbsp;<span style="color: blue;">Optional</span>&nbsp;memberName&nbsp;<span style="color: blue;">As</span>&nbsp;<span style="color: blue;">String</span>&nbsp;=&nbsp;<span style="color: blue;">Nothing</span>)&nbsp;<br />			<span style="color: blue;">As</span>&nbsp;<span style="color: blue;">String</span>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">Return</span>&nbsp;memberName
<span style="color: blue;">End</span>&nbsp;<span style="color: blue;">Function</span></pre>
<p>The key here is that I do not specify the&nbsp;memberName parameter when I call the function, so the compiler fills it in for me.&nbsp;&nbsp;(That's what the attribute is for.)&nbsp; Now I can call this function whenever&nbsp;I need the current method's name.&nbsp; NO custom reflection code required.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Support timelines for SQL Server, .NET Framework, Visual Studio, Team Foundation Server and Windows</title>
      <link>https://docs.microsoft.com/archive/blogs/jerrydixon/support-timelines-for-sql-server-net-framework-visual-studio-team-foundation-server-and-windows</link>
      <pubDate>Wed, 03 Jul 2013 07:46:00 GMT</pubDate>
      <dc:creator><![CDATA[Jerry Dixon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jerrydixon/2013/07/03/support-timelines-for-sql-server-net-framework-visual-studio-team-foundation-server-and-windows/</guid>
      <description><![CDATA[Microsoft maintains a database of all supported products, along with the dates when those products'...]]></description>
      <content:encoded><![CDATA[<p>Microsoft maintains a database of all supported products, along with the dates when those products' various support stages end.&nbsp; Anyone can <a title="search" href="https://support.microsoft.com/lifecycle/search/" target="_blank">search</a> the database for a specific product, but that can be time-consuming when data&nbsp;for&nbsp;more than one product is needed.&nbsp; I have therefore been maintaining&nbsp;a list of important dates and relevant information about several products for my clients.&nbsp; I have decided to consolidate that list here for easy reference.&nbsp; Note that this list is for informational purposes only; the <a title="Product Lifecycle" href="https://support.microsoft.com/lifecycle/" target="_blank">product lifecycle page</a> contains the official dates and policies.&nbsp; Please refer to those pages when questions arise.</p>
<p>Last Updated: 10/3/2014</p>
<p>Recent and upcoming changes&nbsp;are highlighted in <span style="color: #ff0000;">red</span>.</p>
<p><strong>SQL Server</strong></p>
<ul>
<li>7.0</li>
<ul>
<li>No longer supported</li>
</ul>
<li>2000</li>
<ul>
<li><span style="color: #000000;">No longer supported</span></li>
</ul>
<li>2005</li>
<ul>
<li>In extended support</li>
<li>Leaves support completely on 4/12/2016</li>
<li>SP4 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=7218" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=7218</a></li>
</ul>
<li>2008</li>
<ul>
<li><span style="color: #ff0000;">In extended support</span></li>
<li>Leaves support completely on 7/9/2019</li>
<li><span style="color: #ff0000;">SP4 is the current service pack</span>: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=44278">https://www.microsoft.com/en-us/download/details.aspx?id=44278</a></li>
</ul>
<li>2008 R2</li>
<ul>
<li><span style="color: #ff0000;">In extended support</span></li>
<li>Leaves support completely on 7/9/2019</li>
<li><span style="color: #ff0000;">SP3 is the current service pack</span>: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=44271">https://www.microsoft.com/en-us/download/details.aspx?id=44271</a></li>
</ul>
<li>2012</li>
<ul>
<li>In mainstream support</li>
<li>Goes into extended support on 7/11/2017</li>
<li>Leaves support completely on 7/12/2022</li>
<li><span style="color: #000000;">SP1 leaves support on 7/14/2015</span></li>
<li>SP2 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=43340">https://www.microsoft.com/en-us/download/details.aspx?id=43340</a></li>
</ul>
<li>2014</li>
<ul>
<li><span style="color: #000000;">In mainstream support</span></li>
<li><span style="color: #000000;">Goes into extended support on 7/9/2019</span></li>
<li><span style="color: #000000;">Leaves support completely on 7/9/2024</span></li>
</ul>
</ul>
<p>&nbsp;</p>
<p><strong>.NET Framework</strong></p>
<ul>
<li>1.0</li>
<ul>
<li>No longer supported</li>
</ul>
<li>1.1</li>
<ul>
<li><span style="color: #000000;">Standalone versions are no longer supported</span></li>
<li><span style="color: #000000;">Support for the .NET Framework 1.1&nbsp;version bundled with Windows 2003 SP2 x86 will continue until 7/14/2015, when the operating system support ends.</span></li>
</ul>
<li>2.0</li>
<ul>
<li>In extended support</li>
<li>Leaves support completely on 4/12/2016</li>
<li>SP2 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=1639" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=1639</a></li>
</ul>
<li>3.0</li>
<ul>
<li>No longer supported</li>
</ul>
<li>3.5</li>
<ul>
<li>RTM is no longer supported</li>
<li>SP1 is now considered a part of the operating system on which it is supported.&nbsp; It will be supported and serviced along with the operating system.</li>
<li>SP1 download: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=22" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=22</a></li>
</ul>
<li>3.5.1</li>
<ul>
<li>3.5.1 is now considered a part of the operating system on which it is supported.&nbsp; It will be supported and serviced along with the operating system.</li>
</ul>
<li>4.0</li>
<ul>
<li>4.0 is now considered a part of the operating system on which it is supported.&nbsp; It will be supported and serviced along with the operating system.</li>
</ul>
<li>4.5</li>
<ul>
<li>It is a replacement for .NET 4.0, not a separate install (4.5 updates 4.0)</li>
<li>It is considered a component of the operating on which it is installed.&nbsp; It will be supported and serviced along with the operating system.</li>
</ul>
<li>4.5.1</li>
<ul>
<li><span style="color: #000000;">It is a replacement for .NET 4.0 and .NET 4.5, not a separate install (4.5.1 updates 4.x)</span></li>
<li><span style="color: #000000;">It is considered a component of the operating on which it is installed.&nbsp; It will be supported and serviced along with the operating system.</span></li>
</ul>
</ul>
<p>&nbsp;</p>
<p><strong>Visual Studio</strong></p>
<ul>
<li>2002</li>
<ul>
<li>No longer supported</li>
</ul>
<li>2003</li>
<ul>
<li><span style="color: #000000;">No longer supported</span></li>
</ul>
<li>2005</li>
<ul>
<li>In extended support</li>
<li>Leaves support completely on 4/12/2016</li>
<li>SP1 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=5553" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=5553</a></li>
</ul>
<li>2005 Team Editions</li>
<ul>
<li>All versions except the database edition</li>
<ul>
<li>In extended support</li>
<li>Leaves support completely on 4/12/2016</li>
<li>SP1 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=5553" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=5553</a></li>
</ul>
<li>Database edition</li>
<ul>
<li>In extended support</li>
<li>Leaves support completely on 4/11/2017</li>
<li>SP1 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=5553" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=5553</a></li>
</ul>
</ul>
<li>2008</li>
<ul>
<li><span style="color: #000000;">In extended support</span></li>
<li>Leaves support completely on 4/10/2018</li>
<li>SP1 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=10986" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=10986</a></li>
</ul>
<li>2010</li>
<ul>
<li>In mainstream support</li>
<li>Goes into extended support on 7/14/2015</li>
<li>Leaves support completely on 9/8/2020</li>
<li>SP1 is the current service pack: <a href="https://www.microsoft.com/download/en/details.aspx?id=23691" target="_blank">https://www.microsoft.com/download/en/details.aspx?id=23691</a></li>
</ul>
<li>2012</li>
<ul>
<li>In mainstream support</li>
<li>Goes into extended support on 1/9/2018</li>
<li>Leaves support completely on 1/10/2023</li>
<li>RTM (no service pack) is the current version</li>
<li><span style="color: #000000;">Update 4 is available</span>: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=39305">https://www.microsoft.com/en-us/download/details.aspx?id=39305</a></li>
</ul>
<li>2013</li>
<ul>
<li><span style="color: #000000;">In mainstream support</span></li>
<li><span style="color: #000000;">Goes into extended support on 4/9/2019</span></li>
<li><span style="color: #000000;">Leaves support completely on 4/9/2024</span></li>
<li><span style="color: #000000;">RTM (no service pack) is the current version</span></li>
<li><span style="color: #000000;">Update 3 is available: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=43721">https://www.microsoft.com/en-us/download/details.aspx?id=43721</a></span></li>
</ul>
</ul>
<p>&nbsp;</p>
<p><strong>Team Foundation Server</strong></p>
<ul>
<li>2005</li>
<ul>
<li>In extended support</li>
<li>Leaves support completely on 7/12/2016</li>
<li>SP1 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=15789" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=15789</a></li>
</ul>
<li>2008</li>
<ul>
<li><span style="color: #000000;">In extended support</span></li>
<li>Leaves support completely on 4/10/2018</li>
<li>SP1 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=6097" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=6097</a></li>
</ul>
<li>2010</li>
<ul>
<li>In mainstream support</li>
<li>Goes into extended support on 7/14/2015</li>
<li>Leaves support completely on 9/8/2020</li>
<li>SP1 is the current service pack: <a href="https://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;id=20506" target="_blank">https://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;id=20506</a></li>
</ul>
<li>2012</li>
<ul>
<li>In mainstream support</li>
<li>Goes into extended support on 1/9/2018</li>
<li>Leaves support completely on 1/10/2023</li>
<li>RTM (no service pack) is the current version</li>
</ul>
<li>2013</li>
<ul>
<li><span style="color: #000000;">In mainstream support</span></li>
<li><span style="color: #000000;">Goes into extended support on 4/9/2019</span></li>
<li><span style="color: #000000;">Leaves support completely on 4/9/2024</span></li>
<li><span style="color: #000000;">RTM (no service pack) is the current version</span></li>
</ul>
</ul>
<p>&nbsp;</p>
<p><strong>Windows Server</strong></p>
<ul>
<li>2000</li>
<ul>
<li>No longer supported</li>
</ul>
<li>2003</li>
<ul>
<li>In extended support</li>
<li>Leaves support completely on 7/14/2015</li>
<li>SP2 is the current service pack: <a href="https://technet.microsoft.com/en-us/windowsserver/bb229701.aspx" target="_blank">https://technet.microsoft.com/en-us/windowsserver/bb229701.aspx</a></li>
</ul>
<li>2003 R2</li>
<ul>
<li>In extended support</li>
<li>Leaves support completely on 7/14/2015</li>
<li>SP2 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=11276" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=11276</a></li>
</ul>
<li>2008</li>
<ul>
<li>In mainstream support</li>
<li>Goes into extended support on 1/13/2015</li>
<li>Leaves support completely on 1/14/2020</li>
<li>SP2 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=16468" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=16468</a></li>
</ul>
<li>2008 R2</li>
<ul>
<li>In mainstream support</li>
<li>Goes into extended support on 1/13/2015</li>
<li>Leaves support completely on 1/14/2020</li>
<li>SP1 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=5842" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=5842</a></li>
</ul>
<li>2012</li>
<ul>
<li>In mainstream support</li>
<li>Goes into extended support on 1/9/2018</li>
<li>Leaves support completely on 1/10/2023</li>
<li>RTM (no service pack) is the current version</li>
</ul>
<li>2012 R2
<ul>
<li>In mainstream support</li>
<li>Goes into extended support on 1/9/2018</li>
<li>Leaves support completely on 1/10/2023</li>
<li>RTM (no service pack) is the current version</li>
</ul>
</li>
</ul>
<p>&nbsp;</p>
<p><strong>Windows Client</strong></p>
<ul>
<li>XP</li>
<ul>
<li><span style="color: #000000;">No longer supported</span></li>
</ul>
<li>Vista</li>
<ul>
<li>In extended support</li>
<li>Leaves support completely on 4/11/2017</li>
<li>SP2 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=16468" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=16468</a></li>
</ul>
<li>7</li>
<ul>
<li>In mainstream support</li>
<li><span style="color: #ff0000;">Goes into extended support on 1/13/2015</span></li>
<li>Leaves support completely on 1/14/2020</li>
<li>SP1 is the current service pack: <a href="https://www.microsoft.com/en-us/download/details.aspx?id=5842" target="_blank">https://www.microsoft.com/en-us/download/details.aspx?id=5842</a></li>
</ul>
<li>8</li>
<ul>
<li>In mainstream support</li>
<li>Must move to Windows 8.1 by 1/12/2016 in order to remain supported</li>
<li>RTM (no service pack) is the current version</li>
</ul>
<li>8.1</li>
<ul>
<li><span style="color: #000000;">In mainstream support</span></li>
<li><span style="color: #000000;">Goes into extended support on 1/9/2018</span></li>
<li><span style="color: #000000;">Leaves support completely on 1/10/2023</span></li>
<li><span style="color: #000000;">RTM (no service pack) is the current version</span></li>
</ul>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Connection-Pooling vs. Reusing one connection</title>
      <link>https://docs.microsoft.com/archive/blogs/jerrydixon/connection-pooling-vs-reusing-one-connection</link>
      <pubDate>Thu, 19 May 2011 12:14:03 GMT</pubDate>
      <dc:creator><![CDATA[Jerry Dixon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jerrydixon/2011/05/19/connection-pooling-vs-reusing-one-connection/</guid>
      <description><![CDATA[I recently had a conversation about .NET connection pooling, and how this compares to reusing a...]]></description>
      <content:encoded><![CDATA[<p>I recently had a conversation about .NET connection pooling, and how this compares to reusing a single open connection.&#160; I have always “known” that connection pooling helps, but that it isn’t as efficient as reusing the connection.&#160; Since I couldn’t provide proof of my belief, I decided to write a test.&#160; I decided to execute a simple T-SQL statement 1,000 times and record how many milliseconds elapsed.&#160; I would then vary the way that connections are managed and see how this affected the elapsed time.</p>  <p>First, I wanted to test using a single connection:</p>  <pre>     Dim sw As Stopwatch = Stopwatch.StartNew</pre>

<pre>     Using conn As New SqlConnection(My.Settings.ConnectionString)<br />          conn.Open()</pre>

<pre>          For i = 1 To 1000<br />               Using cmd As New SqlCommand(&quot;select * from dbo.person&quot;, conn)<br />                    Using rdr As SqlDataReader = cmd.ExecuteReader()<br />                         While rdr.Read<br />                         End While<br />                    End Using<br />               End Using<br />          Next<br />     End Using</pre>

<pre>     sw.Stop()<br />     Dim elapsed As Long = sw.ElapsedMilliseconds</pre>

<pre>     MessageBox.Show(elapsed.ToString)</pre>

<p>I called this test “OC” for “One Connection”.</p>

<p>Next, I wanted to test opening and closing the connection with and without connection pooling:</p>

<pre>     Private Sub MultipleConnections(connectionString As String)</pre>

<pre>          Dim sw As Stopwatch = Stopwatch.StartNew</pre>

<pre>          For i = 1 To 1000<br />               Using conn As New SqlConnection(connectionString)<br />                    conn.Open()<br />                    Using cmd As New SqlCommand(&quot;select * from dbo.person&quot;, conn)<br />                         Using rdr As SqlDataReader = cmd.ExecuteReader()<br />                              While rdr.Read<br />                              End While<br />                         End Using<br />                    End Using<br />                    conn.Close()<br /><br />               End Using<br />          Next</pre>

<pre>          sw.Stop()<br />          Dim elapsed As Long = sw.ElapsedMilliseconds</pre>

<pre>          MessageBox.Show(elapsed.ToString)</pre>

<pre>     End Sub</pre>

<p>I called this two ways.&#160; With pooling enabled (the default, called “CP”):</p>

<pre>     MultipleConnections(My.Settings.ConnectionString)</pre>

<p>and with pooling disabled (called “NCP”):</p>

<pre>     MultipleConnections(My.Settings.ConnectionString &amp; &quot;;Pooling='false'&quot;)</pre>

<p>I then ran each test 10 times and placed the results in a table (values indicate milliseconds):</p>

<table border="1" cellspacing="0" cellpadding="2" width="400"><tbody>
    <tr>
      <td valign="top" width="100">
        <p align="right"><strong>Run #</strong></p>
      </td>

      <td valign="top" width="100">
        <p align="right"><strong>NCP</strong></p>
      </td>

      <td valign="top" width="100">
        <p align="right"><strong>CP</strong></p>
      </td>

      <td valign="top" width="100">
        <p align="right"><strong>OC</strong></p>
      </td>
    </tr>

    <tr>
      <td valign="top" width="100">
        <p align="right">1</p>
      </td>

      <td valign="top" width="100">
        <p align="right">4073</p>
      </td>

      <td valign="top" width="100">
        <p align="right">374</p>
      </td>

      <td valign="top" width="100">
        <p align="right">237</p>
      </td>
    </tr>

    <tr>
      <td valign="top" width="100">
        <p align="right">2</p>
      </td>

      <td valign="top" width="100">
        <p align="right">4032</p>
      </td>

      <td valign="top" width="100">
        <p align="right">341</p>
      </td>

      <td valign="top" width="100">
        <p align="right">298</p>
      </td>
    </tr>

    <tr>
      <td valign="top" width="100">
        <p align="right">3</p>
      </td>

      <td valign="top" width="100">
        <p align="right">3985</p>
      </td>

      <td valign="top" width="100">
        <p align="right">353</p>
      </td>

      <td valign="top" width="100">
        <p align="right">242</p>
      </td>
    </tr>

    <tr>
      <td valign="top" width="100">
        <p align="right">4</p>
      </td>

      <td valign="top" width="100">
        <p align="right">4085</p>
      </td>

      <td valign="top" width="100">
        <p align="right">348</p>
      </td>

      <td valign="top" width="100">
        <p align="right">269</p>
      </td>
    </tr>

    <tr>
      <td valign="top" width="100">
        <p align="right">5</p>
      </td>

      <td valign="top" width="100">
        <p align="right">3964</p>
      </td>

      <td valign="top" width="100">
        <p align="right">369</p>
      </td>

      <td valign="top" width="100">
        <p align="right">256</p>
      </td>
    </tr>

    <tr>
      <td valign="top" width="100">
        <p align="right">6</p>
      </td>

      <td valign="top" width="100">
        <p align="right">4203</p>
      </td>

      <td valign="top" width="100">
        <p align="right">330</p>
      </td>

      <td valign="top" width="100">
        <p align="right">207</p>
      </td>
    </tr>

    <tr>
      <td valign="top" width="100">
        <p align="right">7</p>
      </td>

      <td valign="top" width="100">
        <p align="right">4055</p>
      </td>

      <td valign="top" width="100">
        <p align="right">341</p>
      </td>

      <td valign="top" width="100">
        <p align="right">359</p>
      </td>
    </tr>

    <tr>
      <td valign="top" width="100">
        <p align="right">8</p>
      </td>

      <td valign="top" width="100">
        <p align="right">4071</p>
      </td>

      <td valign="top" width="100">
        <p align="right">357</p>
      </td>

      <td valign="top" width="100">
        <p align="right">286</p>
      </td>
    </tr>

    <tr>
      <td valign="top" width="100">
        <p align="right">9</p>
      </td>

      <td valign="top" width="100">
        <p align="right">3968</p>
      </td>

      <td valign="top" width="100">
        <p align="right">363</p>
      </td>

      <td valign="top" width="100">
        <p align="right">356</p>
      </td>
    </tr>

    <tr>
      <td valign="top" width="100">
        <p align="right">10</p>
      </td>

      <td valign="top" width="100">
        <p align="right">4023</p>
      </td>

      <td valign="top" width="100">
        <p align="right">349</p>
      </td>

      <td valign="top" width="100">
        <p align="right">359</p>
      </td>
    </tr>

    <tr>
      <td valign="top" width="100">
        <p align="right"><strong>AVG</strong></p>
      </td>

      <td valign="top" width="100">
        <p align="right"><strong>4046</strong></p>
      </td>

      <td valign="top" width="100">
        <p align="right"><strong>353</strong></p>
      </td>

      <td valign="top" width="100">
        <p align="right"><strong>287</strong></p>
      </td>
    </tr>
  </tbody></table>

<p>&#160;</p>

<p>Now, what does this mean?&#160; Clearly, if you disable connection pooling, then you will likely suffer a significant performance penalty.&#160; I expected this.&#160; I also expected that using one connection (OC) was faster than using connection pooling (CP).&#160; In these tests, OC is roughly 19% faster than CP.&#160; This sounds significant, but remember that the test code looped 1,000 times.&#160; On average, a single OC call was .066 milliseconds faster than a single CP call.&#160; Unless you are hitting the database many times, such as when running a multi-user ASP.NET application, you won’t notice six hundredths of a millisecond.&#160; (The connection pooling system does a pretty good job of managing the connections.)&#160; Still, it is good to see hard numbers back up what I “know”.</p>]]></content:encoded>
    </item>
    <item>
      <title>Additional reasons to migrate off of Visual Basic 6</title>
      <link>https://docs.microsoft.com/archive/blogs/jerrydixon/additional-reasons-to-migrate-off-of-visual-basic-6</link>
      <pubDate>Wed, 30 Jun 2010 06:48:00 GMT</pubDate>
      <dc:creator><![CDATA[Jerry Dixon]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jerrydixon/2010/06/30/additional-reasons-to-migrate-off-of-visual-basic-6/</guid>
      <description><![CDATA[As most people know by now,&nbsp;support for Visual Basic 6 expired in 2008...]]></description>
      <content:encoded><![CDATA[<p>As most people know by now,&nbsp;support for Visual Basic 6 expired in 2008 (<a href="https://support.microsoft.com/lifecycle/search/default.aspx?sort=PN&amp;alpha=visual+basic+6&amp;Filter=FilterNO">https://support.microsoft.com/lifecycle/search/default.aspx?sort=PN&amp;alpha=visual+basic+6&amp;Filter=FilterNO</a>).&nbsp; However, I&nbsp;frequently receive questions about the risks of NOT migrating.&nbsp; I try to respond to each of these requests individually, but I thought that I would post a typical response here.&nbsp; Perhaps some of you will find this useful.</p>
<p>So, for the question:&nbsp; "What are the risks of NOT moving my applications off of VB 6?"</p>
<p>Visual Basic 6 support falls into three categories; the IDE, the source code itself, and the runtime.&nbsp; </p>
<p>Support for the IDE and&nbsp;source code&nbsp;expired a while ago.&nbsp;Support for the runtime, however, will continue for quite&nbsp;some time.&nbsp; The VB 6 runtime files are considered to be a part of the operating system with which they shipped.&nbsp; As you can see from our official support statement (<a href="https://msdn.microsoft.com/en-us/vbrun/ms788708.aspx">https://msdn.microsoft.com/en-us/vbrun/ms788708.aspx</a> ), the VB 6 runtime will be supported for the life of Windows 7 and Windows Server 2008.&nbsp; (This means that VB 6 applications will be supported on Windows Server 2008 until support for that system expires in 2020.)&nbsp; This sounds like a very long time, but there are caveats:</p>
<ol>
<li>Microsoft does not provide support for third-party VB 6 controls.&nbsp; We have no way of knowing whether these controls will function on newer operating systems.</li>
<li>VB 6 applications are 32-bit only.&nbsp; When running on a 64-bit system, VB 6 apps run in the emulated WOW environment.&nbsp; This can cause problems with some applications.</li>
<li>Not all VB 6 controls are supported on Windows Vista and later operating systems.&nbsp; You can see a list of these controls in the official support statement (<a href="https://msdn.microsoft.com/en-us/vbrun/ms788708.aspx">https://msdn.microsoft.com/en-us/vbrun/ms788708.aspx</a> ).</li>
<li><strong>IMPORTANT</strong>:&nbsp; When you apply a new service pack, install a hot fix, or move to a newer operating system,&nbsp;new&nbsp;security requirements may interfere with the expected performance of your VB 6 application.&nbsp;&nbsp; Microsoft may not be able to restore the former functionality of your application without reducing&nbsp;security.&nbsp;&nbsp;In these cases, Microsoft is not required to issue a "fix".&nbsp; In other words, Microsoft does not have to roll back or remove security enhancements so that your application will continue to work.&nbsp; This is important to understand, since VB 6 applications were&nbsp;often written and tested on systems where users had administrative rights.&nbsp; </li>
<li>There are no plans to include VB6 runtime in future versions of Windows beyond Windows 7 and Windows Server 2008.&nbsp; Although these operating systems are supported until 2020 and 2018 respectively, new systems will most likely be available well before then.&nbsp; These new systems may not include VB 6.</li>
</ol>
<p>As always, the views stated here are my opinion and not Microsoft's.&nbsp; You should contact your Microsoft respresentative for an official statement for your specific situation.</p>]]></content:encoded>
    </item>
  </channel>
</rss>