Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flag to set the edition of Visual Studio being installed #103

Closed
keysight-ansible-galaxy-access opened this issue Apr 27, 2021 · 5 comments

Comments

@keysight-ansible-galaxy-access

Hi, awesome work on the chocolatey packages to install Visual Studio! My present goal is to have a single chocolatey package with no parameters that installs Visual Studio, sets the license key and installs a pre-defined set of workload/components.

Making a modified copy of our visualstudio2017professional package that also inserts our corporate license key was easy enough. I really love your idea of a 1:1 mapping of a chocolatey package with a workload. So I figured I could write a chocolatey package with no powershell scripts and just declare the dependencies of visualstudio and the workloads that I needed. The problem that I ran into is that dependencies are not installed in the order they are listed in the nuspec file. So chocolatey tried to install some workloads before it installed chocolatey. So I figured OK, I'll make variants of the workload packages - but I didn't want to make one for professional and one for enterprise, so I updated my visualStudio2017 package to decided on edition via a pass parameter. That failed because your code is routing all of the chocolatey pass parameters to the visual studio installer. I totally get why, but I'm wondering if your Parse-Parameters.ps1 code could ignore pass parameters with a "/" in them which would allow custom packages that use your code to support parameters without interfearing with the process.

Let me know if this is a possibility and I'll submit a pull request. My present solution is to have the package that installs the workloads to have a dependency on the visualStudio and then iterate through a list of workloads and components in the chocolateyinstall.ps1/uninstallchocolatey.ps1 files. I think having dependencies on the workloads is a more elegant solution - but I don't want maintain sets of workload packages that are identical except for the edition of VisualStudio they depend on.

@jberezanski
Copy link
Owner

The feature you are requesting, if I understand correctly (not passing certain package parameters to the VS Installer), is aready present, in a fashion. The extension recognizes --no-xyz as a directive to remove the --xyz parameter, if one is defined, from the list passed on to the VS Installer. So you can write, for example:

cinst (...) --package-parameters "--visual-studio-edition Professional --no-visual-studio-edition"

and neither of those parameters will be passed on to the native installer. You can try it even now with the packages published on chocolatey.org.

This feature is implemented in the Remove-NegatedArguments function.

As for your suggestion for recognizing the "/" prefix, I'm afraid it would complicate the package parameters parsing code, which is currently very simple and robust, thanks to the existing rule that all parameters must start with --, which is a rather uncommon sequence of characters in contexts such as paths. This makes it possible to avoid quoting paths and other parameter values containing spaces, for example.

@jberezanski
Copy link
Owner

If the "negated arguments" feature did not satisfy your needs, then instead of defining a new parameter symbol, I would be more inclined to recognize a special prefix of parameter names, such as --package:xyz (e.g. --package:visual-studio-product Professional).

Also, could you describe your planned package design in more detail? Are you planning to create a completely new package, depending only on chocolatey-visualstudio.extension, with a ChocolateyInstall.ps1 script that would:

  1. invoke Install-VisualStudio, setting the Product parameter to a value extracted from package parameters,
  2. invoke Add-VisualStudioWorkload/Add-VisualStudioComponent for each workload and component you wish to add?

@keysight-ansible-galaxy-access
Copy link
Author

Thanks for the response. I think the 'ignored' parameter could work for some of my use case; however, I'm not as confident that I can use pass parameters at all. I'll share some of the journey.

As a starter, I did implement the logic to filter out args with the "/". I chose the "/" options because according to the online chocolatey documentation for parsing pass paramters parse-packageparameters-argument, they are recommending using "Get-PackageParameters" and show an example choco install <pkg_id> --params "'/LICENSE:value'". This led me to introduce a parameter of "/edition:Enterprise" with a default of "Professional"

I did hack the Parse-Parameters.ps1 to filter out the "/" options with the code below. The first line removes any "/" options followed by the "--" options. The second line removes any "/" options at the end of the line. The third removes any leftover space.

9 Write-Debug "Starting 'Parse-Parameters' with s:'$s'"; 10 $s = $s -replace '/.+?--','--' 11 $s = $s -replace '/.+(?!--)$','' 12 $s = $s.trim() 13 Write-Debug "Running 'Parse-Parameters' with filtered s:'$s'";

This worked for the following test cases:
Parse-Parameters '/ignoreArgNoVal' Parse-Parameters '/ignoreArg SomeVal' Parse-Parameters '/ignoreArg2:SomeVal2' Parse-Parameters '--arg someval /ignoreArgNoVal' Parse-Parameters '--arg someval /ignoreArg val1' Parse-Parameters '/ignoreArgNoVal --arg someval' Parse-Parameters '/ignoreArgNoVal --arg someval /ignoreArgNoVal2' Parse-Parameters '/ignoreArg val1 --arg someval' Parse-Parameters '/ignoreArg val1 --arg someval /ignoreArg val2' Parse-Parameters '/ignoreArg:val1 --arg someval /ignoreArg:val2' Parse-Parameters '--arg someval1 /ignoreArgNoVal --arg2 someval2' Parse-Parameters '--arg someval1 /ignoreArg val1 --arg2 someval2' Parse-Parameters '--arg someval1 /ignoreArg:val1 --arg2 someval2'

Now, with all of that out of the way, let me describe a bit more about my need.

