如何通过 WiX 3.5 检查 IIS 7 网站是否存在?

发布于 2024-10-02 18:06:38 字数 1104 浏览 0 评论 0原文

注意:这个问题也可以在 上找到WiX 邮件列表

我需要能够根据网站的描述检查 IIS7 网站是否存在。如果该网站不存在,我需要取消安装。如果该网站存在,我想继续安装。我还需要能够保存网站的站点 ID,以便我可以在卸载期间使用它。

出于调试目的,我对网站的描述进行了硬编码。我没有看到任何迹象表明正在 MSI 日志文件中对网站进行检查。这是我正在使用的代码:

 <iis:WebSite Id="IISWEBSITE" Description="Default Web Site" SiteId="*">
      <iis:WebAddress Id="IisWebAddress" Port="1"/>
 </iis:WebSite>

 <Condition Message="Website [IISWEBSITE] not found.">
      <![CDATA[IISWEBSITE]]>
 </Condition>

使用 ORCA 我可以看到 IIsWebAddress 和 IIsWebSite 表已添加到 MSI 中。这些值为:

IIsWebsite

WEB:         IISWEBSITE
Description: Default Web Site
KeyAddress:  IisWebAddress
Id:          -1

IIsWebAddress

Address: IisWebAddress
Web_:    IISWEBSITE
Port:    1
Secure:  0

使用上述代码,安装将停止,并显示错误消息“找不到网站”。看来 IISWEBSITE 永远不会被设置。不过,我知道“默认网站”的存在。我知道我一定错过了一些东西,但是什么呢?

如何在 IIS 7 中执行简单的网站检查是否存在?

Note: This question can also be found on the WiX mailing list.

I need to be able to check for the existence of an IIS7 website based on the website's description. If the website does not exist I need to cancel the installation. If the website exists I want to continue the installation. I also need to be able to save the site id of the website so that I may use it during an uninstall.

For debugging purposes I have hard coded the website's description. I do not see any indication that a check for the website is being made within the MSI log file. This is the code I am using:

 <iis:WebSite Id="IISWEBSITE" Description="Default Web Site" SiteId="*">
      <iis:WebAddress Id="IisWebAddress" Port="1"/>
 </iis:WebSite>

 <Condition Message="Website [IISWEBSITE] not found.">
      <![CDATA[IISWEBSITE]]>
 </Condition>

Using ORCA I can see that IIsWebAddress and IIsWebSite tables are added to the MSI. The values are:

IIsWebsite

WEB:         IISWEBSITE
Description: Default Web Site
KeyAddress:  IisWebAddress
Id:          -1

IIsWebAddress

Address: IisWebAddress
Web_:    IISWEBSITE
Port:    1
Secure:  0

With the above code, the installation is halted with the error message "Website not found". It appears that IISWEBSITE is never getting set. Though, I know that "Default Web Site" exists. I know that I must be missing something, but what?

How can I perform a simple check for the existence of a website in IIS 7?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

坏尐絯℡ 2024-10-09 18:06:38

我也有同样的问题。

我编写了一个自定义操作来从注册表检查 IIS 的版本。

根据注册表值创建虚拟目录

I too had same problem.

I wrote a custom action to check the version of IIS from registry.

On the basis of registry value create virtual directory

蘑菇王子 2024-10-09 18:06:38

我用 Javascript 编写了一个自定义操作来执行此操作。如果您使用的是 IIS7,那么您可以使用 appcmd.exe 工具,只需从 Javascript 中调用它即可获取站点列表。理论上来说,做起来非常简单。但在实践中,你需要跨越一堆障碍。

这是我想出的:

