<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ernesto Cianciotta - Developer Notes]]></title><description><![CDATA[Ernesto Cianciotta - Developer Notes]]></description><link>https://devnotes.ernstc.net</link><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 12:04:19 GMT</lastBuildDate><atom:link href="https://devnotes.ernstc.net/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Solution Secrets v2.0 for Visual Studio]]></title><description><![CDATA[Sensitive data like passwords, connection strings, access keys, etc. should not be included in the source code that is committed in a shared repository. Secrets must not be deployed with the apps, too.
For developers that use Visual Studio, since man...]]></description><link>https://devnotes.ernstc.net/solution-secrets-v20-for-visual-studio</link><guid isPermaLink="true">https://devnotes.ernstc.net/solution-secrets-v20-for-visual-studio</guid><category><![CDATA[visual studio]]></category><category><![CDATA[extension]]></category><category><![CDATA[Security]]></category><category><![CDATA[Devops]]></category><category><![CDATA[agile]]></category><dc:creator><![CDATA[Ernesto Cianciotta]]></dc:creator><pubDate>Fri, 03 Mar 2023 00:47:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677793201965/ef45de55-1e32-42d8-b1c7-0a19617c516d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sensitive data like passwords, connection strings, access keys, etc. should not be included in the source code that is committed in a shared repository. Secrets must not be deployed with the apps, too.</p>
<p>For developers that use Visual Studio, since many years ago, <a target="_blank" href="https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-6.0&amp;tabs=windows#secret-manager"><strong>User Secrets Manager</strong></a> helps you to maintain your secrets out of the solutions folder.</p>
<p>Solution Secrets extension for Visual Studio leverage on User Secrets Manager feature and goes further enabling secure secrets synchronization between development workstations and operating systems.</p>
<h3 id="heading-why-this-extension"><strong>Why this extension?</strong></h3>
<p>When you change your development workstation, you usually clone your project code from a remote repository and then you would like to be up and running for developing and testing your code in a matter of seconds.</p>
<p>But if you have managed secrets with the tool User Secrets Manager you will not be immediately able to test your code because you will miss something very important on your new workstation: <strong>the secret settings</strong> that let your code work.</p>
<p>Using the <strong>Solution Secrets extension</strong> you can be immediately ready to start developing and testing on the new workstation or you can just sync secrets between different workstations.</p>
<h3 id="heading-how-does-it-work"><strong>How does it work?</strong></h3>
<p>This extension adds some new features to the secrets management for the entire solution. The capabilities of this extension are accessible through the <em>Solution Context Menu</em>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677795038928/de38ea39-6649-4036-9ca2-c713fe56274a.webp" alt class="image--center mx-auto" /></p>
<p>Selecting the menu item "Solution Secrets", will open the submenu from where you can use the main features for managing and synching secrets:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677795246600/78ac9941-425a-474b-8ae3-54f84ca44500.png" alt class="image--center mx-auto" /></p>
<p>Secrets are synchronized with a remote repository that can be:</p>
<ul>
<li><p>GitHub Gists</p>
</li>
<li><p>Azure Key Vault</p>
</li>
</ul>
<h3 id="heading-github-gists"><strong>GitHub Gists</strong></h3>
<p>A "Gist" is a snippet of code that can either be public or secret. Visual Studio Solution Secrets uses only <strong>secret</strong> Gists.</p>
<p>GitHub Gists is the default repository used by Visual Studio Solution Secrets for storing solutions secrets. Secrets are collected, <strong>encrypted</strong> and pushed on your GitHub account in a <strong>secret Gist</strong>, so that only you can see them. The encryption key is generated from a passphrase or a key file that you specify during the one-time initialization phase of the tool.</p>
<p>GitHub Gists fits very well for personal use.</p>
<p><img src="https://raw.githubusercontent.com/ernstc/VisualStudioSolutionSecrets/main/media/github-flow.png" alt class="image--center mx-auto" /></p>
<p>For configuring Visual Studio to use GitHub Gists, go to</p>
<p>Tools -&gt; Options -&gt; Solutions Secrets -&gt; GitHub Gists</p>
<p><img src="https://raw.githubusercontent.com/ernstc/SolutionSecretsExtension/main/Resources/screen-options-2022-2-2.png" alt class="image--center mx-auto" /></p>
<p>From here you can authorize access to your GitHub account and you can create the encryption key because even if your secrets are saved in a secret Gist, they can be accessed by someone that acknowledges the Gist URL, hence the secrets are encrypted before they are saved in a Gist.</p>
<h3 id="heading-azure-key-vault"><strong>Azure Key Vault</strong></h3>
<p>Azure Key Vault is a cloud service for securely storing and accessing secrets. Secrets are encrypted at rest and can be accessed only by authorized accounts. No one else can read their contents.</p>
<p>Since the secrets are encrypted at rest and communication with the key vault is secure because it is enforced as HTTPS / TLS 1.2, Visual Studio Solution Secrets does not encrypt the secrets by itself before sending them to the key vault, therefore it is not necessary to use the encryption key on the local machine.</p>
<p>This opens the scenario in which you can share the secrets of the solution with the development team. You just need to authorize the team with read or read/write access to the Azure Key Vault secrets, so that the team can pull secrets.</p>
<p>Azure Key Vault fits better for enterprise use and <strong>is the recommended way for sharing solution secrets within the team.</strong></p>
<p>You can read the Azure Key Vault documentation <a target="_blank" href="https://learn.microsoft.com/en-us/azure/key-vault/general/overview"><strong>here</strong></a></p>
<p><img src="https://raw.githubusercontent.com/ernstc/VisualStudioSolutionSecrets/main/media/azurekv-flow.png" alt class="image--center mx-auto" /></p>
<p>For using Azure Key Vault, you must specify the key vault URL from</p>
<p>Tool -&gt; Options -&gt; Solution Secrets -&gt; Azure Key Vault</p>
<p><img src="https://raw.githubusercontent.com/ernstc/SolutionSecretsExtension/main/Resources/screen-options-2022-2-3.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-default-secrets-repository"><strong>Default Secrets Repository</strong></h3>
<p>Now that you have seen how to configure the use of GitHub Gists and Azure Key Vault as remote secrets repository, you need to specify which one of them must be used by default. This can be done by going to</p>
<p>Tools -&gt; Options -&gt; Solutions Secrets</p>
<p><img src="https://raw.githubusercontent.com/ernstc/SolutionSecretsExtension/main/Resources/screen-options-2022-2-1.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-custom-settings-per-solution"><strong>Custom Settings per Solution</strong></h3>
<p>Solution Secrets v2.0 let you configure a custom remote repository for your solution. For customizing the synchronization settings go to</p>
<p>Solution Context Menu -&gt; Solution Secrets -&gt; Synchronization Settings...</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677796821908/dd4474fc-0f78-4ef4-b2f6-1a2b54517a97.png" alt class="image--center mx-auto" /></p>
<p>The configuration dialog will let you select the repository type GitHub Gist</p>
<p><img src="https://raw.githubusercontent.com/ernstc/SolutionSecretsExtension/main/Resources/screen-config-2022-2-1.png" alt class="image--center mx-auto" /></p>
<p>or Azure Key Vault</p>
<p><img src="https://raw.githubusercontent.com/ernstc/SolutionSecretsExtension/main/Resources/screen-config-2022-2-2.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-conclusions"><strong>Conclusions</strong></h3>
<p>Solution Secrets v2.0 for Visual Studio is available only for Visual Studio for Windows and is based on the same code base as the Visual Studio Solution Secrets project.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://devnotes.ernstc.net/visual-studio-solution-secrets-v2">https://devnotes.ernstc.net/visual-studio-solution-secrets-v2</a></div>
<p> </p>
<p>Sharing secrets between Windows, macOS and Linux is possible thanks to the .NET tool <strong><em>Visual Studio Solution Secrets</em></strong>.</p>
<p>The tool works from the command prompt and is cross-platform. Since it shares settings and format with this extension, is possible to push secrets from Windows using the Solution Secrets for Visual Studio and pull secrets from macOS or Linux using the CLI tool.</p>
<hr />
<h3 id="heading-download-from-the-visual-studio-marketplace"><strong>Download from the Visual Studio Marketplace</strong></h3>
<ul>
<li><p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=ErnestoCianciotta.SolutionSecrets2022"><strong>Solution Secrets 2022</strong></a> | for Visual Studio 2022+</p>
</li>
<li><p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=ErnestoCianciotta.SolutionSecrets2019"><strong>Solution Secrets 2019</strong></a> | for Visual Studio 2019</p>
</li>
</ul>
<hr />
<p>Solution Secrets extension is free and open source and its code is available on <a target="_blank" href="https://github.com/ernstc/SolutionSecretsExtension"><strong>GitHub</strong></a>.</p>
]]></content:encoded></item><item><title><![CDATA[Visual Studio Solution Secrets v2.0]]></title><description><![CDATA[As mentioned in my previous post about the first release of Visual Studio Solution Secrets, as a good practice in DevOps, you must not store secrets (sensitive data like passwords, connection strings, access keys, etc.) in your source code that is co...]]></description><link>https://devnotes.ernstc.net/visual-studio-solution-secrets-v2</link><guid isPermaLink="true">https://devnotes.ernstc.net/visual-studio-solution-secrets-v2</guid><category><![CDATA[Devops]]></category><category><![CDATA[secrets]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[C#]]></category><category><![CDATA[visual studio]]></category><dc:creator><![CDATA[Ernesto Cianciotta]]></dc:creator><pubDate>Wed, 09 Nov 2022 22:20:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1665414906381/XQbBKbYBE.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As mentioned in my <a target="_blank" href="https://devnotes.ernstc.net/visual-studio-solution-secrets">previous post</a> about the first release of Visual Studio Solution Secrets, as a good practice in DevOps, you must not store secrets (sensitive data like passwords, connection strings, access keys, etc.) in your source code that is committed in a shared repository and secrets must not be deployed with the apps.</p>
<p>This tool works with the <a target="_blank" href="https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-6.0&amp;tabs=windows#secret-manager">User Secrets Manager</a> for helping you to maintain your secrets out of the solutions folder and helps you to synchronize secrets on all your development machines.</p>
<p>While User Secrets Manager works at the project level, Visual Studio Solution Secrets works on solutions and manage secrets synchronization for every project of the solution.</p>
<p>This new release adds more flexibility and control on secrets synchronization and opens a new scenario where you can safely share and synchronize secrets within your development team.</p>
<p><strong>Visual Studio Solution Secrets</strong> synchronizes secret settings through the cloud quickly and securely.</p>
<p>The idea is to use a <strong>secure</strong> repository in the cloud for storing secret settings so that when you change the development machine, you don't have to copy any files from the old one.</p>
<p>Just install the tool, configure it and pull the solutions secrets on your new machine and you are ready to code.</p>
<p><strong><em>It's fast!</em></strong></p>
<p>Visual Studio Solution Secrets support two kinds of remote repositories:</p>
<ul>
<li><p>GitHub Gists</p>
</li>
<li><p>Azure Key Vault</p>
</li>
</ul>
<h2 id="heading-github-gists">GitHub Gists</h2>
<p>A "gist" is a snippet of code that can either be public or secret. Visual Studio Solution Secrets uses only <strong>secret</strong> gists.</p>
<p>GitHub Gists is the default repository used by Visual Studio Solution Secrets for storing solutions secrets. Secrets are collected, <strong>encrypted</strong> and pushed on your GitHub account in a <strong>secret gist</strong>, so that only you can see them. The encryption key is generated from a passphrase or a key file that you specify during the one-time initialization phase of the tool.</p>
<p>GitHub Gists fits very well for personal use.</p>
<p><img src="https://raw.githubusercontent.com/ernstc/VisualStudioSolutionSecrets/main/media/github-flow.png" alt="Concept" /></p>
<h2 id="heading-azure-key-vault">Azure Key Vault</h2>
<p>Azure Key Vault is a cloud service for securely storing and accessing secrets. Secrets are encrypted at rest and can be accessed only by authorized accounts. No one else can read their contents.</p>
<p>Since the secrets are encrypted at rest and communication with the key vault is secure because it is enforced as HTTPS / TLS 1.2, Visual Studio Solution Secrets does not encrypt the secrets by itself before sending them to the key vault, therefore it is not necessary to use the encryption key on the local machine.</p>
<p>This opens the scenario in which you can share the secrets of the solution with the development team. You just need to authorize the team with read or read/write access to the Azure Key Vault secrets, so that the team can pull secrets.</p>
<p>Azure Key Vault fits better for enterprise use and <strong>is the recommended way for sharing solution secrets within the team.</strong></p>
<p>You can read the Azure Key Vault documentation <a target="_blank" href="https://learn.microsoft.com/en-us/azure/key-vault/general/overview">here</a></p>
<p><img src="https://raw.githubusercontent.com/ernstc/VisualStudioSolutionSecrets/main/media/azurekv-flow.png" alt="Concept" /></p>
<h1 id="heading-how-to-install">How to install</h1>
<p>The tool is installed using the <strong>dotnet</strong> command line interface:</p>
<pre><code class="lang-shell">dotnet tool install --global vs-secrets
</code></pre>
<p>For upgrading to the latest version, use the command:</p>
<pre><code class="lang-shell">dotnet tool update --global vs-secrets
</code></pre>
<h1 id="heading-configure-the-encryption-key-and-authorizations">Configure the encryption key and authorizations</h1>
<p>In case you use GitHub Gists as secrets repository, after the tool is installed, you need to create the encryption key and then authorize the use of your GitHub Gists.</p>
<blockquote>
<p>The local encryption key is not necessary with Azure Key Vault.</p>
</blockquote>
<p>Create the encryption key from a passphrase:</p>
<pre><code class="lang-shell">vs-secrets init -p &lt;your-passphrase&gt;
</code></pre>
<p>Otherwise, you can create the encryption key from a key file with the command below:</p>
<pre><code class="lang-shell">vs-secrets init --keyfile &lt;file-path&gt;
</code></pre>
<p>In case the encryption key is compromised you can change it.</p>
<pre><code class="lang-shell">vs-secrets change-key --passphrase &lt;new-passphrase&gt;
vs-secrets change-key --keyfile &lt;file-path&gt;
</code></pre>
<p>When you change the encryption key with one of the above commands, any secret already encrypted on GitHub Gists is re-encrypted with the new key. In this way the compromised key becomes useless.</p>
<h1 id="heading-repository-configuration">Repository configuration</h1>
<p>As said, GitHub Gists is the default repository, but in case you need it, any solution can use a different repository for storing its secret settings.</p>
<blockquote>
<p>For example, you can set up your projects to use GitHub Gists and work projects to use Azure Key Vault.</p>
</blockquote>
<p>For configuring the solution to use GitHub Gists:</p>
<pre><code class="lang-shell">vs-secrets configure --repo github
</code></pre>
<p>For configuring the solution to use Azure Key Vault:</p>
<pre><code class="lang-shell">vs-secrets configure --repo azurekv --name &lt;vault-name | vault-uri&gt;
</code></pre>
<p>The <code>--name</code> option works only for Azure Key Vault repositories and can accept the key vault URI (ex: <code>https://my-keyvault.vault.azure.net</code>) or the resource name (ex: <code>my-keyvault</code>). In case you use the key vault resource name, it is then completed in its URI (ex: <code>my-keyvault</code> =&gt; <code>https://my-keyvault.vault.azure.net</code>).</p>
<p>For changing the default repository, use one of the commands below:</p>
<pre><code class="lang-shell">vs-secrets configure --default --repo github
vs-secrets configure --default --repo azurekv --name &lt;vault-name | vault-uri&gt;
</code></pre>
<p>Sometimes you need to check what is the default repository, or if the solution has a custom repository configuration.</p>
<p>The command <code>configure list</code> serves this purpose.</p>
<pre><code class="lang-shell">vs-secrets configure list [&lt;folder-path&gt;] [--all]
</code></pre>
<h1 id="heading-push-solution-secrets">Push solution secrets</h1>
<p>For pushing the secrets of the solution in the current folder:</p>
<pre><code class="lang-shell">vs-secrets push
</code></pre>
<p>For pushing the secrets of the solution in another folder:</p>
<pre><code class="lang-shell">vs-secrets push &lt;solution-path&gt;
</code></pre>
<p>For pushing the secrets of all the solutions in a folder tree:</p>
<pre><code class="lang-shell">vs-secrets push --all
vs-secrets push &lt;path&gt; --all
</code></pre>
<h1 id="heading-pull-solution-secrets">Pull solution secrets</h1>
<p>For pulling the secrets of the solution in the current folder:</p>
<pre><code class="lang-shell">vs-secrets pull
</code></pre>
<p>For pulling the secrets of the solution in another folder:</p>
<pre><code class="lang-shell">vs-secrets pull &lt;solution-path&gt;
</code></pre>
<p>For pulling the secrets of all the solutions in a folder tree:</p>
<pre><code class="lang-shell">vs-secrets pull --all
vs-secrets pull &lt;path&gt; --all
</code></pre>
<h1 id="heading-utility-commands">Utility commands</h1>
<h2 id="heading-search-for-solutions-that-use-secrets">Search for solutions that use secrets</h2>
<p>You can use the tool for just search solutions and projects that use secrets</p>
<pre><code class="lang-shell">vs-secrets search [&lt;solution-path&gt;] [--all]
</code></pre>
<h2 id="heading-checking-the-status">Checking the status</h2>
<p>With the <code>status</code> command you can check for the status of the tool. The command below checks if the encryption key has been defined and if the tool has been authorized to access GitHub Gists:</p>
<pre><code class="lang-shell">vs-secrets status
</code></pre>
<p>If the current folder contains a solution, the <code>status</code> command will show also the synchronization status for the secrets of the solutions.</p>
<p>Optionally you can check the synchronization status in another folder specifying the folder path or in an entire folder tree adding the <code>--all</code> parameter. Here are some examples:</p>
<pre><code class="lang-shell">vs-secrets status --all
vs-secrets status c:\projects\my-project-folder
vs-secrets status c:\projects --all
</code></pre>
<h2 id="heading-clear-secret-settings-from-the-local-machine">Clear secret settings from the local machine</h2>
<p>If there are secrets that you need to clear locally, the <code>clear</code> command erases the solution secrets from the local machine. It is equivalent to applying the command <code>dotnet user-secrets clear</code> to each project in the solution.</p>
<pre><code class="lang-shell">vs-secrets clear
vs-secrets clear .\my-solution.sln
</code></pre>
<h1 id="heading-configuration-files">Configuration files</h1>
<p>Visual Studio Solution Secrets stores its configuration files in the machine's user profile folder.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Platform</td><td>Path</td></tr>
</thead>
<tbody>
<tr>
<td>Windows</td><td><code>%APPDATA%\Visual Studio Solution Secrets</code></td></tr>
<tr>
<td>macSO</td><td><code>~/Library/Application Support/Visual Studio Solution Secrets</code></td></tr>
<tr>
<td>Linux</td><td><code>~/.config/Visual Studio Solution Secrets</code></td></tr>
</tbody>
</table>
</div><p>The files generated by the tool are listed below.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>File</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>cipher.json</td><td>Contains the encryption key</td></tr>
<tr>
<td>github.json</td><td>Contains the access token for managing user's GitHub Gists</td></tr>
<tr>
<td>configuration.json</td><td>Contains the settings for the repository to use by default and for each solution configured with the command <code>configure</code></td></tr>
</tbody>
</table>
</div><hr />
<p><em>Visual Studio Solution Secrets</em> is a free open source tool and its code is available on <a target="_blank" href="https://github.com/ernstc/VisualStudioSolutionSecrets">GitHub</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Yacc/Lex Tools, it's time to upgrade to 1.0.0]]></title><description><![CDATA[Yacc/Lex
With a very short introduction, Lex and Yacc are useful tools that you would use if you want to create a compiler, a transpiler or you just want to interpret a formal language. 

YaccLexTools is focused on C#. Other tools are available for o...]]></description><link>https://devnotes.ernstc.net/yacclextools</link><guid isPermaLink="true">https://devnotes.ernstc.net/yacclextools</guid><category><![CDATA[C#]]></category><category><![CDATA[compiler]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[visual studio]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Ernesto Cianciotta]]></dc:creator><pubDate>Tue, 03 May 2022 22:49:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1651531122515/WjbM8AWxo.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-yacclex">Yacc/Lex</h3>
<p>With a very short introduction, Lex and Yacc are useful tools that you would use if you want to create a compiler, a transpiler or you just want to interpret a formal language. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652438621611/-f7_B5fmI.png" alt="pic1.png" class="image--center mx-auto" /></p>
<p><strong>YaccLexTools</strong> is focused on C#. Other tools are available for other programming languages like C/C++, F#, Java, etc.</p>
<p><strong>YaccLexTools</strong> translantes Yacc and Lex files in C# code thanks to the tools <strong>GPPG</strong> and <strong>GPLEX</strong> and simplify the use of these tools in the C# projects building process.</p>
<h3 id="heading-time-to-update">Time to update</h3>
<p>Some years have passed since I have created the <strong>YaccLexTools</strong> package aimed to simplify the use of <strong>Yacc</strong> and <strong>Lex</strong> files in C# projets. Everything is evolved since then and now we have a lot of .NET everywhere! And it's cross platform, too.</p>
<p>So, it's a long time that this upgrade was needed and now is the time. YaccLexTools is having its long awaited upgrade for finally working with .Net Core, .NET and cross platform along with the .NET Framework with the same easy and automated project setup. With this upgrade the package has been promoted to the version <strong>1.0.0</strong> and it is retro compatible with the projects that have used the old version 0.2.x since now.</p>
<p>When you upgrade the package from the Nuget Package Manager, it will try to automatically upgrade the project settings to the new build model so that everything will work fine as before with some fix and improvements. </p>
<blockquote>
<p>For some reasons sometimes the update of the settings is not triggered. In these cases it is possible to upgrade the project settings from the Package Manager Console with this cmdlet</p>
<pre><code class="lang-powershell">PM&gt; Update-YaccLexToolsSettings
</code></pre>
</blockquote>
<h3 id="heading-major-changes">Major changes</h3>
<ul>
<li>The package works with .NET Framework 2.0+, .Net Core 3.1+, .NET 5+ and can be used on every platform supported by .NET.</li>
<li>The new build system is based on separate packages that provide the MSBuild targets and tooling for compiling <strong><em>.y</em></strong> and 
<strong><em>.lex</em></strong> files respectively with the tools <strong>GPPG</strong> and <strong>GPLEX</strong>.</li>
<li>Huge simplification of the project settings. No more <code>&lt;Target&gt;</code> definitions and package specific settings and metadata.</li>
<li>Common classes have been converted from <code>public</code> to <code>internal</code> for avoiding conflicts in case the project references more libraries and each of them have these classes defined.</li>
<li>Files generated by <strong>GPPG</strong> and <strong>GPLEX</strong> will not include anymore sentitive data like the machine name and the username captured at the moment of the generation of files. There is no reason to publish these information in a public repository.</li>
</ul>
<h3 id="heading-powershell-cmdlets-windows-only">Powershell cmdlets (Windows only)</h3>
<p>Cmdlets are still the same, but can be used only in Visual Studio for Windows.
For adding a new parser the command is</p>
<pre><code class="lang-powershell">PM&gt; Add-Parser MyLanguage Sample.NameSpace
</code></pre>
<p>The Calculator example can be added as usual with</p>
<pre><code class="lang-powershell">PM&gt; Add-CalculatorExample
</code></pre>
<p>Obsolete cmdlets for removing parser settings have been removed because there are no more settings to remove :)</p>
<p>If you need to remove a parser, just remove the files from the Solution Explorer and it's done.</p>
<h3 id="heading-dotnet-ylt-cross-platform">dotnet-ylt (Cross-platform)</h3>
<p>Since cmdlets are not working on macOS and Linux and they do not work with projects other than .NET Framework, it has been necessary to create a new tool that replaces the cmdlets, but has the same features.
The tool is cross-platform and can be installed with the command below</p>
<pre><code class="lang-powershell">dotnet tool install dotnet-ylt --global
</code></pre>
<p>Installing <code>dotnet-ylt</code> globally lets you install it just once and not for every project.</p>
<p>Adding a parser to a .NET console application is very easy. Open the terminal in the project folder and type the command</p>
<pre><code class="lang-powershell">dotnet ylt add-parser -p &lt;parserName&gt;
</code></pre>
<p>The parser name is given with the parameter <code>-p</code> or <code>--parser</code>.</p>
<p>For adding the calculator example:</p>
<pre><code class="lang-powershell">dotnet ylt add-calculator
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651536259056/h8KOP_x_Y.gif" alt="video-sample-1.gif" /></p>
<p>Both commands support the optional parameter <code>-n</code> or <code>--namespace</code> for creating the parser in the given namespace.</p>
<h3 id="heading-new-build-system">New build system</h3>
<p>After adding the calculator example to a .NET 6 console application and after building it, in the Solution Explorer the project looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651529796357/uOJTlAvII.png" alt="image.png" /></p>
<p>The files <code>GplexBuffers.cs</code> and <code>ShiftReduceParserCode.cs</code> are generated during the build process and no more when the parser is added to the project.</p>
<p>The project file becomes as below.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Project</span> <span class="hljs-attr">Sdk</span>=<span class="hljs-string">"Microsoft.NET.Sdk"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">OutputType</span>&gt;</span>Exe<span class="hljs-tag">&lt;/<span class="hljs-name">OutputType</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">TargetFramework</span>&gt;</span>net6.0<span class="hljs-tag">&lt;/<span class="hljs-name">TargetFramework</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ImplicitUsings</span>&gt;</span>enable<span class="hljs-tag">&lt;/<span class="hljs-name">ImplicitUsings</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Nullable</span>&gt;</span>enable<span class="hljs-tag">&lt;/<span class="hljs-name">Nullable</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span> <span class="hljs-attr">Label</span>=<span class="hljs-string">"Calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">YaccFile</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"Calculator\Calculator.Language.grammar.y"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">OutputFile</span>&gt;</span>Calculator\Calculator.Parser.Generated.cs<span class="hljs-tag">&lt;/<span class="hljs-name">OutputFile</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Arguments</span>&gt;</span>/gplex /nolines<span class="hljs-tag">&lt;/<span class="hljs-name">Arguments</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">YaccFile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">None</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"Calculator\Calculator.Parser.Generated.cs"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">AutoGen</span>&gt;</span>True<span class="hljs-tag">&lt;/<span class="hljs-name">AutoGen</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">DesignTime</span>&gt;</span>True<span class="hljs-tag">&lt;/<span class="hljs-name">DesignTime</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">DependentUpon</span>&gt;</span>Calculator.Language.grammar.y<span class="hljs-tag">&lt;/<span class="hljs-name">DependentUpon</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">None</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">LexFile</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"Calculator\Calculator.Language.analyzer.lex"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">OutputFile</span>&gt;</span>Calculator\Calculator.Scanner.Generated.cs<span class="hljs-tag">&lt;/<span class="hljs-name">OutputFile</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">LexFile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">None</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"Calculator\Calculator.Scanner.Generated.cs"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">AutoGen</span>&gt;</span>True<span class="hljs-tag">&lt;/<span class="hljs-name">AutoGen</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">DesignTime</span>&gt;</span>True<span class="hljs-tag">&lt;/<span class="hljs-name">DesignTime</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">DependentUpon</span>&gt;</span>Calculator.Language.analyzer.lex<span class="hljs-tag">&lt;/<span class="hljs-name">DependentUpon</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">None</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PackageReference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"YaccLexTools"</span> <span class="hljs-attr">Version</span>=<span class="hljs-string">"1.0.0"</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Project</span>&gt;</span>
</code></pre>
<p>It is much more compact in respect to the previous format. </p>
<p>The code below is even more compact and produces the same results. The code above has the advantage to hide the generated files as sub-nodes of their respective source files, but for the moment this works only in Visual Studio for Windows. Maybe a future relase of Visual Studio for Mac will implement this feature.
Below, the arguments for the <strong>YaccFile</strong> are omitted because they have the same default value: <code>/gplex /nolines</code>.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Project</span> <span class="hljs-attr">Sdk</span>=<span class="hljs-string">"Microsoft.NET.Sdk"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">OutputType</span>&gt;</span>Exe<span class="hljs-tag">&lt;/<span class="hljs-name">OutputType</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">TargetFramework</span>&gt;</span>net6.0<span class="hljs-tag">&lt;/<span class="hljs-name">TargetFramework</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ImplicitUsings</span>&gt;</span>enable<span class="hljs-tag">&lt;/<span class="hljs-name">ImplicitUsings</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Nullable</span>&gt;</span>enable<span class="hljs-tag">&lt;/<span class="hljs-name">Nullable</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span> <span class="hljs-attr">Label</span>=<span class="hljs-string">"Calculator"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">YaccFile</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"Calculator\Calculator.Language.grammar.y"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">OutputFile</span>&gt;</span>Calculator\Calculator.Parser.Generated.cs<span class="hljs-tag">&lt;/<span class="hljs-name">OutputFile</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">YaccFile</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">LexFile</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"Calculator\Calculator.Language.analyzer.lex"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">OutputFile</span>&gt;</span>Calculator\Calculator.Scanner.Generated.cs<span class="hljs-tag">&lt;/<span class="hljs-name">OutputFile</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">LexFile</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">PackageReference</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"YaccLexTools"</span> <span class="hljs-attr">Version</span>=<span class="hljs-string">"1.0.0"</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Project</span>&gt;</span>
</code></pre>
<p>With the hope that these updates are useful to those who are already using the package and to all of those who will use it, see you in the next one!</p>
<p><em>ernstc</em></p>
<h2 id="heading-old-posts">Old posts</h2>
<ul>
<li><a target="_blank" href="https://devnotes.ernstc.net/languages-and-translators-with-visual-studio">Languages and Translators with Visual Studio</a></li>
<li><a target="_blank" href="https://devnotes.ernstc.net/yacclex-tools-v02">Yacc/Lex Tools v0.2</a></li>
</ul>
<h2 id="heading-references">References</h2>
<ul>
<li>Yacc/Lex Tools project repository: https://github.com/ernstc/YaccLexTools</li>
<li>GPPG original repository: https://github.com/k-john-gough/gppg</li>
<li>GPLEX original repository: https://github.com/k-john-gough/gplex</li>
<li>YACC: https://en.wikipedia.org/wiki/Yacc</li>
<li>LEX: https://en.wikipedia.org/wiki/Lex_(software)</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Solution Secrets extension for Visual Studio]]></title><description><![CDATA[As already mentioned in my previous post, as a good practices, secrets (sensitive data like passwords, connection strings, access keys, etc.) must not be committed with your code in any case and must not be deployed with the apps. That's why we must ...]]></description><link>https://devnotes.ernstc.net/solution-secrets-extension-for-visual-studio</link><guid isPermaLink="true">https://devnotes.ernstc.net/solution-secrets-extension-for-visual-studio</guid><category><![CDATA[visual studio]]></category><category><![CDATA[extension]]></category><category><![CDATA[C#]]></category><category><![CDATA[Security]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Ernesto Cianciotta]]></dc:creator><pubDate>Tue, 03 May 2022 10:35:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1651574030519/g6ysWaLof.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As already mentioned in my previous post, as a good practices, secrets (sensitive data like passwords, connection strings, access keys, etc.) must not be committed with your code in any case and must not be deployed with the apps. That's why we must use the <strong>User Secrets Manager</strong> feature in Visual Studio that let us store secrets out of the solution folder. The User Secrets Manager hides implementation details, but essentially it stores secrets in files located in the workstation's user profile folder.</p>
<p>This extension adds some new features to the secrets management for the entire solution. The capabilities of this extension are accessible trough the <em>Solution Context Menu</em>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651572340508/X9NtEulC-.png" alt="image.png" /></p>
<h3 id="heading-features">Features</h3>
<ul>
<li>Solution secrets synchronization across user's development workstations.</li>
<li>Deletion of user secrets for when you need to dismiss secrets from a development workstation.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651572387410/oPuNs25rv.png" alt="image.png" /></p>
<h3 id="heading-why-this-extension">Why this extension?</h3>
<p>When you change your development workstation usually you clone your project code from a remote repository and then you would like to be up and running for developing and testing your code in a matter of seconds.</p>
<p>But if you have managed secrets with the tool User Secrets Manager you will not be immediatly able to test your code because you will miss something very important on your new workstation: <strong>the secret settings</strong> that let your code work.</p>
<p>Using the <strong>Solution Secrets extension</strong> you can be immediatley ready to start developing and testing on the new workstation or you can just sync secrets between different workstations.</p>
<h3 id="heading-secrets-synchronization">Secrets synchronization</h3>
<p>The synchronization is implemented through a cloud repository that in this case is GitHub Gist. The secrets are encrypted and pushed on GitHub in a secret Gist, so that only you can see them.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651572476340/QXfVtHZxQ.png" alt="image.png" /></p>
<p>The encryption key is generated from a passphrase or a key file. Once you change the development workstation, you don't have to copy any file from the old one. Just install the extension, recreate the encryption key with your passphrase or your key file, authorize access to GitHub Gists and you are ready.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651572503537/ex5QXe_iU.png" alt="image.png" /></p>
<h3 id="heading-cross-platform-secrets-sharing">Cross platform secrets sharing</h3>
<p>Sharing secrets between Windows, macOS and Linux is possible thanks to the .NET tool <strong><em>Visual Studio Solution Secrets</em></strong>. The tool is cross platform and since it shares settings and format with this extension, is possible to push secrets from Windows using the Solution Secrets extension and pulling the secrets from macOS or Linux using the CLI tool.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://devnotes.ernstc.net/visual-studio-solution-secrets">https://devnotes.ernstc.net/visual-studio-solution-secrets</a></div>
<hr />
<h3 id="heading-download-from-the-visual-studio-marketplace">Download from the Visual Studio Marketplace</h3>
<ul>
<li><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=ErnestoCianciotta.SolutionSecrets2022">Solution Secrets 2022</a> | for Visual Studio 2022+ </li>
<li><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=ErnestoCianciotta.SolutionSecrets2019">Solution Secrets 2019</a> | for Visual Studio 2019 </li>
</ul>
<hr />
<p>Solution Secrets extension is free and open source and its code is available on <a target="_blank" href="https://github.com/ernstc/SolutionSecretsExtension">GitHub</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Visual Studio Solution Secrets]]></title><description><![CDATA[A NEW VERSION IS AVAILABLE !!!
Visual Studio Solution Secrets has been updated to version 2.0. Click here to read about the news.

If you are good in DevOps practices, you should know that secrets (sensitive data like passwords, connection strings, a...]]></description><link>https://devnotes.ernstc.net/visual-studio-solution-secrets</link><guid isPermaLink="true">https://devnotes.ernstc.net/visual-studio-solution-secrets</guid><category><![CDATA[visual studio]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[asp.net core]]></category><category><![CDATA[tools]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Ernesto Cianciotta]]></dc:creator><pubDate>Sat, 05 Feb 2022 15:45:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1644075540889/lNEm352Hz.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>A NEW VERSION IS AVAILABLE !!!</strong></p>
<p>Visual Studio Solution Secrets has been updated to version 2.0. <a target="_blank" href="https://devnotes.ernstc.net/visual-studio-solution-secrets-v2">Click here</a> to read about the news.</p>
</blockquote>
<p>If you are good in DevOps practices, you should know that secrets (sensitive data like passwords, connection strings, access keys, etc.) must not be committed with your code in any case and must not be deployed with the apps.</p>
<p>Fortunately Visual Studio and .Net help us in separating secrets from our code with the <strong><em>User Secrets Manager</em></strong> tool that let us store secrets out of the solution folder. The User Secrets Manager hides implementation details, but essentially it stores secrets in files located in the machine's user profile folder.</p>
<p>You can find the <strong>User Secrets Manager</strong> documentation <a target="_blank" href="https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-6.0&amp;tabs=windows#secret-manager">here</a>.</p>
<h2 id="heading-the-problem">The Problem</h2>
<p>When you change your development machine usually you clone your project code from a remote repository and then you would like to be up and running for developing and testing you code in a matter of seconds.</p>
<p>But if you have managed secrets with the tool User Secrets Manager you will not be immediatly able to test your code because you will miss something very important on your new machine: <strong>the secret settings</strong> that let your code work.</p>
<h2 id="heading-the-solution">The Solution</h2>
<p>For being immediatley ready to start developing and testing on the new development machine you have three choices.</p>
<ol>
<li><p>Manually copy secret files from the old machine to the new one, if you still have access to the old machine.</p>
</li>
<li><p>Recreate the secret settings on your new machine for each project of the solution, but this can be tedious because you have to recover passwords, keys, etc. from different resources and it can be time consuming.</p>
</li>
<li><p>Use <strong>Visual Studio Solution Secrets</strong> tool for synchronizing secret settings through the cloud in a quick and secure way.</p>
</li>
</ol>
<p>The idea behind the Visual Studio Solution Secrets tool is to use GitHub Gists as the repository for your secrets. The tool collects all the secret settings used in the solution, encrypts and pushes them on GitHub in a secret Gist, so that only you can see them. The encryption key is generated from a passphrase or a key file that you specify during the one time initialization phase of the tool.</p>
<p>Once you change the development machine, you don't have to copy any file from the old one. Just install the tool, recreate the encryption key with your passphrase or your key file, authorize the tool on GitHub and you are ready.</p>
<p><img src="https://raw.githubusercontent.com/ernstc/VisualStudioSolutionSecrets/main/Concept.png" alt="Concept" /></p>
<h2 id="heading-how-to-use-it">How to use it</h2>
<p>For installing Visual Studio Solution Secrets tool, use the command below:</p>
<pre><code class="lang-plaintext">dotnet tool install --global vs-secrets
</code></pre>
<p>After you have installed the tool, you need to create the encryption key and then authorize it to use yours GitHub Gists. You can do this with the command:</p>
<pre><code class="lang-plaintext">vs-secrets init -p &lt;your-passphrase&gt;
</code></pre>
<p>For creating the encryption key, by default the tool will ask you for a passphrase. If you prefer, you can use a key file as the input to the encryption key generation algorithm with the command below:</p>
<pre><code class="lang-plaintext">vs-secrets init --keyfile &lt;file-path&gt;
</code></pre>
<h3 id="heading-push-solution-secrets">Push solution secrets</h3>
<p>For pushing the secrets of the solution in current folder:</p>
<pre><code class="lang-plaintext">vs-secrets push
</code></pre>
<p>For pushing the secrets of the solution in another folder:</p>
<pre><code class="lang-plaintext">vs-secrets push --path &lt;solution-path&gt;
</code></pre>
<p>For pushing the secrets of all the solutions in a folder tree:</p>
<pre><code class="lang-plaintext">vs-secrets push --all
</code></pre>
<p>or</p>
<pre><code class="lang-plaintext">vs-secrets push --path &lt;path&gt; --all
</code></pre>
<h3 id="heading-pull-solution-secrets">Pull solution secrets</h3>
<p>For pulling the secrets of the solution in current folder:</p>
<pre><code class="lang-plaintext">vs-secrets pull
</code></pre>
<p>For pulling the secrets of the solution in another folder:</p>
<pre><code class="lang-plaintext">vs-secrets pull --path &lt;solution-path&gt;
</code></pre>
<p>For pulling the secrets of all the solutions in a folder tree:</p>
<pre><code class="lang-plaintext">vs-secrets pull --all
</code></pre>
<p>or</p>
<pre><code class="lang-plaintext">vs-secrets pull --path &lt;path&gt; --all
</code></pre>
<h3 id="heading-searching-for-solution-secrets">Searching for solution secrets</h3>
<p>You can also use the tool for just searching solutions and projects that use secrets</p>
<pre><code class="lang-plaintext">vs-secrets search
</code></pre>
<pre><code class="lang-plaintext">vs-secrets search --path &lt;solution-path&gt;
</code></pre>
<pre><code class="lang-plaintext">vs-secrets search --all
</code></pre>
<pre><code class="lang-plaintext">vs-secrets search --path &lt;path&gt; --all
</code></pre>
<h2 id="heading-visual-studio-solution-secrets-files">Visual Studio Solution Secrets files</h2>
<p>Visual Studio Solution Secrets tool stores its files in the machine's user profile folder.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Platform</td><td>Path</td></tr>
</thead>
<tbody>
<tr>
<td>Windows</td><td><code>%APPDATA%\Visual Studio Solution Secrets</code></td></tr>
<tr>
<td>macSO</td><td><code>~/.visualstudiosolutionsecrets</code></td></tr>
<tr>
<td>Linux</td><td><code>~/.visualstudiosolutionsecrets</code></td></tr>
</tbody>
</table>
</div><p>Below are listed the files generated by the tool.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>File</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>cipher.json</td><td>Contains the encryption key</td></tr>
<tr>
<td>github.json</td><td>Contains the access token for managing user's GitHub Gists</td></tr>
</tbody>
</table>
</div><hr />
<p><em>Visual Studio Solution Secrets</em> is a free open source tool and its code is available on <a target="_blank" href="https://github.com/ernstc/VisualStudioSolutionSecrets">GitHub</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Yacc/Lex Tools v0.2]]></title><description><![CDATA[In my previous post "Languages and Translators with Visual Studio" I explained how to add a parser to your C# project using the tools GPPG and GPLEX to compile the files YACC and LEX to generate respectively the parser and its scanner.
In the previou...]]></description><link>https://devnotes.ernstc.net/yacclex-tools-v02</link><guid isPermaLink="true">https://devnotes.ernstc.net/yacclex-tools-v02</guid><category><![CDATA[C#]]></category><category><![CDATA[software development]]></category><category><![CDATA[visual studio]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[compiler]]></category><dc:creator><![CDATA[Ernesto Cianciotta]]></dc:creator><pubDate>Mon, 12 Aug 2013 20:45:59 GMT</pubDate><content:encoded><![CDATA[<p>In my previous post "<a target="_blank" href="https://devnotes.ernstc.net/languages-and-translators-with-visual-studio">Languages and Translators with Visual Studio</a>" I explained how to add a parser to your C# project using the tools <strong>GPPG </strong>and <strong>GPLEX </strong>to compile the files YACC and LEX to generate respectively the parser and its scanner.</p>
<p>In the previous post I have illustrated how to modify the project file by hand after installing the NuGet package <strong>YaccLexTools</strong>.</p>
<p>The package "<strong>YaccLexTools</strong>" has been updated and from version 0.2 i<strong>s no longer necessary to manually edit the XML tags of the project file</strong>. With this new version you can manage everything thanks to new PowerShell Cmd-Let from the "Package Manager Console" in Visual Studio.</p>
<p>For example, to add a parser to your project you will just need to run the command:</p>
<pre><code class="lang-powershell">PM&gt; Add-Parser MyLanguage
</code></pre>
<p>This command will create all files and settings required to compile YACC and LEX files.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651523920508/pdmZ1m6Xi.png" alt="image.png" /></p>
<p>If you want to specify a custom namespace you can run the following command whose second parameter is the namespace:</p>
<pre><code class="lang-powershell">PM&gt; Add-Parser MyLanguage Sample.NameSpace
</code></pre>
<p>To remove the settings for a parser created in the project you can use the following command:</p>
<pre><code class="lang-powershell">PM&gt; Remove-Parser MyLanguage
</code></pre>
<p>This command will not remove files, but only the settings for the specified parser. The files must be removed manually.</p>
<p>Finally, included in the package is a working example to interpret calculus expressions. To add it to the project, just use the command</p>
<pre><code class="lang-powershell"> PM&gt; Add-CalculatorExample
</code></pre>
<h2 id="heading-conclusions">Conclusions</h2>
<p>In this post were shown the simplifications implemented in the new version of the NuGet package <a target="_blank" href="https://www.nuget.org/packages/YaccLexTools">YaccLexTools</a> for the management of parsers within C# projects.</p>
<p>With the hope that these updates are useful to those who already use the package and all of those who will use it,</p>
<p><em>ernstc</em></p>
<h2 id="heading-references">References</h2>
<ul>
<li>GPPG original repository: https://github.com/k-john-gough/gppg</li>
<li>GPLEX original repository: https://github.com/k-john-gough/gplex</li>
<li>Yacc/Lex Tools nuget package: https://www.nuget.org/packages/YaccLexTools</li>
<li>Yacc/Lex Tools project repository: https://github.com/ernstc/YaccLexTools</li>
</ul>
<hr />
<p>This post has been republished from my previous blog (https://ecianciotta-en.blogspot.com/2013/08/yacclex-tools-v02.html).</p>
]]></content:encoded></item><item><title><![CDATA[Languages and Translators with Visual Studio]]></title><description><![CDATA[Warning! the NuGet package YaccLexTools has been updated since this post has been published. Read the post about the updates and the simplifications introduced: Yacc/Lex Tools v0.2

Sometimes it's nice to make sense of what you have studied in the pa...]]></description><link>https://devnotes.ernstc.net/languages-and-translators-with-visual-studio</link><guid isPermaLink="true">https://devnotes.ernstc.net/languages-and-translators-with-visual-studio</guid><category><![CDATA[C#]]></category><category><![CDATA[software development]]></category><category><![CDATA[visual studio]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[compiler]]></category><dc:creator><![CDATA[Ernesto Cianciotta]]></dc:creator><pubDate>Sat, 25 May 2013 22:00:00 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p><strong>Warning!</strong> the NuGet package <strong>YaccLexTools </strong>has been updated since this post has been published. Read the post about the updates and the simplifications introduced: <a target="_blank" href="https://devnotes.ernstc.net/yacclex-tools-v02"><strong>Yacc/Lex Tools v0.2</strong></a></p>
</blockquote>
<p>Sometimes it's nice to make sense of what you have studied in the past and this is the case of Languages and Translators.</p>
<p>I had in mind to enhance the function of quick search of a web application. Normally this quick search takes all the words and makes a Full-Text Search on all data.
So I said to myself, why not to give the option for users to enter filter expressions in a simple way?</p>
<p>Such as:</p>
<pre><code><span class="hljs-attr">year:</span> <span class="hljs-number">2000</span>
<span class="hljs-attr">year:</span> <span class="hljs-string">&gt;=</span> <span class="hljs-number">2000</span>
<span class="hljs-attr">year: 2000..2010 month:</span> <span class="hljs-string">&gt;</span> <span class="hljs-number">6</span>
</code></pre><p>Said and done! What we need here are a parser and a syntax analyzer.</p>
<p>As of today it is not very practical to manually create these tools, but we make use of automatic generators. The ones that I have taken into consideration are <strong>GPPG </strong>to generate the parser and <strong>GPLEX </strong>to generate the sintax analyzer, both created by QUT, Australian university.
<strong>GPPG </strong>generates a parser in C# language from a formal description of the grammar written in YACC and <strong>GPLEX </strong>generates a syntax analyzer (scanner) from the description of the language syntax in LEX.</p>
<p>Given that the reader already has the knowledge about how to write a YACC grammar and a scanner in LEX, the goal of this post is to guide the configuration of the project in Visual Studio to generate the parser and the scanner during the build of the the project itself.</p>
<p>First of all you must add the NuGet package "<a target="_blank" href="https://www.nuget.org/packages/YaccLexTools/">YACC/LEX tools</a>" with the command</p>
<pre><code>PM<span class="hljs-operator">&gt;</span> Install<span class="hljs-operator">-</span>Package YaccLexTools
</code></pre><p>Now suppose you want to create the parser for search queries as described above.</p>
<ol>
<li>Click with the right button on the project and select "Unload Project"</li>
<li>Click with the right button on the project and select "Edit"</li>
<li><p>Add the following snippet at the end of the file, just before the closing tag <code>&lt;/Project&gt;</code> and save.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Target</span> <span class="hljs-attr">Name</span>=<span class="hljs-string">"BeforeBuild"</span> <span class="hljs-attr">DependsOnTargets</span>=<span class="hljs-string">"BuildGen"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Target</span>&gt;</span>
<span class="hljs-comment">&lt;!-- Build generated file target --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Target</span> <span class="hljs-attr">Name</span>=<span class="hljs-string">"BuildGen"</span> <span class="hljs-attr">DependsOnTargets</span>=<span class="hljs-string">"GenerateMyLanguageParser"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Target</span>&gt;</span>
<span class="hljs-comment">&lt;!-- Parser items --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">PropertyGroup</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">ToolsDir</span>&gt;</span>$(SolutionDir)packages\YaccLexTools.0.1.2\tools\<span class="hljs-tag">&lt;/<span class="hljs-name">ToolsDir</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">GplexTool</span>&gt;</span>"$(ToolsDir)gplex.exe"<span class="hljs-tag">&lt;/<span class="hljs-name">GplexTool</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">GppgTool</span>&gt;</span>"$(ToolsDir)gppg.exe"<span class="hljs-tag">&lt;/<span class="hljs-name">GppgTool</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">MyLanguageParser</span>&gt;</span>$(ProjectDir)MyLanguage<span class="hljs-tag">&lt;/<span class="hljs-name">MyLanguageParser</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">PropertyGroup</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">None</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"MyLanguage.parser"</span> /&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"MyLanguage.Parser.cs"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">DependentUpon</span>&gt;</span>MyLanguage.parser<span class="hljs-tag">&lt;/<span class="hljs-name">DependentUpon</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"MyLanguage.Scanner.cs"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">DependentUpon</span>&gt;</span>MyLanguage.parser<span class="hljs-tag">&lt;/<span class="hljs-name">DependentUpon</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">None</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"MyLanguage.Language.grammar.y"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">DependentUpon</span>&gt;</span>MyLanguage.parser<span class="hljs-tag">&lt;/<span class="hljs-name">DependentUpon</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">None</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"MyLanguage.Parser.Generated.cs"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">AutoGen</span>&gt;</span>True<span class="hljs-tag">&lt;/<span class="hljs-name">AutoGen</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">DesignTime</span>&gt;</span>True<span class="hljs-tag">&lt;/<span class="hljs-name">DesignTime</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">DependentUpon</span>&gt;</span>MyLanguage.Language.grammar.y<span class="hljs-tag">&lt;/<span class="hljs-name">DependentUpon</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">None</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"MyLanguage.Language.analyzer.lex"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">DependentUpon</span>&gt;</span>MyLanguage.parser<span class="hljs-tag">&lt;/<span class="hljs-name">DependentUpon</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">None</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">Compile</span> <span class="hljs-attr">Include</span>=<span class="hljs-string">"MyLanguage.Scanner.Generated.cs"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">AutoGen</span>&gt;</span>True<span class="hljs-tag">&lt;/<span class="hljs-name">AutoGen</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">DesignTime</span>&gt;</span>True<span class="hljs-tag">&lt;/<span class="hljs-name">DesignTime</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">DependentUpon</span>&gt;</span>MyLanguage.Language.analyzer.lex<span class="hljs-tag">&lt;/<span class="hljs-name">DependentUpon</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">Compile</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">ItemGroup</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">ItemGroup</span> /&gt;</span>
<span class="hljs-comment">&lt;!--  Generate the parsers --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Target</span> <span class="hljs-attr">Name</span>=<span class="hljs-string">"GenerateMyLanguageParser"</span>
       <span class="hljs-attr">Inputs</span>=<span class="hljs-string">"$(MyLanguageParser).Language.analyzer.lex;$(MyLanguageParser).Language.grammar.y"</span> 
       <span class="hljs-attr">Outputs</span>=<span class="hljs-string">"$(MyLanguageParser).Scanner.Generated.cs;$(MyLanguageParser).Parser.Generated.cs"</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">Message</span> <span class="hljs-attr">Text</span>=<span class="hljs-string">"Generating scanner for $(MyLanguageParser) ..."</span> /&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">Exec</span> <span class="hljs-attr">Command</span>=<span class="hljs-string">"$(GplexTool) <span class="hljs-symbol">&amp;quot;</span>/out:$(MyLanguageParser).Scanner.Generated.cs<span class="hljs-symbol">&amp;quot;</span> <span class="hljs-symbol">&amp;quot;</span>$(MyLanguageParser).Language.analyzer.lex<span class="hljs-symbol">&amp;quot;</span>"</span> 
       <span class="hljs-attr">WorkingDirectory</span>=<span class="hljs-string">"$(ProjectDir)"</span> 
       <span class="hljs-attr">Outputs</span>=<span class="hljs-string">"$(GenDir)Scanner.cs"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">Output</span> <span class="hljs-attr">TaskParameter</span>=<span class="hljs-string">"Outputs"</span> <span class="hljs-attr">ItemName</span>=<span class="hljs-string">"MyLanguageScanner"</span> /&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">Exec</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">Message</span> <span class="hljs-attr">Text</span>=<span class="hljs-string">"Generating parser for $(MyLanguageParser) ..."</span> /&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">Exec</span> <span class="hljs-attr">Command</span>=<span class="hljs-string">"$(GppgTool) /no-lines /gplex <span class="hljs-symbol">&amp;quot;</span>$(MyLanguageParser).Language.grammar.y<span class="hljs-symbol">&amp;quot;</span> &gt; <span class="hljs-symbol">&amp;quot;</span>$(MyLanguageParser).Parser.Generated.cs<span class="hljs-symbol">&amp;quot;</span>"</span> 
       <span class="hljs-attr">WorkingDirectory</span>=<span class="hljs-string">"$(ProjectDir)"</span> 
       <span class="hljs-attr">Outputs</span>=<span class="hljs-string">"$(MyLanguageParser).Parser.Generated.cs"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">Output</span> <span class="hljs-attr">TaskParameter</span>=<span class="hljs-string">"Outputs"</span> <span class="hljs-attr">ItemName</span>=<span class="hljs-string">"MyLanguageParser"</span> /&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">Exec</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Target</span>&gt;</span>
</code></pre>
</li>
<li><p>Copy the files from folder "packages\YaccLexTools.0.1.2\src" into the folder of the project.</p>
</li>
<li>Click with the right button on the project and select "Reload Project".</li>
</ol>
<p>When the project is reloaded, this is what you will have in the Solution Explorer of Visual Studio:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651517630962/vQk5UMdWI.png" alt="image.png" /></p>
<p>The figure above shows all the files that make up the parser.</p>
<ul>
<li><strong>MyLanguage.parser</strong> is just a place holder and does not contain anything interesting. It only serves to group into a single node all the files of the parser.</li>
<li><strong>MyLanguage.Language.analyzer.lex</strong> is the LEX source for syntax analyzer.</li>
<li><strong>MyLanguage.Scanner.Generated.cs</strong> is the C# file generated from the LEX file "MyLanguage.Language.analyzer.lex".</li>
<li><strong>MyLanguage.Language.grammar.y</strong> is the YACC source for the parser. It contains the grammar description.</li>
<li><strong>MyLanguage.Parser.Generated.cs</strong> is the C# file generated from the YACC file "MyLanguage.Language.grammar.y".</li>
</ul>
<p>Finally, the files MyLanguage.Parser.cs and MyLanguage.Scanner.cs are C# partial classes that extend respectively the parser and the scanner generated by YACC and LEX files to add the methods called in the actions for rules in grammar and syntax.</p>
<h2 id="heading-end-notes">End Notes.</h2>
<p>For this work has been very useful to see the Open Source code for projects such as IronRuby compiler. If I could not look into the code of IronRuby I would never do such a thing. What I mean is that you can learn a lot, but also find inspiration, comparing with others ;)</p>
<h2 id="heading-references">References</h2>
<ul>
<li>GPPG original repository: https://github.com/k-john-gough/gppg</li>
<li>GPLEX original repository: https://github.com/k-john-gough/gplex</li>
<li>Yacc/Lex Tools nuget package: https://www.nuget.org/packages/YaccLexTools</li>
<li>Yacc/Lex Tools project repository: https://github.com/ernstc/YaccLexTools</li>
</ul>
<hr />
<p>This post has been republished from my previous blog (https://ecianciotta-en.blogspot.com/2013/05/languages-and-translators-with-visual.html).</p>
]]></content:encoded></item></channel></rss>