Multi Commander Support Forum
		Multi Commander => Script => Topic started by: pncdaspropagandas on February 10, 2017, 19:22:28
		
			
			- 
				I did a script that when focusing on a Shortcut / Symbolic Link / Hardlink / Junction it navigates to it's target.
 
 It's a mix of MC Script, Python and an executable (because it seems no one care about enumerating hardlinks targets)
 
 If there's more than 2 instances of a hardlink or junction, the script asks the user witch one he likes.
 
 I'm posting the main Python code (I used some custom libs I did). If people get interested I can post the full code.
 
 MC Script:
 @var $source_focus_path = '"' + GetSourceFocusPath() + '"';
 @var $python_script_path;
 @var $link_target;
 @var $link_target_temp_file;
 @var $link_target_file_size;
 @var $findlinks_path;
 @var $aux[];
 @var $aux2;
 
 $python_script_path = '"' + GetTagValue("${mcinstallpath}") ^ 'Tools\Links\Resolve Link.py' + '"';
 $link_target_temp_file = GetTagValue("${mcinstallpath}") ^ 'Tools\Links\link_target.txt';
 $findlinks_path = '"' + GetTagValue("${mcinstallpath}") ^ 'Tools\Links\Hardlink\FindLinks.exe' + '"';
 
 
 if (FileExists($link_target_temp_file) == 1)
 {
 $aux = {"NOPROGRESS", "NODIALOG", "SILENT"};
 DeleteFile($link_target_temp_file, $aux);
 }
 
 // There's a bug in StrReplace when using ^ in parameter
 $aux2 = '^"';
 $python_script_path    = StrReplace($python_script_path, '"', $aux2);
 $source_focus_path     = StrReplace($source_focus_path, '"', $aux2);
 $findlinks_path        = StrReplace($findlinks_path, '"', $aux2);
 $link_target_temp_file = StrReplace($link_target_temp_file, '"', $aux2);
 // Run Python script to get link target and store it in a temp file
 LogAppInfo('"H:\Programas\MultiCommander - Projetos\Tools\Command Line Utilities\nircmd\nircmd_x64.exe" execmd "^"C:\Python35\python.exe^" ' + $python_script_path + ' ' + $source_focus_path + ' ^"' + $link_target_temp_file + '^" ' + $findlinks_path + '"');
 MC.Run CMD='"H:\Programas\MultiCommander - Projetos\Tools\Command Line Utilities\nircmd\nircmd_x64.exe"' ARG={'execmd "^"C:\Python35\python.exe^" ' + $python_script_path + ' ' + $source_focus_path + ' ^"' + $link_target_temp_file + '^" ' + $findlinks_path + '"'} WAIT
 
 // Clear selected files in the case of the link target being on the same folder
 arrayAdd($aux, '');
 SetSourceSelected($aux, 1);
 
 // Ao rodar o nircmd ele retorna o sinal de terminado para o MultiComander antes de o Python ter terminado de rodar
 // Então temos que esperar manualmente até o Python ter terminado de rodar
 // A cada 50ms checamos se o arquivo $link_target_temp_file foi criado, até um timeout de 1s
 @var $n;
 for ($n = 0; $n < 20; $n++)
 {
 if (FileExists($link_target_temp_file) == 1)
 {
 break;
 }
 Sleep(50);
 }
 
 // Go to target
 if (FileExists($link_target_temp_file) == 1)
 {
 Sleep(100);
 
 //LogAppInfo($link_target_temp_file);
 $link_target_file_size = GetFileSize($link_target_temp_file);
 if ($link_target_file_size > 0)
 {
 $link_target = LoadStringFromFile($link_target_temp_file);
 //LogAppInfo($link_target);
 
 // Delete temp file
 $aux = {"NOPROGRESS", "NODIALOG", "SILENT"};
 //DeleteFile($link_target_temp_file, $aux);
 
 // Clear selected files in the case of the link target being on the same folder
 arrayAdd($aux, '');
 SetSourceSelected($aux, 1);
 
 // As Mathias said here http://forum.multicommander.com/forum/index.php/topic,1929.0.html
 // "the UI can't be updated until the script is finished since the script is running in the same thread"
 // So there's no way to break going to the folder, then selecting the file in 2 operations
 // We can do it in 1 go using MC.RunCmd ID="Core.1312" that is CTRL+V with the target path on the clipboard
 // The ony downside is that we loose the clipboard content
 SetClipboardText($link_target);
 
 // Check if there's more than 1 link target (hardlinks and junctions)
 @var $link_targets[] = StrLines2Array($link_target);
 // If more than 1, ask the user
 if (arrayCount($link_targets) > 1)
 {
 @var $link_targets_answer = AskOption('Select target', $link_targets, 0);
 if ($link_targets_answer == -1)
 {
 // User cancelled
 break;
 }
 SetClipboardText($link_targets[$link_targets_answer]);
 }
 
 // Go To Link Target
 MC.RunCmd ID="Core.1312"
 }
 else
 {
 LogAppInfo('Error');
 }
 
 }
 else
 {
 MessageBox('Resolve Link', 'Operation timeout', 0);
 }
 
 
 Python:
 
 # -*- coding: utf-8 -*-
 
 # argv[1] = link file/folder path
 # argv[2] = path to exchange text file with Multi Commander
 # argv[3] = path to FindLinks.exe
 
 # argv[1] can't end with /
 # Doesn't work when running inside Multi Commander and argv[1] is a symbolic link inside a junction (but it works inside cmd for example)
 
 import sys
 import os
 import win32com.client
 import mylib.windows.windows as lib_windows
 import mylib.files.file_handling as lib_file_handling
 
 file = open(sys.argv[2], 'w')
 
 if sys.argv[1][-3:].lower() == 'lnk':
 print('Shortcut detected')
 shell = win32com.client.Dispatch("WScript.Shell")
 shortcut = shell.CreateShortCut(sys.argv[1])
 print(shortcut.Targetpath)
 file.write(shortcut.Targetpath)
 
 elif os.path.islink(sys.argv[1]):
 print('Symbolic Link detected')
 link_target = lib_file_handling.get_symlink_target(sys.argv[1])
 if link_target is not None:
 print(link_target)
 file.write(link_target)
 
 elif lib_file_handling.is_junction(sys.argv[1]):
 print('Junction detected')
 link_target = lib_file_handling.get_junction_target(sys.argv[1])
 print(link_target)
 file.write(link_target)
 
 elif os.stat(sys.argv[1]).st_nlink > 1:
 print('Hard Link detected')
 stdout, stderr, returncode = lib_windows.run_command_line('"' + sys.argv[3] + '" "' + sys.argv[1] + '"')
 findlinks_return = stdout.splitlines()
 if int(findlinks_return[7][8:]) > 0:
 for line in range(10, len(findlinks_return)):
 if findlinks_return[line].lower() != sys.argv[1].lower():
 print(findlinks_return[line])
 file.write(findlinks_return[line] + '\n')
 
 file.close()
 
 And the executable is here https://technet.microsoft.com/en-us/sysinternals/hh290814
- 
				Check the latest beta, there are MultiScript function in that to get link type and target, it should make the script smaller and easier
 http://forum.multicommander.com/forum/index.php/topic,1953.0.html
 
 
- 
				This is great! It will make things way more simple and realiable! Thanks Mathias!