// 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; } |