Skip to content

Instantly share code, notes, and snippets.

@kou1okada
Created June 2, 2023 11:25
Show Gist options
  • Save kou1okada/357daaa8e128cc64deffe9af1841a38c to your computer and use it in GitHub Desktop.
Save kou1okada/357daaa8e128cc64deffe9af1841a38c to your computer and use it in GitHub Desktop.
shortcutfile_utils.bat - Utilities for the Windows Shortcut File

shortcutfile_utils.bat - Utilities for the Windows Shortcut File

Usage

Usage: SCF-GetFace.bat <ShortcutFile>
Usage: SCF-SetFace.bat <ShortcutFile> <FontFace>

Referenses

<# ::
@REM shebang4powershell.bat - shebang for PowerShell by Batch file.
@REM Copyright 2022 (c) Koichi OKADA. All rights reserved.
@REM This script is destributed under the MIT license.
@REM References:
@REM https://qiita.com/earthdiver1/items/cab769aad623a03a0f2d
@REM https://stackoverflow.com/q/2609985
@
@SETLOCAL
@SET ARGS=%*
@IF DEFINED ARGS SET ARGS=%ARGS:"=\"%
@SET INIT=echo """"`$PSCommandPath=`'%~f0`';`$PSScriptRoot=`'%~dp0`'.TrimEnd(`'\`');""""
@powershell -Command "&([scriptblock]::Create((&{%INIT%;gc '%~f0'|Out-String})))" %ARGS%
@EXIT /B %ERRORLEVEL%
#>
# SFC-GetFace.bat
# Copyright 2023 (c) Koichi OKADA. All rights reserved.
# This script is destributed under the MIT license.
function indexof {param ([Byte[]] $b1,[Byte[]] $b2)
$s1 = [System.BitConverter]::ToString($b1) + "-"
$s2 = [System.BitConverter]::ToString($b2) + "-"
$i = $s1.IndexOf($s2)
if (0 -lt $i) {$i = $i / 3}
return $i
}
if ( $args.count -ne 1) {
[Console]::Error.WriteLine("Usage: $((ls $PSCommandPath).Name) <ShortcutFile>`n")
exit 1
}
if ( $src = ls $args[0] ) {} else {
[Console]::Error.WriteLine("Error: File not exist: $($args[0])")
exit 1
}
$face_idx = 44
$face_len = 64
$size = [System.BitConverter]::GetBytes([Int32] 76)
$guid = [System.GUID]::Parse("{00021401-0000-0000-c000-000000000046}").ToByteArray()
$sig = [Byte[]] @(0xcc,0x00,0x00,0x00,0x02,0x00,0x00,0xa0) # 0x000000cc, 0xa0000002
$data = [System.IO.File]::ReadAllBytes($src)
if ( (indexof $data $size + $guid) -lt 0 ) {
[Console]::Error.WriteLine("Error: File is not shortcut file: {$src}")
exit 1
}
$p = indexof $data $sig
if ( $p -lt 0 )
{
[Console]::Error.WriteLine("Error: The console properties data block is not found: {$src}")
exit 1
}
$p1 = ($p+$face_idx)
$p2 = ($p+$face_idx+$face_len-1)
$face = $data[($p+$face_idx)..($p+$face_idx+$face_len-1)]
[System.Text.Encoding]::Unicode.GetString($face)
<# ::
@REM shebang4powershell.bat - shebang for PowerShell by Batch file.
@REM Copyright 2022 (c) Koichi OKADA. All rights reserved.
@REM This script is destributed under the MIT license.
@REM References:
@REM https://qiita.com/earthdiver1/items/cab769aad623a03a0f2d
@REM https://stackoverflow.com/q/2609985
@
@SETLOCAL
@SET ARGS=%*
@IF DEFINED ARGS SET ARGS=%ARGS:"=\"%
@SET INIT=echo """"`$PSCommandPath=`'%~f0`';`$PSScriptRoot=`'%~dp0`'.TrimEnd(`'\`');""""
@powershell -Command "&([scriptblock]::Create((&{%INIT%;gc '%~f0'|Out-String})))" %ARGS%
@EXIT /B %ERRORLEVEL%
#>
# SFC-SetFace.bat
# Copyright 2023 (c) Koichi OKADA. All rights reserved.
# This script is destributed under the MIT license.
function timebak {param($src)
$src = ls $src
$dst = "$($src.Directory)\$($src.Name),$($src.LastWriteTime.ToString("yyyyMMdd_HHmmss"))$($src.Extension)"
if (-not (Test-Path $dst)) {
cp $src $dst
}
}
function indexof {param ([Byte[]] $b1,[Byte[]] $b2)
$s1 = [System.BitConverter]::ToString($b1) + "-"
$s2 = [System.BitConverter]::ToString($b2) + "-"
$i = $s1.IndexOf($s2)
if (0 -lt $i) {$i = $i / 3}
return $i
}
if ( $args.count -ne 2) {
[Console]::Error.WriteLine("Usage: $((ls $PSCommandPath).Name) <ShortcutFile> <FontFace>`n")
exit 1
}
if ( $src = ls $args[0] ) {} else {
[Console]::Error.WriteLine("Error: File not exist: $($args[0])")
exit 1
}
$face_raw = $args[1]
$face_idx = 44
$face_len = 64
$size = [System.BitConverter]::GetBytes([Int32] 76)
$guid = [System.GUID]::Parse("{00021401-0000-0000-c000-000000000046}").ToByteArray()
$sig = [Byte[]] @(0xcc,0x00,0x00,0x00,0x02,0x00,0x00,0xa0) # 0x000000cc, 0xa0000002
$data = [System.IO.File]::ReadAllBytes($src)
$face = [System.Text.Encoding]::Unicode.GetBytes($face_raw)
if ($face_len -lt $face.length) {
[Console]::Error.WriteLine("Error: font_face is too long: `"{$face_raw}`"")
[Console]::Error.WriteLine(" Unicode length is $($face.length). It must be <= 64.")
exit 1
}
if ( (indexof $data $size + $guid) -lt 0 ) {
[Console]::Error.WriteLine("Error: File is not shortcut file: {$src}")
exit 1
}
$p = indexof $data $sig
if ( $p -lt 0 )
{
[Console]::Error.WriteLine("Error: The console properties data block is not found: {$src}")
exit 1
}
$p1 = ($p+$face_idx)
$p2 = ($p+$face_idx+$face_len-1)
$l = $face.length
for ($i = $p1; $i -le $p2; $i++) {
$data[$i] = 0
}
for ($i = 0; $i -lt $l; $i++) {
$data[$p1+$i] = $face[$i]
}
timebak $src
[System.IO.File]::WriteAllBytes($src, $data)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment