通過快捷方式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)

  


免責聲明!

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



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