﻿# Windows Service 新增 Installer 功能並自動開啟防火牆設定

最近正準備寫一支 Windows Service 程式，正好來分享如何讓 Windows Service 程式具有自動安裝的能力，而且若要在安裝的過程中順便開啟 Windows Firewall 的設定時 C# 程式要如何撰寫。

首先，先開啟你寫好的 Windows Service 程式進入 Designer 模式，並在空白處點選滑鼠右鍵，再選取 Add Installer 選項。

![首先，先開啟你寫好的 Windows Service 程式進入 Designer 模式，並在空白處點選滑鼠右鍵，再選取 Add Installer 選項。](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/3c6e624b4efb6e4a8982-image_3.png)

接著，Visual Studio 就會幫你建立一個 ProjectInstaller.cs 類別 ( 繼承自 Installer 類別 )，並自動新增兩個與 Windows 服務安裝有關的控制項，分別是 serviceProcessInstaller1 與 serviceInstaller1，方便你直接 Windows 服務安裝時應該設定的參數。

![接著，Visual Studio 就會幫你建立一個 ProjectInstaller.cs 類別 ( 繼承自 Installer 類別 )，並自動新增兩個與 Windows 服務安裝有關的控制項，方便你直接設定。](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/f64db09315815a1a9b0b-image_14.png)

然後，你就修改將這兩個控制項的相關參數，設定 serviceInstaller1 的顯示名稱(DisplayName)、描述(Description)、服務名稱(ServiceName)、啟動類型(StartType)，以及設定 serviceProcessInstaller1 的啟動帳戶(Account)，設定完這些就差不多大功告成了。

![設定 serviceInstaller1 的顯示名稱(DisplayName)、描述(Description)、服務名稱(ServiceName)、啟動類型(StartType)](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/0b0f6cadc93a4f05d97b-image_10.png) ![設定 serviceProcessInstaller1 的啟動帳戶(Account)](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/260cb9f135e2cdb6755c-image_11.png)

最後，將專案編譯之後，該專案所編譯出來的組件(Assembly)就具有「安裝能力」，只要透過 .NET 2.0 提供的[安裝程式工具 (Installutil.exe)](http://msdn.microsoft.com/zh-tw/library/50614e95\(VS.80\).aspx)就可以將該服務順利安裝至系統內。

假設編譯出來的組件名稱是 WindowsService1.exe，那麼執行 Windows 服務安裝的指令就是：

```
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe  WindowsService1.exe
```

解除安裝的指令是：

```
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe /u WindowsService1.exe
```

大功告成！

\---

如果你的 Windows 服務會接受外部的連線，且需要在安裝過程中直接將**目前組件**加入到 Windows 防火牆的「允許的應用程式」清單中的話，就可以運用以下技巧進行設定。

首先必須先加入 Windows 防火牆的 COM 元件參考，並選取 COM 頁籤中的 **NetFwTypeLib** 元件 ( C:\\WINDOWS\\system32\\hnetcfg.dll )：

![Add Reference](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/09c37b8620425223b86f-image_17.png)

![Add Reference - 選取 COM 頁籤中的 NetFwTypeLib 元件 ( C:\\WINDOWS\\system32\\hnetcfg.dll )](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/130c6fb98ef965a5b417-image_20.png)

接著進入你的 ProjectInstaller.cs 的類別中加入以下方法，加入前請記得先在檔案最上方先引用 **NetFwTypeLib** 命名空間 ( using NetFwTypeLib; )：

```csharp
/// <summary>
/// 將目前組件的程式加入到 Windows 防火牆的「允許的應用程式」清單中
/// </summary>
private void SetupWindowsFirewall()
{
    try
    {
        Type NetFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false);
        INetFwMgr mgr = (INetFwMgr)Activator.CreateInstance(NetFwMgrType);

        Type NetFwAuthorizedApplicationType = Type.GetTypeFromProgID("HNetCfg.FwAuthorizedApplication", false);
        INetFwAuthorizedApplication app = (INetFwAuthorizedApplication)Activator.CreateInstance(NetFwAuthorizedApplicationType);

        app.Name = serviceInstaller1.ServiceName;
        app.Enabled = true;
        app.ProcessImageFileName = System.Reflection.Assembly.GetExecutingAssembly().Location;
        app.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;

        mgr.LocalPolicy.CurrentProfile.AuthorizedApplications.Add(app);
    }
    catch (Exception ex)
    {
        System.Diagnostics.EventLog.WriteEntry("Service1Installer", ex.ToString());
    }
}
```

最後，再到 ProjectInstaller() 建構函數裡加上一段 SetupWindowsFirewall(); 即可完成設定，之後只要透過[安裝程式工具 (Installutil.exe)](http://msdn.microsoft.com/zh-tw/library/50614e95\(VS.80\).aspx)就不止可以將該服務順利安裝至系統，還可以在安裝過程中順便將安裝的組件加入到 Windows 防火牆的「允許的應用程式」清單中。

由於上述的 SetupWindowsFirewall 方法牽扯到 Windows Firewall 提供的 **HNetCfg.FwMgr** COM 元件，我不多做說明，不過這段程式幾乎直接抓過去就能用了，有興趣研究如何操作 Windows Firewall 的人請自行參考本文章最後的**相關連結**。

**相關連結**

-   [Windows service - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/Windows_service)
-   [安裝程式工具 (Installutil.exe)](http://msdn.microsoft.com/zh-tw/library/50614e95\(VS.80\).aspx)
-   Windows Firewall Scripting ( 這裡有許多實用的 VBScript 操作範例，是個不錯的參考資訊 )
-   [Windows Firewall Tools and Settings](http://technet.microsoft.com/en-us/library/cc737845.aspx#BKMK_scripting) ( Windows Firewall Scripting Reference )
-   [INetFwMgr Interface](http://msdn.microsoft.com/en-us/library/aa365287\(VS.85\).aspx)
-   [INetFwAuthorizedApplication Interface](http://msdn.microsoft.com/en-us/library/aa365100.aspx)