We're a fairly large organization with a lot of development teams using Visual Studio. Some of them do C#, some do C++, some do python. We have lengthly documents written by IT on where to find a local share drive to get the VS installer and install the corporate license key. Then each team needs to write up it's own lengthly docment on which workloads and components to install. This just results in every setup being an adventure and I want to make it boring.

To make it dead simple for development teams, I want a chocolatey package such as "visualStudio2019professional-myteam" which will install Visual Studio 2019 professional, the corporate license key and the workloads and components required by the team. When a developer is installing the package is possible to ask them pass in pass parameters, but that starts to make it an adventure. One of my visions is to enable teams to create their own 'meta' chocolatey package that has no playload but rather declare the packages they need in the dependency list. So a team member can just execute "choco install myteam-software" and the rest is automatic. So far, the only way I've found to pass parameters to the dependencies is to require the user to provide the --paramsglobal option along with the parameters which defeats my goal of having the settings 'baked' into the package.

So, my current implementation is that I wrote 'k.visualStudio2019professional' which looks identical to your 'visualStudio2017professional' but also calls "StorePID.exe $licenseKey $visualStudioMpc" at the end. So this bakes in our license key. Then I created 'k.visualStudio2019professional-myteam' which declares a dependency on 'k.visualStudio2019professional'. I want to also declare dependencies on packages to install for each of the workloads required by a team; however, since the workloads don't depend on the core visualStudio package and chocolatey does not install dependencies in the order they are listed in the nuspec file, I bump into problems where chocolatey is trying to install the workloads before installing visualstudio which doesn't work. My present solution is to have the 'k.visualStudio2019professional-myteam' package iterate 'Add-VisualStudioWorkload' and 'Add-VisualStudioComponent' over the desire lists of workloads and components.

As I'm writing this, one argument for filtering out the '/' options is that I know I need to install "openssh" which uses '/' options. If I create the metapackage with all of the software a team needs, I might need to pass --paramsglobal --package-parameters='"/SSHServerFeature /KeyBasedAuthenticationFeature"' for the openssh package - and that would tank your visual studio installer.

Anyway, you've done some great work. I really appreciate it.

@jberezanski
Copy link
Owner

Thank you for the kind words :) I'm really glad you find the packages useful.

A couple of thoughts:

(some historical background) The "--" package parameter format actually dates as far back as 2016, when it initially appeared in the VS 2015 packages. Back then Chocolatey did not provide any facility for parsing parameters and there was no established guidance. When I saw that format, I liked its simplicity and lack of need for quoting or other special characters (in contrast to the format introduced later with the Get-PackageParameters helper). The machinery used for VS 2017 and 2019 evolved out of the scripts from VS 2015 packages, so the parameter format was carried over, too (and, by happy concidence, it matched the format used by the new VS Installer, which appeared with VS 2017 Preview 4).

If you are using only one edition of Visual Studio (Professional, I presume), then copying the workload packages might actually be the simplest way of implementing your idea of "-myteam" metapackages. There aren't that many workloads and the packages only need updating in case of a bugfix (and mostly in the form of bumping the extension dependency version), so performing a clone of the packages, changing the ids and adding dependency on the VS 2019 Professional package would be a really quick, easily automated, one-time task. You could also add some code to adjust the defaults, for example pass -IncludeOptionalComponentsByDefault or add something to $env:chocolateyPackageParameters.

How about putting the license key installation in a package by itself? If that is the only change you needed to make to the chocolatey.org visualStudio2019professional package, then with this approach you could just put a dependency on the license key package in your "-myteam" package and use the package from chocolatey.org unmodified, reducing maintenance work.

A function such as Set-VisualStudioProductKey would also make a fine addition to chocolatey-visualstudio.extension, if you were in the mood for making it robust and sharing with the community ;-)

Yes, the "paramsglobal" feature quickly runs into problems when you start adding completely unrelated packages (which themselves may depend on other packages). Myself, I've never really found that feature useful. It is also brittle - even if you manage to achieve a set of packages and global parameters that works one day, it may break tomorrow if a dependent package suddenly gains an optional feature and starts looking at parameters.

Creating a custom package, which sets parameters appropriately and invokes the installation code from the original package, seems to be the only option available in choco right now. The drawback is that the original package is not seen by choco as installed, so the user loses the ability to upgrade the software via choco, unless your custom package follows the updates of the original, which naturally generates maintenance burden.

One solution would be to extend the nuspec to enable providing package parameters for dependencies, e.g.

<dependency id="openssh" version="1.2.3" parameters="/SSHServerFeature /KeyBasedAuthenticationFeature" />

It might be worth suggesting on https://github.com/chocolatey/choco/issues (I'm rather surprised that nobody seems to have done it yet).

In my company we have solved the problem of "a standard team toolset" not via a custom choco package, but rather via a script, which essentially uses choco to install a list of packages, with appropriate parameters where needed. The advantages are simplicity and flexibility, at the cost of people not being able to detect upgrades to the toolset using choco only (without out-of-band information, such as a team- or company-wide announcement) - but that has never been a real problem for us in practice (whenever something is added, we just tell people to run the script again).

This is an unrelated matter, but perhaps as a user of the VS packages you could provide your opinion. I'm thinking of changing the package versioning scheme in order to accomodate both "latest" packages (which always install the latest released VS version, the way the current packages work) and new, "specific version" packages (which always install the specific VS version) under the same package id. The idea is described in this thread: #100. Does it look reasonable?

@jberezanski
Copy link
Owner

Closing due to inactivity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants