无法将类型(未知)的变体转换为类型(调度)



我正在尝试将以下javascript代码移植到inno-setup pascal脚本:

var adminManager = new ActiveXObject('Microsoft.ApplicationHost.AdminManager');
var appPoolsSection = adminManager.GetAdminSection('system.applicationHost/applicationPools', 'MACHINE/WEBROOT/APPHOST');
var appPoolsCollection = applicationPoolsSection.Collection;
for (var i = 0; i < appPoolsCollection.Count; i++)
{
    var appPool = appPoolsCollection.Item(i);
    // doing someting with the application pool
}

此代码已翻译为:

var AdminManager, AppPoolsSection, AppPoolsCollection, AppPool: Variant;
    i: Integer;
begin
  AdminManager := CreateOleObject('Microsoft.ApplicationHost.AdminManager');
  AppPoolsSection := AdminManager.GetAdminSection('system.applicationHost/applicationPools', 'MACHINE/WEBROOT/APPHOST');
  AppPoolsCollection := AppPoolsSection.Collection;
  for i := 0 to AppPoolsCollection.Count-1 do begin
    AppPool := AppPoolsCollection.Item(i);
    // doing someting with the application pool
  end;
end;

但它在AppPoolsCollection := AppPoolsSection.Collection线上引发了以下错误:

Exception: Could not convert variant of type (Unknown) into type (Dispatch).

我可以做些什么来通知pascal scritp AppPoolsSection对象是IDispach,而不仅仅是IUnknown

我找到了一个有效的解决方案,它比"导入"接口定义更简单。

这段代码中使用的所有COM组件都实现了IDispatch(它需要在VBScript或JScript上使用),然后我导入了VariantChangeType函数,将IUnknown引用强制转换为IDdispatch引用(因为pascal脚本似乎不支持它)。

遵循最终代码:

function VariantChangeType(out Dest: Variant; Source: Variant; Flags, vt: Word): HRESULT; external 'VariantChangeType@oleaut32.dll stdcall';
function VarToDisp(Source: Variant): Variant;
begin
  Result := Unassigned;
  OleCheck(VariantChangeType(Result, Source, 0, varDispatch));
end; 
procedure EnumerateAppPools(AppPools: TStrings);
var AdminManager, Section, Collection, Item, Properties: Variant;
    i: Integer;
begin
  AdminManager := CreateOleObject('Microsoft.ApplicationHost.AdminManager');
  Section := VarToDisp(AdminManager.GetAdminSection('system.applicationHost/applicationPools', 'MACHINE/WEBROOT/APPHOST'));
  Collection := VarToDisp(Section.Collection);
  for i := 0 to Collection.Count-1 do begin
    Item := VarToDisp(Collection.Item(i));
    Properties := VarToDisp(Item.Properties);
    if (VarToDisp(Properties.Item('managedPipelineMode')).Value = 1) and 
       (VarToDisp(Properties.Item('managedRuntimeVersion')).Value = 'v4.0') then
      AppPools.Add(VarToDisp(Properties.Item('name')).Value);
  end;
end;

最新更新