Change:
<!-- Do Not Delete This! bugreporttemplate --<!-- Please read our Rules of Conduct: --<!-- Read our guide about submitting issues: --<!-- Search existing issues to avoid creating duplicates. --<!-- Test using the latest Insiders build to see if your issue has already been fixed: --<!-- Instead of creating your report here, use 'Report Issue' from the 'Help' menu in VS Code to pre-fill useful information. --<!-- Launch with to check. --Does this issue occur when all extensions are disabled?: N/A <!-- If you answered No above, use 'Help: Start Extension Bisect' from Command Palette to try to identify the cause. --<!-- Issues caused by an extension need to be reported directly to the extension publisher. The 'Help Report Issue' dialog can assist with this. --- VS Code Version: 1.67.2 OS Version: Win11 Steps to Reproduce: an extension A, that contributes and registers a command "abc". an extension B, that has an activation event for "abc", i.e. . you execute "abc" from the command palette, then extension B is activated as expected. you execute "abc" programmatically with , then extension B is NOT activated. Some background for our scenario: We want to support other extensions interacting with our own, in such a way that activating our extension automatically causes the others to be activated (so they can call our API and supply some things that will immediately be needed). Basically, our extension is A in the above repro steps, and third party extensions would be B. It would be possible for B to copy all of the activation events from A, but in our case there are a lot, the list is changing often, and it would be error prone. An ideal solution would be an activation event that the third party extensions could use. But, alternatively, a command registered by and called by the primary extension could activate the others, if they have activation events for it. This works if that command is called from the palette but not if it's called programmatically. Another approach would be for the primary extension to directly activate them with , but that requires having the primary extension know the IDs of the third party extensions, which is not ideal for our scenario. /cc
I can actually not reproduce this and from looking at the implementation I cannot spot an obvious flaw - when running a command via we either run it "inside the extension host" (), which means the extension contributing the command has been activated already, or we execute it via the renderer, which ensure that an activation is send... Can you craft a minimal repo that shows the behaviour that you are describing?
Yes, I can work on that. The key is that extension B only has an activation event for the command, but is not contributing the command. So B does not have to be activated for the command to be run, we just want running the command to cause B to be activated.
I created You'll need to do in both the and subfolders, but after that you can open from the root and <kbdF5</kbd. Extension B has an activation event. When executing command ("ExtensionA: Command ") via the command palette, both extension A and extension B activate. When executing command via the API ("ExtensionA: Command  but via API"), A is activated, but B is not activated.
Oh, now I get it... So, B is active and contributes the command but you want A to activate as a "side effect". Interesting and definitly not covered.
Yes, exactly. This makes it easy for extension A to activate extension B, without needing to know anything about B. Basically, in the real life scenario, B would be contributing some functionality to A, and so should always be activated alongside A--but A has a ton of activation events and copying them is impractical.
Thanks I'll try this out in the next Insiders build.
<!-- AUTHORVERIFICATIONREQUEST --This bug has been fixed in the latest release of ! you can help us out by commenting if things are now working as expected. If things still don't seem right, please ensure you're on version of Insiders (today's or later - you can use in the command palette to check), and leave a comment letting us know what isn't working as expected. Happy Coding!
/verified
We had to revert this for

Discussion:
} } <ins> $fireCommandActivationEvent(id: string): void { const activationEvent = `onCommand:${id}`; if (!this._extensionService.activationEventIsDone(activationEvent)) { // this is NOT awaited because we only use it as drive-by-activation // for commands that are already known inside the extension host this._extensionService.activateByEvent(activationEvent); } } </ins> async $executeCommand<T>(id: string, args: any[] | SerializableObjectWithBuffers<any[]>, retry: boolean): Promise<T | undefined> { if (args instanceof SerializableObjectWithBuffers) { args = args.value;

export interface MainThreadCommandsShape extends IDisposable { $registerCommand(id: string): void; $unregisterCommand(id: string): void; <ins> $fireCommandActivationEvent(id: string): void; </ins> $executeCommand(id: string, args: any[] | SerializableObjectWithBuffers<any[]>, retry: boolean): Promise<unknown | undefined>; $getCommands(): Promise<string[]>; }

private async _doExecuteCommand<T>(id: string, args: any[], retry: boolean): Promise<T> { if (this._commands.has(id)) { <del> // we stay inside the extension host and support // to pass any kind of parameters around </del> <ins> // - We stay inside the extension host and support // 	 to pass any kind of parameters around. // - We still emit the corresponding activation event //   BUT we don't await that event this.#proxy.$fireCommandActivationEvent(id); </ins> return this._executeContributedCommand<T>(id, args, false); } else {

assert.strictEqual(result, 17); assert.strictEqual(count, 2); }); <ins> test('onCommand:abc activates extensions when executed from command palette, but not when executed programmatically with vscode.commands.executeCommand #150293', async function () { const activationEvents: string[] = []; const shape = new class extends mock<MainThreadCommandsShape>() { override $registerCommand(id: string): void { // } override $fireCommandActivationEvent(id: string): void { activationEvents.push(id); } }; const commands = new ExtHostCommands( SingleProxyRPCProtocol(shape), new NullLogService() ); commands.registerCommand(true, 'extCmd', (args: any): any => args); const result = await commands.executeCommand('extCmd', this); assert.strictEqual(result, this); assert.deepStrictEqual(activationEvents, ['extCmd']); }); </ins> });