Mark Williams 14 Posted January 3 (edited) I cannot understand why the following code does not work: function IsOleObjectActive(OleObject: OleVariant): Boolean; begin Result := not VarIsClear(OleObject) and not VarIsEmpty(OleObject) and not VarIsNull(OleObject); end; procedure TForm1.Button1Click(Sender: TObject); var ServerManager: OleVariant; Site: OleVariant; AppPool: OleVariant; Security: OleVariant; begin // Initialize COM library CoInitialize(nil); try // Create an instance of the ServerManager object ServerManager := CreateOleObject ('Microsoft.ApplicationHost.WritableAdminManager'); ServerManager.CommitPath := 'MACHINE/WEBROOT/APPHOST'; // Add a new site Site := ServerManager.GetAdminSection('system.applicationHost/sites', 'MACHINE/WEBROOT/APPHOST'); - if IsOleObjectActive(Site) then Showmessage('Active') else exit; Site := Site.Collection.AddElement('site'); //FAILS HERE Site.Properties.Item('name').Value := trim(eSiteName.text); // Site.Properties.Item('id').Value := 2; Site.Properties.Item('physicalPath').Value := 'C:\inetpub\wwwroot\' + trim(ePhysicalPath.text); // Configure bindings Site.Bindings.Collection.AddElement('binding'); Site.Bindings.Collection.Item(0).Properties.Item('protocol').Value := 'http'; Site.Bindings.Collection.Item(0).Properties.Item('bindingInformation').Value := '*:80'; Site.Bindings.Collection.AddElement('binding'); Site.Bindings.Collection.Item(1).Properties.Item('protocol').Value := 'https'; Site.Bindings.Collection.Item(1).Properties.Item('bindingInformation').Value := '*:443'; // Add an application pool AppPool := ServerManager.GetAdminSection ('system.applicationHost/applicationPools', 'MACHINE/WEBROOT/APPHOST'); AppPool := AppPool.Collection.AddElement('add'); AppPool.Properties.Item('name').Value := trim(eSiteName.text); AppPool.Properties.Item('managedRuntimeVersion').Value := trim(eNetFramework.text); // Assign the application pool to the site Site.Applications.Collection.Item(0).Properties.Item('applicationPool') .Value := trim(eSiteName.text); // Commit the changes ServerManager.CommitChanges; finally // Uninitialize COM library CoUninitialize; end; When I try to add the new site I get "Variant does not reference an automation object." I've tried adding the application pool first, but same problem. As far as I can see the section names are correct as per the applicationHost.config file and all functions, properties are correct as per the nativerd.dll. I've also tried running the app in elevated mode. Makes no difference. Edited January 3 by Mark Williams Share this post Link to post
PeterBelow 239 Posted Monday at 12:06 PM Try Result := not (VarIsClear(OleObject) or VarIsEmpty(OleObject) or VarIsNull(OleObject)) and (VarType(OleObject) = VT_DISPATCH); Share this post Link to post
Vincent Parrett 781 Posted Tuesday at 06:38 AM There is a type library you can import - would save a lot of casting C:\Windows\System32\inetsrv\nativerd.dll It's a pretty awful api to work with, it's been a while since I looked at it - Microsoft created a pretty extensive dotnet wrapper for it - https://www.nuget.org/packages/Microsoft.Web.Administration you could download the nuget package and use Ilspy to have a look at it - might help 1 Share this post Link to post
Mark Williams 14 Posted Tuesday at 09:18 PM On 1/6/2025 at 12:06 PM, PeterBelow said: Try Result := not (VarIsClear(OleObject) or VarIsEmpty(OleObject) or VarIsNull(OleObject)) and (VarType(OleObject) = VT_DISPATCH); Same result. It reports true for Server Manager, but then fails with the variant does not reference... error on the call to ServerManager.GetAdminSection. Share this post Link to post
Mark Williams 14 Posted Tuesday at 09:20 PM 14 hours ago, Vincent Parrett said: There is a type library you can import - would save a lot of casting C:\Windows\System32\inetsrv\nativerd.dll It's a pretty awful api to work with, it's been a while since I looked at it - Microsoft created a pretty extensive dotnet wrapper for it - https://www.nuget.org/packages/Microsoft.Web.Administration you could download the nuget package and use Ilspy to have a look at it - might help I had started to go down this route. I'm using the 64 bit type library, which is even more of a pain to use. It does seem to work however. Thanks for the reference to the dotnet wrapper. Share this post Link to post
PeterBelow 239 Posted yesterday at 09:16 AM 11 hours ago, Mark Williams said: Same result. It reports true for Server Manager, but then fails with the variant does not reference... error on the call to ServerManager.GetAdminSection. Looks like the GetAdminSection function does not return an automation-compatible interface. Can you check what VarType the returned OleVariant has? Share this post Link to post
Mark Williams 14 Posted 8 hours ago 7 hours ago, PeterBelow said: Looks like the GetAdminSection function does not return an automation-compatible interface. Can you check what VarType the returned OleVariant has? The code I am using was an example I got off the web. Can't even remember where now! Can't fund the MS documentation for it although I can find the documentation for the Application Host Administration Interface. If I change the call as follows: Site := ServerManager.GetAdminSection('sites', 'system.applicationHost/'); I then get an error advising that the first parameter is not a valid section path in the config file. So I think the return value of an OLEVariant is okay. I think the problem lies with the parameters passed to the function. I think the first param is correct 'system.applicationHost/sites'. I think it is the second param that is causing the problem:'MACHINE/WEBROOT/APPHOST'. The second param is already declared in the call to: ServerManager.CommitPath := 'MACHINE/WEBROOT/APPHOST'; That is that is the path to the config file. The MS documentation for the Application Host Administration Interface states it relates to IIS7 and IIS8 and I am using IIS10, but can't find later documentation and I have tested it a little with IIS10 and seems to work. The documentation declares the GetAdminSection function as HRESULT GetAdminSection( [in, string] BSTR bstrSectionName, [in, string] BSTR bstrPath, [out, retval] IAppHostElement** ppAdminSection ); Calling the function as: GetAdminSection('system.applicationHost/', 'MACHINE/WEBROOT/APPHOST', SitesSection); Results in a run time error that there are too many parameters. This works using thee imported type library, but not as an OLE call. That would suggest that the second parameter in the OLE call is also correct. As you can probably see I am floundering! I guess I will have to work with the rather yuk interface! Thanks for your help. Share this post Link to post