1

我正在尝试将以下 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对象是 anIDispach而不仅仅是 an IUnknown?

4

1 回答 1

2

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

此代码中使用的所有 COM 组件都实现了 IDispatch(它需要在 VBScript 或 JScript 上使用),然后我导入了VariantChangeType函数以将 IUnknown 引用强制转换为 IDispatch 引用(因为它似乎不受 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;
于 2013-06-25T18:31:11.467 回答