Page 1 of 1

find path of a shortcut calling a batch file

Posted: 30 Jul 2016 13:41
by mirrormirror
If I have a windows shortcut that launches a batch file is there any way for the batch file to "know" the location of the shortcut for use within the batch file itself?

I don't mean hard-coding the path or even passing it as a parameter within the shortcut call - I want it to dynamically be able to "get" the ull path to the calling .lnk file. For example, if I have a shortcut on my desktop and then move the shortcut to a toolbar or something I would like to know the location of the shrtcut that called the batch file.

The reason is that the batch file modifies the properties of the calling shortcut link.

Re: find path of a shortcut calling a batch file

Posted: 31 Jul 2016 04:58
by aGerman
That's not possible. If you leave out the "Start in" property of the shortcut then the working directory of your batch file will be the location of your shortcut. You still don't know its name though.

Regards
aGerman

Re: find path of a shortcut calling a batch file

Posted: 31 Jul 2016 06:25
by aGerman
Working around the mentioned limitation ...
Requirement: the "Start in" property of the shortcut is left empty!

Code: Select all

@if (@a)==(@b) @end /* Batch portion

@echo off &setlocal
echo working directory "%cd%"

:: find shortcuts in the working directory that target the batch file
for /f "delims=" %%i in ('cscript //nologo //e:jscript "%~fs0"') do echo found "%%i"

:: you may change the working directory afterwards
cd /d "%~dp0"
echo working directory "%cd%"

pause
exit /b


JScript portion */
var objWShell = new ActiveXObject('WScript.Shell'),
    objFSO = new ActiveXObject('Scripting.FileSystemObject'),
    objEnum = new Enumerator(objFSO.GetFolder(objWShell.CurrentDirectory).Files);

for (; !objEnum.atEnd(); objEnum.moveNext()) {
  if (objFSO.GetExtensionName(objEnum.item()).toLowerCase() == 'lnk') {
    var objShortcut = objWShell.CreateShortcut(objEnum.item());
    if (objShortcut.TargetPath == WScript.ScriptFullName) {
      WScript.Echo(objEnum.item());
    }
  }
}

Re: find path of a shortcut calling a batch file

Posted: 31 Jul 2016 14:51
by mirrormirror
Thanks much - I think this may work.

Sometimes I need to disable screensaver / monitor power off features while watching videos (sometimes my player's functionality doesn't work 100%) So I created a small script to toggle these things on/off. It then changes the IconLocation property to a different icon (with a red "x" through it) so I can visually see the state of things.

Once in a while, the icon doesn't display properly after doing the IconLocation script update. Does anyone know how to refresh system icons from the command line? The following seems to work sometimes but not always:

Code: Select all

ASSOC .DummyFileExtension=DummyFile
ASSOC .DummyFileExtension=

If anyone is interested, here are the scripts (I should probably combine them)

Code: Select all

SET "lnkFile=C:\Users\Default\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\ScreenSaver_Toggle.cmd.lnk"
SET "iconPath=c:\utils\Screensaver_Toggle"
SET "srcFiles=c:\utils\Screensaver_Toggle"

SET "qKEY=HKEY_CURRENT_USER\Control Panel\Desktop"
SET "qVAL=ScreenSaveActive"

SET "regVal="
FOR /F "usebackq tokens=* delims=" %%a IN (`REG QUERY "%qKEY%" /v "%qVAL%" ^| FIND /N "REG_SZ"`) DO (
   @ECHO a: %%a
   FOR /F "tokens=3,*" %%b IN ("%%a") DO SET regVal=%%~c
)
@ECHO regVal: "%regVal%"
SET ssState=1
IF "%regVal%"=="0" SET ssState=1
IF "%regVal%"=="1" SET ssState=0

SET OFFico=Monitor_OFF_01.ico
SET ONico=Monitor_ON_01.ico
IF "%ssState%"=="1" (SET currIcon=%ONico%) &&CALL PowerCfg_Toggle_MonPowerOff.cmd ON
IF "%ssState%"=="0" SET currIcon=%OFFico% &&CALL PowerCfg_Toggle_MonPowerOff.cmd OFF

reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaveActive /t REG_SZ /d %ssState% /f
WScript "%srcFiles%\UpdateLnkProperties.vbs" "%lnkFile%" ***-SKIP-*** "%iconPath%\%currIcon%"

REM not sure if these delays are needed...
sleep -m 500
ASSOC .DummyFileExtension=DummyFile
sleep -m 100
ASSOC .DummyFileExtension=

PowerCfg_Toggle_MonPowerOff.cmd

Code: Select all

@ECHO OFF & SETLOCAL DISABLEDelayedExpansion
GOTO :StartScript
REM Checks for existence of %nmMon_NoPowerOff% in Power Plan names and Creates one if not found (Based on "Balanced" or %nmBalanced%)
REM Toggles between ACTIVE Plans: %nmBalanced% and %nmMon_NoPowerOff%
REM         If %nmMon_NoPowerOff% is set active then AC Monitor Timeout Minutes set to %LongTimeoutMinutes%

