Pin shortcut (.lnk) to start menu - batch-file

I'm currently making an installation script by using a .cmd file.
Here is my code:
IF EXIST "%USERPROFILE%\Desktop\Opslag\Opslag.hta" (
START "" "%USERPROFILE%\Desktop\Opslag\Opslag.lnk" /secondary /minimized
MSG "%USERNAME%" The program is already installed.
EXIT
) ELSE (
XCOPY %SOURCE% %DESTINATION% /D /E /C /R /I /K /Y
START "" "%USERPROFILE%\Desktop\Opslag\Opslag.lnk" /secondary /minimized
MSG "%USERNAME%" Setup is complete!
EXIT
)
The %SOURCE% and %DESTINATION% are set earlier in the script.
When the folder has been copied I want the file %USERPROFILE%\Desktop\Opslag\Opslag.lnk to be added to the Start Menu.
I have seen earlier posts like:
How to pin to start menu using PowerShell, but I cannot make it work.
I'm currently testing it on my home laptop which runs Windows 7 with danish language. The machine where I need to do this runs Windows 7 with english language. Therefore I think the $verb is different from the scripts I've found, but I haven't tested on my work station.
Furthermore my work station has a very limited UAC,
and therefore I do not have Administrator rights. And please do not comment on how this should not be done by users, but only Administrators/IT, as I know what I'm doing.
I hope someone can help me pin the Opslag.lnk to the Start Menu, preferably on both languages (danish and english).

Find the location of the Start Menu folder:
For /f "tokens=3*" %%G in ('REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "Start Menu" ^|Find "REG_"') do Call Set _startmenu=%%H
echo %_startmenu%
pause

In another search I stumbled across a very usefull VBScript: http://blogs.technet.com/b/deploymentguys/archive/2009/04/08/pin-items-to-the-start-menu-or-windows-7-taskbar-via-script.aspx:
Const CSIDL_COMMON_PROGRAMS = &H17
Const CSIDL_PROGRAMS = &H2
Set objShell = CreateObject("Shell.Application")
Set objAllUsersProgramsFolder = objShell.NameSpace(CSIDL_COMMON_PROGRAMS)
strAllUsersProgramsPath = objAllUsersProgramsFolder.Self.Path
Set objFolder = objShell.Namespace(strAllUsersProgramsPath & "\Accessories")
Set objFolderItem = objFolder.ParseName("Calculator.lnk")
Set colVerbs = objFolderItem.Verbs
For Each objVerb in colVerbs
Wscript.Echo objVerb
Next
The script lists alle the verbs for the specifik program, in this case the Calculator. Unfortunately the verb "Pin to Start Menu" in my Opslag.lnk is not listed, and therefore I do not think this can be done with verbs. Hope some one else has other ideas.

I used a .vbs to do this in the current profile (and used the registry, runonce to launch the .vbs on all (new)userprofiles). We are working with both Dutch and English devices in our company so you will see that it will try both languages. The problem is that it did not work on a .lnk but you can always create an exe referring to your desired destination.
Dim strFolder, strExecutable
Set objShell = CreateObject("Shell.Application")
strFolder = "C:\Tools"
strExecutable = "Tool.exe"
Set objFolder = objShell.Namespace(strFolder)
Set objFolderItem = objFolder.ParseName(strExecutable)
Set colVerbs = objFolderItem.Verbs
'Loop through the verbs and if PIN is found then 'DoIt' (execute)
blnOptionFound = False
For Each objVerb In colVerbs
If Replace(objVerb.name, "&", "") = "Aan het menu Start vastmaken" Then
objVerb.DoIt
blnOptionFound = True
End If
Next
For Each objVerb In colVerbs
If Replace(objVerb.name, "&", "") = "Pin to Start Menu" Then
objVerb.DoIt
blnOptionFound = True
End If
Next

Related

How can i run the window of the started program minimized

