草庐IT

linux - 在 GNU/Linux 上生成 lnk 文件传输到 windows

coder 2023-06-18 原文

我将首先解释我的目标以避免“XY 问题”的误解。 我希望能够生成一个文件(在 Linux 上),当下载到 Windows 机器并双击时,将打开一个具有已知路径(在本地 Windows 上)的(ms office,但 IIUC 无关紧要)文件机器)由服务器预设。

如果我在 lnk 文件中包含我要打开的文件的路径(以及关于它存储的卷等的其他详细信息),我尝试做的事情似乎是可能的。 我首先检查了 lnk 文件格式规范,试图在 python 脚本中生成文件,但这不是我的小菜一碟(我以前从未编写代码来处理二进制文件)。此外,我想放弃该格式的许多功能,但我仍然需要理解它们的标志/字段/长度/终止等。

然后我偶然发现了 winedump 实用程序和一些由 WINE 在我的 ~/.wine 文件夹中创建的 .lnk 文件。 WINE代码库中一定有一些函数可以生成lnk文件,但我找不到。 它在哪里? 是像win的mklink那样的命令形式吗? 如果不是(如果不是的话,我想它是某处的一个函数)你能把它指向我,这样我就可以编写一个包装命令吗?

或者有没有可以编写lnk文件并运行在GNU/Linux上的库?

最佳答案

这些未经我测试,但我确实在 this site 上找到了 2 个工具其中确实描述了 2 个工具,如下所示:

This application allow you to create Windows Shortcut files (extension .LNK) without needing a Windows OS.

第一个应用程序是 C app ,第二个是 Bash shell 脚本。这是 Shell 脚本,mslink.sh :

#!/bin/bash

#############################################################################################
# mslink.sh v1.0
#############################################################################################
# Ce script permet de créer un Raccourci Windows (Fichier .LNK)
# Script créé en se basant sur la doc 
#   http://msdn.microsoft.com/en-us/library/dd871305.aspx
#############################################################################################

OPTIONS=$(getopt -q -n ${0} -o hl:o:p -l help,lnk-target:,output-file:,printer-link -- "$@")

eval set -- ${OPTIONS}

IS_PRINTER_LNK=0
while true; do
  case "$1" in
    -h|--help) HELP=1 ;;
    -l|--lnk-target) LNK_TARGET="$2" ; shift ;;
    -o|--output-file) OUTPUT_FILE="$2" ; shift ;;
    -p|--printer-link) IS_PRINTER_LNK=1 ;;
    --)        shift ; break ;;
    *)         echo "Option inconnue : $1" ; exit 1 ;;
  esac
  shift
done

