|
| 1 | +#include "pch.h" |
| 2 | +#include "VisualStudioInfo.h" |
| 3 | +#include <windows.h> //DWORD |
| 4 | +#include <functional> //function |
| 5 | +#include <atlconv.h> //CW2A |
| 6 | +#include <comdef.h> //_COM_SMARTPTR_TYPEDEF |
| 7 | +#include <Setup.Configuration.h> |
| 8 | + |
| 9 | +_COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration)); |
| 10 | +_COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances)); |
| 11 | +_COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance)); |
| 12 | +_COM_SMARTPTR_TYPEDEF(ISetupInstanceCatalog, __uuidof(ISetupInstanceCatalog)); |
| 13 | +_COM_SMARTPTR_TYPEDEF(ISetupPropertyStore, __uuidof(ISetupPropertyStore)); |
| 14 | + |
| 15 | +using namespace std; |
| 16 | + |
| 17 | + |
| 18 | +vector<VisualStudioInfo> getInstalledVisualStudios(void) |
| 19 | +{ |
| 20 | + vector<VisualStudioInfo> instances; |
| 21 | + // Idea copied from vswhere, except whole implementation was re-written from scratch. |
| 22 | + { |
| 23 | + ISetupConfigurationPtr setupCfg; |
| 24 | + IEnumSetupInstancesPtr enumInstances; |
| 25 | + |
| 26 | + auto lcid = GetUserDefaultLCID(); |
| 27 | + |
| 28 | + function<void(HRESULT)> hrc = [](HRESULT hr) |
| 29 | + { |
| 30 | + if (FAILED(hr)) |
| 31 | + { |
| 32 | + USES_CONVERSION; |
| 33 | + throw exception(CW2A(_com_error(hr).ErrorMessage())); |
| 34 | + } |
| 35 | + }; |
| 36 | + |
| 37 | + hrc(CoInitialize(nullptr)); |
| 38 | + hrc(setupCfg.CreateInstance(__uuidof(SetupConfiguration))); |
| 39 | + hrc(setupCfg->EnumInstances(&enumInstances)); |
| 40 | + |
| 41 | + while (true) |
| 42 | + { |
| 43 | + ISetupInstance* p = nullptr; |
| 44 | + unsigned long ul = 0; |
| 45 | + HRESULT hr = enumInstances->Next(1, &p, &ul); |
| 46 | + if (hr != S_OK) |
| 47 | + break; |
| 48 | + |
| 49 | + ISetupInstancePtr setupi(p, false); |
| 50 | + ISetupInstanceCatalogPtr instanceCatalog; |
| 51 | + ISetupPropertyStorePtr store; |
| 52 | + hrc(setupi->QueryInterface(&instanceCatalog)); |
| 53 | + hrc(instanceCatalog->GetCatalogInfo(&store)); |
| 54 | + |
| 55 | + CComVariant v; |
| 56 | + hrc(store->GetValue(L"productLineVersion", &v)); |
| 57 | + |
| 58 | + VisualStudioInfo vsinfo; |
| 59 | + vsinfo.version = atoi(CStringA(v).GetBuffer()); |
| 60 | + CComBSTR instpath; |
| 61 | + // GetDisplayName can be used to get name of instance. |
| 62 | + hrc(setupi->GetInstallationPath(&instpath)); |
| 63 | + vsinfo.InstallPath = instpath; |
| 64 | + instances.push_back(vsinfo); |
| 65 | + } |
| 66 | + } |
| 67 | + CoUninitialize(); |
| 68 | + |
| 69 | + return instances; |
| 70 | +} |
| 71 | + |
| 72 | + |
0 commit comments