一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

ActiveX控件開發(fā)

 daren2011 2014-09-06

前言

ActiveX控件以前也叫做OLE控件,它是微軟IE支持的一種軟件組件或?qū)ο?,可以將其插入到Web頁面中,實現(xiàn)在瀏覽器端執(zhí)行動態(tài)程序功能,以增強(qiáng)瀏覽器端的動態(tài)處理能力。通常ActiveX控件都是用C++或VB語言開發(fā),本文介紹另一種方式,在.NET Framework平臺上,使用C#語言開發(fā)ActiveX控件。

雖然本文通篇都在講如何使用C#語言開發(fā)ActiveX控件,但我并不極力推薦使用這種技術(shù),因為該技術(shù)存在明顯的局限,即需要瀏覽器端安裝.NET Framework(版本取決于開發(fā)ActiveX控件使用的.NET Framework版本),該局限對于挑剔的互聯(lián)網(wǎng)用戶,幾乎是不可接受的。所以,我建議以下幾條均滿足時,方可考慮使用該技術(shù):

  • 開發(fā)團(tuán)隊中沒有人掌握使用C++/VB開發(fā)ActiveX控件技術(shù);
  • 該ActiveX控件不用于互聯(lián)網(wǎng);
  • 用戶對僅能使用IE瀏覽器訪問表示可以接受;
  • 用戶對在瀏覽器端安裝.NET Framework組件表示可以接受。

另外,我建議如果不是因為控件的依賴庫基于更高版本的.NET Framework,或需要更高版本的.NET Framework提供的擴(kuò)展功能(如需要WCF等),盡量在.NET Framework 2.0上開發(fā)ActiveX控件,因為.NET Framework 2.0只有20M,相比300M的.NET Framework 3.5和40M的.NET Framework 4.0都要小很多,對客戶端操作系統(tǒng)的要求也要低很多,并且隨著Windows版本的不斷升級換代,Windows Vista以后的版本已經(jīng)內(nèi)置了.NET Framework 2.0。等到Windows XP系統(tǒng)壽終正寢之時,也將迎來該技術(shù)的春天。所以,別被我上面的建議夯退了,掌握該技術(shù)其實還是蠻有實用價值的,畢竟,C#高效的開發(fā)效率很有吸引力。

本文接下來將使用C#語言開發(fā)一個ActiveX控件,實現(xiàn)對瀏覽器端的MAC地址遍歷功能;另外,提供一個在Web靜態(tài)頁面中調(diào)用該控件的測試實例。本實例的開發(fā)環(huán)境為Visual Studio 2010旗艦版(SP1),目標(biāo)框架為.NET Framework 2.0;瀏覽器端測試環(huán)境為Windows 7旗艦版,IE8。

 

控件開發(fā)

使用C#進(jìn)行ActiveX控件開發(fā)過程其實很簡單。首先,在解決方案中添加一個類庫項目,目標(biāo)框架使用.NET Framework 2.0,如圖1所示:

 

圖1創(chuàng)建ActiveX控件類庫

此處有一個關(guān)鍵操作,需要設(shè)置類庫項目屬性->程序集信息->使程序集COM可見,如圖2所示:

 

圖2設(shè)置ActiveX控件類庫程序集COM可見

ActiveX類庫的內(nèi)容大致包括兩部分,IObjectSafety接口和實現(xiàn)該接口的控件類??紤]所有控件類都要實現(xiàn)IObjectSafety接口,可以將該接口的實現(xiàn)抽象為一個控件基類。

一、IObjectSafety接口

為了讓ActiveX控件獲得客戶端的信任,控件類還需要實現(xiàn)一個名為“IObjectSafety”的接口。先創(chuàng)建該接口(注意,不能修改該接口的GUID值),接口內(nèi)容如下:

復(fù)制代碼
 1 [ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
 2 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
 3 public interface IObjectSafety
 4 {
 5     [PreserveSig]
 6     int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);
 7 
 8     [PreserveSig()]
 9     int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
10 }
復(fù)制代碼

二、ActiveXControl控件基類

復(fù)制代碼
 1 public abstract class ActiveXControl : IObjectSafety
 2 {
 3     #region IObjectSafety 成員
 4 
 5     private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
 6     private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
 7     private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
 8     private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
 9     private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";
10 
11     private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
12     private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
13     private const int S_OK = 0;
14     private const int E_FAIL = unchecked((int)0x80004005);
15     private const int E_NOINTERFACE = unchecked((int)0x80004002);
16 
17     private bool _fSafeForScripting = true;
18     private bool _fSafeForInitializing = true;
19 
20 
21     public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
22     {
23         int Rslt = E_FAIL;
24 
25         string strGUID = riid.ToString("B");
26         pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
27         switch (strGUID)
28         {
29             case _IID_IDispatch:
30             case _IID_IDispatchEx:
31                 Rslt = S_OK;
32                 pdwEnabledOptions = 0;
33                 if (_fSafeForScripting == true)
34                     pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
35                 break;
36             case _IID_IPersistStorage:
37             case _IID_IPersistStream:
38             case _IID_IPersistPropertyBag:
39                 Rslt = S_OK;
40                 pdwEnabledOptions = 0;
41                 if (_fSafeForInitializing == true)
42                     pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
43                 break;
44             default:
45                 Rslt = E_NOINTERFACE;
46                 break;
47         }
48 
49         return Rslt;
50     }
51 
52     public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
53     {
54         int Rslt = E_FAIL;
55 
56         string strGUID = riid.ToString("B");
57         switch (strGUID)
58         {
59             case _IID_IDispatch:
60             case _IID_IDispatchEx:
61                 if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) &&
62                         (_fSafeForScripting == true))
63                     Rslt = S_OK;
64                 break;
65             case _IID_IPersistStorage:
66             case _IID_IPersistStream:
67             case _IID_IPersistPropertyBag:
68                 if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) &&
69                         (_fSafeForInitializing == true))
70                     Rslt = S_OK;
71                 break;
72             default:
73                 Rslt = E_NOINTERFACE;
74                 break;
75         }
76 
77         return Rslt;
78     }
79 
80     #endregion
81 }
復(fù)制代碼

三、MacActiveX控件類

復(fù)制代碼
 1 [Guid("65D8E97F-D3E2-462A-B389-241D7C38C518")]
 2 public class MacActiveX : ActiveXControl
 3 {
 4     public string GetMacAddress()
 5     {
 6         var mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
 7         var mos = mc.GetInstances();
 8         var sb = new StringBuilder();
 9 
10         foreach (ManagementObject mo in mos)
11         {
12             var macAddress = mo["MacAddress"];
13 
14             if (macAddress != null)
15                 sb.AppendLine(macAddress.ToString());
16         }
17 
18         return sb.ToString();
19     }
20 }
復(fù)制代碼

注意,第一行指定的Guid值即為該ActiveX控件的唯一標(biāo)識,請保證其唯一性。Guid的生成有多種方法,你可以在系統(tǒng)目錄的Program Files目錄搜索一個名為guidgen.exe的工具,用該工具產(chǎn)生;也可以寫一段測試代碼,調(diào)用Guid.NewGuid()方法產(chǎn)生;有的Visual Studio版本也提供了快捷方式,在“工具->生成GUID”菜單下。另外,訪問MAC需要添加對System.Management系統(tǒng)組件的引用。

到此,控件類庫的開發(fā)工作就做完了,整個實現(xiàn)過程確實很簡單。

 

發(fā)布

C#開發(fā)的ActiveX控件類庫不像OCX那樣可以直接通過regsvr32.exe注冊(實際上,微軟提供了替工具regasm.exe,但由于這種方式要不能實現(xiàn)自動升級,所以本文就不介紹了),要使控件類庫運行于瀏覽器端,可以采取兩種方式,一種是將控件類庫打包為MSI安裝包,然后直接在瀏覽器端安裝;另一種是將MSI再封裝為一個CAB包,這個CAB包就是一個ActiveX控件了,可以將它隨應(yīng)用程序一并發(fā)布,瀏覽器端訪問包含有該控件的頁面時,就會自動提示安裝了。接下來就后一種發(fā)布方式進(jìn)行詳細(xì)講解。

