How To Create a Windows Firewall Rule

// This script creates a rule in Windows Firewall.  When used as an MSI custom action, it must be run in Deferred mode,
// with it's CustomActionData set to INSTALLDIR
// It is written so it can be run outside of MSI to [vastly] simplify debugging.
var ClassName_ScriptingRuntimeShell         = "WScript.Shell";

var argumentString                  = "";
var arguments                       = null;
var installDir                      = "";


// CustomActionData format:  [INSTALLDIR]<?>
// If running in MSI, use arguments via standard CustomActionData interface, otherwise assume running outside MSI in debugger
if (DetectRunningInMSI())
    argumentString = Session.Property("CustomActionData");
else
    argumentString = "c:\\Program Files\\MyProgramDir";
arguments = argumentString.split("<?>");
if (arguments.length == 1)
{
    installDir = arguments[0];
}
else
{
    LogMessage("Argument string invalid (" +arguments.length+ "):  " +argumentString);
    throw 3;
}
installDir = EnsureEndsInBackslash(installDir);

// Don't let a failure here fail the install
try
{
    CreateFirewallRule("Rule Description", installDir +"MyProgramFilename.exe")
}
catch (unexpectedException)
{
    LogMessage("Error " +unexpectedException.number+ " creating firewall rules: " +unexpectedException.message);
}


function CreateFirewallRule( ruleName, exePathname )
{
    var firewallConfig          = null;
    var firewallPolicy          = null;
    var newApplicationRule      = null;
    var activeApplicationRules  = null;


    firewallConfig = SafeGetActiveXObject("HNetCfg.FwMgr");
    if (firewallConfig != null)
        newApplicationRule = SafeGetActiveXObject("HNetCfg.FwAuthorizedApplication");
    if (newApplicationRule != null)
    {
        firewallPolicy = firewallConfig.LocalPolicy.CurrentProfile;
        newApplicationRule.Name             = ruleName;
        newApplicationRule.IPVersion        = 2;
        newApplicationRule.ProcessImageFileName = exePathname;
        newApplicationRule.RemoteAddresses  = "*";
        newApplicationRule.Scope            = 0;
        newApplicationRule.Enabled          = true;
        activeApplicationRules = firewallPolicy.AuthorizedApplications
        activeApplicationRules.Add(newApplicationRule)
        LogMessage("Added rule for "+exePathname);
    }
}

function LogMessage( messageString )
// Writes a line to the MSI log, or the console if running outside MSI.
{
    var     customActionName        = "CreateFirewallRules";
   
    if (DetectRunningInMSI())
    {
        var     msiMessageTypeInfo      = 0x04000000
        var     logRecord               = null;
        var     currTime                = new Date();

        logRecord = Installer.CreateRecord(1);
        logRecord.StringData(0) = currTime.toTimeString() +" "+ customActionName +": [1]";
        logRecord.StringData(1) = messageString;
        Session.Message(msiMessageTypeInfo, logRecord);
        logRecord = null;
    }
    else
    {
        var     currTime                = new Date();

        messageString = currTime.toTimeString() +" "+ customActionName +": "+ messageString;
        WScript.Echo(messageString);
    }
}

function DetectRunningInMSI()
// Returns TRUE if running in MSI, else FALSE
{
    var returnVal       = true;
    var stringVal       = "";

    try
    {
        // Try to reference the Session object, which is only provided by the MSI runtime engine
        stringVal = Session.Property("ProductCode");
    }
    catch (thisException)
    {
        // An exception is only thrown if the runtime couldn't resolve Session, which means
        // this script is not running under MSI
        returnVal = false;
    }

    return returnVal;
}

function SafeGetActiveXObject( className )
// Creates an instance of className and returns it, or null if an error occurs, and logs the error
{
    var returnVal    = null;

    try
    {
        returnVal = new ActiveXObject(className);
    }
    catch (createException)
    {
        LogMessage("SafeGetActiveXObject:  Error " +createException.number+ " creating object of class " +className+ ": " +createException.message);
    }

    return returnVal;
}

function EnsureEndsInBackslash( directoryPath )
// Returns directoryPath ending in a backslash if it does not already end in one.
{
    var returnVal = directoryPath;

    if (returnVal.substring(returnVal.length, returnVal.length-1) != "\\")
        returnVal = returnVal + "\\";

    return returnVal;
}
Comments