• C# shell32.dll 的用法


    
    

    1 首先要使用shell32  请在项目引用中添加shell32.dll 的引用  (备注:该引用是系统dll文件 在C:WindowsSystem32  目录下 可以自行拷贝到项目中)

      
    
    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 + '
    ';  // 窗体界面上创建的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-20170822CMAdministrator
    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

    不同版本的系统

    不同语言的系统

    所以,根据你的程序可能的运行环境,选择适合你的方法;

    再思考:要能在不同语言不同版本的系统将通用,该怎么办?

  • 相关阅读:
    Spring Security简介与入门Demo
    电商项目之多功能增删改查案例
    linux-用户管理
    zabbix3.4配置第三方邮件报警
    zabbix3.4配置客户端配置
    centos7上安装zabbix3.4的详细步骤与问题处理记录
    MyBatis日记(五):一对一关系,一对多关系
    MyBatis日记(四):MyBatis——insert、update、delete、select
    Python日记(二):Python之禅
    Python日记(一):拜见小主——Python
  • 原文地址:https://www.cnblogs.com/woxihuadabai/p/8086003.html
Copyright © 2020-2023  润新知