一、安裝項目

在解決方案中添加一個安裝項目,如圖3所示:

 

圖3添加安裝項目

右鍵點擊新添加的安裝項目,依次選擇“添加->項目輸出”菜單,打開添加項目輸出組對話框,并選擇ActiveX控件類庫“CSharpActiveX”作為主輸出,如圖4所示:

 

圖4添加項目輸出

雙擊安裝項目檢測到的依賴項“Microsoft .NET Framework”,打開安裝項目的啟動條件界面,選中“.NET Framework”項,如圖5所示:

 

圖5安裝項目啟動條件

按F4快捷鍵,打開屬性窗口,設(shè)置.NET Framework項的Version為“.NET Framework 2.0”,如圖6所示:

 

圖6設(shè)置安裝項目的依賴框架

下面這步很關(guān)鍵,選中“主輸出來自CSharpActiveX(活動)”項,如圖7所示:

 

圖7主輸出內(nèi)容項

設(shè)置主輸出項內(nèi)容的Register屬性值為vsdrpCOM,如圖8所示:

 

圖8設(shè)置主輸出項屬性

二、制作CAB包

Visual Studio 2010提供了CAB項目模板,但非常遺憾,無論我怎么設(shè)置,其生成的CAB安裝包都不能在終端成功安裝,最終只能放棄,轉(zhuǎn)而選擇了makecab.exe工具。源碼提供了該打包工具,位于CAB目錄下,共包含makecab.exe、cab.ddf、installer.inf和makecab.bat四個文件,其中cab.ddf和installer.inf文件需要簡單說明下。

cab.ddf文件定義了CAB文件的打包行為,內(nèi)容包括打包參數(shù),打包內(nèi)容項以及輸出文件等。需要指出的是,使用C#開發(fā)的ActiveX控件CAB包中需要包含MSI文件和installer.inf安裝文件兩部分。cab.ddf文件內(nèi)容如下:

復(fù)制代碼
.OPTION   EXPLICIT
.Set Cabinet=on
.Set Compress=on
.Set MaxDiskSize=CDROM
.Set ReservePerCabinetSize=6144
.Set DiskDirectoryTemplate="."
.Set CompressionType=MSZIP
.Set CompressionLevel=7
.Set CompressionMemory=21
.Set CabinetNameTemplate="CSharpActiveX.CAB"
"installer.inf"
"CSharpActiveX.msi"
復(fù)制代碼

installer.inf文件定義了CAB文件的安裝行為,作為控件的一部分打入CAB包中,其內(nèi)容如下:

復(fù)制代碼
[Setup Hooks]
hook1=hook1

[hook1]
run=msiexec /i %EXTRACT_DIR%\CSharpActiveX.msi /qn

[Version]
Signature= "$CHICAGO$"
AdvancedInf=2.0
復(fù)制代碼

makecab.bat文件是調(diào)用makecab.exe進(jìn)行打包的批處理文件,內(nèi)容如下:

makecab.exe   /f   "cab.ddf"

當(dāng)生成安裝項目后,將CSharpActiveX.msi文件拷貝到CAB目錄下,就可以雙擊makecab.exe文件進(jìn)行打包了,執(zhí)行完成后會輸出CSharpActiveX.CAB文件,這就是所謂的ActiveX控件了。

三、簽名

IE采用了AuthentiCode代碼簽名技術(shù),對瀏覽器端安裝ActiveX控件行為進(jìn)行了控制。上面生成的ActiveX控件如果想在瀏覽器端成功安裝,需要對瀏覽器進(jìn)行設(shè)置,具體操作參見部署章節(jié)。

