Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iis 7 如何使用wix在IIS中的文件夹下创建虚拟目录_Iis 7_Wix_Wix3.5 - Fatal编程技术网

Iis 7 如何使用wix在IIS中的文件夹下创建虚拟目录

Iis 7 如何使用wix在IIS中的文件夹下创建虚拟目录,iis-7,wix,wix3.5,Iis 7,Wix,Wix3.5,我想使用Wix在以下现有IIS结构下创建虚拟目录foo //默认网站/mywebapp/editor 在上面的代码片段中,“mywebapp”是一个web应用程序,编辑器是其中的一个非虚拟文件夹。我的新虚拟目录“foo”需要在非虚拟文件夹“editor”中创建 我正在使用IIS7和WIX3.5 可以使用标记完成上述操作,还是需要编写自定义操作来完成 提前谢谢这是个好问题 我没有直接的经验,但是。。。当面临类似的挑战时——使用WiX将ISAPI作为IIS扩展安装到特定的虚拟目录上——我求助于使用J

我想使用Wix在以下现有IIS结构下创建虚拟目录foo

//默认网站/mywebapp/editor

在上面的代码片段中,“mywebapp”是一个web应用程序,编辑器是其中的一个非虚拟文件夹。我的新虚拟目录“foo”需要在非虚拟文件夹“editor”中创建

我正在使用IIS7和WIX3.5

可以使用标记完成上述操作,还是需要编写自定义操作来完成


提前谢谢

这是个好问题

我没有直接的经验,但是。。。当面临类似的挑战时——使用WiX将ISAPI作为IIS扩展安装到特定的虚拟目录上——我求助于使用Javascript实现的自定义操作,在一种情况下,使用VBScript。我发现WiX有一些我需要的东西,但是找到正确的信息很困难,而且并非所有的IIS管理函数都是通过WiX公开的。此外,信不信由你,并不是所有IIS管理员的东西都暴露在Javascript中。在一种情况下,WMI接口需要VBArray

此外,在自定义操作中,代码有时会调用APPCMD.exe来执行实际工作,而不是仅仅依赖IIS WMI编程接口。如果你预先要求IIS7,那么你将拥有这个。使用appcmd创建一个vdir或app将非常简单appcmd add app或appcmd add vdir。对我来说,最困难的部分是围绕它包装必要的支持Javascript和WiX代码。我是这样做的

在主product.wxs文件中:

<InstallExecuteSequence>
   ...
  <!-- configure extension if we need it -->
  <Custom Action="CA.AddExtension" After="InstallFiles">NOT Installed AND &amp;F.Binary = 3</Custom>
  ...
</InstallExecuteSequence>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Fragment>
    <Binary Id="B.JavaScript" SourceFile="CustomActions.js" />
    <Binary Id="B.VBScript" SourceFile="MoreCustomActions.vbs" />

    <CustomAction Id="CA.EnumerateWebSites"
                  BinaryKey="B.JavaScript"
                  JScriptCall="EnumerateWebSites_CA"
                  Execute="immediate"
                  Return="check" />

    <CustomAction Id="CA.AddExtension"
                  BinaryKey="B.VBScript"
                  VBScriptCall="AddExtension_CA"
                  Execute="immediate"
                  Return="check" />

     ....
还有一个单独的customactions.wxs文件:

<InstallExecuteSequence>
   ...
  <!-- configure extension if we need it -->
  <Custom Action="CA.AddExtension" After="InstallFiles">NOT Installed AND &amp;F.Binary = 3</Custom>
  ...
</InstallExecuteSequence>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Fragment>
    <Binary Id="B.JavaScript" SourceFile="CustomActions.js" />
    <Binary Id="B.VBScript" SourceFile="MoreCustomActions.vbs" />

    <CustomAction Id="CA.EnumerateWebSites"
                  BinaryKey="B.JavaScript"
                  JScriptCall="EnumerateWebSites_CA"
                  Execute="immediate"
                  Return="check" />

    <CustomAction Id="CA.AddExtension"
                  BinaryKey="B.VBScript"
                  VBScriptCall="AddExtension_CA"
                  Execute="immediate"
                  Return="check" />

     ....