:StartScript
REM SETLOCAL DISABLEDelayedExpansion
SETLOCAL ENABLEDelayedExpansion
   SET "MonPowerOFF="
   IF /I "%~1"=="ON" SET "MonPowerOFF=ON"
   IF /I "%~1"=="OFF" SET "MonPowerOFF=OFF"
   IF NOT DEFINED MonPowerOFF SET "MonPowerOFF=TOGGLE"
   
   SET /A LongTimeoutMinutes=120
   SET "nmBalanced=Balanced"
   SET "nmMon_NoPowerOff=Custom_Mon_NoPowerOff"
   SET "guidBalanced="
   SET "guidMon_NoPowerOff="

   FOR /F "tokens=2,* delims=:(" %%a IN ('powercfg -list ^|FIND /I "Power Scheme GUID:"') DO (
      FOR /F "delims=)" %%A IN ("%%~b") DO (
         IF "%%~A"=="%nmBalanced%" (
            FOR /F "delims= " %%B IN ("%%~a") DO SET "guidBalanced=%%~B"
         )
         IF "%%~A"=="%nmMon_NoPowerOff%" (
            FOR /F "delims= " %%B IN ("%%~a") DO SET "guidMon_NoPowerOff=%%~B"
         )
      )
   )

@ECHO(

   IF NOT DEFINED guidMon_NoPowerOff (
      FOR /F "tokens=2,* delims=:(" %%a IN ('powercfg -DUPLICATESCHEME "%guidBalanced%"^|FIND /I "Power Scheme GUID:"') DO (
         FOR /F "delims= " %%A IN ("%%~a") DO SET "guidMon_NoPowerOff=%%~A"
         powercfg -changename "!guidMon_NoPowerOff!" "%nmMon_NoPowerOff%"
      )
   )
   @ECHO !nmMon_NoPowerOff!:   "%guidMon_NoPowerOff%"

   SET "ActiveScheme="
   FOR /F "tokens=2,* delims=:(" %%a IN ('POWERCFG -GETACTIVESCHEME ^|FIND /I "Power Scheme GUID:"') DO (
      FOR /F "delims=)" %%A IN ("%%~b") DO SET "ActiveScheme=%%~A"
   )
   
   IF /I "%MonPowerOFF%"=="TOGGLE" (
      IF "%ActiveScheme%" neq "%nmBalanced%" (SET "MonPowerOFF=ON")  ELSE (SET "MonPowerOFF=OFF")
   )

   IF /I "%MonPowerOFF%"=="ON" IF DEFINED guidBalanced POWERCFG -SETACTIVE "%guidBalanced%"
   IF /I "%MonPowerOFF%"=="OFF" (
      IF DEFINED guidMon_NoPowerOff POWERCFG -SETACTIVE "%guidMon_NoPowerOff%"
      IF DEFINED guidMon_NoPowerOff POWERCFG -Change -monitor-timeout-ac %LongTimeoutMinutes%
   )

   @ECHO(
   POWERCFG -GETACTIVESCHEME
   @ECHO(

ENDLocal

UpdateLnkProperties.vbs

Code: Select all

' Param1=lnkName   Param2=lnkTarget   Param3=IconLocation
Set wshShell = WScript.CreateObject("WScript.Shell")

SkipUpdate="***-SKIP-***"
lnkName=WScript.Arguments(0)
lnkTarget=WScript.Arguments(1)
sIconLocation=SkipUpdate
   IF WScript.Arguments.Count>2 THEN sIconLocation=WScript.Arguments(2)

   'Special Folders Example:
      'Set lnk = wshShell.CreateShortcut(wshShell.SpecialFolders("desktop") & "\AE Client.LNK")
Set lnk = wshShell.CreateShortcut(lnkName)
IF lnkTarget <> SkipUpdate THEN lnk.targetpath = lnkTarget
IF sIconLocation <> SkipUpdate THEN lnk.IconLocation=sIconLocation
lnk.save

Set lnk = Nothing
Set wshShell  = Nothing

You'll need to reference existing icons on your machine - or if you want, I can encode the icons I use and post them here.

Re: find path of a shortcut calling a batch file

Posted: 31 Jul 2016 16:36
by aGerman
screensaver

The last time that I used a screensaver was with a CRT display years ago.

Does anyone know how to refresh system icons from the command line?

The only method I knew so far was the SendMessage WinAPI. I found a PS function that wrapped it:
http://powershell.com/cs/media/p/8322.aspx
Append line Refresh-Explorer to the Code and save as "refresh.ps1".
Call the script from within the Batch file using

Code: Select all

powershell -NoProfile -ExecutionPolicy Bypass -Command "& '.\refresh.ps1'"


Regards
aGerman

Re: find path of a shortcut calling a batch file

Posted: 01 Aug 2016 20:57
by mirrormirror
Hello aGerman - you have been very helpful - thank you. I created the script per your instructions and it seems to refresh my desktop icons (I can see the icons flash for a moment) but it doesn't seem to refresh my toolbar icons :( But no need to continue looking I can deal with the issue.