简体   繁体   English

Inno Setup IIS 安装和配置

[英]Inno Setup IIS Installation and Configuration

I have been trying to figure out how to install and register IIS using an Inno Setup Script, but I have so far been unsuccessful.我一直在尝试弄清楚如何使用 Inno 安装脚本安装和注册 IIS,但到目前为止我还没有成功。

I need to create an application, application pool with.Net version 4 and a virtual directory, get the machine's IP and proceed to edit the bindings of the website with this IP.我需要使用 .Net 版本 4 和虚拟目录创建一个应用程序、应用程序池,获取机器的 IP 并继续使用该 IP 编辑网站的绑定。

So far all that works in my install is checking to see if IIS is installed.到目前为止,我安装中的所有工作都是检查是否安装了 IIS。

If anyone has ever done anything like this before, I would really appreciate if you could share your script.如果有人以前做过这样的事情,如果您能分享您的脚本,我将不胜感激。

Thank you.谢谢你。

Here is my complete code to handle IIS (Internet Information Services) with Inno Setup.这是我使用 Inno Setup 处理 IIS(Internet 信息服务)的完整代码。 It contains:它包含:

  • Installation of .NET Framework 4安装 .NET Framework 4
  • Install/Uninstall of IIS+ASP.NET 4 IIS+ASP.NET 4 安装/卸载
  • Registration and removal of Web-Sites/Apps网站/应用程序的注册和删除
  • Helper to get user-account an app pool is running on获取运行应用程序池的用户帐户的帮助程序
  • Helper to get physical path to a Web-Site帮助获取网站的物理路径

It has been tested with the following Windows editions: XP Pro SP3 x86, 2003 R2 x86, 2003 R2 x64, Vista Ultimate x64, 7 Home Premium x64, 2008 R2 x64, 2011 x64, 8.1 Pro x86, 10 Pro x64它已经过以下 Windows 版本的测试:XP Pro SP3 x86、2003 R2 x86、2003 R2 x64、Vista Ultimate x64、7 Home Premium x64、2008 R2 x64、2011 x64、8.1 Pro x86、10 Pro x64

Everything is done as passive as possible to not break any existing Web-Sites.一切都尽可能被动地完成,以免破坏任何现有的网站。

Important重要的

