WIX: Where and how should my CustomAction create a

2019-04-27 04:59发布

I have a script CustomAction (Yes, I know all about the opinions that say don't use script CustomActions. I have a different opinion.)

I'd like to run a command, and capture the output. I can do this using the WScript.Shell COM object, then invoking shell.Exec(). But, this flashes a visible console window for the executed command.

To avoid that, I understand I can use the shell.Run() call, and specify "hidden" for the window appearance. But .Run() doesn't give me access to the StdOut of the executed process, so that means I'd need to create a temporary file and redirect the exe output to the temp file, then later read that temp file in script.

Some questions:

  • is this gonna work?

  • How do I generate a name for the temporary file? In .NET I could use a static method in the System.IO namespace, but I am using script here. I need to insure that the use has RW access, and also that no anti-virus program is going to puke on this.

  • Better ideas? I am trying very hard to avoid C/C++.


I could avoid all this if there were a way to query websites in IIS7 from script, without resorting to the IIS6 Compatibility pack, without using .NET (Microsoft.Web.Administration.ServerManager), and without execing a process (appcmd list sites). I already asked a separate question on that topic; any suggestions on that would also be appreciated.

1条回答
We Are One
2楼-- · 2019-04-27 05:52

Answering my own question...

  1. yes, this is going to work.

  2. Use the Scripting.FileSystemObject thing within Javascript. There's a GetTempName() method that produces a file name suitable for temporary use, and a GetSpecialFolder() method that gets the location of the temp folder. There's even a BuildPath() method to combine them.

  3. so far I don't have any better ideas.

Here's the code I used:

function GetWebSites_IIS7_B()
{
    var ParseOneLine = function(oneLine) {
        ...regex parsing of output...
    };

    LogMessage("GetWebSites_IIS7_B() 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") + " list sites";

    // use cmd.exe to redirect the output
    var rc = shell.Run("%comspec% /c " + appcmd + "> " + tmpFileName, WindowStyle.Hidden, true);
    // WindowStyle.Hidden == 0
    var ts = fso.OpenTextFile(tmpFileName, OpenMode.ForReading);
    var sites = [];

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

    return sites;
}
查看更多
登录 后发表回答