<?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>DavidHardin@microsoft</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/davidhardin/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/davidhardin/feed.xml</link>
    <description>Information to assist other developers learned by David Hardin while working at Microsoft.</description>
    <lastBuildDate>Tue, 16 Apr 2019 05:00:26 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Azure IoT Edge Preview 2 – Installing Prerequisites on Server Core</title>
      <link>https://docs.microsoft.com/archive/blogs/davidhardin/azure-iot-edge-preview-2-installing-prerequisites-on-server-core</link>
      <pubDate>Fri, 08 Jun 2018 22:47:57 GMT</pubDate>
      <dc:creator><![CDATA[david.hardin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davidhardin/?p=505</guid>
      <description><![CDATA[Installing the IoT Edge prerequisites on Server Core 1709 requires using the command line.

If you...]]></description>
      <content:encoded><![CDATA[Installing the IoT Edge prerequisites on Server Core 1709 requires using the command line.

If you are in Azure, start by creating a VM using the "Windows Server, version 1709 with Containers" image.

If you are using Hyper-V, build up a VM using Server Core 1709.  The 1803 and Windows Server 2019 versions fail prerequisite validation.

Core does not have the GUI desktop so follow these steps after creating VM.  First see if Docker needs to be upgraded:
<ol type="1">
 	<li>Run PowerShell</li>
 	<li>Invoke-Expression (Invoke-WebRequest -useb https://aka.ms/iotedgewin)If it reports the wrong version of Docker then upgrade Docker with:</li>
 	<li>Install-Module DockerProvider</li>
 	<li>Install-Package Docker -ProviderName DockerProvider -RequiredVersion preview -VerboseAnswer A when executing both commands</li>
 	<li>Invoke-Expression (Invoke-WebRequest -useb https://aka.ms/iotedgewin)Should now report prerequisites were satisfied except installing Python for pip.</li>
</ol>
Docker preview = 17.10.0-ee-preview-3 when this was written.

Next Install Python:
<ol>
 	<li>Run PowerShell</li>
 	<li>$url = "https://www.python.org/ftp/python/3.6.5/python-3.6.5.exe"</li>
 	<li>$destination=".\python-3.6.5.exe"</li>
 	<li>[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12</li>
 	<li>Invoke-WebRequest -uri $url -OutFile $destination</li>
 	<li>Unblock-File -Path $destination</li>
 	<li>exit</li>
 	<li>python-3.6.5.exeCheck Add Python 3.6 to PATH does not seem to work so:</li>
 	<li>set path=%path%;C:\Python36-32\Scripts;</li>
</ol>
[TODO] see if firewall ports need to be opened.

Install Edge Runtime:
<ol>
 	<li>pip install -U azure-iot-edge-runtime-ctl</li>
</ol>
Now you can issue the "iotedgectl setup", "iotedgectl login", and "iotedgectl start" commands.  If you encountered the "Hostname cannot be empty or greater than 64 characters" issue then follow the <a href="https://docs.microsoft.com/en-us/azure/iot-edge/troubleshoot#iotedgectl-setup-fails-with-an-invalid-hostname">workaround described in IoT Edge's documentation</a>.

Wait a bit and the "docker ps" command should show that your containers are running.

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Azure IoT Edge Preview 2 – Restart Error</title>
      <link>https://docs.microsoft.com/archive/blogs/davidhardin/azure-iot-edge-preview-2-restart-error</link>
      <pubDate>Fri, 08 Jun 2018 22:21:17 GMT</pubDate>
      <dc:creator><![CDATA[david.hardin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davidhardin/?p=495</guid>
      <description><![CDATA[Currently there is a problem starting IoT Edge runtime unless the "iotedgectl setup" and "iotedgectl...]]></description>
      <content:encoded><![CDATA[Currently there is a problem starting IoT Edge runtime unless the "iotedgectl setup" and "iotedgectl login" commands are issued first.  This happens anytime the runtime stops and is started again, such as after a device reboot or the "iotedgectl restart" command is used.

The error is:  <span style="float: none;background-color: transparent;color: #24292e;font-family: 'SFMono-Regular',Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size: 11.93px;font-style: normal;font-variant: normal;font-weight: 400;letter-spacing: normal;line-height: 17.29px;text-align: left;text-decoration: none;text-indent: 0px">404 Client Error: Not Found ("network 9d03b337f52a4878c7a82ddf6a1a62afb01c79d33249f434b3e7052e9bfaf986 not found")
</span>

The <a href="https://github.com/Azure/iot-edge/issues/587">iot-edge GitHub issue</a> has more info.]]></content:encoded>
    </item>
    <item>
      <title>Azure IoT Edge Preview 2 – Module Networking</title>
      <link>https://docs.microsoft.com/archive/blogs/davidhardin/azure-iot-edge-preview-2-module-networking</link>
      <pubDate>Fri, 08 Jun 2018 21:30:02 GMT</pubDate>
      <dc:creator><![CDATA[david.hardin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davidhardin/?p=475</guid>
      <description><![CDATA[By default Docker prevents the outside world from communicating with the module running in the...]]></description>
      <content:encoded><![CDATA[By default Docker prevents the outside world from communicating with the module running in the container unless you configure a host port to container port mapping.

The following container create options, used while setting the module, open a port into the container:
<pre>  {
    "ExposedPorts": {
      "5672/tcp": {}
    },
    "HostConfig": {
      "PortBindings": {
        "5672/tcp": [
          {
            "HostPort": "5672"
          }
        ]
      }
    }
  }
</pre>
The example above maps the host's 5672 port to the container's 5672 port.  The port numbers can be different, for example, two different modules might want to listen to port 80 so the mappings might use host ports 81 and 82.

Each container also gets its own IP address.  The "docker inspect &lt;container id&gt;" command shows that the container is connected to a network called "azure-iot-edge" that has IPAddress property, which is the IP address of the container.  The easiest way to access the container though is to use the container's Hostname in the Uri rather than the IP address.  The Hostname matches the container id.

Within the module's code you can listen to the port on any IP address using code like:
<pre>  IPAddress address;

  if (Socket.OSSupportsIPv4)
    address = IPAddress.Any;

  if (Socket.OSSupportsIPv6)
    address = IPAddress.IPv6Any;</pre>
In my case I use <a href="https://github.com/Azure/amqpnetlite">AMQP.Net Lite</a> for AMQP TCP communication into the module.  The ContainerHost address URI, such as "amqp://guest:guest@localhost:5672", uses localhost which causes that library to listen on any address.  Other processes running on the host call it using "amqp://guest:guest@&lt;container id&gt;:5672".

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Azure IoT Edge Preview 2 – Use Chrome with the Portal</title>
      <link>https://docs.microsoft.com/archive/blogs/davidhardin/azure-iot-edge-preview-2-use-chrome-with-the-portal</link>
      <pubDate>Fri, 08 Jun 2018 02:55:27 GMT</pubDate>
      <dc:creator><![CDATA[david.hardin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davidhardin/?p=485</guid>
      <description><![CDATA[For whatever reason the IoT Edge section of the Azure Portal works better inside Google Chrome than...]]></description>
      <content:encoded><![CDATA[For whatever reason the IoT Edge section of the Azure Portal works better inside Google Chrome than the Edge web browser.  The Edge web browser hangs and gives BadRequest notifications:

BadRequest:{ "Message": "ErrorCode:InvalidProtocolVersion;BadRequest", "ExceptionMessage": "Tracking ID:dd8904d6213046:14-TimeStamp:06/08/2018 02:51:08" }

This can also happen to Chrome.  When it does, I've found that another computer can still access the IoT Edge section successfully.]]></content:encoded>
    </item>
    <item>
      <title>Azure IoT Edge Preview 2 - Debugging Container Exceptions</title>
      <link>https://docs.microsoft.com/archive/blogs/davidhardin/azure-iot-edge-preview-2-debugging-container-exceptions</link>
      <pubDate>Fri, 08 Jun 2018 02:47:29 GMT</pubDate>
      <dc:creator><![CDATA[david.hardin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davidhardin/?p=465</guid>
      <description><![CDATA[The "docker ps" command shows which containers are running.  There should be two containers running...]]></description>
      <content:encoded><![CDATA[The "docker ps" command shows which containers are running.  There should be two containers running from the Azure IoT Edge team plus the containers you configured modules for.  If they are not running troubleshoot by:
<ol>
 	<li>Run the "iotedgectl start" command to ensure the Edge runtime is started.</li>
 	<li>Run "docker ps" to see if the containers are running.</li>
 	<li>Run "docker ps --all" to find all the relevant container id's.</li>
 	<li>View the logs of each container with the "docker logs &lt;container id&gt;" command. I find it helpful to add "--tail 50" to reduce the output to only the last 50 lines in the log.</li>
 	<li>If microsoft/azureiotedge-hub:1.0-preview or microsoft/azureiotedge-agent:1.0-preview containers logged an exception then:
<ol>
 	<li>In PowerShell run "Invoke-Expression (Invoke-WebRequest -useb https://aka.ms/iotedgewin)" to validate your prerequisites.</li>
 	<li>Try setting up the device again:
<ol>
 	<li>Run "iotedgectl uninstall" to uninstall the existing containers.</li>
 	<li>Run "iotedgectl setup..." to install the containers.</li>
 	<li>Run "iotedgectl login..." to provide the container registry credentials.</li>
 	<li><span style="float: none;background-color: transparent;color: #333333;cursor: text;font-family: Georgia,'Times New Roman','Bitstream Charter',Times,serif;font-size: 16px;font-style: normal;font-variant: normal;font-weight: 400;letter-spacing: normal;line-height: 24px;text-align: left;text-decoration: none;text-indent: 0px">Run "iotedgectl start".</span></li>
 	<li>View the logs of the new containers to see what happened.</li>
</ol>
</li>
</ol>
</li>
</ol>
One tip is that the logs show which docker commands were executed but not the raw output.  To see what happened, copy the command out of the log and run it from the command line.]]></content:encoded>
    </item>
    <item>
      <title>Azure IoT Edge Preview 2 - Windows Server 1709 is Core</title>
      <link>https://docs.microsoft.com/archive/blogs/davidhardin/azure-iot-edge-preview-2-windows-server-1709-is-core</link>
      <pubDate>Fri, 08 Jun 2018 02:33:25 GMT</pubDate>
      <dc:creator><![CDATA[david.hardin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davidhardin/?p=455</guid>
      <description><![CDATA[Windows Server version 1709 is only released in the Server Core configuration.  There is no Server...]]></description>
      <content:encoded><![CDATA[Windows Server version 1709 is only released in the Server Core configuration.  There is no Server 1709 version that includes a Desktop UI.  In my case this prevented me from installing a legacy Windows Form application I needed for device polling.

I tried Windows Server 2019 preview but it failed Edge's prerequisites validation.

I will wait to try Windows Server 2019 and Azure IoT Edge together when they exit their respective previews, as suggested by the Edge product team.

For now I'm developing and running on Windows 10 Pro N, Version 1709.]]></content:encoded>
    </item>
    <item>
      <title>Azure IoT Edge Preview 2 - Edge Requires Azure VM's with Nested Virtualization</title>
      <link>https://docs.microsoft.com/archive/blogs/davidhardin/azure-iot-edge-preview-2-edge-requires-azure-vms-with-nested-virtualization</link>
      <pubDate>Fri, 08 Jun 2018 02:32:00 GMT</pubDate>
      <dc:creator><![CDATA[david.hardin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davidhardin/?p=445</guid>
      <description><![CDATA[This applied to running Edge dev or device VM's in Azure.

Azure D and E version 3 VM's support...]]></description>
      <content:encoded><![CDATA[This applied to running Edge dev or device VM's in Azure.

Azure D and E version 3 VM's support the nested virtualization that Azure IoT Edge requires. <a href="https://azure.microsoft.com/en-us/blog/nested-virtualization-in-azure/">Nested virtualization support was announced last year</a> so perhaps other version 3 or newer VM's support it too.

If you pick the wrong VM type, you can pass Edge's prerequisite validation but containers will fail to start with a message that no hypervisor is installed. At first I used a B8ms VM and encountered this problem. Luckily Azure lets you change the VM Size so I switched to the D8s_v3 size and it worked.]]></content:encoded>
    </item>
    <item>
      <title>Azure IoT Edge Preview 2 - Windows OS Version Prerequisites</title>
      <link>https://docs.microsoft.com/archive/blogs/davidhardin/azure-iot-edge-preview-2-windows-os-version-prerequisites</link>
      <pubDate>Fri, 08 Jun 2018 02:27:28 GMT</pubDate>
      <dc:creator><![CDATA[david.hardin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davidhardin/?p=435</guid>
      <description><![CDATA[The Edge documentation's Quick Start has a prerequisites section with a note specifying the OS...]]></description>
      <content:encoded><![CDATA[The Edge documentation's <a href="https://docs.microsoft.com/en-us/azure/iot-edge/quickstart#prerequisites">Quick Start</a> has a prerequisites section with a note specifying the OS version to use. This applies to both your development and edge servers. It specifically says to use the Windows Fall Creator Update / Build 16299 versions. This is also known as version 1709, for being released in September of 2017.

I ran into the issue when my dev box applied a mandatory upgrade from version 1709 to version 1803 which caused one of Edge's Docker containers to throw exceptions. The issue is discussed <a href="https://github.com/Azure/iot-edge/issues/600">here</a>.

Ultimately I settled on using an Azure VM created with the "Windows 10 Pro N, Version 1709" image for both my dev and device. I then disabled the Windows Update service to ensure I didn't get upgraded out of Edge's prerequisites.  I encountered the "<span>Hostname cannot be empty or greater than 64 characters</span>" issue and did the <a href="https://docs.microsoft.com/en-us/azure/iot-edge/troubleshoot#iotedgectl-setup-fails-with-an-invalid-hostname">workaround described in IoT Edge's documentation</a>.]]></content:encoded>
    </item>
    <item>
      <title>Azure IoT Edge Preview 2 - Lessons Learned Series</title>
      <link>https://docs.microsoft.com/archive/blogs/davidhardin/azure-iot-edge-preview-2-lessons-learned-series</link>
      <pubDate>Fri, 08 Jun 2018 02:23:23 GMT</pubDate>
      <dc:creator><![CDATA[david.hardin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davidhardin/?p=425</guid>
      <description><![CDATA[I'm writing a series of posts tagged with IoTEdgePreviewLessonsLearned to share knowledge about...]]></description>
      <content:encoded><![CDATA[I'm writing a series of posts tagged with <a href="https://blogs.msdn.microsoft.com/davidhardin/tag/iotedgepreviewlessonslearned/">IoTEdgePreviewLessonsLearned</a> to share knowledge about Azure IoT Edge Preview 2.

The background is that I'm developing an Azure IoT Edge proof of concept  to replace a custom monitoring pipeline I designed a couple years ago.  The current pipeline collects telemetry into Event Hub and stream processes it with Worker Roles.  The goal is to move the high rate event processing to the source of the events leveraging Azure IoT Edge modules for the real-time monitoring and AI control algorithms.  The modules will then flow aggregate and statistical information to the cloud for machine learning and other analysis.]]></content:encoded>
    </item>
    <item>
      <title>Logging Azure Startup Task to WAD</title>
      <link>https://docs.microsoft.com/archive/blogs/davidhardin/logging-azure-startup-task-to-wad</link>
      <pubDate>Tue, 16 Jun 2015 14:46:00 GMT</pubDate>
      <dc:creator><![CDATA[david.hardin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/davidhardin/2015/06/16/logging-azure-startup-task-to-wad/</guid>
      <description><![CDATA[Debugging startup tasks is very challenging so it is useful to log what they are doing. &nbsp;Say...]]></description>
      <content:encoded><![CDATA[<p>Debugging startup tasks is very challenging so it is useful to log what they are doing. &nbsp;Say that you have a ServiceDefinition.csdef file that looks like this:</p>
<p>&nbsp;</p>
<p style="padding-left: 30px;">&lt;?xml version="1.0" encoding="utf-8"?&gt;</p>
<p style="padding-left: 30px;">&lt;ServiceDefinition name="Foo" xmlns="<a href="https://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">https://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition</a>" schemaVersion="2012-10.1.8"&gt;</p>
<p style="padding-left: 30px;">&nbsp; &lt;WebRole name="Bar" vmsize="Medium" enableNativeCodeExecution="true"&gt;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp; &lt;Startup&gt;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Task commandLine="Startup\ConfigureIIS.cmd" executionContext="elevated" taskType="simple" /&gt;</p>
<p style="padding-left: 30px;">&nbsp; &nbsp; &lt;/Startup&gt;</p>
<p style="padding-left: 30px;">&nbsp; &nbsp; ...</p>
<p style="padding-left: 30px;">&nbsp;</p>
<p>And within your project you created a Startup folder and included your scripts with Build Action None and Copy Always, then within the scripts you can pipe the output into a log directory like this:</p>
<p>&nbsp;</p>
<p style="padding-left: 30px;">SET ConfigureIIS_LogDir=%~dp0Log\</p>
<p style="padding-left: 30px;">MKDIR "%ConfigureIIS_LogDir%"</p>
<p style="padding-left: 30px;">%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00 &gt;&gt; "%ConfigureIIS_LogDir%ConfigureIIS.txt" 2&gt;&amp;1</p>
<p style="padding-left: 30px;">%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.recycling.periodicRestart.time:168:00:00 &gt;&gt; "%ConfigureIIS_LogDir%ConfigureIIS.txt" 2&gt;&amp;1</p>
<p style="padding-left: 30px;">EXIT /b 0</p>
<p style="padding-left: 30px;">&nbsp;</p>
<p>BTW, the %~dp0 is a very special replaceable parameter and as used above means &ldquo;%ROLEROOT%\approot\bin\Startup\&rdquo;. &nbsp;Also notice that using a script to launch exe's is nice because it allows redirecting the output to the log file.</p>
<p>&nbsp;</p>
<p>Then in diagnostics.wad you can transfer the log to Azure Storage for diagnostics:</p>
<p>&nbsp;</p>
<p style="padding-left: 30px;">&nbsp; &lt;Directories bufferQuotaInMB="1024" scheduledTransferPeriod="PT5M"&gt;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp; &lt;CrashDumps container="wad-crash-dumps" directoryQuotaInMB="128" /&gt;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp; &lt;FailedRequestLogs container="wad-frq" directoryQuotaInMB="128"/&gt;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp; &lt;IISLogs container="wad-iis" directoryQuotaInMB="128" /&gt;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp; &lt;DataSources&gt;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;DirectoryConfiguration container="wad-startup" directoryQuotaInMB="10"&gt;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- Absolute specifies an absolute path with optional environment expansion --&gt;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Absolute expandEnvironment="true" path="%ROLEROOT%\approot\bin\Startup\Log" /&gt;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/DirectoryConfiguration&gt;</p>
<p style="padding-left: 30px;">&nbsp;</p>
<p>You can also remote desktop to the instance and view the log too.</p>
<p>&nbsp;</p>
<p>Happy coding...</p>]]></content:encoded>
    </item>
  </channel>
</rss>