function RunAppCmd(command, deleteOutput) {
    var shell = new ActiveXObject("WScript.Shell"), 
        fso = new ActiveXObject("Scripting.FileSystemObject"), 
        tmpdir = fso.GetSpecialFolder(SpecialFolders.TemporaryFolder), 
        tmpFileName = fso.BuildPath(tmpdir, fso.GetTempName()), 
        windir = fso.GetSpecialFolder(SpecialFolders.WindowsFolder), 
        appcmd = fso.BuildPath(windir,"system32\\inetsrv\\appcmd.exe") + " " + command, 
        rc;

    deleteOutput = deleteOutput || false;

    LogMessage("shell.Run("+appcmd+")");

    // use cmd.exe to redirect the output
    rc = shell.Run("%comspec% /c " + appcmd + "> " + tmpFileName, WindowStyle.Hidden, true);
    LogMessage("shell.Run rc = "  + rc);

    if (deleteOutput) {
        fso.DeleteFile(tmpFileName);
    }
    return {
        rc : rc,
        outputfile : (deleteOutput) ? null : tmpFileName
    };
}



// GetWebSites_Appcmd()
//
// Gets website info using Appcmd.exe, only on IIS7+ .
//
// The return value is an array of JS objects, one per site.
//
function GetWebSites_Appcmd() {
    var r, fso, textStream, sites, oneLine, record,
        ParseOneLine = function(oneLine) {
            // split the string: capture quoted strings, or a string surrounded
            // by parens, or lastly, tokens separated by spaces,
            var tokens = oneLine.match(/"[^"]+"|\(.+\)|[^ ]+/g),
                // split the 3rd string: it is a set of properties separated by colons
                props = tokens[2].slice(1,-1),
                t2 = props.match(/\w+:.+?(?=,\w+:|$)/g),
                bindingsString = t2[1],

                ix1 = bindingsString.indexOf(':'),
                t3 = bindingsString.substring(ix1+1).split(','),
                L1 = t3.length,
                bindings = {}, i, split, obj, p2;

            for (i=0; i<L1; i++) {
                split = t3[i].split('/');
                obj = {};
                if (split[0] == "net.tcp") {
                    p2 = split[1].split(':');
                    obj.port = p2[0];
                }
                else if (split[0] == "net.pipe") {
                    p2 = split[1].split(':');
                    obj.other = p2[0];
                }
                else if (split[0] == "http") {
                    p2 = split[1].split(':');
                    obj.ip = p2[0];
                    if (p2[1]) {
                        obj.port = p2[1];
                    }
                    obj.hostname = "";
                }
                else {
                    p2 = split[1].split(':');
                    obj.hostname = p2[0];
                    if (p2[1]) {
                        obj.port = p2[1];
                    }
                }
                bindings[split[0]] = obj;
            }

            // return the object describing the website
            return {
                id          : t2[0].split(':')[1],
                name        : "W3SVC/" + t2[0].split(':')[1],
                description : tokens[1].slice(1,-1),
                bindings    : bindings,
                state       : t2[2].split(':')[1] // started or not
            };
        };

    LogMessage("GetWebSites_Appcmd() ENTER");

    r = RunAppCmd("list sites");
    if (r.rc !== 0) {
        // 0x80004005 == E_FAIL
        throw new Exception("ApplicationException", "exec appcmd.exe returned nonzero rc ("+r.rc+")", 0x80004005);
    }

    fso = new ActiveXObject("Scripting.FileSystemObject");
    textStream = fso.OpenTextFile(r.outputfile, OpenMode.ForReading);
    sites = [];

    // Read from the file and parse the results.
    while (!textStream.AtEndOfStream) {
        oneLine = textStream.ReadLine();
        record = ParseOneLine(oneLine);
        LogMessage("  site: " + record.name);
        sites.push(record);
    }
    textStream.Close();
    fso.DeleteFile(r.outputfile);

    LogMessage("GetWebSites_Appcmd() EXIT");

    return sites;
}

I wrote a custom action in Javascript to do this. If you are assuming IIS7, then you can use the appcmd.exe tool, and just invoke it from within Javascript to get the list of sites. In theory, it's pretty simple to do. But in practice, there's a bunch of hoops you need to jump through.

Here's what I came up with:

