C# shell32.dll 的用法


 
        

1 首先要使用shell32  請在項目引用中添加shell32.dll 的引用  (備注:該引用是系統dll文件 在C:\Windows\System32  目錄下 可以自行拷貝到項目中)

  

private void  btnTest_Click(object sender, EventArgs e)     //測試的按鈕點擊事件
{

//測試,將excel中的student導入到sqlserver的DB_MES中,如果sql中的數據表不存在則創建 
System.Windows.Forms.OpenFileDialog fd = new OpenFileDialog();  // new 一個打開文件對話框用於選擇文件 
if (fd.ShowDialog() == DialogResult.OK)
{
string filePath = fd.FileName;

//實例化一個shell 對象

Shell32.Shell shell = new Shell32.ShellClass();

//獲取文件所在父目錄對象 
Folder folder = shell.NameSpace(filePath.Substring(0, filePath.LastIndexOf('\\')));
//獲取文件對應的FolderItem對象 
FolderItem item = folder.ParseName(filePath.Substring(filePath.LastIndexOf('\\') + 1));
//字典存放屬性名和屬性值的鍵值關系對 
Dictionary<string, string> Properties = new Dictionary<string, string>();
int i = 0;
while (true)
{
//獲取屬性名稱 
string key = folder.GetDetailsOf(null, i);
if (string.IsNullOrEmpty(key))
{
//當無屬性可取時,推出循環 
break;
}
//獲取屬性值 
string value = folder.GetDetailsOf(item, i);
//保存屬性 
Properties.Add(key, value);
this.richTextBox1.Text += i.ToString() + key + ":" + value + '\n';  // 窗體界面上創建的richTextBox 控件上顯示所有的屬性值
i++;
}



}

  

 

 

 

//------我的開的文件名是1.xls---------實際運行效果如下------根據運行結果可以查看我們需要的信息對應的索引

0名稱:1.xls
1大小:16.0 KB
2項目類型:Microsoft Office Excel 97-2003 工作表
3修改日期:2017/12/22 11:35
4創建日期:2017/12/22 10:38
5訪問日期:2017/12/22 11:35
6屬性:A
7脫機狀態:
8脫機可用性:
9假設的類型:文檔
10所有者:USER-20170822CM\Administrator
11種類:文檔
12拍攝日期:
13參與創作的藝術家:
14唱片集:
15年:
16流派:
17指揮者:
18標記:
19分級:未分級
20作者:Administrator
21標題:
22主題:
23類別:
24備注:
25版權:
26#:
27長度:
28比特率:
29保護:
30照相機型號:
31尺寸:
32照相機制造商:
33公司:
34文件說明:
35程序名稱:
36持續時間:
37聯機:
38重復:
39位置:
40可選參加者地址:
41可選的與會者:
42組織者地址:
43組織者名稱:
44提醒時間:
45必選的與會者地址:
46必選的與會者:
47資源:
48會議狀態:
49忙閑狀態:
50總大小:
51帳戶名:
52任務狀態:
53計算機:USER-20170822CM (本機)
54紀念日:
55助理姓名:
56助理電話:
57生日:
58商務地址:
59公司所在市縣:
60公司所在國家/地區:
61公司郵箱:
62公司所在地的郵政編碼:
63公司所在省市自治區:
64公司所在街道地址:
65業務傳真:
66公司主頁:
67商務電話:
68回呼號碼:
69車載電話:
70子女:
71公司主要電話:
72部門:
73電子郵件地址:
74電子郵件2:
75電子郵件3:
76電子郵件列表:
77電子郵件顯示名稱:
78文件為:
79名字:
80全名:
81性別:
82名:
83個人愛好:
84住宅地址:
85住宅所在市/縣:
86住宅所在國家/地區:
87住宅郵箱:
88住宅所在地的郵政編碼:
89住宅所在省市自治區:
90住宅所在街道地址:
91住宅傳真:
92住宅電話:
93即時通訊地址:
94姓名縮寫:
95職務:
96標簽:
97姓氏:
98通訊地址:
99中間名:
100手機:
101昵稱:
102辦公位置:
103其他地址:
104其他市縣:
105其他國家/地區:
106其他郵政信箱:
107其他郵政編碼:
108其他省市自治區:
109其他街道地址:
110尋呼機:
111稱謂:
112市縣:
113國家/地區:
114郵箱:
115郵政編碼:
116省市自治區:
117街道地址:
118主要電子郵件:
119主要電話:
120職業:
121配偶/伙伴:
122后綴:
123TTY/TTD 電話:
124Telex:
125網頁:
126內容狀態:
127內容類型:
128獲取日期:
129存檔日期:
130完成日期:
131設備類別:
132已連接:
133發現方法:
134友好名稱:
135本地計算機:
136制造商:
137型號:
138已配對:
139分類:
140打印機狀態:
141客戶端 ID:
142參與者:
143創建內容的時間:
144最后一次打印的時間:
145最后一次保存的日期:‎2017/‎12/‎22 ‏‎11:35
146分部:
147文檔 ID:
148頁碼范圍:
149幻燈片:
150總編輯時間:
151字數:
152截止日期:
153結束日期:
154文件計數:
155文件名:1.xls
156文件版本:
157標志顏色:
158標記狀態:
159可用空間:
160位深度:
161水平分辯率:
162寬度:
163垂直分辯率:
164高度:
165重要性:
166是附件:
167已刪除:
168加密狀態:
169有標志:
170已完成:
171不完整:
172閱讀狀態:
173已共享:否
174編寫者:
175日期:
176文件夾名稱:桌面
177文件夾路徑:C:\用戶\Administrator\桌面
178文件夾:桌面 (C:\用戶\Administrator)
179參加者:
180路徑:C:\用戶\Administrator\桌面\1.xls
181依位置:
182類型:Microsoft Office Excel 97-2003 工作表
183聯系人:
184條目類型:
185語言:
186訪問時間:
187描述:
188鏈接狀態:未解析
189鏈接目標:
190URL:
191創建媒體日期:
192發布日期:
193編碼人員:
194制作人:
195發布者:
196副標題:
197用戶 Web URL:
198創作人:
199附件:
200密件抄送地址:
201密件抄送:
202抄送地址:
203抄送:
204會話 ID:
205接收日期:
206發送日期:
207發件人地址:
208發件人:
209帶有附件:
210發信人地址:
211發信人:
212存儲:
213收件人地址:
214操作標題:
215收件人:
216里程:
217唱片集藝術家:
218唱片集 ID:
219每分鍾節拍數:
220作曲者:
221初始調性:
222編譯的一部分:
223氛圍:
224部分設置:
225時期:
226顏色:
227家長分級:
228父級分級原因:
229已用空間:
230EXIF 版本:
231事件:
232曝光補償:
233曝光程序:
234曝光時間:
235光圈值:
236閃光燈模式:
237焦距:
23835mm 焦距:
239ISO 速度:
240鏡頭制造商:
241鏡頭型號:
242光源:
243最大光圈:
244測光模式:
245方向:
246人員:
247程序模式:
248飽和度:
249目標距離:
250白平衡:
251優先級:
252項目:
253頻道號:
254劇集名稱:
255關閉字幕:
256重新運行:
257SAP:
258廣播日期:
259節目描述:
260記錄時間:
261電台呼叫信號:
262電台名:
263摘要:
264片段:
265自動匯總:
266搜索級別:
267敏感度:
268共享設備:
269共享狀態:專用
270產品名稱:
271產品版本:
272支持鏈接:
273源:
274開始日期:
275帳單信息:
276完成:
277任務所有者:
278總計文件大小:
279合法商標:
280視頻壓縮:
281導演:
282數據速率:
283幀高度:
284幀速率:
285幀寬度:
286總比特率:

  

上面的方法返回所有屬性值,在我的Win7 Pro 64bit 上,返回了287個屬性!可以想象,信息是很豐富的,但是速度也是夠慢的。

可以看到,上面代碼用了一個循環,獲取屬性名和屬性值時都是通過i來索引的。那么,我們是不是就能不通過循環,而直接用下標來獲取想要的屬性呢?代碼如下:

/// <summary>

        /// 獲取指定文件指定下標的屬性值

        /// </summary>

        /// <param name="filePath">文件路徑</param>

        /// <param name="index">屬性下標</param>

        /// <returns>屬性值</returns>

        public static string GetPropertyByIndex(string filePath, int index)

        {

            if (!File.Exists(filePath))

            {

                throw new FileNotFoundException("指定的文件不存在。", filePath);

            }

            //初始化Shell接口 

            Shell32.Shell shell = new Shell32.ShellClass();

            //獲取文件所在父目錄對象 

            Folder folder = shell.NameSpace(Path.GetDirectoryName(filePath));

            //獲取文件對應的FolderItem對象 

            FolderItem item = folder.ParseName(Path.GetFileName(filePath));

            string value = null;

 

            //獲取屬性名稱 

            string key = folder.GetDetailsOf(null, index);

            if (false == string.IsNullOrEmpty(key))

            {

                //獲取屬性值 

                value = folder.GetDetailsOf(item, index);

            }

            return value;

        }


  

在我的系統環境上,分辨率“尺寸”下標是31,那么我只需要GetPropertyByIndex(fd.fileName,31)就可以獲取到分辨率信息了。但是特別需要注意,“尺寸”屬性的下標,在不同的Windows版本(XP,Vista,Win7,Win2003等)不一定是一樣的。

ok,我們還注意到每個屬性都有對應的一個“屬性名”,那么,我們能不能通過屬性名來獲取屬性值呢,這樣會比使用下標保險多了吧。代碼如下:

/// <summary>

        /// 獲取指定文件指定屬性名的值

        /// </summary>

        /// <param name="filePath">文件路徑</param>

        /// <param name="propertyName">屬性名</param>

        /// <returns>屬性值</returns>

        public static string GetProperty(string filePath, string propertyName)

        {

            if (!File.Exists(filePath))

            {

                throw new FileNotFoundException("指定的文件不存在。", filePath);

            }

            //初始化Shell接口 

            Shell32.Shell shell = new Shell32.ShellClass();

            //獲取文件所在父目錄對象 

            Folder folder = shell.NameSpace(Path.GetDirectoryName(filePath));

            //獲取文件對應的FolderItem對象 

            FolderItem item = folder.ParseName(Path.GetFileName(filePath));

            string value = null;

            int i = 0;

            while (true)

            {

                //獲取屬性名稱 

                string key = folder.GetDetailsOf(null, i);

                if (string.IsNullOrEmpty(key))

                {

                    //當無屬性可取時,退出循環 

                    break;

                }

                if (true == string.Equals(key, propertyName, StringComparison.CurrentCultureIgnoreCase))

                {

                    //獲取屬性值 

                    value = folder.GetDetailsOf(item, i);

                    break;

                }

 

                i++;

            }

            return value;

        }

GetProperty

  

這個方法是我一開始寫的,通過在while里面加上屬性名的判斷,直到找到對應的屬性名,則返回相應的屬性值。

不過這個方法還是不夠簡潔,“尺寸”屬性在31,意味着每一次都需要循環31次才能拿到我要的值,如果我要獲取的屬性名下標為287(參看上面),那么次數將更多,於是,我又對代碼做了一些優化:

/// <summary>

        /// 存儲屬性名與其下標(key值均為小寫)

        /// </summary>

        private static Dictionary<string, int> _propertyIndex = null;

 

        /// <summary>

        /// 獲取指定文件指定屬性名的值

        /// </summary>

        /// <param name="filePath">文件路徑</param>

        /// <param name="propertyName">屬性名</param>

        /// <returns>屬性值</returns>

        public static string GetPropertyEx(string filePath, string propertyName)

        {

            if (_propertyIndex == null)

            {

                InitPropertyIndex();

            }

            //轉換為小寫

            string propertyNameLow = propertyName.ToLower();

            if (_propertyIndex.ContainsKey(propertyNameLow))

            {

                int index = _propertyIndex[propertyNameLow];

                return GetPropertyByIndex(filePath, index);

            }

            return null;

        }

 

        /// <summary>

        /// 初始化屬性名的下標

        /// </summary>

        private static void InitPropertyIndex()

        {

            Dictionary<string, int> propertyIndex = new Dictionary<string, int>();

            //獲取本代碼所在的文件作為臨時文件,用於獲取屬性列表

            string tempFile = System.Reflection.Assembly.GetExecutingAssembly().FullName;

            Dictionary<string, string> allProperty = GetProperties(tempFile);

            if (allProperty != null)

            {

                int index = 0;

                foreach (var item in allProperty.Keys)

                {

                    //屬性名統一轉換為小寫,用於忽略大小寫

                    _propertyIndex.Add(item.ToLower(), index);

                    index++;

                }

            }

            _propertyIndex = propertyIndex;

        }

GetPropertyEx

  

propertyIndex用於存儲屬性名與其下標,用Dictionary是因為_propertyIndex[key]的時間復雜度是O(1)。然后在GetPropertyEx方法中找到屬性名對應的下標,直接返回該下標的屬性值。InitPropertyIndex方法只會被調用一次。

好了,我們現在通過屬性名來獲取屬性值,在不同系統之間應該不會有問題了吧?

不一定,原因你肯定也想到了,如果是在一個英文windows上,它的屬性名里面不會有“尺寸”,對應的應該是“Resolution”之類的(我沒有英文版系統,所以只是猜測),也不會有“名稱”屬性,而是“Name”;

總結一下,

方法名

適用

不適用

GetPropertyByIndex

不同語言的系統

不同版本的系統

GetPropertyEx

不同版本的系統

不同語言的系統

所以,根據你的程序可能的運行環境,選擇適合你的方法;

再思考:要能在不同語言不同版本的系統將通用,該怎么辦?

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM