Can't get package references registered to an

2020-07-27 23:28发布

问题:

I need to define whether a specific extension is installed in Visual Studio 2017. I can get package references registered to the instance of VS using Microsoft.VisualStudio.Setup.Configuration.Interop with C#. Here is example of the working code:

var query = (ISetupConfiguration2) new SetupConfiguration();
var e = query.EnumInstances();
int fetched;
var instances = new ISetupInstance[1];
do
{
    e.Next(1, instances, out fetched);
    if (fetched <= 0) continue;

    ISetupInstance2 instance = instances[0] as ISetupInstance2;
    if (instance == null)
        continue;

    var temp = instance.GetPackages();
    var temp2 = temp.Select(p => p.GetId());

} while (fetched > 0);

The problem is that I have to do it using Inno Setup with its Pascal Script. At this moment I have the following code:

const
  CLSID_SetupConfiguration = '{177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D}';
type
  ISetupPackageReference = interface(IUnknown)
    '{DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5}'
    function GetId(out result: WideString): HResult;
  end;

  packageReference = array[0..10] of ISetupPackageReference;

  ISetupInstance2 = interface(IUnknown)
    '{89143C9A-05AF-49B0-B717-72E218A2185C}'
    function GetPackages(out pack: packageReference): HResult;
  end;

  arrISetupInstance2 = array[1..1] of ISetupInstance2;

  IEnumSetupInstances = interface(IUnknown)
    '{6380BCFF-41D3-4B2E-8B2E-BF8A6810C848}'
    function Next(celt: Integer; var rgelt: arrISetupInstance2; out pceltFetched: Integer): HResult;
    function Skip(celt: Integer): HResult;
    function Reset: HResult;
    function Clone(out pEnumSetupInstances: IEnumSetupInstances): HResult;
  end;

  ISetupConfiguration = interface(IUnknown)
    '{42843719-DB4C-46C2-8E7C-64F1816EFD5B}'
    function EnumInstances(out pEnumSetupInstances: IEnumSetupInstances): HResult;
  end;

  ISetupConfiguration2 = interface(IUnknown)
    '{26AAB78C-4A60-49D6-AF3B-3C35BC93365D}'
    function EnumInstances(out pEnumSetupInstances: IEnumSetupInstances): HResult;
  end;

procedure GetArrayOfVSExtensions;
var
  MyResult: String;
  obj: IUnknown;
  setupConfiguration: ISetupConfiguration2;
  setupInstances: IEnumSetupInstances;
  instances: arrISetupInstance2;
  instance: ISetupInstance2;
  fetched: Integer;
  hr: HResult;
  MyPackages: packageReference;
  FirstInstance: ISetupPackageReference;
  NameOfExtension: WideString;

begin
  obj := CreateComObject(StringToGUID(CLSID_SetupConfiguration));
  setupConfiguration := ISetupConfiguration2(obj);
  hr := setupConfiguration.EnumInstances(setupInstances);
   fetched := 0;

  hr := setupInstances.Next(1, instances, fetched); 
  instance := instances[1];
  hr := instance.GetPackages(MyPackages);

  FirstInstance := MyPackages[3];
  hr := FirstInstance.GetId(NameOfExtension); { Here I get null pointer exception }
end;

It seems like method GetPackages() doesn't work properly in my case and as result MyPackages is empty.

Does anyone know how I can get a valid array of extensions and make this method work?

Thanks in advance.

回答1:

I managed to solve the problem thanks to the comment by Martin Prikryl (thank you once again).

The GetPackages() method is declared in the ISetupInstance2 interface, inherited from ISetupInstance. Consequently, methods from ISetupInstance had to be declared when declaring ISetupInstance2.

The declaration of the ISetupInstance2 interface in order to use the GetPackages() method has to look like this:

ISetupInstance2 = interface(IUnknown)
    '{89143C9A-05AF-49B0-B717-72E218A2185C}'
    { Inherited methods from ISetupInstance }
    function GetInstanceId(out id: WideString): HResult;
    procedure Dummy2;
    function GetInstallationName(out installationName: WideString): HResult;
    function GetInstallationPath(out installationName: WideString): HResult;
    function GetInstallationVersion(out installationVersion: WideString): HResult;
    function GetDisplayName(lcid: Integer; out displayName: WideString): HResult;
    function GetDescription(lcid: Integer; out description: WideString): HResult;
    function ResolvePath(pwszRelativePath: WideString; out result: WideString): HResult;
    { Own methods of ISetupInstance2 }
    procedure Dummy3;
    function GetPackages(out pack: packageReference): HResult;
    procedure Dummy4;
    procedure Dummy5;
    procedure Dummy6;
    procedure Dummy7;
    procedure Dummy8;
    procedure Dummy9;
    procedure Dummy10;
  end;

Maybe this will help someone in solving similar problems.