This might need the Unicode-Version of Inno-Setup (I'm using 5.5.6(u)).这可能需要 Inno-Setup 的Unicode 版本(我使用的是 5.5.6(u))。 It is also required to force 64-bit mode on x64 machines (otherwise registry and file access will redirect to 32-bit stuff):还需要在 x64 机器上强制使用 64 位模式(否则注册表和文件访问将重定向到 32 位内容):

[Setup]
ArchitecturesInstallIn64BitMode=x64

Required Helpers需要帮手

#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif

const
  // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382.aspx
  ERROR_SUCCESS = 0;
  ERROR_INVALID_FUNCTION = 1;
  ERROR_NOT_SUPPORTED = 50;
  ERROR_NOT_FOUND = 1168;
  ERROR_SUCCESS_REBOOT_REQUIRED = 3010;

function ExpandEnvironmentStrings(lpSrc: String; lpDst: String; nSize: DWORD): DWORD;
  external 'ExpandEnvironmentStrings{#AW}@kernel32.dll stdcall';
function ExpandEnvVars(const Input: String): String;
var
  Buf: String;
  BufSize: DWORD;
begin
  BufSize := ExpandEnvironmentStrings(Input, #0, 0);
  if BufSize > 0 then
  begin
    SetLength(Buf, BufSize);
    if ExpandEnvironmentStrings(Input, Buf, BufSize) = 0 then
      RaiseException(Format('Expanding env. strings failed. %s', [SysErrorMessage(DLLGetLastError)]));
#if AW == "A"
    Result := Copy(Buf, 1, BufSize - 2);
#else
    Result := Copy(Buf, 1, BufSize - 1);
#endif
  end
  else
    RaiseException(Format('Expanding env. strings failed. %s', [SysErrorMessage(DLLGetLastError)]));
end;

// Exec with output stored in result. ResultString will only be altered if True is returned.
function ExecWithResult(const Filename, Params, WorkingDir: String; const ShowCmd: Integer; const Wait: TExecWait; var ResultCode: Integer; var ResultString: String): Boolean;
var
  TempFilename: String;
  TempAnsiStr: AnsiString;
  Command: String;
begin
  TempFilename := ExpandConstant('{tmp}\~execwithresult.txt');
  // Exec via cmd and redirect output to file. Must use special string-behavior to work.
  Command := Format('"%s" /S /C ""%s" %s > "%s""', [ExpandConstant('{cmd}'), Filename, Params, TempFilename]);
  Result := Exec(ExpandConstant('{cmd}'), Command, WorkingDir, ShowCmd, Wait, ResultCode);
  if not Result then
    Exit;
  LoadStringFromFile(TempFilename, TempAnsiStr);  // Cannot fail
  ResultString := String(TempAnsiStr);
  DeleteFile(TempFilename);
  // Remove new-line at the end
  if (Length(ResultString) >= 2) and (ResultString[Length(ResultString) - 1] = #13) and (ResultString[Length(ResultString)] = #10) then
    Delete(ResultString, Length(ResultString) - 1, 2);
end;

function IIs7ExecAppCmd(Params: String; var ResultString: String; var ResultCode: Integer): Boolean;
var
  AppCmdFilePath: String;
  Command: String;
begin
  AppCmdFilePath := ExpandConstant('{sys}\inetsrv\appcmd.exe');
  Result := ExecWithResult(AppCmdFilePath, Params, '', SW_HIDE, ewWaitUntilTerminated, ResultCode, ResultString);
end;

.NET 4 Installation .NET 4 安装

Will install .NET 4.0 for Win XP/2003.将为 Win XP/2003 安装 .NET 4.0。 .NET 4.6 for Vista/2008 and later. .NET 4.6 适用于 Vista/2008 及更高版本。 Will do nothing if .NET 4 is already included with the system (Win 8/2012/10).如果 .NET 4 已包含在系统中 (Win 8/2012/10),将不执行任何操作。 The following files are required and must be included in the setup:以下文件是必需的,并且必须包含在设置中:

- -

[Files]
Source: "dotNetFx40_Full_setup.exe"; DestDir: "{tmp}"; Flags: ignoreversion dontcopy
Source: "NDP46-KB3045560-Web.exe"; DestDir: "{tmp}"; Flags: ignoreversion dontcopy
Source: "wic_x64_enu.exe"; DestDir: "{tmp}"; Flags: ignoreversion dontcopy
Source: "wic_x86_enu.exe"; DestDir: "{tmp}"; Flags: ignoreversion dontcopy

Since I'm using the Web-Installers, an internet connection might be required during installation.由于我使用的是 Web 安装程序,因此在安装过程中可能需要 Internet 连接。

// Checks if .NET 4 "Full" is installed
function IsDotNet4FullInstalled(): Boolean;
var
  Success: Boolean;
  Install: Cardinal;
begin
  try
    ExpandConstant('{dotnet40}');  // This will throw an exception if .NET 4 is not installed at all
    Success := RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Install', Install);  // Check for "Full" version
    Result := Success and (Install = 1);
  except
    Result := False;
  end;
end;

// Returns True if a restart is required.
function InstallDotNet4(): Boolean;
var
  Version: TWindowsVersion;
  ResultCode: Integer;
  Success: Boolean;
begin
  GetWindowsVersionEx(Version);
  if (Version.Major <= 5) then  // 4.0 for XP, 2003
    ExtractTemporaryFile('dotNetFx40_Full_setup.exe')
  else  // 4.6
    ExtractTemporaryFile('NDP46-KB3045560-Web.exe');
  if (Version.Major <= 5) then  // XP, 2003: Install .NET 4.0
  begin
    Success := Exec(ExpandConstant('{tmp}\dotNetFx40_Full_setup.exe'), '/passive', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
    if Success and (ResultCode = 5100) then  // Indicates that "Windows Imaging Component" is missing (probably 2003)
    begin
      if IsWin64 then
      begin
        ExtractTemporaryFile('wic_x64_enu.exe');
        if not Exec(ExpandConstant('{tmp}\wic_x64_enu.exe'), '/passive', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) or (ResultCode <> ERROR_SUCCESS) then
          RaiseException('Failed to install "Windows Imaging Component": ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
        // Retry .NET
        Success := Exec(ExpandConstant('{tmp}\dotNetFx40_Full_setup.exe'), '/passive', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
      end
      else
      begin
        ExtractTemporaryFile('wic_x86_enu.exe');
        if not Exec(ExpandConstant('{tmp}\wic_x86_enu.exe'), '/passive', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) or (ResultCode <> ERROR_SUCCESS) then
          RaiseException('Failed to install "Windows Imaging Component": ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
        // Retry .NET
        Success := Exec(ExpandConstant('{tmp}\dotNetFx40_Full_setup.exe'), '/passive', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
      end;
    end
  end
  else  // Vista / 2008 or later: Install .NET 4.6
    Success := Exec(ExpandConstant('{tmp}\NDP46-KB3045560-Web.exe'), '/passive', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
  // Check for errors
  if not Success or ((ResultCode <> ERROR_SUCCESS) and (ResultCode <> ERROR_SUCCESS_REBOOT_REQUIRED)) then
    RaiseException('Failed to install .NET: ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
  Result := ResultCode = ERROR_SUCCESS_REBOOT_REQUIRED;
end;

IIS Installation / Uninstall IIS 安装/卸载

Installs IIS with ASP.NET 4. Will activate the same (default-)features as if it was activated via GUI.使用 ASP.NET 4 安装 IIS。将激活与通过 GUI 激活相同的(默认)功能。 After installation is completed, ASP.NET is (re-)registered with IIS.安装完成后,ASP.NET 将(重新)注册到 IIS。

Note: For Win XP/2003, the "Windows Installation CD" is required.注意:对于 Win XP/2003,需要“Windows 安装光盘”。

// Returns True if a restart is required. Throws exceptions.
function InstallIIs(): Boolean;
var
  Version: TWindowsVersion;
  Success: Boolean;
  ResultCode: Integer;
  IIS56IniFile: String;
begin
  GetWindowsVersionEx(Version);
  if (Version.Major <= 5) then  // XP / 2003: Use "sysocmgr"
  begin
    IIS56IniFile := ExpandConstant('{tmp}\~iis56.ini');
    SaveStringToFile(IIS56IniFile, '[Components]' + #13#10 + 'iis_common = ON' + #13#10 + 'iis_www = ON' + #13#10 + 'iis_inetmgr = ON', False);
    Success := Exec('sysocmgr', ExpandConstant('/i:"{win}\inf\sysoc.inf" /u:"' + IIS56IniFile + '"'), '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
    DeleteFile(IIS56IniFile);
  end
  else if (Version.Major = 6) and (Version.Minor = 0) then  // Vista / 2008: Use "pkgmgr"
  begin
    Success := Exec('pkgmgr', '/iu:' +
      // Enables everything a fresh install would also (implicitly) enable.
      // This is important in case IIS was already installed and some features manually disabled.
      'WAS-WindowsActivationService;WAS-ProcessModel;WAS-NetFxEnvironment;WAS-ConfigurationAPI' +
      ';IIS-WebServerRole' +
      ';IIS-WebServerManagementTools;IIS-ManagementConsole' +
      ';IIS-WebServer' +
      ';IIS-ApplicationDevelopment;IIS-NetFxExtensibility;IIS-ASPNET;IIS-ISAPIExtensions;IIS-ISAPIFilter' +
      ';IIS-CommonHttpFeatures;IIS-HttpErrors;IIS-DefaultDocument;IIS-StaticContent;IIS-DirectoryBrowsing' +
      ';IIS-Performance;IIS-HttpCompressionStatic' +
      ';IIS-Security;IIS-RequestFiltering' +
      ';IIS-HealthAndDiagnostics;IIS-RequestMonitor;IIS-HttpLogging',
      '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
  end
  else if (Version.Major = 6) and (Version.Minor = 1) then  // 7 / 2008 R2 / 2011: Use "Dism"
  begin
    Success := Exec('Dism', '/Online /Enable-Feature' +
      // Enables everything a fresh install would also (implicitly) enable.
      // This is important in case IIS was already installed and some features manually disabled.
      // "Parent fetaures" are NOT automatically enabled by "Dism".
      ' /FeatureName:WAS-WindowsActivationService /FeatureName:WAS-ProcessModel /FeatureName:WAS-NetFxEnvironment /FeatureName:WAS-ConfigurationAPI' +
      ' /FeatureName:IIS-WebServerRole' +
      ' /FeatureName:IIS-WebServerManagementTools /FeatureName:IIS-ManagementConsole' +
      ' /FeatureName:IIS-WebServer' +
      ' /FeatureName:IIS-ApplicationDevelopment /FeatureName:IIS-NetFxExtensibility /FeatureName:IIS-ASPNET /FeatureName:IIS-ISAPIExtensions /FeatureName:IIS-ISAPIFilter' +
      ' /FeatureName:IIS-CommonHttpFeatures /FeatureName:IIS-HttpErrors /FeatureName:IIS-DefaultDocument /FeatureName:IIS-StaticContent /FeatureName:IIS-DirectoryBrowsing' +
      ' /FeatureName:IIS-Performance /FeatureName:IIS-HttpCompressionStatic' +
      ' /FeatureName:IIS-Security /FeatureName:IIS-RequestFiltering' +
      ' /FeatureName:IIS-HealthAndDiagnostics /FeatureName:IIS-RequestMonitor /FeatureName:IIS-HttpLogging',
      '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
  end
  else  // 8 / 2012 and later: Use "Dism"
  begin
    Success := Exec('Dism', '/Online /Enable-Feature' +
      // Enables everything a fresh install would also (implicitly) enable.
      // This is important in case IIS was already installed and some features manually disabled.
      ' /FeatureName:WAS-WindowsActivationService /FeatureName:WAS-ProcessModel /FeatureName:WAS-NetFxEnvironment /FeatureName:WAS-ConfigurationAPI' +
      ' /FeatureName:IIS-ManagementConsole' +
      ' /FeatureName:IIS-HttpErrors /FeatureName:IIS-DefaultDocument /FeatureName:IIS-StaticContent /FeatureName:IIS-DirectoryBrowsing' +
      ' /FeatureName:IIS-ASPNET45' +
      ' /FeatureName:IIS-HttpCompressionStatic' +
      ' /FeatureName:IIS-RequestFiltering' +
      ' /FeatureName:IIS-HttpLogging' +
      ' /All',  // Implicitly enables dependent features
      '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
  end;
  if not Success or ((ResultCode <> ERROR_SUCCESS) and (ResultCode <> ERROR_SUCCESS_REBOOT_REQUIRED)) then
    RaiseException('Cannot install IIS: ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
  Result := ResultCode = ERROR_SUCCESS_REBOOT_REQUIRED;
  // Register ASP.NET 4 with IIS. This is required since .NET 4 was probably installed before IIS.
  // This will NOT change existing web-sites (which might be using other ASP.NET versions already)
  if not Exec(ExpandConstant('{dotnet40}') + '\aspnet_regiis.exe', '-iru -enable', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) or
    (ResultCode <> ERROR_SUCCESS) then
    RaiseException('Cannot register ASP.NET: ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
end;

// Returns True if a restart is required. Throws exceptions.
function UninstallIIs(): Boolean;
var
  Version: TWindowsVersion;
  Success: Boolean;
  ResultCode: Integer;
  IIS56IniFile: String;
begin
  GetWindowsVersionEx(Version);
  if (Version.Major <= 5) then  // XP / 2003: Use "sysocmgr"
  begin
    IIS56IniFile := ExpandConstant('{tmp}\~iis56.ini');
    SaveStringToFile(IIS56IniFile, '[Components]' + #13#10 + 'iis_common = OFF' + #13#10 + 'iis_www = OFF' + #13#10 + 'iis_inetmgr = OFF', False);
    Success := Exec('sysocmgr', ExpandConstant('/i:"{win}\inf\sysoc.inf" /u:"' + IIS56IniFile + '"'), '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
    DeleteFile(IIS56IniFile);
  end
  else if (Version.Major = 6) and (Version.Minor = 0) then  // Vista / 2008: Use "pkgmgr"
    Success := Exec('pkgmgr', '/norestart /uu:IIS-WebServerRole', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
  else  // 7 / 2008 R2 and later: Use "Dism"
    Success := Exec('Dism', '/NoRestart /Online /Disable-Feature /FeatureName:IIS-WebServerRole', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
  if not Success or ((ResultCode <> ERROR_SUCCESS) and (ResultCode <> ERROR_SUCCESS_REBOOT_REQUIRED)) then
    RaiseException('Cannot uninstall IIS: ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
  Result := ResultCode = ERROR_SUCCESS_REBOOT_REQUIRED;
end;

Web-Site/App Registration and Removal网站/应用程序注册和删除

Creates a virtual directory and an ASP.NET 4 Application Pool.创建虚拟目录和 ASP.NET 4 应用程序池。

Note: IIsServerNumber is the actual Web-Site which usually defaults to 1 (=> "Default Web Site").注意:IIsServerNumber 是实际的网站,通常默认为 1(=>“默认网站”)。

Usage:用法:

RegisterAppAtIIs('MyAppName', 1, 'MyAppAppPoolName');
DeleteAppFromIIs('MyAppName', 1, 'MyAppAppPoolName');
// Throws exceptions.
procedure RegisterAppAtIIs(const IIsAppName: String; const IIsServerNumber: Integer; const IIsApplicationPoolName: String);
var
  Version: TWindowsVersion;
  // IIS 5.1 - 6.0
  IIS, WebService, WebSite, WebRoot, vDir, AppPools, AppPool: Variant;
  // IIS 7 and later
  ResultCode: Integer;
  ExecResult: String;
  WebSiteName: String;
begin
  GetWindowsVersionEx(Version);
  if (Version.Major = 5) and (Version.Minor <= 2) then  // XP, 2003: IIS 5.1 - 6.0
  begin
    try
      // Create the main IIS COM Automation object
      IIS := CreateOleObject('IISNamespace');
      WebService := IIS.GetObject('IIsWebService', 'localhost/W3SVC');
      // Get web site
      WebSite := WebService.GetObject('IIsWebServer', IntToStr(IIsServerNumber));
      WebRoot := WebSite.GetObject('IIsWebVirtualDir', 'Root');
    except
      RaiseException(Format('Web-site #%d not found: ', [IIsServerNumber]) + GetExceptionMessage());
    end;
    // Delete the virtual dir if it already exists
    try
      WebRoot.Delete('IIsWebVirtualDir', IIsAppName);
      WebRoot.SetInfo();
    except
    end;
    if (Version.Minor = 1) then  // XP: IIS 5.1
    begin
      // Create the virtual directory
      try
        vDir := WebRoot.Create('IIsWebVirtualDir', IIsAppName);
        vDir.AccessRead := True;
        vDir.AccessScript := True;
        vDir.AppFriendlyName := IIsAppName;
        vDir.Path := ExpandConstant('{app}');
        vDir.AppCreate(True);  // Create in "InProc" mode (don't really know why though)
        vDir.SetInfo();
      except
        RaiseException('Cannot create virtual directory: ' + GetExceptionMessage());
      end;
    end
    else if (Version.Minor = 2) then  // 2003: IIS 6.0
    begin
      // Application pool stuff
      AppPools := WebService.GetObject('IIsApplicationPools', 'AppPools');
      try
        // Check if the application pool already exists
        AppPool := AppPools.GetObject('IIsApplicationPool', IIsApplicationPoolName);
      except
        AppPool := Null;
      end;
      if VarIsNull(AppPool) then
      begin
        // Create the application pool
        try
          AppPool := AppPools.Create('IIsApplicationPool', IIsApplicationPoolName);
          AppPool.SetInfo();
        except
          RaiseException('Cannot add application pool: ' + GetExceptionMessage());
        end;
      end;
      // Create the virtual directory
      try
        vDir := WebRoot.Create('IIsWebVirtualDir', IIsAppName);
        vDir.AccessRead := True;
        vDir.AccessScript := True;
        vDir.AppFriendlyName := IIsAppName;
        vDir.Path := ExpandConstant('{app}');
        vDir.AppCreate(True);  // Create in "InProc" mode
        vDir.AppPoolId := IIsApplicationPoolName;
        vDir.SetInfo();
      except
        RaiseException('Cannot create virtual directory: ' + GetExceptionMessage());
      end;
    end;
    // Register handlers for ASP.NET 4 (important if other ASP.NET versions are present)
    if not ExecWithResult(ExpandConstant('{dotnet40}') + '\aspnet_regiis.exe',Format('-s "W3SVC/%d/ROOT/%s"', [IIsServerNumber, IIsAppName]),'',SW_HIDE,ewWaitUntilTerminated, ResultCode, ExecResult) or (ResultCode <> ERROR_SUCCESS) then
      RaiseException('Cannot set ASP.NET version: ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
  end
  else if (Version.Major >= 6) then  // Vista / 2008 or later : IIS 7 or later
  begin
    // Get name of web-site
    if not IIs7ExecAppCmd(Format('list site /id:%d /text:name', [IIsServerNumber]), ExecResult, ResultCode) then
      RaiseException(Format('Cannot get name of web-site #%d: ', [IIsServerNumber]) + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
    if (Length(Trim(ExecResult)) = 0) then
      RaiseException(Format('Web-site #%d not found.', [IIsServerNumber]));
    WebSiteName := ExecResult;
    // Delete the application if it already exists
    if not IIs7ExecAppCmd(Format('delete app "%s/%s"', [WebSiteName, IIsAppName]), ExecResult, ResultCode) or
      ((ResultCode <> ERROR_SUCCESS) and (ResultCode <> ERROR_NOT_FOUND) and (ResultCode <> ERROR_NOT_SUPPORTED)) then
      RaiseException('Cannot delete application: ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
    // Check if the application pool already exists (we don't delete it, since another GVS instance might be using it too)
    if not IIs7ExecAppCmd(Format('list apppool "%s" /text:name', [IIsApplicationPoolName]), ExecResult, ResultCode) or
      ((ResultCode <> ERROR_SUCCESS) and (ResultCode <> ERROR_INVALID_FUNCTION)) then
      RaiseException('Cannot list application pools: ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
    // Create the application pool
    if (ExecResult <> IIsApplicationPoolName) then
    begin
      if not IIs7ExecAppCmd(Format('add apppool /name:"%s" /managedRuntimeVersion:v4.0', [IIsApplicationPoolName]), ExecResult, ResultCode) or (ResultCode <> ERROR_SUCCESS) then
        RaiseException('Cannot add application pool: ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
    end;
    // Create the application
    if not IIs7ExecAppCmd(Format('add app /site.name:"%s" /path:"/%s" /physicalPath:"%s" /applicationPool:"%s"', [WebSiteName, IIsAppName, ExpandConstant('{app}'), IIsApplicationPoolName]), ExecResult, ResultCode) or
      (ResultCode <> ERROR_SUCCESS) then
      RaiseException('Cannot add application: ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
  end
  else
    RaiseException('Cannot register web-site: Unknown OS version.');
end;

// Throws exceptions.
procedure DeleteAppFromIIs(const IIsAppName: String; const IIsServerNumber: Integer; const IIsApplicationPoolName: String);
var
  Version: TWindowsVersion;
  // IIS 5.1 - 6.0
  IIS, WebService, WebSite, WebRoot, AppPools: Variant;
  // IIS 7 and later
  ResultCode: Integer;
  ExecResult: String;
  WebSiteName: String;
begin
  GetWindowsVersionEx(Version);
  if (Version.Major = 5) and (Version.Minor <= 2) then  // XP, 2003: IIS 5.1 - 6.0
  begin
    try
      // Create the main IIS COM Automation object
      IIS := CreateOleObject('IISNamespace');
      WebService := IIS.GetObject('IIsWebService', 'localhost/W3SVC');
      // Get web site
      WebSite := WebService.GetObject('IIsWebServer', IntToStr(IIsServerNumber));
      WebRoot := WebSite.GetObject('IIsWebVirtualDir', 'Root');
    except
      RaiseException(Format('Web-site #%d not found: ', [IIsServerNumber]) + GetExceptionMessage());
    end;
    // Delete the virtual dir
    try
      WebRoot.Delete('IIsWebVirtualDir', IIsAppName);
      WebRoot.SetInfo();
    except
    end;
    if (Version.Minor = 2) then  // 2003: IIS 6.0
    begin
      // Application pool stuff
      AppPools := WebService.GetObject('IIsApplicationPools', 'AppPools');
      try
        // Delete the application pool
        AppPools.Delete('IIsApplicationPool', IIsApplicationPoolName);
      except
      end;
    end;
  end
  else if (Version.Major >= 6) then  // Vista / 2008 or later : IIS 7 or later
  begin
    // Get name of web-site
    if not IIs7ExecAppCmd(Format('list site /id:%d /text:name', [IIsServerNumber]), ExecResult, ResultCode) then
      RaiseException(Format('Cannot get name of web-site #%d: ', [IIsServerNumber]) + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
    if (Length(Trim(ExecResult)) = 0) then
      RaiseException(Format('Web-site #%d not found.', [IIsServerNumber]));
    WebSiteName := ExecResult;
    // Delete the application
    if not IIs7ExecAppCmd(Format('delete app "%s/%s"', [WebSiteName, IIsAppName]), ExecResult, ResultCode) or
      ((ResultCode <> ERROR_SUCCESS) and (ResultCode <> ERROR_NOT_FOUND) and (ResultCode <> ERROR_NOT_SUPPORTED)) then
      RaiseException('Cannot delete application: ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
    // Delete the application pool
    if not IIs7ExecAppCmd(Format('delete apppool "%s"', [IIsApplicationPoolName]), ExecResult, ResultCode) or
      ((ResultCode <> ERROR_SUCCESS) and (ResultCode <> ERROR_NOT_FOUND)) then
      RaiseException('Cannot delete application pool: ' + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
  end
  else
    RaiseException('Cannot delete web-site: Unknown OS version.');
end;

Useful Helpers有用的帮手

Finds the Windows user-account used by ASP.NET to read/write files in the virtual directory.查找 ASP.NET 用于读取/写入虚拟目录中的文件的 Windows 用户帐户。 Useful to set permissions for "App_Data".用于设置“App_Data”的权限。

// Throws exceptions.
function GetIIsAppPoolIdentity(const IIsApplicationPoolName: String): String;
var
  Version: TWindowsVersion;
  ResultCode: Integer;
  ExecResult: String;
  IIS, AppPool: Variant;
begin
  GetWindowsVersionEx(Version);
  if (Version.Major = 5) and (Version.Minor = 1) then  // XP: IIS 5.1
  begin
    // TODO: Should be read from "[.NET 4]\Config\machine.config" -> system.web.processModel.userName
    // - "System"
    // - "Machine" -> "ASPNET" (default)
    // - A custom user account
    // See https://msdn.microsoft.com/en-us/library/dwc1xthy.aspx
    Result := 'ASPNET';
  end
  else if (Version.Major = 5) and (Version.Minor = 2) then  // 2003: IIS 6.0
  begin
    try
      IIS := CreateOleObject('IISNamespace');
      AppPool := IIS.GetObject('IIsApplicationPool', 'localhost/W3SVC/AppPools/' + IIsApplicationPoolName);
      if (AppPool.AppPoolIdentityType = 0) then
        Result := 'NT AUTHORITY\SYSTEM'
      else if (AppPool.AppPoolIdentityType = 1) then
        Result := 'NT AUTHORITY\LOCAL SERVICE'
      else if (AppPool.AppPoolIdentityType = 2) then
        Result := 'NT AUTHORITY\NETWORKSERVICE'
      else if (AppPool.AppPoolIdentityType = 3) then
        Result := AppPool.WAMUserName
      else
        RaiseException('Cannot get application pool identity: Unknown identity type (' + IntToStr(AppPool.AppPoolIdentityType) + ')');
    except
      RaiseException('Cannot get application pool identity: Unable to get object');
    end;
  end
  else if (Version.Major >= 6) then  // Vista / 2008 or later
  begin
    if not IIs7ExecAppCmd(Format('list apppool "%s" /text:processModel.identityType', [IIsApplicationPoolName]), ExecResult, ResultCode) or
      (ResultCode <> ERROR_SUCCESS) then
      RaiseException('Cannot get application pool identity.');
    if (ExecResult = 'LocalSystem') then
      Result := 'NT AUTHORITY\SYSTEM'
    else if (ExecResult = 'LocalService') then
      Result := 'NT AUTHORITY\LOCAL SERVICE'
    else if (ExecResult = 'NetworkService') then
      Result := 'NT AUTHORITY\NETWORKSERVICE'
    else if (ExecResult = 'ApplicationPoolIdentity') then
      Result := 'IIS AppPool\' + IIsApplicationPoolName
    else
      RaiseException('Cannot get application pool identity: Unknown identity type "' + ExecResult + '"');
  end
  else
    RaiseException('Cannot get application pool identity: Unknown OS version: ' + IntToStr(Version.Major) + '.' + IntToStr(Version.Minor));
end;

Returns the physical path to a Web-Site.返回网站的物理路径。 Useful to find the correct place to install files to.有助于找到安装文件的正确位置。

// Throws exceptions.
function IIsGetPhysicalPath(const IIsServerNumber: Integer): String;
var
  Version: TWindowsVersion;
  IIS, WebService, WebSite, WebRoot: Variant;
  ResultCode: Integer;
  ExecResult: String;
  WebSiteName: String;
  PhysPath: String;
begin
  GetWindowsVersionEx(Version);
  if (Version.Major = 5) then
  begin
    try
      // Create the main IIS COM Automation object
      IIS := CreateOleObject('IISNamespace');
      WebService := IIS.GetObject('IIsWebService', 'localhost/W3SVC');
      // Get web site
      WebSite := WebService.GetObject('IIsWebServer', IntToStr(IIsServerNumber));
      WebRoot := WebSite.GetObject('IIsWebVirtualDir', 'Root');
    except
      RaiseException(Format('Web-site #%d not found: ', [IIsServerNumber]) + GetExceptionMessage());
    end;
    PhysPath := WebRoot.Path;
  end
  else if (Version.Major >= 6) then  // Vista / 2008 or later
  begin
    // Get name of web-site
    if not IIs7ExecAppCmd(Format('list site /id:%d /text:name', [IIsServerNumber]), ExecResult, ResultCode) then
      RaiseException(Format('Cannot get name of web-site #%d: ', [IIsServerNumber]) + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
    if (Length(Trim(ExecResult)) = 0) then
      RaiseException(Format('Web-site #%d not found.', [IIsServerNumber]));
    WebSiteName := ExecResult;
    // Get physical path
    if not IIs7ExecAppCmd(Format('list vdir /app.name:"%s"/ /text:physicalPath', [WebSiteName]), ExecResult, ResultCode) or
      (ResultCode <> ERROR_SUCCESS) then
      RaiseException(Format('Cannot get physical path to web-site "%s": ', [WebSiteName]) + SysErrorMessage(ResultCode) + ' (' + IntToStr(ResultCode) + ')');
    PhysPath := ExecResult;
  end
  else
    RaiseException('Cannot get physical path to web-site root: Unknown OS version: ' + IntToStr(Version.Major) + '.' + IntToStr(Version.Minor));
  // Expand environment variables in path (e.g. "%SystemDrive%")
  Result := ExpandEnvVars(PhysPath);
end;

So, in the end what I did was create a separate executable coded in C# which will install IIS through the command line before installation and will then register IIS with the appropriate application pool etc after installation.所以,最后我所做的是创建一个用 C# 编码的单独的可执行文件,它将在安装前通过命令行安装 IIS,然后在安装后将 IIS 注册到适当的应用程序池等。 I then proceeded to call the executable through Inno Setup in PrepareToInstall to install IIS, and in CurStepChanged to register IIS.然后,我继续通过 PrepareToInstall 中的 Inno Setup 调用可执行文件来安装 IIS,并在 CurStepChanged 中调用可执行文件来注册 IIS。

we are using also IIS and thinking about to automate the IIS installation.我们也在使用 IIS 并考虑自动化 IIS 安装。 As far as I know is it possible to do all the stuff via command line tools.据我所知,是否可以通过命令行工具完成所有工作。 So you can create your own Inno Custom Pages to retrieve the necessary data from the user.因此,您可以创建自己的 Inno 自定义页面以从用户那里检索必要的数据。 (You can use the Inno Setup Form Designer for this). (您可以为此使用 Inno Setup Form Designer)。 Once you've collected all your stuff, you can create and then fill your prepared template batch files and in the post install the batches will be executed.一旦你收集了所有的东西,你就可以创建并填充你准备好的模板批处理文件,并且在安装后将执行批处理。

I would try it like this:我会这样尝试:

  • try to do everything with a batch file concerning your IIS installation (Take a look at this archived page尝试使用有关 IIS 安装的批处理文件完成所有操作(查看此存档页面
  • when you can do anything with batch files for the IIS Configuration, then you need to make template batch files for the Inno setup当您可以对 IIS 配置的批处理文件执行任何操作时,您需要为 Inno 设置制作模板批处理文件
  • create custom pages for Inno to retrieve the necessary data为 Inno 创建自定义页面以检索必要的数据
  • in Inno, replace the template batches with the variables在 Inno 中,用变量替换模板批次
  • execute the batches in Inno在 Inno 中执行批处理

Hope this helps希望这可以帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM