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;

}