zoukankan      html  css  js  c++  java
  • 通过快捷方式lnk获得文件真实路径

    通过快捷方式.lnk获得文件真实路径
    前提
    最近开发资源管理,需要预先上传大量资源,负责整理资源的同学因为空间不足,直接用快捷键方式整理视频资源OTZ,所以只能想办法通过.lnk文件获得文件的真实地址。

    以下所有内容都来自网络,博主仅做了参考与总结。

    .lnk文件格式解析
    此处对lnk文件组成做一个大概介绍主旨是帮助了解如何从link文件中提取需要的信息
    一个lnk文件包括一下几个模块:

    模块 备注


    注意:
    不是所有的模块都必须包含在内,但如果存在就要按上述的顺序排列。

    以下我们详细了解需要用到的两个模块:
    1. 文件头(lnk file header)

    偏移 长度 类型 备注


    0x14处16进制数的含义:


    0x18处16进制数的含义:


    2. 文件位置信息段(File location info)


    0x08偏移flags 具体含义:

    如果目标文件是本地文件,那么文件名称 = 本地路径信息+剩余偏移路径
    如果目标文件是网络文件,那么文件名称 = 网络卷中共享名称+剩余偏移路径
    所以,File location info节之后的数据是,本地卷信息表,及网络卷信息表。
    1. 本地卷信息表结构


    2. 网络卷信息表结构


    注意:
    八个比特(Bit)称为一个字节(Byte),两个字节称为一个字(Word),两个字称为一个双字(Dword),两个双字称为一个四字(Qword)。

    代码

    private void parseLink(File f) throws FileNotFoundException, IOException {
        FileInputStream fin = new FileInputStream(f); 
        byte[] link = new byte[(int)f.length()]; 
        //读取文件中的内容到link[]数组
        fin.read(link);    
        fin.close(); 
    
        // 判断当前文件是否为快捷方式
        if(!isLnkFile(link)){
            return;
        }
        // 获得flags信息
        byte flags = link[0x14]; 
    
        int shell_len = 0;
        // 0000 0000 xxxx xxxx & 0000 0000 0000 0001(判断是否包含shell item id list段)
        if((flags & 0x1) > 0) { 
            // 如果存在,则获取shell item id list段的总长度,加2是为了将link[0x4c]本身的长度计算在内
            shell_len = bytes2short(link,0x4c) + 2; 
        } 
        // 获得文件位置信息段的开始位置=shell item id list段的开始位置+shell item id list段的总长度
        int file_start = 0x4c + shell_len; 
        // 获取本地路径信息的偏移
        int local_sys_off = link[file_start + 0x10] + file_start;
        String real_file = getNullDelimitedString(link, local_sys_off);
        System.out.println(real_file);
    } 
    
    private boolean isLnkFile(byte[] link) {
        if (link[0x00]== 0x4c) {// 76,L,0x4c代表lnk文件格式
            return true;
        }
        return false;
    }
    
    /**
     * 将两个字节转换为short<br>
     * 注意,因为仅限英特尔操作系统,所以这是小端字节<br>
     */
    private int bytes2short(byte[] bytes, int off) {
        return bytes[off] | (bytes[off + 1] << 8);
    }
    
    /**
     * 获得从偏移位置off到以‘0’为结尾分割字符串
     * @param bytes 源数组
     * @param off 偏移位置
     * @return 字符串
     */
    private String getNullDelimitedString(byte[] bytes, int off) {
        int len = 0;
        // 计算字符串占用数组的真实长度
        while (true) {
            if (bytes[off + len] == 0) {
                break;
            }
            len++;
        }
        byte[] results = new byte[len];
        for (int i = off, j = 0; i < off + len; i++, j++) {
            results[j] = bytes[i];
        }
        try {
            // 因为我是中文系统,所以设置了字符集GBK,否则中文路径会出现乱码
            return new String(bytes, off, len, "GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }
    

      

    import sys
    import win32com.client 
    
    shell = win32com.client.Dispatch("WScript.Shell")
    shortcut = shell.CreateShortCut("t:\test.lnk")
    print(shortcut.Targetpath)
    

      

  • 相关阅读:
    GB/T 38879-2020 颗粒 粒度分析 彩色图像分析法
    GB/T 30431-2020 实验室气相色谱仪
    GB/T 50165-2020 古建筑木结构维护与加固技术标准
    GB/T 51405-2019 船厂总体设计标准
    GB/T 38922-2020 35kV及以下标准化继电保护装置通用技术要求
    GB/T 38953-2020 微电网继电保护技术规定
    GB/T 38886-2020 高温轴承钢等最新国家标准(2020-6-19)
    pytest_02(使用pychar执行pytest)
    pytest-01(安装pytest及运行规则)
    python-05(关于map函数的使用)
  • 原文地址:https://www.cnblogs.com/navysummer/p/12055419.html
Copyright © 2011-2022 走看看