rubicon-oss / LicenseHeaderManager

Manage license headers for your source code files in Visual Studio

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Location for settings under Tools/Options/License Header Manager/Languages menu in Visual Studio

NJ261 opened this issue · comments

I have added the extensions for other languages (Tools/Options/License Header Manager/Languages menu in Visual Studio) and I want to export this settings so that it can be used later for new environment. Can you please tell me where to look? Thanks!

The settings are saved here: C:\Users\Administrator\AppData\Local\Microsoft\VisualStudio{version}\Settings\CurrentSettings.vssettings

The contents are saved like this:

  <Category name="License Header Manager_Languages" Category="{d1b5984c-1693-4f26-891e-0ba3bf5760b4}" Package="{4c570677-8476-4d33-bd0c-da36c89287c8}" RegisteredName="License Header Manager_Languages" PackageName="LicenseHeadersPackage">
    <PropertyValue name="LanguagesSerialized">&lt;Languages&gt;
  &lt;Language LineComment="//" BeginComment="/*" EndComment="*/" BeginRegion="#region" EndRegion="#endregion" SkipExpression=""&gt;
    &lt;Extensions&gt;
      &lt;Extension&gt;.cs&lt;/Extension&gt;
    &lt;/Extensions&gt;
  &lt;/Language&gt;
  &lt;Language LineComment="'" BeginComment="" EndComment="" BeginRegion="#Region" EndRegion="#End Region" SkipExpression=""&gt;
    &lt;Extensions&gt;
      &lt;Extension&gt;.vb&lt;/Extension&gt;
    &lt;/Extensions&gt;
  &lt;/Language&gt;
  &lt;/Languages&gt;
  </PropertyValue>
 </Category>
</UserSettings>

Can anyone tell me how can I add the new Language with powershell? So far, I'm using this code.

$file = "C:\Users\TempUser\Downloads\CurrentSettings.xml"

[xml]$xml = Get-Content $file

$extensions = @(
    ,@( @("#", "<#", "#>", ""), @(".ps1", ".psm1"))
    ,@( @("//", "/*", "*/", ""), @(".js", ".ts")))
$AttributeNames = @("LineComment", "BeginComment", "EndComment", "SkipExpression")

$xml.UserSettings.Category.PropertyValue | Where-Object { $_.name -eq "LanguagesSerialized" } | %{ 

    foreach ($elements in $extensions) {
        $lang = $xml.CreateElement("Language")   

        for ($j=0; $j -lt $AttributeNames.length; $j++) {
            $lang.SetAttribute($AttributeNames[$j], $elements[0][$j]) 
        }

        $extsElement = $lang.AppendChild($xml.CreateElement("Extensions"))
            
        foreach($ext in $elements[1]){
            $extElement = $extsElement.AppendChild($xml.CreateElement("Extension"))
            $extElement.AppendChild($xml.CreateTextNode($ext))
        }

        $_.AppendChild($lang)
    }
      
}

$xml.Save($file)

Expected Result:

&lt;Language LineComment="#" BeginComment="@*" EndComment="*@" BeginRegion="" EndRegion="" SkipExpression=""&gt;
    &lt;Extensions&gt;
      &lt;Extension&gt;.ps1&lt;/Extension&gt;
      &lt;Extension&gt;.psm1&lt;/Extension&gt;
    &lt;/Extensions&gt;
  &lt;/Language&gt;

Hi @NJ261,

I am going to give you an relatively lengthy answer (thus the longer response time - sorry), hoping to give you context to the whole situation.

First of all, the persistence of the settings you can access via the Visual Studio option pages are stored via Microsoft's default implementation of DialogPage, which is reading from and writing to the registry (from VS 2017 onward, there is a private registry to provide better isolation, e.g. for side-by-side installations) - in order to read up more about this, see for example here. As mentioned in the article, this change from 2015 is transparent by means of registry redirection. However, in the following, I am assuming you are using a VS version of at least 2017.

So, in order to have our internal data structures stored to the registry by MS's DialogPage, we have custom TypeConverters, e.g.

class LanguageConverter : XmlTypeConverter<IEnumerable<Language>>
.

If you want to access those values in the registry, close all VS instances, open regedit and select the HKEY_LOCAL_MACHINE node. In the File -> Load hive ... action, locate the privateregistry.bin file at (in my case) C:\Users\raffael.foidl\AppData\Local\Microsoft\VisualStudio\16.0_1fe5dfb5\privateregistry.bin and give it a (temporary) name of your choice, e.g. VSPrivateRegistry. This process is also explained by Microsoft here.

Iin my case, there now is a key Computer\HKEY_LOCAL_MACHINE\VSPrivateRegistry\Software\Microsoft\VisualStudio\16.0_1fe5dfb5\ApplicationPrivateSettings\LicenseHeaderManager\Options with its subkeys representing the serialized LHM configuration. You should be able to export this key as a .reg file and import it elsewhere.

image

You can make changes here (be sure not to break the expected format), unload the hive (important because VS otherwise gets troubles launching) and start VS again - the changes will be loaded by VS.

The method you found via the vssettings file is nothing we actively do or control. I have to be honest, this was new to me. I briefly searched for this behaviour and could not find it documented, seems to be something Visual Studio just does (I did't search for too long, so maybe it is explained somewhere). In the end, it's the same strings as the ones stored in the private registry (with characters like > and < being escaped) and after trying it out, it does seem to work to make changes to this file, start VS, see those changes in the VS Settings Dialog and also after closing VS and loading the hive to have the changes reflected in the private registry.

So, why am I telling you all of this - as explained above, the mechanism with the vssettings is nothing we have active control over. We have a PR lined up (#134) that still needs a little bit work but is planned to be merged this summer. It contains a lot of refactorings, switch to async APIs (which should also solve the issue you closed yourself, #143) and a custom DialogPage implementation that serializes the options to JSON files in the AppData. These JSON files will surely be more easily modified (and transferred) programmatically.
However, until then, we unfortunately do not have the resources to aid you in creating PowerShell scripts to automatically add new language definitions.

Regarding your other question in #143 (how to use the tool via CMD/PS): The VS extension itself cannot be used directly via the command-line. However, as soon as the the PR mentioned above is merged, there is a DLL that handles the core functionality of the extension (inserting, removing, updating license headers based on the license header definition files). Another PR, #135, gives an example on how this core component may be used to create an application that is independent from VS but is still able to provide the main features. However, this one was more a proof-of-concept application in order to verify that we have extracted everything essential that does not strictly require VS and we haven't fully decided on we want to to merge it eventually, too. But, as said, it shows how to use the core DLL - one should be able to load it via a PS script and call the respective functions.

I hope I was able to address your question(s) properly.

Kind regards.

Thanks @raffaelfoidl for detailed explanation. It makes more sense now.

Tried the above regkeys approach but then I wasn't able export Languages. I found another approach, exported this extension's settings to another file from VS (Tools → Import and Export Settings and select "Export selected environment settings"). Now only select 3 checkboxes which are named as 0.

import-4

To import the settings in new VM via powershell

$SettingsFile = "C:\Users\nj123\Downloads\Exported-2021-07-14.vssettings"
$DevEnv = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.exe"
& $DevEnv /ResetSettings $SettingsFile
Start-Sleep -s 5
Get-Process devenv | Foreach-Object { $_.CloseMainWindow() | Out-Null }