if [ $# -ne 0 ]; then
  echo "Option(s) inconnue(s) : $@"
  exit 1
fi

[ ${#LNK_TARGET} -eq 0 ] || [ ${#OUTPUT_FILE} -eq 0 ] && echo "
Usage :
 ${0} -l cible_du_fichier_lnk -o mon_fichier.lnk [-p]

Options :
 -l, --lnk-target               Précise la cible du raccourci
 -o, --output-file              Enregistre le raccourci dans un fichier
 -p, --printer-link             Génère un raccourci de type imprimante réseau
" && exit 1

#############################################################################################
# Fonctions
#############################################################################################

function ascii2hex() {
    echo $(echo -n ${1} | hexdump -v -e '/1 " x%02x"'|sed s/\ /\\\\/g)
}

function gen_IDLIST() {
        ITEM_SIZE=$(printf '%04x' $((${#1}/4+2)))
        echo '\x'${ITEM_SIZE:2:2}'\x'${ITEM_SIZE:0:2}${1}
}

function convert_CLSID_to_DATA() {
    echo -n ${1:6:2}${1:4:2}${1:2:2}${1:0:2}${1:11:2}${1:9:2}${1:16:2}${1:14:2}${1:19:4}${1:24:12}|sed s/"\([A-Fa-f0-9][A-Fa-f0-9]\)"/\\\\x\\1/g
}

#############################################################################################
# Variables issues de la documentation officielle de Microsoft
#############################################################################################

HeaderSize='\x4c\x00\x00\x00'                           # HeaderSize
LinkCLSID=$(convert_CLSID_to_DATA "00021401-0000-0000-c000-000000000046")   # LinkCLSID
LinkFlags='\x01\x01\x00\x00'                            # HasLinkTargetIDList ForceNoLinkInfo 

FileAttributes_Directory='\x10\x00\x00\x00'                 # FILE_ATTRIBUTE_DIRECTORY
FileAttributes_File='\x20\x00\x00\x00'                      # FILE_ATTRIBUTE_ARCHIVE

CreationTime='\x00\x00\x00\x00\x00\x00\x00\x00'
AccessTime='\x00\x00\x00\x00\x00\x00\x00\x00'
WriteTime='\x00\x00\x00\x00\x00\x00\x00\x00'

FileSize='\x00\x00\x00\x00'
IconIndex='\x00\x00\x00\x00'
ShowCommand='\x01\x00\x00\x00'                          # SW_SHOWNORMAL
Hotkey='\x00\x00'                               # No Hotkey
Reserved='\x00\x00'                             # Valeur non modifiable
Reserved2='\x00\x00\x00\x00'                            # Valeur non modifiable
Reserved3='\x00\x00\x00\x00'                            # Valeur non modifiable
TerminalID='\x00\x00'                               # Valeur non modifiable

CLSID_Computer="20d04fe0-3aea-1069-a2d8-08002b30309d"               # Poste de travail
CLSID_Network="208d2c60-3aea-1069-a2d7-08002b30309d"                # Favoris réseau

#############################################################################################
# Constantes trouvées à partir de l'analyse de fichiers lnk
#############################################################################################

PREFIX_LOCAL_ROOT='\x2f'                            # Disque local
PREFIX_FOLDER='\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'        # Dossier de fichiers
PREFIX_FILE='\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'          # Fichier
PREFIX_NETWORK_ROOT='\xc3\x01\x81'                      # Racine de serveur de fichiers réseau
PREFIX_NETWORK_PRINTER='\xc3\x02\xc1'                       # Imprimante réseau

END_OF_STRING='\x00'

#############################################################################################

# On retire l'anti-slash final s'il y en a un
LNK_TARGET=${LNK_TARGET%\\}

# On sépare le chemin racine du lien de la cible finale
# On distingue aussi si le lien est de type local ou réseau
# On définie la valeur Item_Data suivant le cas d'un lien réseau ou local

IS_ROOT_LNK=0
IS_NETWORK_LNK=0

if [[ ${LNK_TARGET} == \\\\* ]]; then
    IS_NETWORK_LNK=1
    PREFIX_ROOT=${PREFIX_NETWORK_ROOT}
    Item_Data='\x1f\x58'$(convert_CLSID_to_DATA ${CLSID_Network})

        TARGET_ROOT=${LNK_TARGET%\\*}
        if [[ ${LNK_TARGET} == \\\\*\\* ]]; then
                TARGET_LEAF=${LNK_TARGET##*\\}
        fi
        if [ ${TARGET_ROOT} == \\ ]; then
                TARGET_ROOT=${LNK_TARGET}
        fi
else
    PREFIX_ROOT=${PREFIX_LOCAL_ROOT}
    Item_Data='\x1f\x50'$(convert_CLSID_to_DATA ${CLSID_Computer})

    TARGET_ROOT=${LNK_TARGET%%\\*}
        if [[ ${LNK_TARGET} == *\\* ]]; then
        TARGET_LEAF=${LNK_TARGET#*\\}
        fi
    [[ ! ${TARGET_ROOT} == *\\ ]] && TARGET_ROOT=${TARGET_ROOT}'\'
fi

if [ ${IS_PRINTER_LNK} -eq 1 ]; then
    PREFIX_ROOT=${PREFIX_NETWORK_PRINTER}
    TARGET_ROOT=${LNK_TARGET}
    IS_ROOT_LNK=1
fi

[ ${#TARGET_LEAF} -eq 0 ] && IS_ROOT_LNK=1

#############################################################################################

# On sélectionne le préfixe qui sera utilisé pour afficher l'icône du raccourci

if [[ ${TARGET_LEAF} == *.??? ]]; then
    PREFIX_OF_TARGET=${PREFIX_FILE}
    TYPE_TARGET="fichier"
    FileAttributes=${FileAttributes_File}
else
    PREFIX_OF_TARGET=${PREFIX_FOLDER}
    TYPE_TARGET="dossier"
    FileAttributes=${FileAttributes_Directory}
fi

# On convertit les valeurs des cibles en binaire
TARGET_ROOT=$(ascii2hex ${TARGET_ROOT})
TARGET_ROOT=${TARGET_ROOT}$(for i in `seq 1 21`;do echo -n '\x00';done) # Nécessaire à partir de Vista et supérieur sinon le lien est considéré comme vide (je n'ai trouvé nul part d'informations à ce sujet)

TARGET_LEAF=$(ascii2hex ${TARGET_LEAF})

# On crée l'IDLIST qui représente le cœur du fichier LNK

if [ ${IS_ROOT_LNK} -eq 1 ];then
    IDLIST_ITEMS=$(gen_IDLIST ${Item_Data})$(gen_IDLIST ${PREFIX_ROOT}${TARGET_ROOT}${END_OF_STRING})
else
    IDLIST_ITEMS=$(gen_IDLIST ${Item_Data})$(gen_IDLIST ${PREFIX_ROOT}${TARGET_ROOT}${END_OF_STRING})$(gen_IDLIST ${PREFIX_OF_TARGET}${TARGET_LEAF}${END_OF_STRING})
fi

IDLIST=$(gen_IDLIST ${IDLIST_ITEMS})

#############################################################################################

if [ ${IS_NETWORK_LNK} -eq 1 ]; then
    TYPE_LNK="réseau"
    if [ ${IS_PRINTER_LNK} -eq 1 ]; then
        TYPE_TARGET="imprimante"
    fi
else
    TYPE_LNK="local"
fi

echo "Création d'un raccourci de type \""${TYPE_TARGET}" "${TYPE_LNK}"\" avec pour cible "${LNK_TARGET} 1>&2

echo -ne ${HeaderSize}${LinkCLSID}${LinkFlags}${FileAttributes}${CreationTime}${AccessTime}${WriteTime}${FileSize}${IconIndex}${ShowCommand}${Hotkey}${Reserved}${Reserved2}${Reserved3}${IDLIST}${TerminalID} > "${OUTPUT_FILE}"

关于linux - 在 GNU/Linux 上生成 lnk 文件传输到 windows,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14982181/

有关linux - 在 GNU/Linux 上生成 lnk 文件传输到 windows的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  4. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  5. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  6. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  8. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  9. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  10. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

随机推荐