然后javascript看起来像这样:

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

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

    // use cmd.exe to redirect the output
    var 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+ .
//
// This fn always returns site state info with each record.
//
function GetWebSites_Appcmd() {
    var 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
        var props = tokens[2].slice(1,-1);
        var t2 = props.match(/\w+:.+?(?=,\w+:|$)/g);
        var bindingsString = t2[1];
        //say(bindingsString);
        var ix1 = bindingsString.indexOf(':');
        var t3 = bindingsString.substring(ix1+1).split(',');

        var bindings = {};
        for (var i=0; i<t3.length; i++) {
            var split = t3[i].split('/');
            var obj = {};
            if (split[0] == "net.tcp") {
                var p2 = split[1].split(':');
                obj.port = p2[0];
            }
            else if (split[0] == "net.pipe") {
                var p3 = split[1].split(':');
                obj.other = p3[0];
            }
            else if (split[0] == "http") {
                var p4 = split[1].split(':');
                obj.ip = p4[0];
                if (p4[1]) {
                    obj.port = p4[1];
                }
                obj.hostname = "";
            }
            else {
                var p5 = split[1].split(':');
                obj.hostname = p5[0];
                if (p5[1]) {
                    obj.port = p5[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");

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

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

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

    LogMessage("GetWebSites_Appcmd() EXIT");

    return sites;
}

也许你会发现这很有用。

这是个好问题

我没有直接的经验,但是。。。当面临类似的挑战时——使用WiX将ISAPI作为IIS扩展安装到特定的虚拟目录上——我求助于使用Javascript实现的自定义操作,在一种情况下,使用VBScript。我发现WiX有一些我需要的东西,但是找到正确的信息很困难,而且并非所有的IIS管理函数都是通过WiX公开的。此外,信不信由你,并不是所有IIS管理员的东西都暴露在Javascript中。在一种情况下,WMI接口需要VBArray

此外,在自定义操作中,代码有时会调用APPCMD.exe来执行实际工作,而不是仅仅依赖IIS WMI编程接口。如果你预先要求IIS7,那么你将拥有这个。使用appcmd创建一个vdir或app将非常简单appcmd add app或appcmd add vdir。对我来说,最困难的部分是围绕它包装必要的支持Javascript和WiX代码。我是这样做的

在主product.wxs文件中:

<InstallExecuteSequence>
   ...
  <!-- configure extension if we need it -->
  <Custom Action="CA.AddExtension" After="InstallFiles">NOT Installed AND &amp;F.Binary = 3</Custom>
  ...
</InstallExecuteSequence>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Fragment>
    <Binary Id="B.JavaScript" SourceFile="CustomActions.js" />
    <Binary Id="B.VBScript" SourceFile="MoreCustomActions.vbs" />

    <CustomAction Id="CA.EnumerateWebSites"
                  BinaryKey="B.JavaScript"
                  JScriptCall="EnumerateWebSites_CA"
                  Execute="immediate"
                  Return="check" />

    <CustomAction Id="CA.AddExtension"
                  BinaryKey="B.VBScript"
                  VBScriptCall="AddExtension_CA"
                  Execute="immediate"
                  Return="check" />

     ....
还有一个单独的customactions.wxs文件:

<InstallExecuteSequence>
   ...
  <!-- configure extension if we need it -->
  <Custom Action="CA.AddExtension" After="InstallFiles">NOT Installed AND &amp;F.Binary = 3</Custom>
  ...
</InstallExecuteSequence>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Fragment>
    <Binary Id="B.JavaScript" SourceFile="CustomActions.js" />
    <Binary Id="B.VBScript" SourceFile="MoreCustomActions.vbs" />

    <CustomAction Id="CA.EnumerateWebSites"
                  BinaryKey="B.JavaScript"
                  JScriptCall="EnumerateWebSites_CA"
                  Execute="immediate"
                  Return="check" />

    <CustomAction Id="CA.AddExtension"
                  BinaryKey="B.VBScript"
                  VBScriptCall="AddExtension_CA"
                  Execute="immediate"
                  Return="check" />

     ....
然后javascript看起来像这样:

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

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

    // use cmd.exe to redirect the output
    var 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+ .
//
// This fn always returns site state info with each record.
//
function GetWebSites_Appcmd() {
    var 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
        var props = tokens[2].slice(1,-1);
        var t2 = props.match(/\w+:.+?(?=,\w+:|$)/g);
        var bindingsString = t2[1];
        //say(bindingsString);
        var ix1 = bindingsString.indexOf(':');
        var t3 = bindingsString.substring(ix1+1).split(',');

        var bindings = {};
        for (var i=0; i<t3.length; i++) {
            var split = t3[i].split('/');
            var obj = {};
            if (split[0] == "net.tcp") {
                var p2 = split[1].split(':');
                obj.port = p2[0];
            }
            else if (split[0] == "net.pipe") {
                var p3 = split[1].split(':');
                obj.other = p3[0];
            }
            else if (split[0] == "http") {
                var p4 = split[1].split(':');
                obj.ip = p4[0];
                if (p4[1]) {
                    obj.port = p4[1];
                }
                obj.hostname = "";
            }
            else {
                var p5 = split[1].split(':');
                obj.hostname = p5[0];
                if (p5[1]) {
                    obj.port = p5[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");

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

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

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

    LogMessage("GetWebSites_Appcmd() EXIT");

    return sites;
}

也许你会发现这很有用。

最后我找到了一个简单的解决方案。了解到我们可以使用相对路径作为webvirtualdir元素的别名属性。因此,为了创建虚拟文件夹foo,我做了以下操作

使用网站元素引用了默认网站

<iis:WebSite  Id="My.Site" Description="Default Website">
  <iis:WebAddress Id="My.Web.Address" Port="12300"/>
</iis:WebSite>
添加了webvirtualdir元素,别名设置为mywebapp/editor/foo webapp/subfolder/virtualdir

<Directory Id="TARGETDIR" Name="SourceDir">
 <Directory Id="ProgramFilesFolder">
    <Directory Id="INSTALLLOCATION" Name="IISDemo">
      <Component Id="IIS.Component" Guid="{6FAD9EC7-D2B0-4471-A657-C8AF5F6F707F}" KeyPath="yes">
        <iis:WebVirtualDir Id="My.VirtualDir" Alias="mywebapp/editor/foo" Directory="INSTALLLOCATION" WebSite="My.Site">              
        </iis:WebVirtualDir>
      </Component>
    </Directory>
  </Directory>
</Directory>

没想到解决办法会这么简单。但与此同时,我已经使用system.directoryservices编写了一个自定义操作来实现同样的功能。但是这个更简单,更整洁。可能对面临相同情况的人有用。谢谢

我终于找到了一个简单的解决办法。了解到我们可以使用相对路径作为webvirtualdir元素的别名属性。因此,为了创建虚拟文件夹foo,我做了以下操作

使用网站元素引用了默认网站

<iis:WebSite  Id="My.Site" Description="Default Website">
  <iis:WebAddress Id="My.Web.Address" Port="12300"/>
</iis:WebSite>
添加了webvirtualdir元素,别名设置为mywebapp/editor/foo webapp/subfolder/virtualdir

<Directory Id="TARGETDIR" Name="SourceDir">
 <Directory Id="ProgramFilesFolder">
    <Directory Id="INSTALLLOCATION" Name="IISDemo">
      <Component Id="IIS.Component" Guid="{6FAD9EC7-D2B0-4471-A657-C8AF5F6F707F}" KeyPath="yes">
        <iis:WebVirtualDir Id="My.VirtualDir" Alias="mywebapp/editor/foo" Directory="INSTALLLOCATION" WebSite="My.Site">              
        </iis:WebVirtualDir>
      </Component>
    </Directory>
  </Directory>
</Directory>

没想到解决办法会这么简单。但与此同时,我已经使用system.directoryservices编写了一个自定义操作来实现同样的功能。但是这个更简单,更整洁。可能对面临相同情况的人有用。谢谢你的回答。找到一个简单的解决方案,请检查答案…谢谢你的回答。找到一个简单的解决方案,请检查答案。。。