В Windows имеется такая штука, как ярлык для файла. Это очень удобно для классификаций. Вот сделал я файл MyFile.doc, который имеет расположение C:\Users\Buhgalter\...\MyFile.doc, сделал на него ярлык, где указал этот путь - и могу вызывать этот файл из любого места проекта через копию ярлыка. И при любом запуске ты будешь иметь дело с одним файлом, там будут одинаковые изменения и память ты истратишь только на один этот файл. Копии ярлыков никакой памяти на диске не занимают, практически.
И я могу копии файла хранить и по контрагенту (если это на тему постоянного клиента), и в продажах (если это покупатель), и в судах (если судимся), и в образцах (если в нём есть что-то общеупотребительное) и т.д. И не только ярлык на файл - можно так же и каталог через ярлыки на него использовать.
Но вот проблема. Обычно большой проект (фирму, бухгалтерию которой веду, например) я могу использовать на нескольких машинах и дома. Копируя проект с места на место. Но дома я имею дело вот с таким каталогом, например: C:\Users\dmitgu\...\MyFile.doc
Где многоточие - там одно и то же - я так копирую проект всегда в одно место в выделенной мне части диска. Но путь ведь изменился и ярлыки перестают работать. Однако, в Windows 10 (и даже сильно раньше) появилась возможность обозначать часть пути в ярлыке, которая отвечает за активного пользователя (а комп «понимает», кто сейчас работает и какая часть из пользовательских файлов - его) вот так: %USERPROFILE%. И тогда путь в ярлыке будет в любом случае иметь вид:
%USERPROFILE%\...\MyFile.doc
И ярлык будет работать на любом компе, на который ты стандартным образом в своём пользовательском каталоге расположишь свой проект.
Но как добиться такого «универсального» пути в ярлыках? Можно вручную редактировать ярлыки, но это тоска. Или можно написать программу, используя возможности Windows PowerShell.
Я несколько лет назад пытался, но были проблемы с русской кодировкой - программа работала только в кодировке UTF-8 (иначе интерпретатор её не воспринимал), но все пользовательские сообщения лезли «кракозябрами» и я начихал возится с эти. И вдруг - дело наладилось. Прогу оказалось возможным сохранять в обычной кодировке 1251 и сообщения работали нормально. Есть мелкие проблемы, но преодолимые.
Дальше я привожу программу на JavaScript для локального компьютера, эта программа использует возможности Windows PowerShell (создавая объекты из разных библиотек Windows при помощи WScript.CreateObject). Можно запускать эту программу по двойному щелчку мыши, если поставить в соответствие расширению .js программу «Microsoft ® Windows Based Script Host». Тогда программ делает все ярлыки в своей директории (откуда её запустили) «универсальными» - пригодными для разных рабочих мест.
Или можно запускать её bat-файлом в той же директории, только сохраняйте bat-файл в кодировке 866 (в отличие от скрипта на JavaScript):
Файл «_lab_link_modif_v1.0_RUN.bat»:
rem I use Notepad++ OEM_866 (Cyrillic) for edit this file.
rem Moscow. 00:02 AM 02.01.2021
@echo off
rem Следующая команда (Список файлов) - работает
rem с cscript "_lab_link_modif_v1.0.js"
cscript _lab_link_modif_v1.0.js
pause
Прежде чем дать программный текст файла «_lab_link_modif_v1.0.js» упомяну, почему я этим занялся. Вообще-то я сейчас пишу модель «Машина исполнения компьютерных алгоритмов». Так как для теории (которую мне надо подготовить к публикации) мне нужна модель с бесконечной памятью. А я не могу просто «масштабировать» современные компы в бесконечность, так как компы работают с ограниченной памятью, размер которой определяется разрядностью процессора и разрядностью памяти.
А мне надо сделать архитектуру, в которой память можно наращивать неограниченно - это же для математической модели надо. И я придумал и довольно красиво - хоть и кучу вариантов перепробовал и придумал специальный «аппаратный» язык отправки «одновременных» сообщений соседним устройствам (так информация передаётся от ячейке к соседней ячейке по «эстафете», притом разные ячейки работают одновременно, передавая целые «пакеты» сообщений «вплотную» друг к другу).
И получилось под 100 страниц, хоть и не сложно, когда уже придумано. И всё это я не могу проверить отладкой - это же пока просто «инженерный» проект! И да, такой комп действительно можно сделать - в нём память можно наращивать как угодно, не меняя процессор.
И я уже просто обалдел от невозможности практически «почувствовать» алгоритмы. Ведь модель - это не теория, а очень практическая штука, где ты опираешься не на аксиомы и логические выводы из них, а на реальность и своё сопоставление твоих программ и свойств реальности.
Поэтому вернулся к старой отложенной задаче - мне надо освежить связь с реальностью. И да - после такой сложной разработки для неограниченного по своей памяти компьютера - мне оказалось легко решить старую практическую задачу. Но она действительно не сложная, но полезная ведь.
Файл «_lab_link_modif_v1.0.js» (до конца данной записи):
// Это версия 1.0 от 04 января 2021 г. скрипта для "универсализации" ярлыков в каталоге данного скрипта,
// заменой начала пути файла (из стандартного набора имен для каталогов рабочих мест) на %USERPROFILE%\.
// При этом проверка - менять ли ярлык - проводится только по имени рабочего каталога
// и в имени Ярлыка убирается концевая подстрока "Ярлык" - если таковая есть.
// Чтобы программа работала корректно, её надо сохранять в кодировке Windows 1251 в программе
// Notepad++, например. Но там надо периодически проверять, не "слетела" ли кодировка.
// И восстанавливать, если "слетела" (пункт в Меню так и называет "Кодировка"
//, а там ищи Кириллица и далее
var WshShell, path, fso, oFolder, oFiles;
var i, strList;
var FullFileName;
var Shl, ShortcutObj, bl;
function UserProFileReplace(TargetPath0) {
// Эта функция по аргументу-пути файла/каталога проводит его модификацию, если он указывает на файлы
// некоторого Юзера (например - начало C:\Users\Buhgalter\), из перечня внутри программы,
// заменяя это начало пути на "%USERPROFILE%\"
// Результат будет истина, если модификация была проведена и ложь, если ярлык указывает НЕ на файл пользователя,
// притом из специального перечня UserProFiles[] внутри данной функции
var UserProFiles = ["C:\\Users\\Buhgalter\\", "C:\\Users\\dmitgu\\"];
var userbeg, forcomp, result;
userbeg = "%USERPROFILE%\\";
result = TargetPath0;
for (var i = 0; i < UserProFiles.length; ++i) {
forcomp = TargetPath0.substring(0, UserProFiles[i].length).toLocaleLowerCase();
// WScript.Echo(forcomp + "\n" + UserProFiles[i].toLocaleLowerCase());
if ( forcomp == UserProFiles[i].toLocaleLowerCase() )
{ result = userbeg + TargetPath0.substring(UserProFiles[i].length);
break;
}
}
return result;
}
function ShortcutModif(ShortcutObj) {
// Эта функция по аргументу-ярлыку WScript.Shell.CreateShortcut(FullFileName) из файловой системы
// Проводит его модификацию, если он указывает на файлы некоторого Юзера, заменяя это начало пути на
// %USERPROFILE%\ Результат будет истина, если модификация была проведена и ложь, если ярлык указывает
// не на файл пользователя.
var OldTardet, OldDir, NewWorkingDir, NewTargetPath;
OldTardet = ShortcutObj.TargetPath; // Полный путь с именем файла/приложения, но без аргументов
// OldArgums = ShortcutObj.Arguments // Аргументы
OldDir = ShortcutObj.WorkingDirectory; // Рабочий каталог
if (OldDir == "") {
// Не могу оставлять пустой рабочий каталог (это ярлык на каталог, значит), потому что именно по строке в нём
// идёт проверка - был ли модифицирован ярлык (универсализирован)
OldDir = OldTardet
}
NewWorkingDir = UserProFileReplace(OldDir);
// WScript.Echo(OldDir + "\n" + NewWorkingDir);
NewTargetPath = UserProFileReplace(OldTardet);
// WScript.Echo(OldTardet + "\n" + NewTargetPath);
// if (NewWorkingDir != OldDir || NewTargetPath != OldTardet)
if (NewWorkingDir != OldDir) // Только свойство TargetPath выдаёт директорию буквально, не "переводя" %USERPROFILE%\ в тот каталог, который он обозначает
{
ShortcutObj.TargetPath = NewTargetPath;
ShortcutObj.WorkingDirectory = NewWorkingDir
ShortcutObj.Save();
return true;
} else return false;
}
path = WScript.ScriptFullName;
path = path.substring(0, path.lastIndexOf("\\")+1); // 2-й аргумент в substring - номер 1-го не включаемого символа
path = path + "";
/* Объект для получения семейства файлов в папке */
fso = WScript.CreateObject("Scripting.FileSystemObject");
oFolder = fso.GetFolder(path);
/* Объект для работы с конкретным файлом, когда это ярлык */
Shl = WScript.CreateObject("WScript.Shell");
/* Инициализация семейства файлов каталога и обработка ярлыков среди них при переборе этих файлов */
strList = "";
oFiles = new Enumerator(oFolder.Files);
for(; !oFiles.atEnd(); oFiles.moveNext()) {
objItem = oFiles.item();
if (objItem.Name.slice(-4) == ".lnk") {
FullFileName = path + objItem.Name
strList = strList + FullFileName + "\n";
ShortcutObj = Shl.CreateShortcut(FullFileName);
bl = ShortcutModif(ShortcutObj);
// if (bl) {WScript.Echo(" да");} else WScript.Echo(" нет");
if (objItem.Name.slice(-9).toLocaleLowerCase() == "Ярлык.lnk".toLocaleLowerCase())
{
// Приходится использовать .toLocaleLowerCase(), т.к. заглавные буквы констант в Notepad++ не всегда соответствуют написанию в программе
// WScript.Echo("!");
objItem.Name = objItem.Name.slice(0, -9) + ".lnk";
}
}
}
// WScript.Echo(" файлы:\n" + strList);