i want to run a .wav-file. This is with
start "" SoundFile.wav
totally practical. But how can i run the window of the standard-windows-soundplayer minimized? So that nothing of my view changes?
start "" SoundFile.wav /MIN
start "" SoundFile.wav /min
start "" SoundFile.wav -MIN
start "" SoundFile.wav -min
didn't work sadly.
Can you help me?
Greets.
Sorry but i am not familiar with stackoverflow, so i can't make it that understandable, but i hope that this is enough.
In a simple way, you could just use a VBS like this:
s = createobject("WScript.Shell")
s.run "music.mp3", 2
Or create an automatic and CLI program to do this:
runmusic.bat
#echo off
set music=%1
set music=%music:"=%
if ":" neq "%music:~1,1%" set music=%cd%\%music%
if "%music:~-4%" neq ".mp3" set music=%music%.mp3
set katorn=%random%
echo >>"%temp%\%katorn%.vbs" set s = createobject("WScript.Shell")
echo >>"%temp%\%katorn%.vbs" s.run "%music%", 2
cscript "%temp%\%katorn%.vbs"
:: Uncomment the next line to autodelete the vbs file.
:: del /q /f "%temp%\%katorn%.vbs"
Usage:
runmusic (name or full path with quotation marks)
In a "professional way" you could do a shortcut file that starts the file minimized.
It could be useful if you needs the musics to have the "artist logo" or something like that, also if you don't want to use an CMD all the time...
Delete all comments to execute.
Set WshShell = CreateObject ("Wscript.Shell")
strDesktop = "X:\Shortcutlocation\yoo"
Set Shortcut = WshShell.CreateShortcut(strDesktop + "\MusicNameMaybe.lnk")
Shortcut.WindowStyle = "7"
Shortcut.IconLocation = "X:\IconPath\youricon.ico" // You can delete this and the file will be the same ever and forever.
Shortcut.TargetPath = "X:\yourpath\music.mp3"
Shortcut.Save
And you don't have to keep the shortcuts on the desktop if you don't want to, you don't even have to keep them fixed. Example:
runmusic.bat
#echo off
set music=%1
set music=%music:"=%
if ":" neq "%music:~1,1%" set music=%cd%\%music%
set music=%music%.mp3
set katorn=%random%
echo >>"%temp%\%katorn%.vbs" Set WshShell = CreateObject ("Wscript.Shell")
echo >>"%temp%\%katorn%.vbs" strDesktop = "%temp%"
echo >>"%temp%\%katorn%.vbs" Set Shortcut = WshShell.CreateShortcut(strDesktop + "\%katorn%.lnk")
echo >>"%temp%\%katorn%.vbs" Shortcut.WindowStyle = "7"
echo >>"%temp%\%katorn%.vbs" Shortcut.TargetPath = "%music%"
echo >>"%temp%\%katorn%.vbs" Shortcut.Save
cscript "%temp%\%katorn%.vbs"
:: Uncomment the next two lines to delete the temporary files.
:: del /q /f "%temp%\%katorn%.vbs"
:: del /q /f "%temp%\%katorn%.lnk"
echo Enjoy!
Usage:
runmusic (name or full path with quotation marks)
Now that you understand, you can even leave a folder with the songs and the other with just the customized shortcuts, which can come in handy.
Hope this helps,
K.

Delete random services with number name script (ex. 10009752)

