Change:
<!-- Do Not Delete This! bugreporttemplate --As I understand profiles, we should be able to save a profile with a full set of extension details, disable some extensions, save another profile with this reduced extension set, then restore the first to get all extension settings back. That's not what I'm seeing. Version: 1.74.2 (system setup) Commit: Date: 2022-12-20T10:29:14.590Z Electron: 19.1.8 Chromium: 102.0.5005.167 16.14.2 V8: 10.2.154.15-electron.0 OS: Windows_NT x64 10.0. Sandboxed: No Steps to Reproduce: a workspace with many enabled extensions. a profile "v1", extensions only, all other options unchecked. the top 10 extensions. and verify the extensions are disabled. a profile "v2", extensions only, all other options unchecked. profile "v1". Expectation: Disabled extensions will re-enable. Actual: All extensions seemed to reinstall or update. The disabled extensions remained disabled. , no change. workspace and re-open, no change. Issue 1: It would improve the UX/DX if existing extensions with correct configuration are not reloaded on profile import. Issue 2: I don't see a field in .code-profile data for an Enabled status - even in a full export with all options checked. It seems obvious that the import doesn't restore the setting because export isn't saving it.
May I know why you want to export an installed extension that is disabled? I do not see a reason to import a disabled extension?
My 2 cents here Its related to maybe this helps. We are trying to find a solution, how we can have a workspace with extension A + B enabled, but not C. In an other workspace/folder we would like to have maybe A + C enabled, but not B. This all started with some incompatibility of extensions, but also simply makes sense, if you think, that not all projects one works on, does need all extensions. Some projects simply don't need some extensions, and it would be nice we can manage this somehow in workspace or other settings.
thanks - you've been in on this stuff since the start. I have the understanding that profiles were created to allow one environment to look like another. With this ticket I'm demonstrating that since the Enabled status of extensions is not exported, it's also not imported, and therefore the target environment does not look like the source. Is that a bug per-spec, or was this a design decision? In it was suggested that Profiles might be a solution to the challenge : "Enable/disable extensions from config file". This ticket is evidence that Profile export/import is not a solution - yet. If this ticket is processed and we can use profiles to enabled/disable extensions, then we can close that ticket. If not, then many of us will look forward to new comments from the team about what can be done. HTH - TY
Its related to maybe this helps. We are trying to find a solution, how we can have a workspace with extension A + B enabled, but not C. In an other workspace/folder we would like to have maybe A + C enabled, but not B. I do not want to say profiles is the solution for the above issue. But if you want to use different set of extensions for different workspaces using profiles it is possible like below Workspace 1: Use a profile with Extension A and Extension B Workspace 2: Use a profile with Extension A and Extension C Whether an extension is installed or enabled or disabled is an implementation detail IMO.
Yes, your understanding is correct. We can export an extension in the profile even if it is disabled and when the profile is imported, the extension is installed and disabled. How different is it to not to include this extension at all? You still get the same running environment (this is more considered). If you want to have a new extension in the profile, you can simply install it.
wrote: That is correct but only addresses one use case. You are saying that an extension that is disabled will be restored as disabled when the profile is imported. Yes, but that's only because there's nothing in the profile to tell it to change state. I'm saying, that if the extension is enabled and we save the profile, the extension is not enabled on profile import ... because there's nothing in the profile to tell it to change state. And if the extension is disabled and we save the profile, and the extension is already enabled in the target, the extension is not disabled on profile import ... because there's nothing in the profile to tell it to change state. I hope and believe we're finally arriving at an "aha!" moment.
I am not sure what you mean by this. The exported profile file has already have the information of enablement. So when importing the extension is enabled/disabled accordingly. Why do not you want extension to be enabled when you import a profile that has extension enabled? On the target you will not have any extensions except builtin extensions. If an built in extension is marked as disabled, after importing the profile, extension is marked as disabled. As said, at present an installed extension (not builtin) will not be exported if it is disabled in the source. Actually I have to say, I am not sure what we are trying to come up here. To simplify our discussion are we talking about the following statement or do you have more other thoughts? Ability to export an user installed extension that is disabled in a profile and ability to import that profile and install that extension in the target and disable it
That's only one possible use case, in a new installation. We all have VSCode already installed and configured. As noted in many of us want to import and occasionally change a standard set of extensions across systems. If a source system and a target system have the same extension, the profile should export the state of the extension's enablement as well as the state of its existence. In the current platform: If the extension is already installed on the target, the new state is not changed to match the source. And if the extension is not installed on the target, it is installed with the default set to enabled, even if it was disabled when the profile was saved. That is correct. Use case: all of your extensions. Why? Use cases are noted in , including desire to whitelist extensions, eliminate cognitive load, and testing. a workspace. the extension to Enable in Workspace Workspace. . all of your extensions so that you can export to profile, because that's how it works. to profile. all of your extensions again because that's your preference. If you're already at the "I don't want to do that" stage, +1 this issue. . Let's pretend you're on another machine. the profile and Reload. all of your extensions again - yes, again, because that's your preference. Tired yet? the workspace. Yay, the extension is enabled! Workspace. another profile now, with all of the extensions disabled. the top 10 or so extensions and Reload. Let's pretend you're on another machine. the most recent profile. the workspace. Hey, I can't work without that first extension - what happened? What happened is that the profile does not include disabled extensions. So on the target system the extension wasn't even installed for the "Enable (Workspace)" feature. Here's another scenario to support profile including the enabled status. Developer 1 wants Developer 2 to duplicate an issue. She sends him the code, the .code-workspace, and a .code-profile. He can't duplicate the issue. Why? Because she has the same extensions that he has, but one of hers is enabled and the same one on his is disabled. The profile import doesn't change the enabled status on his target. Her system manifests the issue because of the enabled extension. Again, my impression, which I believe is shared, is that the Profle Export/Import is intended to duplicate an environment so that it can be restored on a single system, and so that it can be replicated to other systems in a team. This ideal has not been realized because (1) profiles do not export disabled plugin specs, and (2) enabled plugins, when imported, do not override a disabled status on a target system. Note from above a side-effect - that if a disabled plugin is not imported, then by definition the "Enable (Workspace)" setting is also not imported. I don't know where that setting is stored, but it's not in the .code-workspace or the .code-profile. It should be in the profile. I can think of at least another two tickets that could be created for this problem. So now do we have any sense of agreement about the problems and solutions?
Today, my friend want me to share my VSCode environment to him, but I found the profile can't export the installed extension which is disabled. I had to use command line to export extensions ids to him. The settings sync extension had been marked depracated, and we can't install it any more. I think VSCode builtin settings sync and profiles together is designed to replace the settings sync extension, but now seems can't
Are we still trying to get a common understanding of the issue and use-case? Or are we in agreement that there is an issue that "might" later be addressed? I'm not looking for a commitment for a change. I just want to know if we're still in discussion about whether or not there is an issue, if there is legit use case, justification for some level of prioritization in a milestone, etc. Obviously others are now stumbling on this, so I'm hoping we can conclude that this is legitimate. If so, this might be the answer to . Now that Profiles have been announced for production, I predict we'll see more dupes of this. Thanks as always for your time.
I am sorry that I did not give this a read yet, will get back to this and let you know.
If I understand correctly, you want to use a single profile for a set of workspaces and for each workspace you want to enable specific set of extensions per workspace. You want to export that profile to some one else so that they can do the same for the same set of workspaces. This is instead of having profile per workspace?
This issue has been closed automatically because it needs more information and has not had recent activity. See also our guidelines. Happy Coding!
Let's try again We have "Feature Request: Enable/disable extensions from config file" . Think of the ExtensionState as separate from workspaces and profiles. ExtensionState includes the list of installed extensions. A subset of that is the list of enabled extensions. A subset of that is the list of extensions that is disabled for the current workspace. We're talking about how the following data stored: ! ! ! We're looking for the ability to duplicate ExtensionState across environments. How do we copy ExtensionState? The above detail is not included in file .code-workspace, nor in .code.profile. There have been attempts to access that data using third-party extensions, but those are not adequate, and they only exist because someone hid the configuration data and stored it in a proprietary format. Request asks for this data to be accessible in a standard format, ideally JSON in something like .code.extensions. Then that file name would be saved in the .code-workspace file. This abstracts the extensions out from workspace and profile. Now, some time ago it was suggested that since Profiles were still in development, we should try to use Profiles to achieve the goal, rather than trying to come up with a completely new concept. We have done that, but a number of us have found and reported that Profiles do not have the above detail. IF Profiles are intended to share ExtensionState, this ticket details the issue. If Profiles are NOT the way to go, let's close this and go back to to discuss how we might be able to export and import ExtensionState as a config file. "Why?" you may ask again ... We have provided many use cases in both of these tickets. The simplest answer is that it is a common need for our environment to be consistent with another environment - across individuals, systems, and projects. This is exactly why we have and package-, and tools like Composer. We cannot truly duplicate a VSCode environment because there is no defined way to save or restore ExtensionState. The Workspace is great for some of this. Profiles are great for some of this. But, while Extensions are integrated with Workspaces, and there is some handling of Extensions in Profiles, neither of those components contain the entire ExtensionState for our access and manipulation.
If we include enablement state in the exported profile template file , then it will be just if the extension is enabled or not. May I know if this is good enough? It cannot contain if an extension is enabled/disabled at workspace level because there is no workspace semantics (identification) information stored in the profile file.
It can? Or it can not? to better understand your point, does it mean: That you could just say if the extension is enabled or not. You can not identify or save, if the extension was disabled for the workspace or not. Correct? I guess this would be okey, because if I understand correctly, the profile is something globally, and not specific to a workspace, right? Side note: (I can create separate ticket if you want): I am wondering: Is there any possibility (or is it planned in the future) to support the case: That one could say: "Workspace X" uses "Profile Y"? So is there a way, to kind of automate, that a specific workspace has a specific profile to use? If you save these information on a "workspace" level, some other DEV loads your project, it would contain the workspace settings and applying the profile? Or would it more likely be an "shell" command, to start vs code with Workspace X and apply Profile Y?
I am sorry. It cannot. Updated my comment. Thats correct. To be clear, profile will contain that if an extension is enabled/disabled in that profile. For eg., if it is enabled in the profile and disabled in the workspace, extension state will be enabled in the exported profile. That one could say: "Workspace X" uses "Profile Y"? It is not possible now and this needs workspace identification. I think there is an ask for this to have profile info at the workspace level. This is already supported from CLI -
I think we have agreement. Thanks for working with us, Thinking through a couple use cases... 1 sends their profile to Dev2. Opening that profile results in all of the required extensions being loaded, and all extensions being disabled as defined in the profile. What might happen to extensions that Dev2 has that are not mentioned in the profile? They would be untouched in the Dev2 setup, and thus not the recreating the same environment in the Dev2 system. To recreate the DEV1 environment, DEV2 needs to create their own preferred profile for a later restore (not a bad idea for all of us to do this anyway). Then use the existing feature to "Disable all installed extensions". Then run with the DEV1 profile. On completion, DEV2 reloads the "backup" to restore the previous DEV2 settings to its preferred state. Is that an acceptable workflow? To me it is. (Question open to all devs) But that seems like a manual way of handling something that the tool is still not quite doing for us. The solution here would be for an option on CLI and menu for Import Profile, to disable all extensions prior to opening the new profile. Personally, I'd vote to let that be the Default, and the Option would be to Not disable all extensions, for those who actually do want a hybrid environment between DEV1 and DEV2. Side note: Without doubt, someone will disable all extensions without a backup and then cry about the need to manually re-enable. I'm just documenting this as a procedural advisory/requirement, unless the profile import gets an enhancement to create up to three default backups prior to import. workstation, multiple instances of VSCode. Example: We have a JavaScript project up in one instance for front-end, and a PHP project for back-end, and we don't want to use the same extensions. In this scenario I think extension management with Workspaces works. However, it's important to have a common baseline of extensions for both workspaces which comes from a single profile, maybe opened by the CLI. In summary: "If we include enablement state in the exported profile template file .code-profile, then it will be just if the extension is enabled or not." Yes, this resolves this ticket and . I would just ask ... PLEASE don't encode this data in an unnecessarily "proprietary", compressed, or otherwise machine-only-readable manner. Use standard JSON. Then people can write code to manipulate the .code-profile details as desired, injecting or changing extension data as requested in . If we have agreement here, let's get concensus from the folks in . Agreed?
I would be adding the extension enablement state to the profile and I am happy that it helps you with your scenarios or use cases. But I am little skeptical to announce that this is the solution for and instead I would love if community jumps in and try around and see if it satisfies their needs. Regarding making the profile template file readable, please follow or track this issue -
To verify: Create a custom profile by disabling some builtin and installed extensions Export the profile Delete the above custom profile Import the profile and make sure extensions you disabled and disabled
Revision to verification steps - accounting for language issue and a more rigorous test: To verify: /export a custom profile P1, saving extension settings /enable some builtin and installed extensions (note original and new state) /export another custom profile P2, saving extension settings P1 that extensions have the original state from step 1 P2 that the extensions are disabled/enabled with the new state as they were at step 3 P1 the state of extension enablement should be returned to the original On another system: /export a custom profile P3, saving extension settings /enable some builtin and installed extensions (note original and new state) /export another custom profile P4, saving extension settings P2 from the first system that extensions look as they did at step 3 for the first system P3 that extensions have the original state from this system's step 1