讓所有用戶都對IE進(jìn)行設(shè)置,顯得不太友好,為此,我們可以考慮使用AuthentiCode技術(shù)對ActiveX控件進(jìn)行簽名。Visual Studio 2010附帶的signtool.exe(以前版本的VS提供的是另一個工具signcode.exe)代碼簽名工具可以完成該工作(注意,并非一定要用微軟提供的工具進(jìn)行簽名,只要按照AuthentiCode技術(shù)標(biāo)準(zhǔn),使用 PKCS#7標(biāo)準(zhǔn)定義的數(shù)據(jù)結(jié)構(gòu)生成待簽名文件的數(shù)字簽名,并加入到待簽名文件的PE結(jié)構(gòu)中即可)。但需要先準(zhǔn)備一個PKCS#12(證書及私鑰)文件(.pfx),注意,該證書的增強(qiáng)型密鑰用法須包含代碼簽名這項,如圖9所示:

 

圖9代碼簽名證書

本文源碼提供了一份測試PKCS#12文件Apollo.pfx,PIN碼為11111111。在Visual Studio命令提示(2010)中,進(jìn)入源碼的CAB目錄,輸入如下命令即可對ActiveX控件進(jìn)行簽名操作了:

signtool sign –f Apollo.pfx –p 11111111 CSharpActiveX.CAB

圖10對比了簽名前后的ActiveX控件文件屬性,可以看出,簽名后的ActiveX控件屬性中已經(jīng)多了一項數(shù)字簽名,表示該文件已經(jīng)過簽名。

 

圖10簽名前后的ActiveX控件屬性對比

出于方便考慮,本文源碼的CAB目錄下提供了一份signtool.exe工具的拷貝,這樣就可以將簽名命令加入makecab.bat文件中,修改后的makecab.bat我將其命名為makecabsigned.bat,內(nèi)容如下:

makecab.exe   /f   "cab.ddf"
signtool sign -f Apollo.pfx -p 11111111 CSharpActiveX.CAB

 

應(yīng)用

ActiveX控件用于HTML靜態(tài)頁面,執(zhí)行于IE瀏覽器端。需要以<object>標(biāo)簽的形式引入頁面文件,然后使用Javascript語言調(diào)用它。測試代碼如下:

復(fù)制代碼
 1 <html>
 2 <head>
 3     <title>CSharpActiveX測試</title>
 4 </head>
 5 <body>
 6 <object id="cSharpActiveX" classid="clsid:65D8E97F-D3E2-462A-B389-241D7C38C518" codebase="CSharpActiveX.CAB#version=1,0,0" style="display: none;"></object>
 7     <script type="text/javascript" language="javascript" defer="defer">
 8         var activeX = document.getElementById("cSharpActiveX");
 9         alert(activeX.GetMacAddress());
10     </script>
11 </body>
12 </html>
復(fù)制代碼

注意,<object>標(biāo)簽的classid屬性值即為MacActiveX類的Guid特性值。

 

部署

ActiveX控件在IE瀏覽器端的部署會因ActiveX控件是否簽名而有所區(qū)別。下面就以此分類進(jìn)行說明。當(dāng)然,首先需要將test.htm和CSharpActiveX.CAB文件部署到服務(wù)器上,假設(shè)部署后的訪問地址為http://192.168.1.1/test.htm。

一、部署未簽名的ActiveX控件

未簽名的ActiveX控件不受瀏覽器端信任,默認(rèn)是不被允許安裝的。需要先將站點添加為可信站點,具體步驟為:依次打開IE“工具->Internet選項”,在“安全”選項卡中,選中“可信站點”,如圖11所示:

 

圖11 Internet安全選項

點擊“站點”按鈕,打開可信站點管理對話框,將服務(wù)器站點添加到可信站點列表中,如圖12所示:

 

圖12可信站點對話框

回到“Internet選項”對話框,點擊“自定義級別”選項卡,打開可信站點的安全設(shè)置對話框,如圖13所示:

 

圖13可信站點安全設(shè)置對話框

確認(rèn)“對未標(biāo)記為可安全執(zhí)行腳本的ActiveX控件初始化并執(zhí)行腳本”項設(shè)置為“啟用”,“下載未簽名的ActiveX控件”項設(shè)置為“提示”。

IE設(shè)置完成后,訪問http://192.168.1.1/test.htm測試頁面(注意,Windows 7需要“以管理員身份運行”IE方可成功安裝ActiveX控件),IE便會提示加載ActiveX控件,如圖14所示:

 

圖14首次訪問提示加載ActiveX控件

點擊“為此計算機(jī)上的所有用戶安裝此加載項”,IE將彈出安全警告,確認(rèn)是否要安裝該ActiveX控件,如圖15所示:

 

圖15 ActiveX控件安裝安全警告

點擊“安裝”按鈕,確認(rèn)安裝該ActiveX控件,待IE狀態(tài)欄進(jìn)度條完成,說明控件已安裝完成,可以通過查看“卸載或更改程序”項來確認(rèn)是否安裝成功,如圖16所示:

 

圖16確認(rèn)ActiveX控件成功安裝

我們可以從ActiveX控件安裝過程看出,瀏覽器端其實是以靜默安裝的方式完成對CAB包中的MSI安裝文件的安裝(有點拗口J)。安裝完成后,頁面成功調(diào)用ActiveX控件,彈出接口調(diào)用結(jié)果(注意Windows 7需要重啟IE,且不能用“以管理員身份運行”方式啟動,否則會再次提示安裝ActiveX控件,但其實控件已經(jīng)成功安裝了,這個問題很奇怪),效果如圖17所示:

 

圖17成功調(diào)用ActiveX控件接口

二、部署已簽名的ActiveX控件

因為IE默認(rèn)允許安裝并運行收信任的已簽名ActiveX控件,所以通過對ActiveX控件簽名,可以有效簡化瀏覽器端的配置工作。你僅需要安裝簽名所用的證書及其證書鏈文件(本文源碼提供的簽名文件所含證書是自簽名證書,所以它的證書鏈就只是它自己)。打開源碼CAB目錄下的Apollo.cer(與Apollo.pfx文件對應(yīng)的數(shù)字證書文件)代碼簽名證書文件,如圖18所示:

 

圖18簽名證書文件

點擊“安裝證書”按鈕,將該證書安裝到“受信任的根證書頒發(fā)機(jī)構(gòu)”,如圖19所示:

 

圖19安裝代碼簽名證書

打開IE的“工具->Internet選項”對話框,選擇“內(nèi)容”選項卡,點擊“證書”按鈕,打開IE證書對話框,確認(rèn)在“受信任的根證書頒發(fā)機(jī)構(gòu)”選項卡中包含剛才導(dǎo)入的代碼簽名證書,如圖20所示:

 

圖20成功導(dǎo)入代碼簽名證書

此時,再訪問測試頁面http://192.168.1.1/test.htm,IE就會提示安裝ActiveX控件了,而不再需要將站點添加到可信站點并設(shè)置IE選項了。

但是,如果用戶不能接受初次安裝需要導(dǎo)入代碼簽名證書及其證書鏈的方式,怎么辦呢?從圖20可以看到,Windows其實默認(rèn)內(nèi)置了一些權(quán)威的CA機(jī)構(gòu)證書,可以向這些機(jī)構(gòu)申請一份代碼簽名證書及私鑰文件來對ActiveX控件簽名,這樣就可以避免該問題了。但是,向權(quán)威的CA機(jī)構(gòu)申請證書是需要付費的,所以需要權(quán)衡成本和易用性后,再做出選擇。

 

升級

要使C#編寫的ActiveX控件支持自動升級,需要做四件事情,即升級ActiveX控件庫版本、升級安裝項目版本、設(shè)置安裝項目注冊表項版本和升級網(wǎng)頁<object>版本。

一、升級ActiveX控件版本

打開ActiveX控件項目的“程序集信息”對話框,升級程序集版本和文件版本,如圖21所示:

 

圖21升級ActiveX控件版本

二、升級安裝項目版本

選中安裝項目,按F4快捷鍵打開安裝項目的屬性窗口,升級安裝項目的版本,如圖22所示:

 

圖22升級安裝項目版本

注意,此處還有一項關(guān)鍵工作要做,就是設(shè)置RemovePreviousVersions屬性值為True,這樣就會在升級時先自動卸載之前版本的控件。

三、設(shè)置安裝項目注冊表項版本

瀏覽器端檢測ActiveX控件是否需要升級,是通過比對<object>標(biāo)簽的codebase屬性值和本地HKEY_CLASSES_ROOT/CLSID/{GUID}/InstalledVersion鍵值是否相等來判斷的。所以,如果要實現(xiàn)自動更新,需要手動添加該注冊表項,并在每次升級控件時,相應(yīng)更改該項鍵值。

右鍵點擊安裝項目,依次選擇“視圖->注冊表”菜單,打開安裝項目的注冊表編輯界面,并在HKEY_CLASSES_ROOT節(jié)點下,建立CLSID/{GUID}/InstalledVersion注冊表鍵路徑,如圖23所示:

 

圖23創(chuàng)建注冊表鍵路徑

右鍵點擊InstalledVersion鍵節(jié)點,選擇“新建->字符串值”菜單,新建一個名稱為空(空名稱會顯示為“(默認(rèn)值)”),值為當(dāng)前控件版本號的鍵值,如圖24所示:

 

圖24添加InstalledVersion默認(rèn)鍵值

該步驟有幾個地方需要特別說明。首先,{GUID}指的是ActiveX控件類的GUID,對應(yīng)本文MacActiveX類指定的GUID,且該項需要包括左右花括號;其次,如果該安裝項目用于發(fā)布多個ActiveX控件(類),需要創(chuàng)建多個{GUID}/InstalledVersion路徑;最后,InstalledVersion的默認(rèn)鍵值的主次版本號間是用“,”分隔,而不是“.”,后續(xù)升級時,需要同步升級該鍵值版本號。

四、升級網(wǎng)頁<object>版本

最后,需要升級網(wǎng)頁中的ActiveX對象引用版本號,如下用下劃線標(biāo)識部分:

<object id="csharpActiveX" classid="clsid:65D8E97F-D3E2-462A-B389-241D7C38C518" codebase="CSharpActiveX.CAB#version=1,0,1" style="display: none;"></object>

重新生成安裝程序,打CAB包,將升級的頁面及ActiveX控件(CAB包)更新到服務(wù)器。此時,瀏覽器端重新訪問時,就會提示/自動升級ActiveX控件了。

 

總結(jié)

本文是《使用C#開發(fā)ActiveX控件》一文的升級版本,從ActiveX控件的開發(fā)、發(fā)布、應(yīng)用、部署和升級整個生命周期,系統(tǒng)地介紹了使用C#開發(fā)ActiveX控件技術(shù)的方方面面,對整個過程中可能遇到的一些技術(shù)難點進(jìn)行了逐一講解,并對其中涉及的一些知識進(jìn)行了簡單介紹。希望本文能夠解答自上一篇文章發(fā)布以來眾多網(wǎng)友提出的種種問題,幫助大家成功掌握這門技術(shù)。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    亚洲a码一区二区三区| 午夜视频在线观看日韩| 嫩呦国产一区二区三区av| 国产精品午夜视频免费观看| 日韩中文字幕欧美亚洲| 亚洲精品国产精品日韩| 成人精品一区二区三区在线 | 久热99中文字幕视频在线| 久热香蕉精品视频在线播放| 一区二区三区18禁看| 欧美黄色成人真人视频| 欧美日韩成人在线一区| 国内午夜精品视频在线观看| 在线观看视频日韩精品| 午夜视频免费观看成人| 亚洲一区二区三区四区性色av | 国产成人精品久久二区二区| 欧美高潮喷吹一区二区| 色哟哟哟在线观看视频| 在线观看免费视频你懂的| 中文字幕人妻一区二区免费 | 国产亚洲精品一二三区| 在线播放欧美精品一区| 东京热男人的天堂社区| 久久热麻豆国产精品视频| 日韩不卡一区二区视频| 亚洲中文字幕三区四区| 精品国产成人av一区二区三区| 91后入中出内射在线| 国产视频一区二区三区四区| 久久精品伊人一区二区| 日韩人妻一区中文字幕| 国产不卡最新在线视频| 亚洲一区二区三区av高清| 国产日韩精品欧美综合区| 91精品国产综合久久精品| 精品少妇一区二区视频| 91一区国产中文字幕| 日本一区二区三区黄色| 国产熟女一区二区精品视频| 亚洲一区二区三区一区|