I work for a IT consulting company and one of our clients got hit with a virus that created a bunch of random exe files on the PC and then it created services to try to run those files automatically. I've since removed the virus from all machines, but there are a lot of orphaned services left I need to remove.
All in all there are 4,000 unique services combined from all of the computers at their facility. The services are random numbers and I am hoping to find a way to remove them with a script of some sort, but I can't figure out how to do a wildcard for the commands I know....
I've tried
reg delete hklm\system\currentcontrolset\services\1*
and
sc delete \\pcname 1*
without any luck. Any help would be appreciated so I don't have to go to each machine (again) and manually delete the services. Sorry I am always learning new scripts by going out and seeing what other people have created, but I can't find anything to even build off of for this situation.
Thank you in advance.
We can imagine a script that get all services names and check if the name is numeric, if so delete the service :
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
for /f "tokens=1 delims= " %%a in ('tasklist') do (
set "$service=%%a"
echo !$service:.exe=! | findstr "^[-][1-9][0-9]*$ ^[1-9][0-9]*$ ^0$">nul && call:delete %%a || echo %%a is not numeric
)
exit/b
:delete
echo %1 is Numeric
echo here the command to delete the service (%1)echo off
Put the command to remove the service in the :delete label
Using #Endoro's solution to check if a value is Numeric :
#echo off
setlocal
set "root_key=HKLM\system\currentcontrolset\services"
for /f "tokens=5 delims=\" %%A in ('reg query "%root_key%"') do (
call :check_key "%%~A"
if errorlevel 1 call :del_key "%%~A"
)
goto :eof
:check_key
setlocal enabledelayedexpansion
set "filtered="
set "original=%~1"
if not defined original exit /b 0
for /f "delims=0123456789" %%A in ("!original!") do set "filtered=%%~A"
if not defined filtered exit /b 1
exit /b 0
:del_key
echo "%~1"
rem sc stop "%~1"
rem sc delete "%~1"
goto :eof
Use of reg query to loop through the services key. The 5th token
delimited after \ is the key name of the service.
call :check_key with the for loop delimits on digits 0 to 9. If
filtered is not defined, then only digits existed in the key name
so it will exit the label setting errorlevel 1.
If errorlevel 1 is caught in the main for loop, then call :del_key
runs sc stop to stop the service and sc delete deletes the service
key. Remove the rem before the sc commands to enable them.
Created for local machine use though some minor changes could do remote use.
You can use a VbScript for that, simple, first instance the WMI service:
Computer = "." 'IP or Network Name ("." is Local host)
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & Computer & "\root\cimv2") 'If your user have the access
or.. if you need use other user.
Computer = "." 'IP or Network Name
UserAndDomain = ".\Administrator" 'Account WITH domain "\"
Pass = "" ' Account Password
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objWMIService = objSWbemLocator.ConnectServer(Computer, "Root\CIMv2", UserAndDomain , Pass)
Now obtain the Services Collection:
Set colServices = objWMIService.ExecQuery("Select * from Win32_Service") ' Where Name ='" & strServiceName & "'" or "Like = 'Someting%'"
'Or
Set colServices = objSWbemServices.InstancesOf("Win32_Service")
And then to delete:
For Each Service in colServices
If IsNumeric(Service.Name) Then 'Or other condition.
Service.Delete
End If
Next

How to change a drive letter dynamically on a .bat script