Discussion:
return this.withProfileScopedServices(profile, async (extensionEnablementService) => { const profileExtensions: IProfileExtension[] = await this.getProfileExtensions(content); const installedExtensions = await this.extensionManagementService.getInstalled(undefined, profile.extensionsResource); <del> const extensionsToEnableOrDisable: { extension: ILocalExtension; enable: boolean }[] = []; </del> <ins> const extensionsToEnableOrDisable: { extension: IExtensionIdentifier; enable: boolean }[] = []; </ins> const extensionsToInstall: IProfileExtension[] = []; for (const e of profileExtensions) { const isDisabled = extensionEnablementService.getDisabledExtensions().some(disabledExtension => areSameExtensions(disabledExtension, e.identifier));

if (!installedExtension || (!installedExtension.isBuiltin && installedExtension.preRelease !== e.preRelease)) { extensionsToInstall.push(e); } <del> if (installedExtension && isDisabled !== !!e.disabled) { extensionsToEnableOrDisable.push({ extension: installedExtension, enable: !e.disabled }); </del> <ins> if (isDisabled !== !!e.disabled) { extensionsToEnableOrDisable.push({ extension: e.identifier, enable: !e.disabled }); </ins> } } const extensionsToUninstall: ILocalExtension[] = installedExtensions.filter(extension => !extension.isBuiltin && !profileExtensions.some(({ identifier }) => areSameExtensions(identifier, extension.identifier))); for (const { extension, enable } of extensionsToEnableOrDisable) { if (enable) { <del> this.logService.trace(`Importing Profile (${profile.name}): Enabling extension...`, extension.identifier.id); await extensionEnablementService.enableExtension(extension.identifier); this.logService.info(`Importing Profile (${profile.name}): Enabled extension...`, extension.identifier.id); </del> <ins> this.logService.trace(`Importing Profile (${profile.name}): Enabling extension...`, extension.id); await extensionEnablementService.enableExtension(extension); this.logService.info(`Importing Profile (${profile.name}): Enabled extension...`, extension.id); </ins> } else { <del> this.logService.trace(`Importing Profile (${profile.name}): Disabling extension...`, extension.identifier.id); await extensionEnablementService.disableExtension(extension.identifier); this.logService.info(`Importing Profile (${profile.name}): Disabled extension...`, extension.identifier.id); </del> <ins> this.logService.trace(`Importing Profile (${profile.name}): Disabling extension...`, extension.id); await extensionEnablementService.disableExtension(extension); this.logService.info(`Importing Profile (${profile.name}): Disabled extension...`, extension.id); </ins> } } if (extensionsToInstall.length) {

// skip user extensions without uuid continue; } <del> if (disabled && !extension.isBuiltin) { // skip user disabled extensions continue; } </del> } const profileExtension: IProfileExtension = { identifier, displayName: extension.manifest.displayName }; if (disabled) {