2

I am running Windows 11 Pro 64-bit 24H2. When I press WIN+C (the shortcut to show Copilot), I get this screen asking me to sign in Copilot.

This IMO shows that Copilot is installed on my machine.

Now I need to check this programmatically. For this purpose, I have created this unit in Delphi 12.2:

unit CopilotUtils;

// (c) 2025 - A reusable utility unit for interacting with Microsoft Copilot on Windows.

interface

// --- Public Interface ---

// Detects if Copilot is installed by checking its ActivatableClassId in the registry.
function IsCopilotInstalled: Boolean;

// Launches the Copilot sidebar.
procedure LaunchCopilot;

implementation

// --- Implementation Details ---

uses
  System.SysUtils,
  System.Win.Registry,
  Winapi.Windows,
  Winapi.ShellAPI;

// --- Private Constants ---
const
  // The definitive registry key for Copilot's core component, discovered through user investigation.
  COPILOT_ACTIVATABLE_CLASS_KEY = 'SOFTWARE\Microsoft\WindowsRuntime\ActivatableClassId\WindowsUdk.UI.Shell.WindowsCopilot';

  // The custom URI protocol used to launch Copilot.
  COPILOT_URI_SCHEME = 'ms-copilot://';

// --- Function Implementations ---

function IsCopilotInstalled: Boolean;
var
  Registry: TRegistry;
begin
  Result := False;
  Registry := TRegistry.Create;
  try
    Registry.RootKey := HKEY_LOCAL_MACHINE;

    // **THE CRUCIAL FIX for a 32-bit app on 64-bit Windows:**
    // This flag forces our 32-bit application to access the native 64-bit
    // registry view, bypassing the Wow6432Node redirection. This is required
    // to see the registry keys of modern 64-bit applications like Copilot.
    Registry.Access := KEY_READ or KEY_WOW64_64KEY;

    // Now, we check for the specific, correct ActivatableClassId key.
    Result := Registry.KeyExists(COPILOT_ACTIVATABLE_CLASS_KEY);
  finally
    Registry.Free;
  end;
end;

procedure LaunchCopilot;
var
  SEInfo: TShellExecuteInfo;
begin
  FillChar(SEInfo, SizeOf(SEInfo), 0);
  SEInfo.cbSize := SizeOf(SEInfo);
  SEInfo.fMask := SEE_MASK_FLAG_NO_UI; // Don't show an error dialog if launch fails.
  SEInfo.lpVerb := 'open';
  SEInfo.lpFile := PChar(COPILOT_URI_SCHEME);
  SEInfo.nShow := SW_SHOWNORMAL;
  ShellExecuteEx(@SEInfo);
end;

end.

Upon execution, IsCopilotInstalled returns TRUE as expected. But I am not sure whether this works on any other Windows machine.

Question: What is the official Delphi method for detecting if Copilot is installed?

7
  • 3
    Why would Delphi need, or want, an "official" method to do this ? Commented Jul 27 at 22:02
  • 2
    Since you need to use a Copilot URL to launch it, I would suggest checking if the Copilot url scheme has a handler registered. Commented Jul 28 at 2:38
  • ...which would be a key in HKEY_CLASSES_ROOT\PROTOCOLS\Handler (and HKEY_CLASSES_ROOT\Wow6432Node\PROTOCOLS\Handler) and maybe in HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations. Commented Jul 28 at 13:17
  • A url scheme can also be registered at the top-level of HKCR, eg HKEY_CLASSES_ROOT\<scheme> by adding a URL Protocol value in it, and a Shell subkey to invoke an action. I don't have CoPilot installed so I can't verify if it uses this approach, but it is something to check as well. Commented Jul 28 at 16:33
  • @RemyLebeau I thought so myself, but then again I can only find very few there - not even mailto. I weighted my comment on where I found the not unimportant mailto protocol/scheme. Commented Jul 30 at 22:49

1 Answer 1

0

Here's some useful functions for you. They're not tested on hundreds of different computers, but I tested them on a couple of personal computers and a couple of remote servers and they seem to work in terms of detecting Copilot.


Check if WindowsUdk.UI.Shell.WindowsCopilot key in Registry:

function IsCopilotInstalled: Boolean;
const
  COPILOT_REG_KEY = 'SOFTWARE\Microsoft\WindowsRuntime\ActivatableClassId\WindowsUdk.UI.Shell.WindowsCopilot';
begin
  Result := False;
  var Registry := TRegistry.Create;
  try
    Registry.RootKey := HKEY_LOCAL_MACHINE;
    Registry.Access := KEY_READ or KEY_WOW64_64KEY;
    Result := Registry.KeyExists(COPILOT_REG_KEY);
  finally
    Registry.Free;
  end;
end;

Check for ms-copilot:// URI Protocol in Registry:

function IsCopilotProtocolRegistered: Boolean;
begin
  Result := False;
  var Registry := TRegistry.Create;
  try
    Registry.RootKey := HKEY_CLASSES_ROOT;
    Result := Registry.KeyExists('ms-copilot');
  finally
    Registry.Free;
  end;
end;

Detect Copilot.exe via Running Processes:

function IsCopilotProcessRunning: Boolean;
begin
  Result := False;
  var SnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if SnapShot <> INVALID_HANDLE_VALUE then
  begin
    var ProcEntry: TProcessEntry32;
    ProcEntry.dwSize := SizeOf(TProcessEntry32);

    if Process32First(Snapshot, ProcEntry) then
    begin
      repeat
        if SameText(ProcEntry.szExeFile, 'Copilot.exe') then
        begin
          Result := True;
          Break;
        end;
      until not Process32Next(Snapshot, ProcEntry);
    end;
    CloseHandle(Snapshot);
  end;
end;

Launch Copilot using ms-copilot:// URI Protocol

procedure LaunchCopilot;
begin
  var SEInfo := Default(TShellExecuteInfo);
  SEInfo.cbSize := SizeOf(SEInfo);
  SEInfo.fMask := SEE_MASK_FLAG_NO_UI;
  SEInfo.lpVerb := 'open';
  SEInfo.lpFile := PChar('ms-copilot://');
  SEInfo.nShow := SW_SHOWNORMAL;
  ShellExecuteEx(@SEInfo);
end;
Sign up to request clarification or add additional context in comments.

1 Comment

Registry.KeyExists('ms-copilot') alone is not enough - you should still check if in that key a string named URL Protocol exists. Checking running processes is ambiguous, too, since any program can itself name Copilot.exe (think of a game); also this requires the own program to always run in 64 bit, never in 32 bit. Also: why using a const for a string literal in one function, although only used once, but not in other functions?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.