I'm currently working with an old script for a process that was in place before I took a look at it, the premise is to automatically create a folder and copy the contents of a flash drive into a C: drive. Below is the portion of the script I am concerned with:
xcopy "E:\directory" "c:\directory" /s /y
This is the script as I have it now, currently I need to change the first directory entry almost every time I plug into a new device as the drive letter as it appears in the script is sometimes different then what is on the local device. For example, the UBS drive would be D: on a laptop, but E: on most desktops, or some other letter in the case of a device with multiple peripherals.
Previously the script looked something like:
xcopy "...\directory" "c:\directory" /s /y
This doesn't function as the .bat file would come back with an inability to locate said directory on the UBS drive. When I manually change the .bat file to hard set the USB drive letter everything flows fine, all directories copy and the subsequent scripts run fine.
My question, any ideas on how to set the xcopy script to recognize the dynamic USB drive letter and allow for copying without having to change the script on each device?
Thanks!
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set evtDevice = objWMIService.ExecNotificationQuery ("SELECT * FROM Win32_VolumeChangeEvent")
Wscript.Echo "Waiting for events ..."
Do
Set objReceivedEvent = evtDevice.NextEvent
'report an event
Wscript.Echo " Win32_Device Changed event occurred" & VBNewLine
If objReceivedEvent.EventType = 1 Then
Wscript.Echo "Type = Config Changed"
ElseIf objReceivedEvent.EventType = 2 Then
Wscript.Echo "Type = Device Arrived"
Set colItems = objWMIService.ExecQuery("Select * From Win32_Volume")
For Each objItem in colItems
If objitem.DriveType = 2 then
Wscript.Echo objItem.DriveType & " " & objItem.Name & " " & objItem.driveletter
Set objShell = CreateObject("Shell.Application")
Set Ag=Wscript.Arguments
set WshShell = WScript.CreateObject("WScript.Shell")
Set SrcFldr=objShell.NameSpace(objitem.driveletter)
Set DestFldr=objShell.NameSpace("c:\test\")
Set FldrItems=SrcFldr.Items
DestFldr.CopyHere FldrItems, &H214
Wscript.Echo "Finished Copying"
Wscript.sleep 2000
End If
Next
ElseIf objReceivedEvent.EventType = 3 Then
Wscript.Echo "Type = Device Left"
ElseIf objReceivedEvent.EventType = 4 Then
Wscript.Echo "Type = Computer Docked"
End If
Loop
This vbs script waits for a USB to be inserted then copies it to a folder.
Remove all the debugging wscript.echo lines. Change the destination folder.
It copies all attached USB drives.
despite the previous answer from Noodles
#echo off
set "destDrive="
for /F "usebackq tokens=1,2 delims==" %i in (`"wmic logicaldisk get caption, drivetype"`) do (
if %%j EQU 2 set "destDrive=%%i"
)
if "%destDrive%" EQU "" (
echo No pendrive found
) else (
echo copying
xcopy "%destDrive%\directory\*.*" "c:\directory\*.*" /s /y
echo done...
)
Why not modify the batch file to ask for the drive letter before the copy begins?
SET /P USB=Enter USB Drive Letter (C:, D:, E: etc):
XCOPY "%USB%\directory" "C:\directory" /s /y

Batch trying to log information from a REG_MULTI_SZ value

Have seen - Assigning newline character to a variable in a batch script
I am wanting to take a REG_MULTI_SZ and split to multiple lines..
For example, we have:
if %PROCESSOR_ARCHITECTURE% == AMD64 SET ApacheKey="HKLM\SOFTWARE\Wow6432Node\Apache Software Foundation\Procrun 2.0\Tomcat6\Parameters\Java"
if NOT %PROCESSOR_ARCHITECTURE% == AMD64 SET ApacheKey="HKLM\SOFTWARE\Apache Software Foundation\Procrun 2.0\Tomcat6\Parameters\Java"
POWERSHELL "Get-ItemProperty 'HKLM:%ApacheKey%' |select -ExpandProperty Options" >> somelog.txt
Thanks to the response below and the post found at - How to read multi line multi string registry entries in PowerShell?
as this is now working!
Please note: I cannot use vbs (well I could) but would rather not as I have to codesign my scripts.
Can break out the "\0" delimiters. The issue that I have right now is that I type in echo %SETTINGS% from the command-line and I can see the new lines.. Probably going to have to PIPE the original variable to a text file. Read in (type) the file and if the "\0" is found to echo. which should write the file properly.
The original log shows:
-Dcatalina.base=C:\tomcat\0-Dcatalina.home=C:\tomcat\0-Djava.endorsed.dirs=C:\tomcat\endorsed\0-Djava.io.tmpdir=C:\tomcat\temp\0-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager\0-Djava.util.logging.config.file=C:\tomcat\conf\logging.properties\0-Dcom.sun.management.jmxremote\0-Dcom.sun.management.jmxremote.port=1092\0-Dcom.sun.management.jmxremote.ssl=false\0-Dcom.sun.management.jmxremote.authenticate=false\0-XX:MaxPermSize=256m\0-Xmx1024m\0-Xms1024m\0-Xverify:none\0-XX:+UseConcMarkSweepGC\0-XX:+UseParNewGC\0-XX:MinHeapFreeRatio=40\0-XX:MaxHeapFreeRatio=60\0-XX:MaxGCPauseMillis=200
What I want it to show is:
-Dcatalina.base=C:\tomcat
-Dcatalina.home=C:\tomcat
-Djava.endorsed.dirs=C:\tomcat\endorsed
-Djava.io.tmpdir=C:\tomcat\temp
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djava.util.logging.config.file=C:\tomcat\conf\logging.properties
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=1092
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-XX:MaxPermSize=256m
-Xmx1024m
-Xms1024m
-Xverify:none
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:MinHeapFreeRatio=40
-XX:MaxHeapFreeRatio=60
-XX:MaxGCPauseMillis=200
It can be simple using Vbscript working with your batch script:
:: Create readMulti.vbs
(
echo/Const HKEY_LOCAL_MACHINE = ^&H80000002
echo/strComputer = "."
echo/Set oReg=GetObject^("winmgmts:{impersonationLevel=impersonate}!\\" ^& _
echo/ strComputer ^& "\root\default:StdRegProv"^)
echo/strKeyPath = "SOFTWARE\Apache Software Foundation\Procrun 2.0\tomcat6\Parameters\Java"
echo/strValueName = "Options"
echo/oReg.GetMultiStringValue HKEY_LOCAL_MACHINE,strKeyPath, _
echo/ strValueName,arrValues
echo/For Each strValue In arrValues
echo/ Wscript.Echo strValue
echo/Next)>readMulti.vbs
for /f "tokens=*" %%a in ('cscript //nologo readMulti.vbs') do (echo/%%a>>log.txt)
del readMulti.vbs

Error in running a batch file from VB Script

VB scripting is completely alien to me but today landed in a situation to write a small one. I need Admin rights to run my .bat file. So I am trying to elevate to Admin rights if not have them. With the help of SO and Google I reached upto:
Function Length()
Set WshShell = WScript.CreateObject("WScript.Shell")
If WScript.Arguments.length = 0 Then
Set ObjShell = CreateObject("Shell.Application")
ObjShell.ShellExecute "wscript.exe", """" & WScript.ScriptFullName & """" & " RunAsAdministrator", , "runas", 1
Else
Dim shell
set shell=createobject("wscript.shell")
shell.run "ExtractFiles.bat"
End If
End Function
Length
Here, this .vbs and ExtractFiles.bat are saved in same folder. I opened 2 command prompts. One in Admin mode and other normal. When running this script thorugh command prompt in Admin mode, I am getting success. But in normal mode, first I get a window to switch to Admin mode and I press Yes on it. Then I get below error:
Can anyone point me to correct code. I am getting error in line shell.run "ExtractFiles.bat". Please help!
As I have also mentioned the requirement, a different approach is also welcome. In this problem, I am not sure how I am able to run the bat file in admin mode and failing in normal mode.
Add the Admin VBS code into your bat file. Here is my routine for the job.
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:Admin <Return> [Needed] [Success]
:: Check for Administrator privileges and request privileges if Needed 'true'.
:::: Usage: call :Admin xReturn true
:: Return success value, if user is Admin. Default `true` if Success not set.
setlocal
set "xVBUAC=%Temp%\AdminUAC.vbs"
set "xSuccess=true"
set "xAdmin=false"
if not "%~3"=="" set "xSuccess=%~3"
:: Check for Access
::net session >nul 2>&1
>nul 2>&1 "%SystemRoot%\system32\cacls.exe" "%SystemRoot%\system32\config\system"
if %ErrorLevel% EQU 0 set "xAdmin=%xSuccess%"
:: Execute UAC
if /i not "%xAdmin%"=="%xSuccess%" if not "%~2"=="" if /i "%~2"=="true" (
echo Set UAC = CreateObject^("Shell.Application"^) > "%xVBUAC%"
echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%xVBUAC%"
if exist "%xVBUAC%" (
"%xVBUAC%"
rem if %ErrorLevel% EQU 5 echo Access Denied. Launching UAC.
del "%xVBUAC%"
)
)
endlocal & if not "%~1"=="" set "%~1=%xAdmin%"
goto :eof
How to Use it
:: Example Admin check
#echo off
setlocal EnableExtensions
call :Admin xReturn true 1
if not "%xReturn%"=="1" goto End
:: Do my .bat stuff here.
goto End
:: TODO Place the admin function here.
:End
Depending on how you launch the VBScript the directory in which the scripts reside isn't necessarily the working directory. Try this:
Set fso = CreateObject("Scripting.FileSystemObject")
scriptDir = fso.GetParentFolderName(WScript.ScriptFullName)
shell.run "%COMSPEC% /c """ & fso.BuildPath(scriptDir, "ExtractFiles.bat") & """"
What you enter in the command prompt? Is it...
InstallACS.vbs ExtractFiles.bat
Your script works just fine on XP x64 (if that important) never mind how I'll run it - from the sell or from the console, and also work with and without argument.

Resources