<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Code on Ash Tewari</title><link>https://www.tewari.info/category/code/</link><description>Recent content in Code on Ash Tewari</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Mon, 06 Apr 2026 04:48:17 +0000</lastBuildDate><atom:link href="https://www.tewari.info/category/code/feed.xml" rel="self" type="application/rss+xml"/><item><title>Giving OpenClaw Secure Access to Cloud Services Without Sharing Your Password</title><link>https://www.tewari.info/2026/04/06/device-code-auth-flow-with-openclaw/</link><pubDate>Mon, 06 Apr 2026 04:48:17 +0000</pubDate><guid>https://www.tewari.info/2026/04/06/device-code-auth-flow-with-openclaw/</guid><description>&lt;p&gt;Device Code Flow has been built into OAuth2 for years, originally designed for TVs and game consoles. It works just as well for a Docker container. It requires no credentials stored on the agent machine. It gives you narrow, revocable access that the agent cannot exceed.&lt;/p&gt;&#10;&lt;p&gt;I have OpenClaw deployed in a sandboxed docker container on a dedicated host. I communicate with it via a Telegram bot, in a locked-down chat.&lt;/p&gt;&#10;&lt;p&gt;I wired the device-code authentication pattern up with OpenClaw and Microsoft (Personal/Consumer) services, but the authentication approach works with any app and any command-line tool you want to run in a headless environment, including Custom APIs. Device code flow + Entra ID app registrations give you a zero-stored-credentials gateway to any HTTP API you can build, not just Microsoft Graph.&lt;/p&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/openclaw-telegram-integration.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;p&gt;&lt;strong&gt;What Is Device Code Flow?&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;OAuth2 device code flow (RFC 8628) was designed for &amp;ldquo;input-constrained devices&amp;rdquo; — things without a keyboard or a browser. Think of how you sign in to Netflix on a smart TV: a short code appears on screen, you visit a URL on your phone, you type the code in, and the TV logs in. You never type your password on the TV.&lt;/p&gt;&#10;&lt;p&gt;The official name for that pattern is the device authorization grant. A Docker container is, from the protocol&amp;rsquo;s perspective, exactly the same kind of device. It has no browser. It cannot perform an interactive redirect. But it can make HTTP requests, and that is all it needs.&lt;/p&gt;&#10;&lt;p&gt;The flow has three steps:&lt;/p&gt;&#10;&lt;p&gt;1. The app posts to the identity provider&amp;rsquo;s device code endpoint. It gets back a short user code (like &amp;ldquo;WDJB-MJHT&amp;rdquo;), a verification URL, and a polling device code.&lt;/p&gt;&#10;&lt;p&gt;2. The user visits the URL on any browser, on any device — their phone, laptop, anything — and enters the short code. They sign in normally, with their usual credentials and MFA if it is enabled.&lt;/p&gt;&#10;&lt;p&gt;3. The app polls the token endpoint in the background. Once the user finishes signing in, the poll returns a real access token and a refresh token. The app stores these and uses them for API calls going forward.&lt;/p&gt;&#10;&lt;p&gt;The app never sees the password. The password goes directly from the user&amp;rsquo;s browser to the identity provider. The app only ever handles two things: a short temporary code that it sends to the user, and a token that the identity provider gives back once the user has authenticated.&lt;/p&gt;&#10;&lt;p&gt;OpenClaw running in a Docker container fits this model exactly.&lt;/p&gt;&#10;&lt;h2 id="which-services-support-this"&gt;Which Services Support this?&#10;&lt;/h2&gt;&lt;p&gt;Device code flow is not a Microsoft-only feature. It is a standard OAuth2 extension (RFC 8628) and most major identity providers support it — including Microsoft, Google, GitHub, and AWS. If a service uses Okta or Auth0 for identity, those support it too.&lt;/p&gt;&#10;&lt;h2 id="the-security-architecture"&gt;The Security Architecture&#10;&lt;/h2&gt;&lt;p&gt;The agent never sees your credentials. Your password is typed in your browser, on your device, to your identity provider&amp;rsquo;s servers. It never touches the container. The agent only handles a short temporary code to give you, and a token issued by the provider once you have authenticated.&lt;/p&gt;&#10;&lt;p&gt;The device code is one-time and short-lived. After the user authenticates, the code is permanently invalidated. An intercepted code is useless without the user&amp;rsquo;s credentials and MFA.&lt;/p&gt;&#10;&lt;p&gt;Scopes define the ceiling. You configure the OAuth app or app registration to request only specific permissions. The agent cannot exceed those scopes. If you configure read-only access to email, the token cannot be used to send or delete email.&lt;/p&gt;&#10;&lt;p&gt;This is the authentication pattern that many of the consumer devices you already own use to access your accounts on your behalf. Your TV&amp;rsquo;s YouTube app, your smart home hub&amp;rsquo;s Google integration, the GitHub CLI you use on your workstation — these all use device flow. You have been trusting it for years without knowing what it was called.&lt;/p&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/device-code-flow-workflow.drawio.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;h2 id="how-the-implementation-works"&gt;How the implementation works&#10;&lt;/h2&gt;&lt;p&gt;There are three components, and they run as separate Docker services that talk to each other through the Docker socket.&lt;/p&gt;&#10;&lt;p&gt;The app sidecar is your application container. It runs your CLI tool and your auth logic. It does nothing on its own. Its only job is to hold the authenticated token cache and execute commands on demand when OpenClaw calls into it.&lt;/p&gt;&#10;&lt;p&gt;OpenClaw is the AI agent container. It connects to Telegram, understands natural language, and knows which skills to run for which requests. It does not know anything about OAuth or your specific app. It just runs shell commands you specified and reports results back to you.&lt;/p&gt;&#10;&lt;p&gt;The Telegram auth bridge is a small script that lives inside the sidecar. It registers a device code callback, requests an auth flow, and uses the Telegram Bot API to forward the code to you — then confirms when authentication completes.&lt;/p&gt;&#10;&lt;p&gt;The compose file looks roughly like this:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;services&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;myapp-sidecar&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ghcr.io/youruser/myapp:latest&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;command&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;sleep&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;infinity&amp;#34;&lt;/span&gt;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;environment&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;XDG_DATA_HOME=/data&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;${APP_DATA_DIR:-./app-data}:/data&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;unless-stopped&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;openclaw-gateway&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;build&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;context&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;dockerfile&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Dockerfile.openclaw&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;./skills:/app/skills&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;group_add&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;${DOCKER_GID:-999}&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;environment&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;18789:18789&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;unless-stopped&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="the-callback-pattern"&gt;The Callback Pattern&#10;&lt;/h2&gt;&lt;p&gt;The auth manager has a method called set_device_code_callback. You pass it a function, and when the device code is ready, the auth manager calls your function with the code and the verification URL rather than trying to open a browser.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AuthManager&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__init__&lt;/span&gt;(self, client_id: str, authority: str) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_client_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; client_id&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_authority &lt;span style="color:#f92672"&gt;=&lt;/span&gt; authority&lt;span style="color:#f92672"&gt;.&lt;/span&gt;rstrip(&lt;span style="color:#e6db74"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_on_device_code &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_tokens &lt;span style="color:#f92672"&gt;=&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_load_cache()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;set_device_code_callback&lt;/span&gt;(self, fn) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_on_device_code &lt;span style="color:#f92672"&gt;=&lt;/span&gt; fn&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_device_code_auth&lt;/span&gt;(self) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; httpx&lt;span style="color:#f92672"&gt;.&lt;/span&gt;AsyncClient() &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; client:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resp &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;post(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_authority&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/oauth2/v2.0/devicecode&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; data&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;client_id&amp;#34;&lt;/span&gt;: self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_client_id, &lt;span style="color:#e6db74"&gt;&amp;#34;scope&amp;#34;&lt;/span&gt;: OAUTH_SCOPES},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; timeout&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; flow &lt;span style="color:#f92672"&gt;=&lt;/span&gt; resp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;json()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; user_code &lt;span style="color:#f92672"&gt;=&lt;/span&gt; flow[&lt;span style="color:#e6db74"&gt;&amp;#34;user_code&amp;#34;&lt;/span&gt;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; verification_uri &lt;span style="color:#f92672"&gt;=&lt;/span&gt; flow[&lt;span style="color:#e6db74"&gt;&amp;#34;verification_uri&amp;#34;&lt;/span&gt;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; device_code &lt;span style="color:#f92672"&gt;=&lt;/span&gt; flow[&lt;span style="color:#e6db74"&gt;&amp;#34;device_code&amp;#34;&lt;/span&gt;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; interval &lt;span style="color:#f92672"&gt;=&lt;/span&gt; flow&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;interval&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; expires_in &lt;span style="color:#f92672"&gt;=&lt;/span&gt; flow&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;expires_in&amp;#34;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;300&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_on_device_code:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_on_device_code({&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;user_code&amp;#34;&lt;/span&gt;: user_code,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;verification_uri&amp;#34;&lt;/span&gt;: verification_uri,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: flow&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;),&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; webbrowser&lt;span style="color:#f92672"&gt;.&lt;/span&gt;open(verification_uri)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;except&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Exception&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;pass&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; deadline &lt;span style="color:#f92672"&gt;=&lt;/span&gt; time&lt;span style="color:#f92672"&gt;.&lt;/span&gt;time() &lt;span style="color:#f92672"&gt;+&lt;/span&gt; expires_in&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; time&lt;span style="color:#f92672"&gt;.&lt;/span&gt;time() &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; deadline:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; asyncio&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sleep(interval)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; httpx&lt;span style="color:#f92672"&gt;.&lt;/span&gt;AsyncClient() &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; client:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; resp &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;post(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_authority&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/oauth2/v2.0/token&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; data&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;client_id&amp;#34;&lt;/span&gt;: self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_client_id,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;grant_type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;urn:ietf:params:oauth:grant-type:device_code&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;device_code&amp;#34;&lt;/span&gt;: device_code,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; timeout&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; body &lt;span style="color:#f92672"&gt;=&lt;/span&gt; resp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;json()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; resp&lt;span style="color:#f92672"&gt;.&lt;/span&gt;status_code &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt; &lt;span style="color:#f92672"&gt;and&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;access_token&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;in&lt;/span&gt; body:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;_store_tokens(body)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; error &lt;span style="color:#f92672"&gt;=&lt;/span&gt; body&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; error &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;authorization_pending&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; error &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;slow_down&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; interval &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;elif&lt;/span&gt; error &lt;span style="color:#f92672"&gt;in&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#34;authorization_declined&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;expired_token&amp;#34;&lt;/span&gt;):&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;raise&lt;/span&gt; AuthError(error)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;raise&lt;/span&gt; AuthError(body&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;error_description&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Auth failed&amp;#34;&lt;/span&gt;))&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The polling loop handles the three error codes the spec defines: authorization_pending (keep waiting), slow_down (back off and increase the interval by 5 seconds), and the terminal errors that stop polling.&lt;/p&gt;&#10;&lt;h2 id="the-telegram-bridge"&gt;The Telegram Bridge&#10;&lt;/h2&gt;&lt;p&gt;With the callback mechanism in place, the Telegram bridge is just a script that registers a callback and uses the Telegram Bot API to deliver the code to you:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; asyncio&lt;span style="color:#f92672"&gt;,&lt;/span&gt; os&lt;span style="color:#f92672"&gt;,&lt;/span&gt; sys&lt;span style="color:#f92672"&gt;,&lt;/span&gt; traceback&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; httpx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; your_app.auth &lt;span style="color:#f92672"&gt;import&lt;/span&gt; AuthManager&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; your_app.config &lt;span style="color:#f92672"&gt;import&lt;/span&gt; Settings&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TELEGRAM_BOT_TOKEN &lt;span style="color:#f92672"&gt;=&lt;/span&gt; os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;environ[&lt;span style="color:#e6db74"&gt;&amp;#34;TELEGRAM_BOT_TOKEN&amp;#34;&lt;/span&gt;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TELEGRAM_CHAT_ID &lt;span style="color:#f92672"&gt;=&lt;/span&gt; os&lt;span style="color:#f92672"&gt;.&lt;/span&gt;environ[&lt;span style="color:#e6db74"&gt;&amp;#34;TELEGRAM_CHAT_ID&amp;#34;&lt;/span&gt;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;send_telegram&lt;/span&gt;(text: str) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; url &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://api.telegram.org/bot&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;TELEGRAM_BOT_TOKEN&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/sendMessage&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; httpx&lt;span style="color:#f92672"&gt;.&lt;/span&gt;AsyncClient() &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; client:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; client&lt;span style="color:#f92672"&gt;.&lt;/span&gt;post(url, json&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;chat_id&amp;#34;&lt;/span&gt;: TELEGRAM_CHAT_ID,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;: text,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;parse_mode&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Markdown&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }, timeout&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;async&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; int:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; settings &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Settings()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; auth &lt;span style="color:#f92672"&gt;=&lt;/span&gt; AuthManager(settings&lt;span style="color:#f92672"&gt;.&lt;/span&gt;client_id, settings&lt;span style="color:#f92672"&gt;.&lt;/span&gt;authority)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; auth&lt;span style="color:#f92672"&gt;.&lt;/span&gt;is_signed_in():&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; send_telegram(&lt;span style="color:#e6db74"&gt;&amp;#34;Already authenticated.&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;on_device_code&lt;/span&gt;(info: dict) &lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; msg &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;*Auth Required*&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Go to: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;info[&lt;span style="color:#e6db74"&gt;&amp;#39;verification_uri&amp;#39;&lt;/span&gt;]&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Enter code: `&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;info[&lt;span style="color:#e6db74"&gt;&amp;#39;user_code&amp;#39;&lt;/span&gt;]&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Complete sign-in in your browser and I&amp;#39;ll confirm when done.&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; asyncio&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get_event_loop()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;create_task(send_telegram(msg))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;except&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RuntimeError&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;import&lt;/span&gt; requests&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; requests&lt;span style="color:#f92672"&gt;.&lt;/span&gt;post(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://api.telegram.org/bot&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;TELEGRAM_BOT_TOKEN&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/sendMessage&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; json&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;chat_id&amp;#34;&lt;/span&gt;: TELEGRAM_CHAT_ID, &lt;span style="color:#e6db74"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;: msg, &lt;span style="color:#e6db74"&gt;&amp;#34;parse_mode&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Markdown&amp;#34;&lt;/span&gt;},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; timeout&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; auth&lt;span style="color:#f92672"&gt;.&lt;/span&gt;set_device_code_callback(on_device_code)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;try&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; user_info &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; auth&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sign_in()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; send_telegram(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;*Signed in* as &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;user_info[&lt;span style="color:#e6db74"&gt;&amp;#39;name&amp;#39;&lt;/span&gt;]&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt; (&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;user_info[&lt;span style="color:#e6db74"&gt;&amp;#39;email&amp;#39;&lt;/span&gt;]&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;)&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;except&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Exception&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; exc:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; send_telegram(&lt;span style="color:#e6db74"&gt;f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;*Auth failed:* &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;exc&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;```&lt;/span&gt;&lt;span style="color:#e6db74"&gt;{&lt;/span&gt;traceback&lt;span style="color:#f92672"&gt;.&lt;/span&gt;format_exc()[:&lt;span style="color:#ae81ff"&gt;800&lt;/span&gt;]&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;```&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; __name__ &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sys&lt;span style="color:#f92672"&gt;.&lt;/span&gt;exit(asyncio&lt;span style="color:#f92672"&gt;.&lt;/span&gt;run(main()))&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="the-openclaw-skill"&gt;The OpenClaw Skill&#10;&lt;/h2&gt;&lt;p&gt;On the OpenClaw side, a &amp;ldquo;skill&amp;rdquo; is a markdown file. When OpenClaw sees a trigger phrase in Telegram, it runs the associated shell command. The markdown file looks like this:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;myapp-auth&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;description&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Authenticate with the cloud service via device code flow, coordinated through Telegram.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;---&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;## myapp-auth&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Use this skill when the user sends &amp;#34;/auth&amp;#34;, &amp;#34;authenticate&amp;#34;, or &amp;#34;sign in&amp;#34;.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Run the following command and wait up to 360 seconds for it to complete.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;The script sends the device code to the user via Telegram and confirms when done.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; docker exec myapp-sidecar-1 python /app/scripts/telegram_auth.py&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="summary"&gt;Summary&#10;&lt;/h2&gt;&lt;p&gt;Device code flow is a mature, widely-supported OAuth2 pattern that maps naturally onto OpenClaw running in Docker container. With this pattern OpenClaw never handles your credentials. It gets scoped, revocable tokens from the identity provider, after you have authenticated in your own browser. A Telegram bot is all you need to coordinate the handoff of the temporary code.&lt;/p&gt;&#10;&lt;p&gt;The approach works for many use-cases across Microsoft accounts, Google, GitHub, AWS, Auth0, Okta and others. It supports exactly the kinds of personal automations that make an OpenClaw genuinely useful in daily life.&lt;/p&gt;&#10;&lt;h2 id="references"&gt;References&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://docs.openclaw.ai/" target="_blank" rel="noopener"&#10; &gt;OpenClaw Documentation&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://docs.openclaw.ai/tools/creating-skills" target="_blank" rel="noopener"&#10; &gt;OpenClaw: Creating Skills&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://datatracker.ietf.org/doc/html/rfc8628" target="_blank" rel="noopener"&#10; &gt;RFC 8628: OAuth 2.0 Device Authorization Grant&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/en-us/entra/identity-platform/scenario-desktop-acquire-token-device-code-flow" target="_blank" rel="noopener"&#10; &gt;Microsoft Identity Platform: Acquire a Token Using Device Code Flow&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/en-us/graph/permissions-reference" target="_blank" rel="noopener"&#10; &gt;Microsoft Graph Permissions Reference&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://auth0.com/docs/get-started/authentication-and-authorization-flow/device-authorization-flow" target="_blank" rel="noopener"&#10; &gt;Auth0: Device Authorization Flow&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://developer.okta.com/docs/guides/device-authorization-grant/main/" target="_blank" rel="noopener"&#10; &gt;Okta: Configure Device Authorization Grant Flow&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://core.telegram.org/bots/api" target="_blank" rel="noopener"&#10; &gt;Telegram Bot API&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/reference/compose-file/" target="_blank" rel="noopener"&#10; &gt;Docker Compose File Reference&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>Security Analysis of Etheruem Smart Contracts with Mythril</title><link>https://www.tewari.info/2022/05/22/security-analysis-of-etheruem-smart-contracts-with-mythril/</link><pubDate>Sun, 22 May 2022 23:32:20 +0000</pubDate><guid>https://www.tewari.info/2022/05/22/security-analysis-of-etheruem-smart-contracts-with-mythril/</guid><description>&lt;p&gt;&lt;a class="link" href="https://github.com/ConsenSys/mythril" target="_blank" rel="noopener"&#10; &gt;Mythril&lt;/a&gt; is an open-source security analysis tool for EVM bytecode, courtesy of &lt;a class="link" href="https://consensys.net/diligence/tools/" target="_blank" rel="noopener"&#10; &gt;ConsenSys&lt;/a&gt;. It is also a component of their Security Analysis Service - &lt;a class="link" href="https://mythx.io/" target="_blank" rel="noopener"&#10; &gt;Mythx&lt;/a&gt;. Mythril detects security vulnerabilities in smart contracts built for Ethereum and other EVM-compatible blockchains.&lt;/p&gt;&#10;&lt;p&gt;Vulnerabilities found by Mythril are reported with reference to the weaknesses listed on the Smart Contract Weakness Classification Registry (&lt;a class="link" href="https://swcregistry.io/" target="_blank" rel="noopener"&#10; &gt;SWC Registry&lt;/a&gt;). I will use two entries from SWC Registry for the examples in this article:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://swcregistry.io/docs/SWC-106#simple_suicidesol" target="_blank" rel="noopener"&#10; &gt;SWC-106&lt;/a&gt; - Due to missing or insufficient access controls, malicious parties can self-destruct the contract.&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://swcregistry.io/docs/SWC-107#simple_daosol" target="_blank" rel="noopener"&#10; &gt;SWC-107&lt;/a&gt; - One of the major dangers of calling external contracts is that they can take over the control flow. In the reentrancy attack (a.k.a. recursive call attack), a malicious contract calls back into the calling contract before the first invocation of the function is finished.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="install-mythril-on-windows"&gt;Install Mythril on Windows&#10;&lt;/h3&gt;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;gt; docker import mythril/myth&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://mythril-classic.readthedocs.io/en/master/installation.html" target="_blank" rel="noopener"&#10; &gt;https://mythril-classic.readthedocs.io/en/master/installation.html&lt;/a&gt;&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-16.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;h3 id="get-test-files-from-github"&gt;Get test files from github&#10;&lt;/h3&gt;&lt;p&gt;Source code for these tests is on github : &lt;a class="link" href="https://github.com/ashtewari/mythril-tests" target="_blank" rel="noopener"&#10; &gt;mythril-tests&lt;/a&gt;. Clone the repo locally and adjust the paths in the commands below to match your local environment.&lt;/p&gt;&#10;&lt;h3 id="analyze-a-local-smart-contract"&gt;Analyze a local smart contract&#10;&lt;/h3&gt;&lt;h5 id="analysis-of"&gt;&lt;strong&gt;Analysis of &lt;a class="link" href="https://github.com/ashtewari/mythril-tests/blob/master/mythx-tests/05222022-25/SelfDestructMultiTxFeasible.sol" target="_blank" rel="noopener"&#10; &gt;SelfDestructMultiTxFeasible.sol&lt;/a&gt;&lt;/strong&gt;&#10;&lt;/h5&gt;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;gt; docker run -v E:\share\:/data mythril/myth -v4 analyze /data/mythx-tests\05222022-25/SelfDestructMultiTxFeasible.sol&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;Mythril reports an instance of SWC-106 vulnerability:&lt;/p&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-17.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;h5 id=""&gt;&#10;&lt;/h5&gt;&lt;p&gt;&lt;strong&gt;Analysis of &lt;a class="link" href="https://github.com/ashtewari/mythril-tests/blob/master/mythx-tests/05222022-25/SimpleDAO.sol" target="_blank" rel="noopener"&#10; &gt;SimpleDAO.sol&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;gt; docker run -v E:\share\:/data mythril/myth -v4 analyze /data/mythx-tests\05222022-25/SimpleDAO.sol&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;Mythril reports three instances of SWC-107 and one instance of SWC-105:&lt;/p&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-18.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;h5 id="analysis-of-a"&gt;&lt;strong&gt;Analysis of a &lt;a class="link" href="https://github.com/ashtewari/mythril-tests/blob/master/mythx-tests/05222022-25/flatenned-01.sol" target="_blank" rel="noopener"&#10; &gt;flatenned contract file&lt;/a&gt;&lt;/strong&gt;&#10;&lt;/h5&gt;&lt;p&gt;File containing the two test contracts returns five instances of vulnerabilities of both contracts:&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;gt; docker run -v E:\share\:/data mythril/myth -v4 analyze /data/mythx-tests\05222022-25/flatenned-01.sol&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-19.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;h5 id="analyze-a-contract-with-imported-contract"&gt;&lt;strong&gt;Analyze a contract with imported contract&lt;/strong&gt;&#10;&lt;/h5&gt;&lt;p&gt;Most smart contracts import other contracts to reuse functionality. You do not have to flatten the contracts into one file. Mythril can work with contracts with imports specified in them : &lt;a class="link" href="https://github.com/ashtewari/mythril-tests/blob/master/mythx-tests/05222022-26/SimpleDAOWithImport.sol" target="_blank" rel="noopener"&#10; &gt;SimpleDAOWithImport.sol&lt;/a&gt;&lt;/p&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-20.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;gt; docker run -v E:\share\:/data mythril/myth -v4 analyze /data/mythx-tests\05222022-26/SimpleDAOWithImport.sol&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;h5 id="analyze-a-contract-with-openzeppelin-style-import"&gt;&lt;strong&gt;Analyze a contract with @OpenZeppelin style import&lt;/strong&gt;&#10;&lt;/h5&gt;&lt;p&gt;Mythril relies on &lt;a class="link" href="https://github.com/ethereum/solc-js" target="_blank" rel="noopener"&#10; &gt;solc&lt;/a&gt; for compiling contract source code. For @OpenZeppelin style imports, you have to specify &amp;ndash;solc-json file containing remapping for solc to locate the referenced files : &lt;a class="link" href="https://github.com/ashtewari/mythril-tests/blob/master/mythx-tests/05222022-26/SimpleDAOWith-OzImport.sol" target="_blank" rel="noopener"&#10; &gt;SimpleDAOWith-OzImport.sol&lt;/a&gt;&lt;/p&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-22.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;gt; docker run -v E:\share\:/data mythril/myth -v4 analyze /data/mythx-tests\05222022-26/SimpleDAOWith-OzImport.sol &amp;ndash;solc-json=/data/solc-args.json&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-21.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;h3 id="analyzing-on-chain-contracts"&gt;Analyzing On-Chain Contracts&#10;&lt;/h3&gt;&lt;p&gt;Mythril can &lt;a class="link" href="https://mythril-classic.readthedocs.io/en/master/security-analysis.html#analyzing-on-chain-contracts" target="_blank" rel="noopener"&#10; &gt;analyze contracts deployed on the blockchain&lt;/a&gt; directly. You do not need source code of the contract. Support for &lt;a class="link" href="https://infura.io/" target="_blank" rel="noopener"&#10; &gt;infura&lt;/a&gt; is built-in, you can also use custom RPC endpoint. Replace INFURA_ID with your Infura project id and CONTACT_ADDRESS with the address of your contract on the blockchain :&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&amp;gt; docker run mythril/myth -v4 analyze &amp;ndash;rpc infura-rinkeby &amp;ndash;infura-id INFURA_ID -a CONTACT_ADDRESS&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/image-23.png"&gt;&#10;&lt;/figure&gt;&#10;&#10;</description></item><item><title>KeyNode with Node.js and Microsoft Azure</title><link>https://www.tewari.info/2016/03/10/keynode-with-node-js-and-microsoft-azure/</link><pubDate>Fri, 11 Mar 2016 00:23:06 +0000</pubDate><guid>https://www.tewari.info/2016/03/10/keynode-with-node-js-and-microsoft-azure/</guid><description>&lt;p&gt;&lt;a class="link" href="https://github.com/ashtewari/keynode" title="KeyNode"&#10; target="_blank" rel="noopener"&#10; &gt;KeyNode&lt;/a&gt; is a application to issue and verify software license keys. Technology stack for KeyNode is &lt;a class="link" href="https://nodejs.org/" title="Node.js"&#10; target="_blank" rel="noopener"&#10; &gt;Node.j&lt;/a&gt; s, &lt;a class="link" href="https://www.mongodb.org/" title="MongoDB"&#10; target="_blank" rel="noopener"&#10; &gt;MongoDB&lt;/a&gt; and &lt;a class="link" href="https://azure.microsoft.com/" title="Microsoft Azure"&#10; target="_blank" rel="noopener"&#10; &gt;Microsoft Azure&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;I had built this functionality with &lt;a class="link" href="https://c9.io" title="C9.io"&#10; target="_blank" rel="noopener"&#10; &gt;C9.io&lt;/a&gt; (a cloud-based IDE with a built-in source code repository and debugger), &lt;a class="link" href="http://www.prnewswire.com/news-releases/mongohq-becomes-compose-270174611.html" target="_blank" rel="noopener"&#10; &gt;mongohq&lt;/a&gt; (MongoDB as a service - now part of &lt;a class="link" href="https://www.compose.io/" title="compose.io"&#10; target="_blank" rel="noopener"&#10; &gt;compose.io&lt;/a&gt;) and &lt;a class="link" href="https://www.ctl.io/appfog/" title="AppFog"&#10; target="_blank" rel="noopener"&#10; &gt;appfog&lt;/a&gt; (Cloud PAAS built on top of &lt;a class="link" href="https://www.cloudfoundry.org/" title="CloudFoundry"&#10; target="_blank" rel="noopener"&#10; &gt;CloudFoundry&lt;/a&gt;). It used SMTP/gmail to email license files. That was the version I created a couple of years ago to issue tamper-proof signed xml license files for &lt;a class="link" href="http://codedemo.net/" target="_blank" rel="noopener"&#10; &gt;CodeDemo&lt;/a&gt; (a code snippet tool for developers, presenters and instructors).&lt;/p&gt;&#10;&lt;p&gt;For KeyNode (open source) I switched to a different toolset : &lt;a class="link" href="https://code.visualstudio.com/" title="Visual Studio Code"&#10; target="_blank" rel="noopener"&#10; &gt;Visual Studio Code&lt;/a&gt; and &lt;a class="link" href="https://azure.microsoft.com/" target="_blank" rel="noopener"&#10; &gt;Windows Azure&lt;/a&gt;, simplified the code to remove signed xml file and open-sourced it on &lt;a class="link" href="https://github.com/ashtewari/keynode" target="_blank" rel="noopener"&#10; &gt;GitHub&lt;/a&gt;. Signed xml allowed offline verification in CodeDemo (a Wpf/Desktop app). Removing signed xml requires verification to happen online. I am working on adding the web endpoint for verification of license keys. This version uses &lt;a class="link" href="https://sendgrid.com/" title="SendGrid"&#10; target="_blank" rel="noopener"&#10; &gt;SendGrid&lt;/a&gt; to email license keys. KeyNode is deployed as a &lt;a class="link" href="https://azure.microsoft.com/en-us/services/app-service/web/" target="_blank" rel="noopener"&#10; &gt;Windows Azure Web App&lt;/a&gt;. The Azure Web App is on Continuous Deployment feed from the source code repository on GitHub.&lt;/p&gt;&#10;&lt;p&gt;I created and tested this Node.js application locally without IIS and deployed it as an Azure Web App without making any changes to the code at all. Node.js applications are hosted in Azure under IIS with &lt;a class="link" href="https://github.com/tjanczuk/iisnode" title="iisnode"&#10; target="_blank" rel="noopener"&#10; &gt;iisnode&lt;/a&gt;. &lt;a class="link" href="https://github.com/tjanczuk/iisnode" target="_blank" rel="noopener"&#10; &gt;Iisnode&lt;/a&gt; is a native IIS module that allows hosting of node.js applications in IIS on Windows. Read more about iisnode &lt;a class="link" href="https://tomasz.janczuk.org/2011/08/hosting-nodejs-applications-in-iis-on.html" target="_blank" rel="noopener"&#10; &gt;here&lt;/a&gt;. Iisnode architecture also makes it significantly &lt;a class="link" href="https://blogs.msdn.microsoft.com/hanuk/2012/05/04/top-benefits-of-running-node-js-on-windows-azure/" target="_blank" rel="noopener"&#10; &gt;easier&lt;/a&gt; to take advantages of scalability afforded by Azure.&lt;/p&gt;&#10;&lt;p&gt;KeyNode is a work in progress. My plan is to use this as the basis for further explorations in the following areas :&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;DevOps, Docker and Microservices (at miniature scale of course!)&lt;/li&gt;&#10;&lt;li&gt;Create a Web UI with &lt;a class="link" href="http://expressjs.com/" target="_blank" rel="noopener"&#10; &gt;Express&lt;/a&gt;(a Node.js web application framework)&lt;/li&gt;&#10;&lt;li&gt;Integrate with &lt;a class="link" href="https://azure.microsoft.com/en-us/services/storage/" target="_blank" rel="noopener"&#10; &gt;Azure Storage/Queues&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;and more&amp;hellip;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;I invite you to check out the &lt;a class="link" href="http://keynode.azurewebsites.net/" target="_blank" rel="noopener"&#10; &gt;live site on Azure&lt;/a&gt; and fork it for your own experiments : &lt;a class="link" href="https://github.com/ashtewari/keynode" target="_blank" rel="noopener"&#10; &gt;KeyNode on GitHub&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Resources :&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://azure.microsoft.com/en-us/develop/nodejs/" target="_blank" rel="noopener"&#10; &gt;Node.js Developer Center&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://tomasz.janczuk.org/2011/08/hosting-nodejs-applications-in-iis-on.html" target="_blank" rel="noopener"&#10; &gt;Hosting Node.js Applications in IIS on Windows&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://blogs.msdn.microsoft.com/hanuk/2012/05/04/top-benefits-of-running-node-js-on-windows-azure/" target="_blank" rel="noopener"&#10; &gt;Top Benefits of Running Node.js on Windows Azure&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Photo Credit : Piano Keyboard (&lt;a class="link" href="https://www.kpmalinowski.pl/" target="_blank" rel="noopener"&#10; &gt;www.kpmalinowski.pl&lt;/a&gt;)&lt;/p&gt;&#10;</description></item><item><title>Using Powershell with Splunk</title><link>https://www.tewari.info/2016/02/22/using-powershell-with-splunk/</link><pubDate>Tue, 23 Feb 2016 03:20:14 +0000</pubDate><guid>https://www.tewari.info/2016/02/22/using-powershell-with-splunk/</guid><description>&lt;p&gt;&lt;a class="link" href="http://dev.splunk.com/view/splunk-powershell-resource-kit/SP-CAAADRU" title="Splunk Powershell Resource Kit"&#10; target="_blank" rel="noopener"&#10; &gt;Splunk Powershell Resource Kit&lt;/a&gt; is a convenient and very capable wrapper over &lt;a class="link" href="http://www.splunk.com/" target="_blank" rel="noopener"&#10; &gt;Splunk&lt;/a&gt; &lt;a class="link" href="http://dev.splunk.com/restapi" target="_blank" rel="noopener"&#10; &gt;REST API&lt;/a&gt;. You can use the &lt;a class="link" href="https://msdn.microsoft.com/en-us/powershell" target="_blank" rel="noopener"&#10; &gt;Powershell&lt;/a&gt; commandlets exposed by this resource kit to deploy, check and manage splunk services as well as execute splunk searches. In this post, you will be introduced to the Splunk Powershell Resource Kit, you will learn how to use powershell commandlets to connect to a splunk instance and execute searches.&lt;/p&gt;&#10;&lt;p&gt;1. First, you will need to download the resource kit from &lt;a class="link" href="https://github.com/splunk/splunk-reskit-powershell" target="_blank" rel="noopener"&#10; &gt;github&lt;/a&gt;.&#10;2. Installation is very simple. All you have to do is download and extract the files from the zip archive and double click on install.bat to install the splunk powershell module.&#10;3. Open Windows Powershell console from Windows Start menu.&#10;4. Verify that the Splunk module is installed by executing Get-Module commandlet.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Get-Module SplunkSearch&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;5. Import splunk resource kit commandlets using Import-Module command.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Import-Module -Name Splunk&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;6. Next, you need to use Get-Credentials and then Connect-Splunk commandlets to connect to splunk. You need to do this once per session or if you need to switch to a different splunk instance.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$credential = Get-Credential&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connect-Splunk -Credential $credential -ComputerName localhost&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I have a local Splunk Enterprise instance running on my machine, so I am using localhost as the ComputerName to connect to it. If you have a SplunkCloud subscription you can use YourSubscriptionId.splunkcloud.com as the ComputerName to connect to your subscription. Like so -&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connect-Splunk -Credential $credential -ComputerName MySubscription.splunkcloud.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;7. Next, use Search-Splunk commandlet to execute searches -&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Search-Splunk -Search &amp;#34;Error&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here is a sample script:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$lastDay = ( get-date ).addDays( -1 ).toString( ‘s’ )&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$searches = @(&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;ERROR&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , &amp;#34;source=&amp;#34;&amp;#34;tutorialdata.zip:*&amp;#34;&amp;#34; ERROR&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; , &amp;#34;CreditDoesNotMatch&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ,&amp;#34;source=&amp;#34;&amp;#34;tutorialdata.zip:.\\www3/access.log&amp;#34;&amp;#34; productId=WC-SH-G04&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Write-Output $lastDay&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;foreach($search in $searches)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $qry = $search + &amp;#34; | stats count&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Write-Output $qry&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Search-Splunk -Search $qry -StartTime $lastDay | Select-Object -ExpandProperty Count&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The sample script executes multiple Splunk searches and outputs the count of results matching these search queries. Note that I am &amp;ldquo;-StartTime&amp;rdquo; parameter to scope the search to a narrower time window and &amp;ldquo;stats count&amp;rdquo; command to get the count of results. You can get this sample script as a &lt;a class="link" href="https://gist.github.com/ashtewari/c29a8ac98587d42c91bd" target="_blank" rel="noopener"&#10; &gt;github gist&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;You can also use -EndTime and –MaxReturnCount to further constrain the query results and Format-List, Format-Table, Format-Wide commands to format the results. You can learn more about other Search parameters as well as other capabilities exposed in the resource kit &lt;a class="link" href="https://github.com/splunk/splunk-reskit-powershell/raw/master/Docs/Splunk%20PowerShell%20Resource%20Kit.docx" target="_blank" rel="noopener"&#10; &gt;documentation&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Resources :&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;a class="link" href="http://dev.splunk.com/view/splunk-powershell-resource-kit/SP-CAAADRU" target="_blank" rel="noopener"&#10; &gt;Splunk Powershell ResourceKit&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://github.com/splunk/splunk-reskit-powershell" target="_blank" rel="noopener"&#10; &gt;Splunk Powershell ResourceKit on github&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://github.com/splunk/splunk-reskit-powershell/raw/master/Docs/Splunk%20PowerShell%20Resource%20Kit.docx" target="_blank" rel="noopener"&#10; &gt;Splunk Powershell ResourceKit Documentation&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;Image credit : &lt;a class="link" href="https://thenounproject.com/search/?q=shell&amp;amp;i=209178" target="_blank" rel="noopener"&#10; &gt;terminal by Andrea Mazzini&lt;/a&gt; from the Noun Project&lt;/p&gt;&#10;</description></item><item><title>The Site44 Workflow</title><link>https://www.tewari.info/2013/02/06/the-site44-workflow/</link><pubDate>Wed, 06 Feb 2013 17:32:50 +0000</pubDate><guid>https://www.tewari.info/2013/02/06/the-site44-workflow/</guid><description>&lt;p&gt;A light weight development workflow with real-time website deployment.&lt;/p&gt;&#10;&lt;p&gt;I recently built &lt;a class="link" href="http://ash.site44.com/hero.html" target="_blank" rel="noopener"&#10; &gt;a sample website&lt;/a&gt; to illustrate &lt;a class="link" href="http://blog.appliedis.com/2013/02/04/bootstrap-with-less/" target="_blank" rel="noopener"&#10; &gt;how clean, semantic html&lt;/a&gt; markup can be maintained when using &lt;a class="link" href="http://twitter.github.com/bootstrap/index.html" target="_blank" rel="noopener"&#10; &gt;Bootstrap&amp;rsquo;s&lt;/a&gt; &lt;a class="link" href="http://twitter.github.com/bootstrap/scaffolding.html#gridSystem" target="_blank" rel="noopener"&#10; &gt;grid system&lt;/a&gt;. The solution is to use a &lt;a class="link" href="http://lesscss.org" target="_blank" rel="noopener"&#10; &gt;css pre-processor&lt;/a&gt; to incorporate Bootstrap&amp;rsquo;s &lt;a class="link" href="http://lesscss.org" target="_blank" rel="noopener"&#10; &gt;LESS&lt;/a&gt; based &lt;a class="link" href="http://twitter.github.com/bootstrap/extend.html#built-with-less" target="_blank" rel="noopener"&#10; &gt;mixins&lt;/a&gt; into your own .less files and push the Bootstrap instructions down into your stylesheets. There are two ways to &amp;ldquo;compile&amp;rdquo; .less stylesheets - use a &lt;a class="link" href="http://winless.org/" target="_blank" rel="noopener"&#10; &gt;stand-alone LESS compiler&lt;/a&gt; or use &lt;a class="link" href="https://github.com/cloudhead/less.js" target="_blank" rel="noopener"&#10; &gt;less.js&lt;/a&gt;. I found it very convenient to use &lt;a class="link" href="https://raw.github.com/cloudhead/less.js/master/dist/less-1.3.3.min.js" target="_blank" rel="noopener"&#10; &gt;less.js&lt;/a&gt; (note that it is not recommended in production deployment). As I started working on developing the sample code I found it a bit cumbersome to work with an entire web application project in Visual Studio, considering I was working with some really simple sample client-side html, css. As I craved for an alternative, I stumbled on to a development workflow that is incredibly simple and a lot of fun. I call it the Site44 workflow. Site44 turns your dropbox folders into websites. And it is awesome! Here is what you do -&lt;/p&gt;&#10;&lt;p&gt;1. Sign into &lt;a class="link" href="http://www.site44.com" target="_blank" rel="noopener"&#10; &gt;Site44.com&lt;/a&gt; using your &lt;a class="link" href="http://www.dropbox.com" target="_blank" rel="noopener"&#10; &gt;dropbox&lt;/a&gt; credentials.&lt;/p&gt;&#10;&lt;p&gt;2. Create a new site (all you have to do is come up with a name). I named it &amp;ldquo;ash&amp;rdquo;. A sub-folder with this name will show up in your &lt;a class="link" href="http://www.dropbox.com" target="_blank" rel="noopener"&#10; &gt;dropbox&lt;/a&gt; folder.&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://www.tewari.info/wp-content/site44-dropbox-folder.png" &gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.tewari.info/wp-content/site44-dropbox-folder.png"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;3. Drag this folder to your &lt;a class="link" href="http://www.github.com" target="_blank" rel="noopener"&#10; &gt;Github&lt;/a&gt; for Windows screen and drop it there to create a github repo in that folder and &lt;a class="link" href="https://github.com/ashtewari/ash.site44.com" target="_blank" rel="noopener"&#10; &gt;push it to github&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://www.tewari.info/wp-content/site44-to-github.png" &gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.tewari.info/wp-content/site44-to-github.png"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;4. Smile and write code.&lt;/p&gt;&#10;&lt;p&gt;As you save your code. The changes are deployed in real-time to your website. You commit to your github repo as you please. If you revert to a different version/branch of our code from your git repo, that version will be deployed (almost) instantly to your website. I wish there was a .site44ignore feature in &lt;a class="link" href="http://www.site44.com" target="_blank" rel="noopener"&#10; &gt;Site44&lt;/a&gt;, just like .gitignore. That will allow me to keep my .git folder (and some other files) from getting published to the website. Other than that, this worked out really well for me.&lt;/p&gt;&#10;&lt;p&gt;I wrote about the experience of extending Bootstrap with LESS here : &lt;a class="link" href="http://blog.appliedis.com/2013/02/04/bootstrap-with-less/" target="_blank" rel="noopener"&#10; &gt;Bootstrap with LESS&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Hat tip to &lt;a class="link" href="http://www.justinsaraceno.com/" target="_blank" rel="noopener"&#10; &gt;Justin Saraceno&lt;/a&gt; for introducing me to &lt;a class="link" href="http://www.site44.com" target="_blank" rel="noopener"&#10; &gt;site44&lt;/a&gt;.&lt;/p&gt;&#10;</description></item><item><title>Understanding and Using System.Transactions</title><link>https://www.tewari.info/2012/10/17/understanding-and-using-system-transactions/</link><pubDate>Wed, 17 Oct 2012 16:10:42 +0000</pubDate><guid>https://www.tewari.info/2012/10/17/understanding-and-using-system-transactions/</guid><description>&lt;p&gt;These are some resources to help grasp &lt;a class="link" href="http://msdn.microsoft.com/en-us/library/vstudio/system.transactions%28v=vs.90%29.aspx" title="System.Transactions Namespace"&#10; target="_blank" rel="noopener"&#10; &gt;System.Transactions&lt;/a&gt; functionality and use it effectively in your projects:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a class="link" href="http://msdn.microsoft.com/en-us/library/vstudio/ee818755%28v=vs.100%29.aspx" target="_blank" rel="noopener"&#10; &gt;Features Provided by System.Transactions&lt;/a&gt; to &lt;a class="link" href="http://msdn.microsoft.com/en-us/library/vstudio/ee818751%28v=vs.100%29.aspx" target="_blank" rel="noopener"&#10; &gt;create transactional applications&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a class="link" href="http://msdn.microsoft.com/en-us/library/vstudio/ee818746%28v=vs.100%29.aspx" target="_blank" rel="noopener"&#10; &gt;Implementing an Implicit Transaction using Transaction Scope&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;MSDN Magazine Articles by &lt;a class="link" href="http://www.johnpapa.net/" target="_blank" rel="noopener"&#10; &gt;John Papa&lt;/a&gt;:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="link" href="http://msdn.microsoft.com/en-us/magazine/cc163847.aspx" target="_blank" rel="noopener"&#10; &gt;ADO.NET and System.Transactions&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="http://msdn.microsoft.com/en-us/magazine/cc163527.aspx" target="_blank" rel="noopener"&#10; &gt;Revisiting System.Transactions&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;These are specific to &lt;a class="link" href="http://msdn.microsoft.com/en-us/library/vstudio/system.transactions.transactionscope%28v=vs.100%29.aspx" target="_blank" rel="noopener"&#10; &gt;TransactionScope&lt;/a&gt;(the way to go in most cases):&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Here is a practical example of &lt;a class="link" href="http://thewayofcode.wordpress.com/2011/12/11/handling-transactions-in-net-using-transactionscope/" target="_blank" rel="noopener"&#10; &gt;Using TransactionScope to handle transactions in .net&lt;/a&gt;.&lt;/li&gt;&#10;&lt;li&gt;This &lt;a class="link" href="http://msdn.microsoft.com/en-us/magazine/cc300805.aspx" target="_blank" rel="noopener"&#10; &gt;article in MSDN Magazine&lt;/a&gt; gets in depth with the way a TransactionScope like functionality can be implemented. Gives you a good understanding of what is happening under the hood when using TransactionScope in some Repository implementations in multi-threaded scenarios.&lt;/li&gt;&#10;&lt;li&gt;This CodeProject article is another example of &lt;a class="link" href="http://www.codeproject.com/Articles/31270/A-Transactional-Repository-Implementation-in-NET" target="_blank" rel="noopener"&#10; &gt;implementing a transactional repository&lt;/a&gt;.&lt;/li&gt;&#10;&lt;li&gt;There are &lt;a class="link" href="http://blogs.msdn.com/b/dbrowne/archive/2010/06/03/using-new-transactionscope-considered-harmful.aspx" target="_blank" rel="noopener"&#10; &gt;excellent tips here&lt;/a&gt; about configuring TransactionScope when using it with SQL Server.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;This is a good resource for &lt;a class="link" href="http://www.codeproject.com/Articles/55472/Committable-Transactions-in-C-SQL" target="_blank" rel="noopener"&#10; &gt;understanding CommitableTransaction&lt;/a&gt; usage.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;And this one on the CodeProject has brilliant, in-depth and under-the-hood coverage - &lt;a class="link" href="http://www.codeproject.com/Articles/35087/Truly-Understanding-NET-Transactions-and-WCF-Imple" target="_blank" rel="noopener"&#10; &gt;Truly Understanding .NET Transactions and WCF Implementation&lt;/a&gt;.&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Features Provided by System.Transactions&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="http://msdn.microsoft.com/en-us/library/vstudio/ee818755%28v=vs.100%29.aspx" target="_blank" rel="noopener"&#10; &gt;http://msdn.microsoft.com/en-us/library/vstudio/ee818755(v=vs.100).aspx&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Implementing an Implicit Transaction using Transaction Scope&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="http://msdn.microsoft.com/en-us/library/vstudio/ee818746%28v=vs.100%29.aspx" target="_blank" rel="noopener"&#10; &gt;http://msdn.microsoft.com/en-us/library/vstudio/ee818746(v=vs.100).aspx&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;MSDN Articles by John Papa&lt;/p&gt;&#10;&lt;p&gt;ADO.NET and System.Transactions&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="http://msdn.microsoft.com/en-us/magazine/cc163847.aspx" target="_blank" rel="noopener"&#10; &gt;http://msdn.microsoft.com/en-us/magazine/cc163847.aspx&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Revisiting System.Transactions&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="http://msdn.microsoft.com/en-us/magazine/cc163527.aspx" target="_blank" rel="noopener"&#10; &gt;http://msdn.microsoft.com/en-us/magazine/cc163527.aspx&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;These are specific to TransactionScope (the way to go in most cases)&lt;/p&gt;&#10;&lt;p&gt;Here is a practical example of Using TransactionScope :&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="http://thewayofcode.wordpress.com/2011/12/11/handling-transactions-in-net-using-transactionscope/" target="_blank" rel="noopener"&#10; &gt;http://thewayofcode.wordpress.com/2011/12/11/handling-transactions-in-net-using-transactionscope/&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;This one gets in depth with the way a TransactionScope like functionality can be implemented. Gives you a good understanding of what is happening under the hood when using TransactionScope in some Repository implementations in multi-threaded scenarios.&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="http://msdn.microsoft.com/en-us/magazine/cc300805.aspx" target="_blank" rel="noopener"&#10; &gt;http://msdn.microsoft.com/en-us/magazine/cc300805.aspx&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Here is another example of implementing a transactional repository :&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="http://www.codeproject.com/Articles/31270/A-Transactional-Repository-Implementation-in-NET" target="_blank" rel="noopener"&#10; &gt;http://www.codeproject.com/Articles/31270/A-Transactional-Repository-Implementation-in-NET&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;There are excellent tips here about configuring TransactionScope when used with SQL Server:&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="http://blogs.msdn.com/b/dbrowne/archive/2010/06/03/using-new-transactionscope-considered-harmful.aspx" target="_blank" rel="noopener"&#10; &gt;http://blogs.msdn.com/b/dbrowne/archive/2010/06/03/using-new-transactionscope-considered-harmful.aspx&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;This is a good resource for CommitableTransaction usage - &lt;a class="link" href="http://www.codeproject.com/Articles/55472/Committable-Transactions-in-C-SQL" target="_blank" rel="noopener"&#10; &gt;http://www.codeproject.com/Articles/55472/Committable-Transactions-in-C-SQL&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;And this one has brilliant under-the-hood coverage - &lt;a class="link" href="http://www.codeproject.com/Articles/35087/Truly-Understanding-NET-Transactions-and-WCF-Impl" target="_blank" rel="noopener"&#10; &gt;http://www.codeproject.com/Articles/35087/Truly-Understanding-NET-Transactions-and-WCF-Impl&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>Solution to the fetch puzzle</title><link>https://www.tewari.info/2012/01/03/solution-to-the-fetch-puzzle/</link><pubDate>Wed, 04 Jan 2012 03:00:38 +0000</pubDate><guid>https://www.tewari.info/2012/01/03/solution-to-the-fetch-puzzle/</guid><description>&lt;p&gt;Here is a brute force solution to the fetch problem -&lt;/p&gt;&#10;&lt;p&gt;Basically, at each step there are three possibilities :&lt;/p&gt;&#10;&lt;p&gt;1. You can fill a bucket.&lt;/p&gt;&#10;&lt;p&gt;2. You can transfer water from one bucket to the other one.&lt;/p&gt;&#10;&lt;p&gt;3. You can dump out the water from a bucket.&lt;/p&gt;&#10;&lt;p&gt;In this brute force solution, I try each one of these steps and then try all three again after each one of the previous steps. And on&lt;/p&gt;&#10;&lt;p&gt;and on untill I get the required amount of water in one of the buckets.&lt;/p&gt;&#10;&lt;p&gt;Check it out. Source code is on my github repo -&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://github.com/ashtewari/fetch" target="_blank" rel="noopener"&#10; &gt;https://github.com/ashtewari/fetch&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Here is a brute force solution to the &lt;a class="link" href="https://www.tewari.info/2011/12/26/solve-puzzle-with-code/" title="fetch-puzzle"&#10; &gt;fetch puzzle&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;The puzzle goes like this – You have two buckets. A 3 gallon bucket and a 5 gallon bucket. Buckets are not marked or graduated. You are to fetch 4 gallons of water in a single trip to the river. How will you do it?&lt;/p&gt;&#10;&lt;p&gt;Basically, at each step there are three possibilities :&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;You can fill a bucket.&lt;/li&gt;&#10;&lt;li&gt;You can transfer water from one bucket to the other one.&lt;/li&gt;&#10;&lt;li&gt;You can dump out the water from a bucket.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;In this brute force solution, I try each one of these steps and then try all three again after each one of the previous steps. And on and on until I get the required amount of water in one of the buckets.&lt;/p&gt;&#10;&lt;p&gt;Check it out. Source code is on my github repo - &lt;a class="link" href="https://github.com/ashtewari/fetch" title="github-repo-fetch"&#10; target="_blank" rel="noopener"&#10; &gt;https://github.com/ashtewari/fetch&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>Solve puzzle with code</title><link>https://www.tewari.info/2011/12/26/solve-puzzle-with-code/</link><pubDate>Tue, 27 Dec 2011 04:44:17 +0000</pubDate><guid>https://www.tewari.info/2011/12/26/solve-puzzle-with-code/</guid><description>&lt;p&gt;Here is a quite common programming interview puzzle - You have two buckets. A 3 gallon bucket and a 5 gallon bucket. Buckets are not marked or graduated. You are to fetch 4 gallon of water in a single trip to the river. How will you do it?&lt;/p&gt;&#10;&lt;p&gt;Obviousy, this question is asked by changing the capacities of the two buckets and the amount of water to be fetched.&lt;/p&gt;&#10;&lt;p&gt;Your mission, should you choose to accept it, is to write a program to solve this puzzle in a generic way. Your program should take 3 inputs - capacities of the two buckets and the amount of water to be fetched. After solving the puzzle, your program must write out the solution step-by-step. You can use any programming language, any platform, any programming technique to write the program. Use whatever you like - C#, VB, C, C++, Java, Ruby, Python, F#, Boo, Javascript or any other language of your choice. Use design patterns, TDD, BDD, MVVM, Linq or whatever. Make it blazing fast, exploit multiple cores, use artificial intelligence. Go nuts! If you want to write the whole program in T-sql, powershell script or a batch script, go ahead. Heck ! you can even do it with regular expressions, if that your thing!&lt;/p&gt;&#10;&lt;p&gt;Your mission, should you choose to accept it, is to write a program to solve this common programming interview puzzle in a generic way.&lt;/p&gt;&#10;&lt;p&gt;The puzzle goes like this - You have two buckets. A 3 gallon bucket and a 5 gallon bucket. Buckets are not marked or graduated. You are to fetch 4 gallons of water in a single trip to the river. How will you do it?&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="tommylees-flickr-buckets" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.tewari.info/wp-content/tommylees-flickr-buckets.jpg"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;em&gt;Photo Credit : http://www.flickr.com/photos/71256895@N00/3688461774/sizes/l/in/photostream/&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;Your program should take 3 inputs - capacities of the two buckets and the amount of water to be fetched. After solving the puzzle, your program must write out the solution step-by-step. You can use any language, any platform and any technique to write the program. Use whatever you like - C#, VB, C, C++, Java, Ruby, Python, F#, Boo, Javascript, powershell script or any other language of your choice. Use design patterns, TDD, BDD, MVVM, Linq or whatever. Make it blazing fast, exploit multiple cores, use artificial intelligence. Go nuts! If you want to write the whole program in T-sql, go ahead. Heck ! you can even do it with regular expressions, if that your thing!&lt;/p&gt;&#10;</description></item><item><title>ChildWindow Positioning</title><link>https://www.tewari.info/2011/06/07/childwindow-positioning/</link><pubDate>Tue, 07 Jun 2011 11:23:52 +0000</pubDate><guid>https://www.tewari.info/2011/06/07/childwindow-positioning/</guid><description>&lt;p&gt;Silverlight &lt;a class="link" href="http://msdn.microsoft.com/en-us/library/system.windows.controls.childwindow%28v=vs.95%29.aspx" title="MSDN_Silverlight_ChildWindow"&#10; target="_blank" rel="noopener"&#10; &gt;ChildWindow&lt;/a&gt; is centered over the parent control. I have extended ChildWindow to open it at a specific position.&lt;/p&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/images/PositionedChildWindow-screenshot.png"&#10;&#9;&#9;&#9;alt="Positioned ChildWindow"&gt;&lt;figcaption&gt;&#10;&#9;&#9;&#9;&lt;p&gt;Positioned ChildWindow&lt;/p&gt;&#10;&#9;&#9;&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;p&gt;Here is a live demo : &lt;a class="link" href="https://www.tewari.info/childwindow-positioning-demo/" &gt;childwindow-positioning-demo&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;And here is the code :&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;public partial class ChildWindowEx : ChildWindow&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Point _pt = new Point(0,0);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; public ChildWindowEx()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; InitializeComponent();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; public ChildWindowEx(Point pt) : this()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; _pt = pt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; protected override Size ArrangeOverride(Size finalSize)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Grid grid = Utils.FindChild(this, &amp;#34;ContentRoot&amp;#34;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if (grid != null)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; grid.Arrange(new Rect(_pt.X, _pt.Y, grid.DesiredSize.Width, grid.DesiredSize.Height));&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return finalSize;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return base.ArrangeOverride(finalSize);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Visual Studio 2010 Solution : &lt;a class="link" href="https://www.tewari.info/downloads/PositionedChildWindow.zip" &gt;download&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>Using Model-View-ViewModel in WPF Applications</title><link>https://www.tewari.info/2010/01/25/using-model-view-viewmodel-in-wpf-applications/</link><pubDate>Mon, 25 Jan 2010 22:23:39 +0000</pubDate><guid>https://www.tewari.info/2010/01/25/using-model-view-viewmodel-in-wpf-applications/</guid><description>&lt;p&gt;I am presenting at &lt;a class="link" href="http://www.socalcodecamp.com/" title="socalcodecamp website"&#10; target="_blank" rel="noopener"&#10; &gt;SoCalCodeCamp&lt;/a&gt; this weekend (January 30th, 2010) - &lt;a class="link" href="http://www.socalcodecamp.com/socalcodecamp/session.aspx?sid=0b2ee44f-595d-4f55-a5d6-2b1293f546d0" title="WPF MVVM Presntation "&#10; target="_blank" rel="noopener"&#10; &gt;Advanced WPF - Using Model-View-ViewModel in WPF Applications&lt;/a&gt;.&lt;/p&gt;&#10;&lt;figure&gt;&lt;img src="https://www.tewari.info/wp-content/tasklist.png"&#10;&#9;&#9;&#9;alt="tasklist-mockup"&gt;&lt;figcaption&gt;&#10;&#9;&#9;&#9;&lt;p&gt;tasklist-mockup&lt;/p&gt;&#10;&#9;&#9;&lt;/figcaption&gt;&#10;&lt;/figure&gt;&#10;&#10;&lt;p&gt;Agenda :&lt;/p&gt;&#10;&lt;p&gt;1. Roles of the M-V-VM triad&lt;/p&gt;&#10;&lt;p&gt;2. Why use M-V-VM ?&lt;/p&gt;&#10;&lt;p&gt;3. Characteristics of the ViewModel&lt;/p&gt;&#10;&lt;p&gt;4. Build a Sample WPF Application using M-V-VM&lt;/p&gt;&#10;&lt;p&gt;Resources :&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;a class="link" href="http://msdn.microsoft.com/en-us/magazine/dd419663.aspx" title="MSDN Magazine Article"&#10; target="_blank" rel="noopener"&#10; &gt;MSDN Magazine Article&lt;/a&gt; and Sample Application &lt;a class="link" href="http://code.msdn.microsoft.com/mag200902MVVM/Release/ProjectReleases.aspx" title="Download Demo Application Code"&#10; target="_blank" rel="noopener"&#10; &gt;Download&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="http://martinfowler.com/eaaDev/PresentationModel.html" title="MartinFowler.com"&#10; target="_blank" rel="noopener"&#10; &gt;Martin Fowler’s description of the ‘Presentation Model ‘&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="http://codebetter.com/blogs/jeremy.miller/archive/2007/07/25/the-build-your-own-cab-series-table-of-contents.aspx" title="Jeremy Miller&amp;#39;s - Build Your CAB"&#10; target="_blank" rel="noopener"&#10; &gt;Jeremy Miller’s ‘Build Your Own CAB’ series&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;</description></item><item><title>ReSharper vs CodeRush + Refactor Pro</title><link>https://www.tewari.info/2009/02/21/resharper-vs-coderush-refactor-pro/</link><pubDate>Sat, 21 Feb 2009 17:43:03 +0000</pubDate><guid>https://www.tewari.info/2009/02/21/resharper-vs-coderush-refactor-pro/</guid><description>&lt;p&gt;I have been playing with JetBrains &lt;a class="link" href="http://www.jetbrains.com/resharper/" target="_blank" rel="noopener"&#10; &gt;ReSharper&lt;/a&gt;(version 4.1) and DevExpress &lt;a class="link" href="http://devexpress.com/Products/Visual_Studio_Add-in/Coding_Assistance/" target="_blank" rel="noopener"&#10; &gt;CodeRush + Refactor! Pro&lt;/a&gt; (version 3.2.2) lately. I wanted to decide on which one to go with. Here are some notes -&lt;/p&gt;&#10;&lt;p&gt;R# = ReSharper&#10;CodeRush = CodeRush + Refactor! Pro&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;R# seems to be better for refactoring, because it does not assume that I follow a rigid work flow when writing code. For example, I don&amp;rsquo;t always decide on the class hierarchies upfront. I do discover them as I write code. So, when I discover that I need to extract a base class from the class I am working on, I can do so with R#. I couldn&amp;rsquo;t find a way to do extract a base/super class with CodeRush.&lt;/li&gt;&#10;&lt;li&gt;In R#, I can create an overloaded constructor using &amp;ldquo;Change Signature&amp;rdquo; refactoring (Ctrl+R, S). I couldn&amp;rsquo;t find a way to do this in CodeRush. CodeRush does allow me to create overloaded methods.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;However, comparisons that only focus on how many refactorings each tool can do are not very important to me. After all, it should be easy for the individual missing refactorings to be implemented in the subsequent releases of these tools. I want to know which one is a better investment in the long run. The investment is not just a couple of hundred dollars, it is going to be an investment of time too.&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;R# &amp;ldquo;finds&amp;rdquo; Types as you try to use them and adds references and &amp;ldquo;using&amp;rdquo; directives from other projects in your solution. You will not believe how useful this is! You don&amp;rsquo;t have to interrupt your train of thought to go add references and &amp;ldquo;using&amp;rdquo; directives. CodeRush doesn&amp;rsquo;t do that.&lt;/li&gt;&#10;&lt;li&gt;I found R# &amp;ldquo;&lt;a class="link" href="http://www.jetbrains.com/resharper/features/code_generation.html#Create_from_Usage" target="_blank" rel="noopener"&#10; &gt;Create From Usage&lt;/a&gt;&amp;rdquo; feature incredibly useful with &lt;a class="link" href="http://en.wikipedia.org/wiki/Test-driven_development" title="TDD"&#10; target="_blank" rel="noopener"&#10; &gt;TDD&lt;/a&gt;. This feature will be available in &lt;a class="link" href="http://blogs.msdn.com/somasegar/archive/2008/12/19/code-focused-development-in-vs-2010.aspx" title="Code Focused Development in VS 2010"&#10; target="_blank" rel="noopener"&#10; &gt;Visual Studio 2010&lt;/a&gt;. They are calling it “Consume-First Development”.&lt;/li&gt;&#10;&lt;li&gt;R# has keyboard shortcuts for individual refactorings. All refactorings are accessible from ALT+ENTER or ALT+R. Again, R# helps you keep focused on the code you are writing.  In CodeRush, individual refactorings don&amp;rsquo;t have keyboard shortcuts.&lt;/li&gt;&#10;&lt;li&gt;R# allows me to specify exactly what to include when doing ExtractXXX refactorings. CodeRush doesn&amp;rsquo;t.&lt;/li&gt;&#10;&lt;li&gt;R# seems to know what I want to do. For example, when I discover that an existing class would be a good starting point to write the class I am thinking about and copy-paste the class and attempt to rename it, CodeRush renames both classes. R# renames the one you intend to rename.&lt;/li&gt;&#10;&lt;li&gt;R# introduces much less friction when running unit tests. It is possible to add unit-testing add-ins to Visual Studio and access similar functionality, but the way unit-testing is integrated into R#, it is much more conducive to &lt;a class="link" href="http://en.wikipedia.org/wiki/Test-driven_development" title="TDD"&#10; target="_blank" rel="noopener"&#10; &gt;TDD&lt;/a&gt;.&lt;/li&gt;&#10;&lt;li&gt;Collapse a class region. Now try to do a refactoring on this class, like “Rename file to match type” etc. In CodeRush, you will not be able to do it because the three-dot glyph will not be displayed when the class is collapsed.&lt;/li&gt;&#10;&lt;li&gt;CodeRush keeps getting in my way by automatically writing over as I type. It expands its “smart templates” when you press space. Guess what! That is how I separate words in my sentences - by pressing space. It gets quite annoying. I wish I could turn it off.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;As you have probably guessed by now, I think ReSharper is a better fit for me.&lt;/p&gt;&#10;&lt;p&gt;Here is a list of some other comparisons, covering aspects and features of these products I haven’t mentioned here that might be important to you. Some of these concluded in favor of CodeRush. Keep in mind that some of the following articles are a couple of years old.&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="link" href="http://devlicio.us/blogs/derik_whittaker/archive/2008/05/05/resharper-4-0-vs-coderush-refactor-smack-down-results.aspx" target="_blank" rel="noopener"&#10; &gt;Derik Whittaker&lt;/a&gt; is keeping CodeRush but uninstalled Refactor Pro.&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="http://davidhayden.com/blog/dave/archive/2008/04/23/ReSharperCodeRushRefactorProInterestingDiscussion.aspx" target="_blank" rel="noopener"&#10; &gt;David Hayden&lt;/a&gt; is keeping an open mind.&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="http://www.hanselman.com/blog/ReSharperVsCodeRush.aspx" target="_blank" rel="noopener"&#10; &gt;Scott Hanselman&lt;/a&gt; likes CodeRush better.&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="http://ryangaraygay.com/blog/post/2008/04/Resharper-vs-CodeRush.aspx" target="_blank" rel="noopener"&#10; &gt;Ryan Garagay&lt;/a&gt; went with R#.&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="http://stackoverflow.com/questions/24216/resharper-vs-coderush" target="_blank" rel="noopener"&#10; &gt;StackOverflow.com&lt;/a&gt; has some useful comments and more links.&lt;/li&gt;&#10;&lt;li&gt;There is some discussion on &lt;a class="link" href="http://discuss.joelonsoftware.com/default.asp?joel.3.515309.7" target="_blank" rel="noopener"&#10; &gt;JoelOnSoftware.com&lt;/a&gt;.&lt;/li&gt;&#10;&lt;li&gt;Ian decided to stick with &lt;a class="link" href="http://ianolsen.com/2006/06/21/resharper-vs-coderush-part-1/" target="_blank" rel="noopener"&#10; &gt;ReSharper&lt;/a&gt;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>Using NHibernate With SQLite in DbUpdater</title><link>https://www.tewari.info/2008/09/09/using-nhibernate-with-sqlite-in-dbupdater/</link><pubDate>Wed, 10 Sep 2008 04:46:39 +0000</pubDate><guid>https://www.tewari.info/2008/09/09/using-nhibernate-with-sqlite-in-dbupdater/</guid><description>&lt;p&gt;&lt;a class="link" href="https://www.tewari.info/dbupdater/" &gt;DbUpdater&lt;/a&gt; (&lt;a class="link" href="http://sourceforge.net/projects/dbupdater/" target="_blank" rel="noopener"&#10; &gt;version 1.3&lt;/a&gt; onwards) can be used with &lt;a class="link" href="http://www.sqlite.org/" target="_blank" rel="noopener"&#10; &gt;sqlite3&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Review the files included in &lt;a class="link" href="https://www.tewari.info/downloads/DbUpdater-sqlite3.zip" &gt;DbUpdater-sqlite3.zip&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;1. DbUpdater.exe.config must be modified. Note changes to the following keys - exe-file, exe-args, dialect, driver_class, connetion_string.&#10;2. SchemaVersion.hbm.xml must be modified. The &amp;lsquo;class&amp;rsquo; attributes value for the &amp;lsquo;generator&amp;rsquo; of &amp;lsquo;id&amp;rsquo; must be changed to &amp;lsquo;identity&amp;rsquo;. No other changes are needed here.&#10;3. \SqlScripts\schema-version-table.sql is modified. Note that the datatypes of all columns are changed to TEXT, except for SchemaChangeId, which is changed to integer primary key. integer primary key is used for auto-incremented columns in sqlite.&#10;4. \SqlScripts\baseline.sql is modified. Note the use of current_timestamp function. The actual sql syntax in this file must conform to sqlite dialect.&#10;5. All other .sql scripts in \SqlScripts directory are also modified to conform to sqlite dialect.&lt;/p&gt;&#10;&lt;p&gt;The following files are expected to be in DbUpdater.exe directory (as configured in the DbUpdater.exe.config file) -&lt;/p&gt;&#10;&lt;p&gt;1. sqlite3.exe : &lt;a class="link" href="http://www.sqlite.org/download.html" target="_blank" rel="noopener"&#10; &gt;download&lt;/a&gt;.&#10;2. System.Data.SQLite.dll : &lt;a class="link" href="http://sqlite.phxsoftware.com/" target="_blank" rel="noopener"&#10; &gt;download&lt;/a&gt;.&#10;3. createdb.bat file : This file is included. This batch script will call sqlite3.exe to execute sql queries.&lt;/p&gt;&#10;&lt;p&gt;Another very useful tool for working with sqlite database files is &lt;a class="link" href="http://sqlitebrowser.sourceforge.net/" target="_blank" rel="noopener"&#10; &gt;SQLite Database Browzer&lt;/a&gt;. &lt;a class="link" href="https://www.tewari.info/wp-content/sqlite-support.html" title="sqlite-support.html"&#10; &gt;sqlite-support.html&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>Dial Gauge is a ProgressBar</title><link>https://www.tewari.info/2008/06/10/dial-gauge-is-a-progressbar/</link><pubDate>Wed, 11 Jun 2008 06:49:43 +0000</pubDate><guid>https://www.tewari.info/2008/06/10/dial-gauge-is-a-progressbar/</guid><description>&lt;p&gt;I am not just being philosophical here. In &lt;a class="link" href="http://msdn.microsoft.com/en-us/netframework/aa663326.aspx" title="MSDN-WPF"&#10; target="_blank" rel="noopener"&#10; &gt;WPF&lt;/a&gt;, &lt;a class="link" href="http://msdn.microsoft.com/en-us/magazine/cc163497.aspx" title="Using Templates to Customize WPF Controls"&#10; target="_blank" rel="noopener"&#10; &gt;ControlTemplates&lt;/a&gt; allow you to transform a control&amp;rsquo;s appearance. This is not the same as applying stylesheets. This is an entirely new level of customization. What you see in the screenshot below looks like a Dial but is actually a simple ProgressBar control wearing a &amp;ldquo;Dial&amp;rdquo; template. The Dial template was created using &lt;a class="link" href="http://www.microsoft.com/expression/products/Overview.aspx?key=blend" title="Microsoft-Expression-Blend"&#10; target="_blank" rel="noopener"&#10; &gt;Microsoft Expression Blend&lt;/a&gt; .&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="dial-is-a-progressbar.PNG" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.tewari.info/images/dial-is-a-progressbar.PNG"&gt;&lt;/p&gt;&#10;&lt;p&gt;Include the ControlTemplate as a Window.Resource and then assign it to ProgressBar element&amp;rsquo;s Template attribute :&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course that is not all. The ControlTemplate must define some named elements of FrameworkElement type. Charles Petzold has explained it in detail : &lt;a class="link" href="http://msdn.microsoft.com/en-us/magazine/cc163497.aspx" title="Charles-Petzold-Using Templates to Customize WPF Controls"&#10; target="_blank" rel="noopener"&#10; &gt;MSDN Magazine Article&lt;/a&gt;. So, I will not repeat it here.&lt;/p&gt;&#10;&lt;p&gt;The sample code can be downloaded here : &lt;a class="link" href="https://www.tewari.info/downloads/DialTest.zip" title="DialTest.zip"&#10; &gt;DialTest.zip&lt;/a&gt;&#10;License : &lt;a class="link" href="http://creativecommons.org/licenses/by-nc-sa/3.0/us/" target="_blank" rel="noopener"&#10; &gt;Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>PostSharp with SharpDevelop</title><link>https://www.tewari.info/2008/04/28/postsharp-with-sharpdevelop/</link><pubDate>Tue, 29 Apr 2008 05:04:43 +0000</pubDate><guid>https://www.tewari.info/2008/04/28/postsharp-with-sharpdevelop/</guid><description>&lt;p&gt;&lt;a class="link" href="http://sharpdevelop.net/OpenSource/SD/Default.aspx" title="SharpDevelop HomePage"&#10; target="_blank" rel="noopener"&#10; &gt;SharpDevelop3.0&lt;/a&gt; uses &lt;a class="link" href="http://en.wikipedia.org/wiki/MSBuild" title="MSBuild on wikipedia"&#10; target="_blank" rel="noopener"&#10; &gt;MSBuild&lt;/a&gt;. Including PostSharp in your build process is transparent if you are doing a global install using PostSharp installer. If you are doing a per-project installation using &amp;ldquo;Binary - No Installer&amp;rdquo;&lt;a class="link" href="http://www.postsharp.org/download/" title="postsharp download"&#10; target="_blank" rel="noopener"&#10; &gt;download&lt;/a&gt;, you will need to import the PostSharp targets into your .csproj file -&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; True&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;C:\code\PostSharp-1.0.8.316-Binary\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For more details, read the install instructions included in the PostSharp &lt;a class="link" href="http://www.postsharp.org/download/" title="postsharp download"&#10; target="_blank" rel="noopener"&#10; &gt;download&lt;/a&gt; and &lt;a class="link" href="http://www.postsharp.org/blog/2008/01/under-hood-of-msbuild-integration.html" title="under-hood-of-msbuild-integration"&#10; target="_blank" rel="noopener"&#10; &gt;under-the-hood-of-msbuild-integration&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;To use local PostSharp binaries (relative to your project) , modify your .csproj file as follows -&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; True&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $(MSBuildProjectDirectory)\PostSharp\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;$(MSBuildProjectDirectory) is the directory containing your .csproj file.&#10;\PostSharp\ is the directory containing local PostSharp binaries.&lt;/p&gt;&#10;&lt;p&gt;2. You will need to exclude the Aspect class itself from being woven.&lt;/p&gt;&#10;&lt;p&gt;If you are following the &lt;a class="link" href="http://www.postsharp.org/about/getting-started/" title="getting-started-sample"&#10; target="_blank" rel="noopener"&#10; &gt;getting-started sample&lt;/a&gt;, see the following example:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[Serializable]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[Trace( null, AttributeExclude = true )]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;public sealed class TraceAttribute : OnMethodBoundaryAspect&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;3. Compile your project.&lt;/p&gt;&#10;</description></item><item><title>Using Custom Converter in XAML</title><link>https://www.tewari.info/2008/04/15/using-custom-converter-in-xaml/</link><pubDate>Wed, 16 Apr 2008 05:22:12 +0000</pubDate><guid>https://www.tewari.info/2008/04/15/using-custom-converter-in-xaml/</guid><description>&lt;p&gt;In my previous post : &lt;a class="link" href="https://www.tewari.info/2008/03/07/wpf-linq-to-sql-sample/" title="wpf-linq-to-sql-sample"&#10; &gt;WPF-LINQ To SQL Sample&lt;/a&gt;, I had to resort to modifying .dbml file to get the images stored as varbinary into the WPF ListView control. I had to change the Type of image fields to System.Byte[], instead of using System.Data.Linq.Binary. A better way to do this is to use a custom converter. WPF allows you to specify custom converter as part of the Binding in .xaml, like this -&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;Image Grid.Row=&amp;#34;2&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Source=&amp;#34;{Binding Path=ThumbNailPhoto ,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Converter={StaticResource imageConverter}}&amp;#34;&amp;gt;&amp;lt;/Image&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The custom converter is declared in the same .xaml file as a resource -&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;Window.Resources&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;local:ImageDataConverter x:Key=&amp;#34;imageConverter&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/Window.Resources&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ImageDataConverter is implemented in .xaml.cs file -&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;public class ImageDataConverter : IValueConverter&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; public object Convert(object value, Type targetType, object parameter,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.Globalization.CultureInfo culture)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; byte[] image = ((System.Data.Linq.Binary)value).ToArray();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return image;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; public object ConvertBack(object value, Type targetType, object parameter,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; System.Globalization.CultureInfo culture)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; throw new NotSupportedException();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The updated sample code can be downloaded here : &lt;a class="link" href="https://www.tewari.info/downloads/Linq2SqlSample2.zip" title="Linq2SqlSample2.zip"&#10; &gt;WPF-LINQ to SQL Sample&lt;/a&gt;&#10;License : &lt;a class="link" href="http://creativecommons.org/licenses/by-nc-sa/3.0/us/" target="_blank" rel="noopener"&#10; &gt;Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>WPF - LINQ to SQL Sample</title><link>https://www.tewari.info/2008/03/07/wpf-linq-to-sql-sample/</link><pubDate>Fri, 07 Mar 2008 07:15:35 +0000</pubDate><guid>https://www.tewari.info/2008/03/07/wpf-linq-to-sql-sample/</guid><description>&lt;p&gt;This exercise in binding a WPF ListView control with LINQ to SQL was a lot of fun ! The following image shows data from &lt;a class="link" href="http://www.codeplex.com/MSFTDBProdSamples" title="MSSQL Sample Databases"&#10; target="_blank" rel="noopener"&#10; &gt;AdventureWorks&lt;/a&gt; sample database displayed in the ListView control. The end result is very admirable, even in this very basic demo. Feeling a complete sense of freedom is unavoidable when working with WPF.&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="Linq2SqlSample1.Png" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.tewari.info/images/Linq2SqlSample1.Png"&gt;&lt;/p&gt;&#10;&lt;p&gt;This sample demonstrates :&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;LINQ to SQL mapping.&lt;/li&gt;&#10;&lt;li&gt;WPF ListView Control DataBinding.&lt;/li&gt;&#10;&lt;li&gt;Displaying images stored in database as varbinary in WPF control.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;The sample code can be downloaded here : &lt;a class="link" href="https://www.tewari.info/downloads/Linq2SqlSample.zip" title="Linq2SqlSample.zip"&#10; &gt;WPF-LINQ to SQL Sample&lt;/a&gt;&#10;License : &lt;a class="link" href="http://creativecommons.org/licenses/by-nc-sa/3.0/us/" target="_blank" rel="noopener"&#10; &gt;Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.&lt;/a&gt; &lt;a class="link" href="http://creativecommons.org/licenses/by-nc-sa/3.0/us/" target="_blank" rel="noopener"&#10; &gt;&lt;img alt="Creative Commons License" class="gallery-image" data-flex-basis="681px" data-flex-grow="283" height="31" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="http://i.creativecommons.org/l/by-nc-sa/3.0/us/88x31.png" width="88"&gt;&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>Customize log4net Output Path</title><link>https://www.tewari.info/2008/03/06/customize-log4net-output-path/</link><pubDate>Fri, 07 Mar 2008 00:56:55 +0000</pubDate><guid>https://www.tewari.info/2008/03/06/customize-log4net-output-path/</guid><description>&lt;p&gt;The default log4net output path is relative to the startup directory of your executable. To customize the output path, you can override the base Appender&amp;rsquo;s File property in your own Appender class. The following example describes how to route the log files relative to the temp folder :&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; public class MyOwnAppender : log4net.Appender.RollingFileAppender&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; public override string File&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; get&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; return base.File;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; set&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if (Path.IsPathRooted(value))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; base.File = value;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; else&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; base.File = Path.Combine(Path.GetTempPath(), value);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Your log4net config file must be modified so that log4net can locate and use your custom Appender. If MyOwnAppender is in MyNamespace and you have implemented it in MyLoggerLib.dll :&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>OpenSimSim 1.0-RC is out</title><link>https://www.tewari.info/2007/12/24/opensimsim-10-rc-is-out/</link><pubDate>Mon, 24 Dec 2007 17:04:31 +0000</pubDate><guid>https://www.tewari.info/2007/12/24/opensimsim-10-rc-is-out/</guid><description>&lt;p&gt;&lt;a class="link" href="http://opensimsim.sourceforge.net" title="OpenSimSim Website"&#10; target="_blank" rel="noopener"&#10; &gt;OpenSimSim&lt;/a&gt; : Your Password Solution. Download 1.0 Release Candidate here : &lt;a class="link" href="https://sourceforge.net/project/showfiles.php?group_id=194886" title="OpenSimSim 1.0-RC"&#10; target="_blank" rel="noopener"&#10; &gt;OpenSimSim 1.0-RC&lt;/a&gt;&lt;img alt="opensimsim-screenshot" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="225" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="http://opensimsim.sourceforge.net/opensimsim-screenshot-1.png" width="300"&gt;&lt;/p&gt;&#10;</description></item><item><title>Leveraging XPATH Axes</title><link>https://www.tewari.info/2007/12/20/leveraging-xpath-axes/</link><pubDate>Fri, 21 Dec 2007 01:14:29 +0000</pubDate><guid>https://www.tewari.info/2007/12/20/leveraging-xpath-axes/</guid><description>&lt;p&gt;XPATH axes come in very handy when nodes need to be selected based on (attribute&amp;rsquo;s or child element&amp;rsquo;s) values that must match those of other nodes elsewhere in the xml tree. Consider the following log4net configuration file :&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34;?&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;configuration&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;configSections&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;section name=&amp;#34;nhibernate&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type=&amp;#34;System.Configuration.NameValueSectionHandler, System,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Version=2.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;section name=&amp;#34;log4net&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type=&amp;#34;log4net.Config.Log4NetConfigurationSectionHandler,log4net&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/configSections&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;nhibernate&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;add key=&amp;#34;hibernate.connection.provider&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; value=&amp;#34;NHibernate.Connection.DriverConnectionProvider&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;add key=&amp;#34;hibernate.connection.driver_class&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; value=&amp;#34;NHibernate.Driver.SqlClientDriver&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;add key=&amp;#34;hibernate.connection.connection_string&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; value=&amp;#34;Server=servername; Database=dbname;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; User=username; Password=secret;&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;add key=&amp;#34;hibernate.connection.isolation&amp;#34; value=&amp;#34;ReadCommitted&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;add key=&amp;#34;hibernate.dialect&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; value=&amp;#34;NHibernate.Dialect.MsSql2000Dialect&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/nhibernate&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;log4net&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;appender name=&amp;#34;NHibernateFileLog&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type=&amp;#34;log4net.Appender.RollingFileAppender&amp;#34;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;file value=&amp;#34;Logs/nhibernate.txt&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;appendToFile value=&amp;#34;true&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;rollingStyle value=&amp;#34;Size&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;maxSizeRollBackups value=&amp;#34;10&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;maximumFileSize value=&amp;#34;100KB&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;staticLogFileName value=&amp;#34;true&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;layout type=&amp;#34;log4net.Layout.PatternLayout&amp;#34;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;conversionPattern&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; value=&amp;#34;%d{HH:mm:ss.fff} [%t] %-5p %c - %m%n&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/layout&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/appender&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;appender name=&amp;#34;GeneralLog&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type=&amp;#34;log4net.Appender.RollingFileAppender&amp;#34;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;file value=&amp;#34;Logs/general.txt&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;appendToFile value=&amp;#34;true&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;maximumFileSize value=&amp;#34;100KB&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;rollingStyle value=&amp;#34;Size&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;maxSizeRollBackups value=&amp;#34;5&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;layout type=&amp;#34;log4net.Layout.PatternLayout&amp;#34;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;conversionPattern&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; value=&amp;#34;%d{HH:mm:ss.fff} [%t] %-5p %c - %m%n&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/layout&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/appender&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;appender name=&amp;#34;DataLog&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; type=&amp;#34;log4net.Appender.RollingFileAppender&amp;#34;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;file value=&amp;#34;Logs/data.txt&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;appendToFile value=&amp;#34;true&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;maximumFileSize value=&amp;#34;100KB&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;rollingStyle value=&amp;#34;Size&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;maxSizeRollBackups value=&amp;#34;5&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;layout type=&amp;#34;log4net.Layout.PatternLayout&amp;#34;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;conversionPattern&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; value=&amp;#34;%d{HH:mm:ss.fff} [%t] %-5p %c - %m%n&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/layout&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/appender&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;!-- levels: DEBUG, INFO, WARN, ERROR, FATAL --&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;root&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;level value=&amp;#34;DEBUG&amp;#34;/&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;appender-ref ref=&amp;#34;GeneralLog&amp;#34; /&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/root&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;logger name=&amp;#34;NHibernate&amp;#34; additivity=&amp;#34;false&amp;#34;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;level value=&amp;#34;DEBUG&amp;#34;/&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;appender-ref ref=&amp;#34;NHibernateFileLog&amp;#34;/&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/logger&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;logger name=&amp;#34;Pushable.Data&amp;#34; additivity=&amp;#34;false&amp;#34;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;level value=&amp;#34;DEBUG&amp;#34;/&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;appender-ref ref=&amp;#34;DataLog&amp;#34;/&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/logger&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/log4net&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/configuration&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;p&gt;The &lt;appender&gt;s are referenced by &lt;logger&gt;s using &amp;lsquo;ref&amp;rsquo; attribute of their &amp;lsquo;appender-ref&amp;rsquo; child elements, using the same value as the &amp;rsquo;name&amp;rsquo; attribute of the &lt;appender&gt;. This type of linking is quite common in xml documents. Now, The first question is : How to list files that are referenced by &lt;logger&gt;s ?&#10;In order to solve this problem you will need to reach the &lt;appender&gt;s that are referenced by each &lt;logger&gt; and then extract the &amp;lsquo;value&amp;rsquo; of their &lt;file&gt;s.&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;p&gt;Solution:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34;?&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;xsl:stylesheet xmlns:xsl=&amp;#34;http://www.w3.org/1999/XSL/Transform&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; version=&amp;#34;1.0&amp;#34;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;xsl:output method=&amp;#34;text&amp;#34;/&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;xsl:strip-space elements=&amp;#34;*&amp;#34;/&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;xsl:template match=&amp;#34;log4net&amp;#34;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;xsl:apply-templates&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; select=&amp;#34;appender[@name=parent::log4net/logger/appender-ref/@ref]&amp;#34;/&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/xsl:template&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;xsl:template match=&amp;#34;appender&amp;#34;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;xsl:value-of&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; select=&amp;#34;file/@value&amp;#34;/&amp;gt; &amp;lt;xsl:text&amp;gt;&amp;amp;#10;&amp;lt;/xsl:text&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/xsl:template&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/xsl:stylesheet&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;p&gt;The second question is : How to write an xslt script to transform this xml document into an html document with a table that looks like this -&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Logger&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;File&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;NHibernate&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Logs/nhibernate.txt&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Pushable.Data&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Logs/data.txt&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;hr&gt;&#10;&lt;p&gt;Solution:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;?&lt;/span&gt;xml version&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;?&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;xsl:stylesheet xmlns:xsl&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://www.w3.org/1999/XSL/Transform&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; version&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;xsl:output method&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;html&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;xsl:template match&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;log4net&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;HTML&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;HEAD&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;TITLE&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;www&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tewari&lt;span style="color:#f92672"&gt;.&lt;/span&gt;info : using xpath axes&lt;span style="color:#f92672"&gt;&amp;lt;/&lt;/span&gt;TITLE&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/&lt;/span&gt;HEAD&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;BODY&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;TABLE border&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;1&amp;#34;&lt;/span&gt; width&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;25%&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;TR&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;&lt;/span&gt;TH&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;Logger&lt;span style="color:#f92672"&gt;&amp;lt;/&lt;/span&gt;TH&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;&lt;/span&gt;TH&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/&lt;/span&gt;TH&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;TR&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;xsl:apply&lt;span style="color:#f92672"&gt;-&lt;/span&gt;templates select&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;logger&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/&lt;/span&gt;TABLE&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/&lt;/span&gt;BODY&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/&lt;/span&gt;HTML&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/&lt;/span&gt;xsl:template&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;xsl:template match&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;logger&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;xsl:variable name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;aName&amp;#34;&lt;/span&gt; select&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;appender-ref/@ref&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;TR&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;TD&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;&lt;/span&gt;xsl:value&lt;span style="color:#f92672"&gt;-&lt;/span&gt;of select&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;@name&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;TD&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;TD&lt;span style="color:#f92672"&gt;&amp;gt;&amp;lt;&lt;/span&gt;xsl:value&lt;span style="color:#f92672"&gt;-&lt;/span&gt;of&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; select&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;parent::log4net/appender[@name=$aName]/file/@value&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;TD&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/&lt;/span&gt;TR&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/&lt;/span&gt;xsl:template&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/&lt;/span&gt;xsl:stylesheet&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;p&gt;Credits :&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;xml document from &lt;a class="link" href="http://www.hibernate.org/364.html" title="hibernate"&#10; target="_blank" rel="noopener"&#10; &gt;hibernate&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;xml converted to html using &lt;a class="link" href="http://www.andre-simon.de/" title="Highlight"&#10; target="_blank" rel="noopener"&#10; &gt;Highlight&lt;/a&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a class="link" href="http://www.sketchpath.com" title="SketchPath"&#10; target="_blank" rel="noopener"&#10; &gt;SketchPath&lt;/a&gt; is a brilliant tool to play with xpath. I love the &amp;ldquo;New Context&amp;rdquo; button : Click on a node and hit &amp;ldquo;New Context&amp;rdquo; to change the context for the xpath query processor !&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item></channel></rss>