我有一个通过 ClickOnce 安装和更新的应用程序。该应用程序通过 FTP 下载文件,因此需要将其作为例外添加到 Windows 防火墙。由于 ClickOnce 的工作方式,EXE 的路径会随着每次更新而改变,因此异常也需要改变。对防火墙进行更改以使其对最终用户不可见的最佳方法是什么?
(该应用程序是用 C# 编写的)
不确定这是否是最好的方法,但运行netsh应该可以:
netsh 防火墙添加 allowedprogram C:\MyApp\MyApp.exe MyApp ENABLE
我认为这需要管理员权限,原因很明显:)
编辑:我只是对 ClickOnce 了解不够,不知道您是否可以通过它运行外部程序。
我找到了这篇文章,其中包含一个完整的包装类,用于操作 Windows 防火墙。将应用程序添加到 Windows 防火墙的例外列表中
/// 
/// Allows basic access to the windows firewall API.
/// This can be used to add an exception to the windows firewall
/// exceptions list, so that our programs can continue to run merrily
/// even when nasty windows firewall is running.
///
/// Please note: It is not enforced here, but it might be a good idea
/// to actually prompt the user before messing with their firewall settings,
/// just as a matter of politeness.
/// 
/// 
/// To allow the installers to authorize idiom products to work through
/// the Windows Firewall.
/// 
public class FirewallHelper
{
    #region Variables
    /// 
    /// Hooray! Singleton access.
    /// 
    private static FirewallHelper instance = null;
    /// 
    /// Interface to the firewall manager COM object
    /// 
    private INetFwMgr fwMgr = null;
    #endregion
    #region Properties
    /// 
    /// Singleton access to the firewallhelper object.
    /// Threadsafe.
    /// 
    public static FirewallHelper Instance
    {
        get
        {
            lock (typeof(FirewallHelper))
            {
                if (instance == null)
                    instance = new FirewallHelper();
                return instance;
            }
        }
    }
    #endregion
    #region Constructivat0r
    /// 
    /// Private Constructor.  If this fails, HasFirewall will return
    /// false;
    /// 
    private FirewallHelper()
    {
        // Get the type of HNetCfg.FwMgr, or null if an error occurred
        Type fwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false);
        // Assume failed.
        fwMgr = null;
        if (fwMgrType != null)
        {
            try
            {
                fwMgr = (INetFwMgr)Activator.CreateInstance(fwMgrType);
            }
            // In all other circumnstances, fwMgr is null.
            catch (ArgumentException) { }
            catch (NotSupportedException) { }
            catch (System.Reflection.TargetInvocationException) { }
            catch (MissingMethodException) { }
            catch (MethodAccessException) { }
            catch (MemberAccessException) { }
            catch (InvalidComObjectException) { }
            catch (COMException) { }
            catch (TypeLoadException) { }
        }
    }
    #endregion
    #region Helper Methods
    /// 
    /// Gets whether or not the firewall is installed on this computer.
    /// 
    /// 
    public bool IsFirewallInstalled
    {
        get
        {
            if (fwMgr != null &&
                  fwMgr.LocalPolicy != null &&
                  fwMgr.LocalPolicy.CurrentProfile != null)
                return true;
            else
                return false;
        }
    }
    /// 
    /// Returns whether or not the firewall is enabled.
    /// If the firewall is not installed, this returns false.
    /// 
    public bool IsFirewallEnabled
    {
        get
        {
            if (IsFirewallInstalled && fwMgr.LocalPolicy.CurrentProfile.FirewallEnabled)
                return true;
            else
                return false;
        }
    }
    /// 
    /// Returns whether or not the firewall allows Application "Exceptions".
    /// If the firewall is not installed, this returns false.
    /// 
    /// 
    /// Added to allow access to this metho
    /// 
    public bool AppAuthorizationsAllowed
    {
        get
        {
            if (IsFirewallInstalled && !fwMgr.LocalPolicy.CurrentProfile.ExceptionsNotAllowed)
                return true;
            else
                return false;
        }
    }
    /// 
    /// Adds an application to the list of authorized applications.
    /// If the application is already authorized, does nothing.
    /// 
    /// 
    ///         The full path to the application executable.  This cannot
    ///         be blank, and cannot be a relative path.
    /// 
    /// 
    ///         This is the name of the application, purely for display
    ///         puposes in the Microsoft Security Center.
    /// 
    /// 
    ///         When applicationFullPath is null OR
    ///         When appName is null.
    /// 
    /// 
    ///         When applicationFullPath is blank OR
    ///         When appName is blank OR
    ///         applicationFullPath contains invalid path characters OR
    ///         applicationFullPath is not an absolute path
    /// 
    /// 
    ///         If the firewall is not installed OR
    ///         If the firewall does not allow specific application 'exceptions' OR
    ///         Due to an exception in COM this method could not create the
    ///         necessary COM types
    /// 
    /// 
    ///         If no file exists at the given applicationFullPath
    /// 
    public void GrantAuthorization(string applicationFullPath, string appName)
    {
        #region  Parameter checking
        if (applicationFullPath == null)
            throw new ArgumentNullException("applicationFullPath");
        if (appName == null)
            throw new ArgumentNullException("appName");
        if (applicationFullPath.Trim().Length == 0)
            throw new ArgumentException("applicationFullPath must not be blank");
        if (applicationFullPath.Trim().Length == 0)
            throw new ArgumentException("appName must not be blank");
        if (applicationFullPath.IndexOfAny(Path.InvalidPathChars) >= 0)
            throw new ArgumentException("applicationFullPath must not contain invalid path characters");
        if (!Path.IsPathRooted(applicationFullPath))
            throw new ArgumentException("applicationFullPath is not an absolute path");
        if (!File.Exists(applicationFullPath))
            throw new FileNotFoundException("File does not exist", applicationFullPath);
        // State checking
        if (!IsFirewallInstalled)
            throw new FirewallHelperException("Cannot grant authorization: Firewall is not installed.");
        if (!AppAuthorizationsAllowed)
            throw new FirewallHelperException("Application exemptions are not allowed.");
        #endregion
        if (!HasAuthorization(applicationFullPath))
        {
            // Get the type of HNetCfg.FwMgr, or null if an error occurred
            Type authAppType = Type.GetTypeFromProgID("HNetCfg.FwAuthorizedApplication", false);
            // Assume failed.
            INetFwAuthorizedApplication appInfo = null;
            if (authAppType != null)
            {
                try
                {
                    appInfo = (INetFwAuthorizedApplication)Activator.CreateInstance(authAppType);
                }
                // In all other circumnstances, appInfo is null.
                catch (ArgumentException) { }
                catch (NotSupportedException) { }
                catch (System.Reflection.TargetInvocationException) { }
                catch (MissingMethodException) { }
                catch (MethodAccessException) { }
                catch (MemberAccessException) { }
                catch (InvalidComObjectException) { }
                catch (COMException) { }
                catch (TypeLoadException) { }
            }
            if (appInfo == null)
                throw new FirewallHelperException("Could not grant authorization: can't create INetFwAuthorizedApplication instance.");
            appInfo.Name = appName;
            appInfo.ProcessImageFileName = applicationFullPath;
            // ...
            // Use defaults for other properties of the AuthorizedApplication COM object
            // Authorize this application
            fwMgr.LocalPolicy.CurrentProfile.AuthorizedApplications.Add(appInfo);
        }
        // otherwise it already has authorization so do nothing
    }
    /// 
    /// Removes an application to the list of authorized applications.
    /// Note that the specified application must exist or a FileNotFound
    /// exception will be thrown.
    /// If the specified application exists but does not current have
    /// authorization, this method will do nothing.
    /// 
    /// 
    ///         The full path to the application executable.  This cannot
    ///         be blank, and cannot be a relative path.
    /// 
    /// 
    ///         When applicationFullPath is null
    /// 
    /// 
    ///         When applicationFullPath is blank OR
    ///         applicationFullPath contains invalid path characters OR
    ///         applicationFullPath is not an absolute path
    /// 
    /// 
    ///         If the firewall is not installed.
    /// 
    /// 
    ///         If the specified application does not exist.
    /// 
    public void RemoveAuthorization(string applicationFullPath)
    {
        #region  Parameter checking
        if (applicationFullPath == null)
            throw new ArgumentNullException("applicationFullPath");
        if (applicationFullPath.Trim().Length == 0)
            throw new ArgumentException("applicationFullPath must not be blank");
        if (applicationFullPath.IndexOfAny(Path.InvalidPathChars) >= 0)
            throw new ArgumentException("applicationFullPath must not contain invalid path characters");
        if (!Path.IsPathRooted(applicationFullPath))
            throw new ArgumentException("applicationFullPath is not an absolute path");
        if (!File.Exists(applicationFullPath))
            throw new FileNotFoundException("File does not exist", applicationFullPath);
        // State checking
        if (!IsFirewallInstalled)
            throw new FirewallHelperException("Cannot remove authorization: Firewall is not installed.");
        #endregion
        if (HasAuthorization(applicationFullPath))
        {
            // Remove Authorization for this application
            fwMgr.LocalPolicy.CurrentProfile.AuthorizedApplications.Remove(applicationFullPath);
        }
        // otherwise it does not have authorization so do nothing
    }
    /// 
    /// Returns whether an application is in the list of authorized applications.
    /// Note if the file does not exist, this throws a FileNotFound exception.
    /// 
    /// 
    ///         The full path to the application executable.  This cannot
    ///         be blank, and cannot be a relative path.
    /// 
    /// 
    ///         The full path to the application executable.  This cannot
    ///         be blank, and cannot be a relative path.
    /// 
    /// 
    ///         When applicationFullPath is null
    /// 
    /// 
    ///         When applicationFullPath is blank OR
    ///         applicationFullPath contains invalid path characters OR
    ///         applicationFullPath is not an absolute path
    /// 
    /// 
    ///         If the firewall is not installed.
    /// 
    /// 
    ///         If the specified application does not exist.
    /// 
    public bool HasAuthorization(string applicationFullPath)
    {
        #region  Parameter checking
        if (applicationFullPath == null)
            throw new ArgumentNullException("applicationFullPath");
        if (applicationFullPath.Trim().Length == 0)
            throw new ArgumentException("applicationFullPath must not be blank");
        if (applicationFullPath.IndexOfAny(Path.InvalidPathChars) >= 0)
            throw new ArgumentException("applicationFullPath must not contain invalid path characters");
        if (!Path.IsPathRooted(applicationFullPath))
            throw new ArgumentException("applicationFullPath is not an absolute path");
        if (!File.Exists(applicationFullPath))
            throw new FileNotFoundException("File does not exist.", applicationFullPath);
        // State checking
        if (!IsFirewallInstalled)
            throw new FirewallHelperException("Cannot remove authorization: Firewall is not installed.");
        #endregion
        // Locate Authorization for this application
        foreach (string appName in GetAuthorizedAppPaths())
        {
            // Paths on windows file systems are not case sensitive.
            if (appName.ToLower() == applicationFullPath.ToLower())
                return true;
        }
        // Failed to locate the given app.
        return false;
    }
    /// 
    /// Retrieves a collection of paths to applications that are authorized.
    /// 
    /// 
    /// 
    ///         If the Firewall is not installed.
    ///   
    public ICollection GetAuthorizedAppPaths()
    {
        // State checking
        if (!IsFirewallInstalled)
            throw new FirewallHelperException("Cannot remove authorization: Firewall is not installed.");
        ArrayList list = new ArrayList();
        //  Collect the paths of all authorized applications
        foreach (INetFwAuthorizedApplication app in fwMgr.LocalPolicy.CurrentProfile.AuthorizedApplications)
            list.Add(app.ProcessImageFileName);
        return list;
    }
    #endregion
}
/// 
/// Describes a FirewallHelperException.
/// 
/// 
///
/// 
public class FirewallHelperException : System.Exception
{
    /// 
    /// Construct a new FirewallHelperException
    /// 
    /// 
    public FirewallHelperException(string message)
      : base(message)
    { }
}
ClickOnce 沙盒没有出现任何问题。
可以从防火墙访问数据,请看以下文章。
真正的问题是 ClickOnce 沙盒是否允许这种访问?我的猜测是它没有。也许您可以使用网络服务?(有关 ClickOnce 中数据访问方法的更多信息,请参阅在 ClickOnce 应用程序中访问本地和远程数据)
假设我们使用的是 Visual Studio Installer->Setup Project - 您需要在正在安装的程序集中有这样的安装程序类,然后确保在安装阶段为“主要输出”添加自定义操作。
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.IO;
using System.Diagnostics;
namespace YourNamespace
{
    [RunInstaller(true)]
    public class AddFirewallExceptionInstaller : Installer
    {
        protected override void OnAfterInstall(IDictionary savedState)
        {
            base.OnAfterInstall(savedState);
            var path = Path.GetDirectoryName(Context.Parameters["assemblypath"]);
            OpenFirewallForProgram(Path.Combine(path, "YourExe.exe"),
                                   "Your program name for display");
        }
        private static void OpenFirewallForProgram(string exeFileName, string displayName)
        {
            var proc = Process.Start(
                new ProcessStartInfo
                    {
                        FileName = "netsh",
                        Arguments =
                            string.Format(
                                "firewall add allowedprogram program=\"{0}\" name=\"{1}\" profile=\"ALL\"",
                                exeFileName, displayName),
                        WindowStyle = ProcessWindowStyle.Hidden
                    });
            proc.WaitForExit();
        }
    }
}
    可以在 The Wayback Machine 上找到“将应用程序添加到 Windows 防火墙上的例外列表”的死链接:
这个答案可能为时已晚。这就是我最终使用的:
答案是您只允许受信任的软件以管理员权限运行。有时,某些软件必须具有管理员权限并对您的系统进行敏感更改。否则,您还不如拥有一个只读硬盘...