function RunAppCmd(command, deleteOutput) {
    var shell = new ActiveXObject("WScript.Shell"), 
        fso = new ActiveXObject("Scripting.FileSystemObject"), 
        tmpdir = fso.GetSpecialFolder(SpecialFolders.TemporaryFolder), 
        tmpFileName = fso.BuildPath(tmpdir, fso.GetTempName()), 
        windir = fso.GetSpecialFolder(SpecialFolders.WindowsFolder), 
        appcmd = fso.BuildPath(windir,"system32\\inetsrv\\appcmd.exe") + " " + command, 
        rc;

    deleteOutput = deleteOutput || false;

    LogMessage("shell.Run("+appcmd+")");

    // use cmd.exe to redirect the output
    rc = shell.Run("%comspec% /c " + appcmd + "> " + tmpFileName, WindowStyle.Hidden, true);
    LogMessage("shell.Run rc = "  + rc);

    if (deleteOutput) {
        fso.DeleteFile(tmpFileName);
    }
    return {
        rc : rc,
        outputfile : (deleteOutput) ? null : tmpFileName
    };
}



// GetWebSites_Appcmd()
//
// Gets website info using Appcmd.exe, only on IIS7+ .
//
// The return value is an array of JS objects, one per site.
//
function GetWebSites_Appcmd() {
    var r, fso, textStream, sites, oneLine, record,
        ParseOneLine = function(oneLine) {
            // split the string: capture quoted strings, or a string surrounded
            // by parens, or lastly, tokens separated by spaces,
            var tokens = oneLine.match(/"[^"]+"|\(.+\)|[^ ]+/g),
                // split the 3rd string: it is a set of properties separated by colons
                props = tokens[2].slice(1,-1),
                t2 = props.match(/\w+:.+?(?=,\w+:|$)/g),
                bindingsString = t2[1],

                ix1 = bindingsString.indexOf(':'),
                t3 = bindingsString.substring(ix1+1).split(','),
                L1 = t3.length,
                bindings = {}, i, split, obj, p2;

            for (i=0; i<L1; i++) {
                split = t3[i].split('/');
                obj = {};
                if (split[0] == "net.tcp") {
                    p2 = split[1].split(':');
                    obj.port = p2[0];
                }
                else if (split[0] == "net.pipe") {
                    p2 = split[1].split(':');
                    obj.other = p2[0];
                }
                else if (split[0] == "http") {
                    p2 = split[1].split(':');
                    obj.ip = p2[0];
                    if (p2[1]) {
                        obj.port = p2[1];
                    }
                    obj.hostname = "";
                }
                else {
                    p2 = split[1].split(':');
                    obj.hostname = p2[0];
                    if (p2[1]) {
                        obj.port = p2[1];
                    }
                }
                bindings[split[0]] = obj;
            }

            // return the object describing the website
            return {
                id          : t2[0].split(':')[1],
                name        : "W3SVC/" + t2[0].split(':')[1],
                description : tokens[1].slice(1,-1),
                bindings    : bindings,
                state       : t2[2].split(':')[1] // started or not
            };
        };

    LogMessage("GetWebSites_Appcmd() ENTER");

    r = RunAppCmd("list sites");
    if (r.rc !== 0) {
        // 0x80004005 == E_FAIL
        throw new Exception("ApplicationException", "exec appcmd.exe returned nonzero rc ("+r.rc+")", 0x80004005);
    }

    fso = new ActiveXObject("Scripting.FileSystemObject");
    textStream = fso.OpenTextFile(r.outputfile, OpenMode.ForReading);
    sites = [];

    // Read from the file and parse the results.
    while (!textStream.AtEndOfStream) {
        oneLine = textStream.ReadLine();
        record = ParseOneLine(oneLine);
        LogMessage("  site: " + record.name);
        sites.push(record);
    }
    textStream.Close();
    fso.DeleteFile(r.outputfile);

    LogMessage("GetWebSites_Appcmd() EXIT");

    return sites;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文