Creating a shortcut for a exe using a batch file - batch-file

I know a topic already exists like that but I do not want to use a VB script.
I would hope you can create a shortcut using a command line in DOS.
Please post some example that would be great.
Thanks!
AA

You can't create a shortcut in a .bat file without invoking an external program.
However, every version of Windows since Win2k has a built in scripting language called Windows Script Host
Here is a small WSH script that I wrote a few years ago that can be called from a .bat file,
just save this text as shortcut.wsf, it contains useage information in the script.
<package>
<job id="MakeShortcut">
<runtime>
<description>Create a shortcut (.lnk) file.</description>
<named
name = "Target"
helpstring = "the target script"
type = "string"
required = "true"
/>
<named
name = "Args"
helpstring = "arguments to pass to the script"
type = "string"
required = "false"
/>
<unnamed
name = "basename"
helpstring = "basename of the lnk file to create"
type = "string"
required = "false"
/>
</runtime>
<script language="JScript">
if ( ! WScript.Arguments.Named.Exists("Target"))
{
WScript.Arguments.ShowUsage();
WScript.Quit(2);
}
target = WScript.Arguments.Named.Item("Target");
WScript.Echo("target " + target);
args = WScript.Arguments.Named.Item("Args");
WScript.Echo("args " + args);
base = WScript.Arguments.Unnamed.Item(0);
WScript.Echo("base " + base);
fso = WScript.CreateObject("Scripting.FileSystemObject");
//path = fso.GetParentFolderName(WScript.ScriptFullName);
path = fso.GetAbsolutePathName(".");
WScript.Echo("path = " + path);
Shell = WScript.CreateObject("WScript.Shell");
short = fso.BuildPath(path,base);
if ( ! fso.GetExtensionName(base))
short = short + ".lnk";
link = Shell.CreateShortcut(short);
link.TargetPath = fso.BuildPath(path, target);
if (args != null && args != "")
link.Arguments = args;
else
link.Arguments = base;
//link.Description = "Sound Forge script link";
//link.HotKey = "ALT+CTRL+F";
//link.IconLocation = fso.BuildPath(path, target) + ", 2";
//link.WindowStyle = "1"
//link.WorkingDirectory = path;
link.Save();
</script>
</job>
</package>
run it without any arguments to get useage
c:\> shortcut.wsf
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
Create a shortcut (.lnk) file.
Usage: shortcut.wsf /Target:value [/Args:value] [basename]
Options:
Target : the target script
Args : arguments to pass to the script
basename : basename of the lnk file to create

mklink /D c:\vim "C:\Program Files (x86)\Vim"
More Info Here
And Cygwin's ln - s
http://en.wikipedia.org/wiki/Symbolic_link#Cygwin_symbolic_links

Creating a shortcut in the .lnk format is basically impossible from a batch file without calling an external program of some kind. The file spec can be found here, and a quick glace will explain.
Creating a .url format shortcut is quite easy as the format is a simple text file. The spec can be found here. This format has a few disadvantages, but may accomplish your goal.

you can get shortcut.exe from the resource kit.

It can now be done with Powershell, which arguably sucks somewhat less than VBscript. And powershell can be called from a .bat / .cmd file:
powershell "$s=(New-Object -COM WScript.Shell).CreateShortcut('%userprofile%\Desktop\mylink.lnk'); $s.TargetPath='C:\Path\to\your.exe'; $s.Save()"
See also here for another example: https://ss64.com/nt/shortcut.html#e
See also

Related

how to concatenate two variables when one has spaces in it in AzureDevops batch file

I have this input in my ps script. I am passing $(Build.ArtifactStagingDirectory) system variable to get the path in the input %1. The path has spaces i.e. E:\Build Agents\Agent2\_work\15\a. I need to concatenate this with other path but I am not able to do so.
set BuildDrop=%1
set Directory=%BuildDrop% + "\adapters\bin"
This is my output, which is incorrect as Directory should be something like E:\Build Agents\Agent2\_work\15\a\adapters\bin. How to solve this?
set BuildDrop="E:\Build Agents\Agent2\_work\15\a"
set Directory="E:\Build Agents\Agent2\_work\15\a" + "\adapters\bin"
My task is like this in my build pipeline
Task : Batch script
Description : Run a Windows command or batch script and optionally allow it to change the environment
Version : 1.1.10
I found the solution for this. Since my %1 had space I needed to remove apostrohphe before assigning. I did it using ~ variable. working code looks like this.
set "BuildDrop=%~1"
set "Directory=%BuildDrop%\adapters\bin"
You could try this :
set BuildDrop=%1
set Directory= %BuildDrop%\adapters\bin
echo %Directory%
Sample Output
This is the concatenation code.
%BuildDrop%\adapters\bin
In my above sample I am trying to concatenate C:\Users\svijay\Desktop & \adapters\bin using the batch script
And the output : C:\Users\svijay\Desktop\adapters\bin
UPDATE :
#echo off
set BuildDrop=%1
set Directory= %BuildDrop%\adapters\bin
set Directory= %Directory:"=%
echo %Directory%
If you have space, you could provide the "" to provide input.
In your code you could remove the double quotes.
%Directory:"=% - Removes the Double quotes from the string literal.
Sample output :
You may use this to create Azure DevOps variable containing your path
powershell: |
$directory = $(Build.ArtifactStagingDirectory)
$newDirectory = $directory + "\adapters\bin"
Write-Host "##vso[task.setvariable variable=testvar]$newDirectory "
and if you need set variable in powershell script
$BuildDrop=$args[0]
$Directory=$BuildDrop + "\adapters\bin"
Here you have an article how to use parameters in powershell.
We can use powershell task in the Azure DevOps to concatenate two variables.
Sample:
Write-Host "Build.ArtifactStagingDirectory is $(Build.ArtifactStagingDirectory)"
Write-Host "Build.ArtifactStagingDirectory is $(Build.ArtifactStagingDirectory)\adapters\bin"
Result:
In addition, I found a similar issue, please also check it.
Update1
Use power shell script in the Azure DevOps pipeline
$testpath1 = "E:\Build Agents\Agent2\_work\15\a"
$testpath2 = "\adapters\bin"
Write-Host "path is $($testpath1)$($testpath2)"
Result:
Use local power shell
Result:
Update2
.bat file
set testpath1=E:\Build Agents\Agent2\_work\15\a
set testpath2=\adapters\bin
set newpath=%testpath1%%testpath2%
echo %newpath%
Pipeline result:

Paste of clipboard to text file with batch file [duplicate]

For example, I can copy a file to the clipboard like this:
clip < file.txt
(Now the contents of file.txt is in the clipboard.)
How can I do the opposite:
???? > file.txt
So that the contents of the clipboard will be in file.txt?
If it would be acceptable to use PowerShell (and not cmd), then you can use Get-Clipboard exactly as you were looking for.
Get-Clipboard > myfile.txt
The advantage of this method is that you have nothing to install.
Note: In place of clip you can use Set-Clipboard that has more options.
Note 2: If you really want to run it from cmd, you can call powershell as in the following example powershell -command "Get-Clipboard | sort | Set-Clipboard".
You can use the paste.exe software in order to paste text just like you are describing.
http://www.c3scripts.com/tutorials/msdos/paste.html
With it you can do:
paste | command
to paste the contents of the windows clipboard into the input of the specified command prompt
or
paste > filename
to paste the clipboard contents to the specified file.
Clarifying an answer from #Kpym:
powershell -command "Get-Clipboard" > file.txt
This directly answers the question without using a 3rd party tool.
To get contents of clipboard
From win cmd:
powershell get-clipboard
or (via a temp file from HTML parser) on cmd:
echo x = CreateObject("htmlfile").ParentWindow.ClipboardData.GetData("text") > temp.vbs
echo WScript.Echo x >> temp.vbs
cscript //nologo temp.vbs
Output may be redirected to file.
Using the doskey macro definition feature, you can do:
doskey unclip=(powershell -command "Get-Clipboard") $*
Then (e.g.)
dir/b | clip
unclip | sort/r
I have a pair of utilities (from before the Clip command was part of windows) available on this page:
http://www.clipboardextender.com/general-clipboard-use/command-window-output-to-clipboard-in-vista
There are two utilities in there, Clip2DOS and DOS2Clip. You want Clip2DOS:
Clip2DOS Copyright 2006 Thornsoft Development
Dumps clipboard text (1024 bytes) to stdout.
Usage: Clip2Dos.exe > out.txt
Result: text is in the file.
Limits: 1024 bytes.
License: Free, as in Free Beer!
http://www.thornsoft.com/dist/techsupport/dos2clip.zip
DELPHI SOURCE INCLUDED!
And hey, here it is (Clip2DOS.dpr) :
{Clip2DOS - copyright 2005 Thornsoft Development, Inc. All rights reserved.}
program Clip2Dos;
{$APPTYPE CONSOLE}
uses
Clipbrd,
ExceptionLog,
SysUtils;
var
p : Array[0..1024] of Char;
begin
try
WriteLn('Clip2DOS Copyright 2006 Thornsoft Development');
Clipboard.GetTextBuf(p,1024);
WriteLn(p);
except
//Handle error condition
on E: Exception do
begin
beep;
Writeln(SysUtils.format('Clip2DOS - Error: %s',[E.Message]));
ExitCode := 1; //Set ExitCode <> 0 to flag error condition (by convention)
end;
end
end.
Pasteboard is another option. It can also work from WSL. First, install via choco:
choco install pasteboard
then the command is simply
pbpaste.exe > file.txt
And that works from cmd and wsl bash.
Well, from a million years ago, we did something like this:
type con > filename.txt
... and then you perform your paste operation (Ctrl-v, middle-click the mouse, or choose Edit->Paste from them menu) into the waiting prompt. This will capture the stdin buffer (the console device, named 'con'), and when an end-of-file is received, it will write the contents to the file. So, after your paste, you type 'Ctrl-z' to generate an EOF, and the type command terminates, and the contents of your paste buffer (the clipboard) are captured in 'filename.txt'.
There are third party clip commands that work bidirectionally.
Here's one:
CLIP - Copy the specified text file to the clip board
Copyright (c) 1998,99 by Dave Navarro, Jr. (dave#basicguru.com)
Here is the CLIP program by Dave Navarro, as referred to in the answer by #foxidrive. It is mentioned in an article here: copying-from-clipboard-to-xywrite
A link to the download, along with many other resources is on this page: http://www.lexitec.fi/xywrite/utility.html
Here is a direct link to the download:
"DOWNLOAD Clip.exe Copy from and to the clipboard by Dave Navarro, Jr."
It may be possible with vbs:
Option Explicit
' Gets clipboard's contents as pure text and saves it or open it
Dim filePath : filePath = "clipboard.txt"
' Use the HTML parser to have access to the clipboard and get text content
Dim text : text = CreateObject("htmlfile").ParentWindow.ClipboardData.GetData("text")
' to open
If Not IsNull(text) then
Dim WshShell, somestring, txFldr2Open
Set WshShell = WScript.CreateObject("WScript.Shell")
txFldr2Open = "C:\Users"
txFldr2Open = text
somestring = "EXPLORER.exe /e," & txFldr2Open ', /select
WshShell.run somestring
Set WshShell = Nothing
else
msgbox("Empty")
end if
' Create the file and write on it
msgbox(text)
Dim fileObj : Set fileObj = CreateObject("Scripting.FileSystemObject").CreateTextFile(filePath)
fileObj.Write(text)
fileObj.Close
You can use cbecho, a program I wrote in plain C. It will send any clipboard text to stdout, from where you can pipe it to other programs.
I am not sure if this command was not supported at that time or not, but it surely does work
clip > file.txt
This dirty trick worked for my needs, and it comes with Windows!
notepad.exe file.txt
Ctrl + V, Ctrl + S, Alt + F, X

Jenkins function definition: call a batch file using function arguments

Here is a chunk of code I have in a pipeline:
def doBuild(folder, script, scriptArguments = '') {
bat '''cd folder
call script scriptArgument'''
}
So basically, it is a windows command saying: move to this directory, and call this script.
Of course, during execution, the command will be executed as 'cd folder' and will fail.
How can I make sure the 'folder' is replaced by the value passed in argument ?
Edit:
Following the suggestion of Vitalii, I tried the following code:
/* Environment Properties */
repository_name = 'toto'
extra_repository_branch = 'master'
branch_to_build = "${env.BRANCH_NAME}"
version = "${branch_to_build}_v1.5.4.${env.BUILD_NUMBER}"
/* Methods definitions properties */
def doTag() {
dir(repository_name) {
String tagCommand = """git tag -m "Release tag ${env.BUILD_URL}" ${version}"""
String pushCommand = "git push --tags origin ${branch_to_build}"
bat '''
call $tagCommand
call $pushCommand'''
}
}
Here is the output:
C:\Jenkins\toto>call $tagCommand '$tagCommand' is not recognized
as an internal or external command, operable program or batch file.
C:\Jenkins\toto>call $pushCommand '$pushCommand' is not
recognized as an internal or external command, operable program or
batch file.
Thanks very much for your time
You can use string interpolation
bat """cd $folder
call $script $scriptArgument"""
So I did not think it was the case first but it was really had its answer in What's the difference of strings within single or double quotes in groovy?
Using single quotes, the text is considered as literrate. Using double code, it will interpret correctly the $tagCommand. A working version is:
/* Methods definitions properties */
def doTag() {
dir(repository_name) {
String tagCommand = """git tag -m "Release tag ${env.BUILD_URL}" ${version}"""
String pushCommand = "git push --tags origin ${branch_to_build}"
bat """call $tagCommand
call $pushCommand"""
}
}

Automate WinSCP to get listing of files in remote directory

I've read a lot about automating WinSCP, but some of it I had trouble understanding because it presumed knowledge of other things, like .NET assembly, PowerShell, etc.
I'm wondering if, speaking strictly in VBScript and batch file file type of lingo, once I've downloaded the portable winscp.exe, how to simply open a remote site, give a user name and password, and download a list of the files in a particular directory. FTP protocol only.
There's an example for using the Session.ListDirectory from VBScript:
<job>
<reference object="WinSCP.Session"/>
<script language="VBScript">
Option Explicit
' Setup session options
Dim sessionOptions
Set sessionOptions = WScript.CreateObject("WinSCP.SessionOptions")
With sessionOptions
.Protocol = Protocol_Ftp
.HostName = "ftp.example.com"
.UserName = "user"
.Password = "mypassword"
End With
Dim session
Set session = WScript.CreateObject("WinSCP.Session")
' Connect
session.Open sessionOptions
Dim directoryInfo
Set directoryInfo = session.ListDirectory("/remote/path")
Dim fileInfo
For Each fileInfo In directoryInfo.Files
WScript.Echo fileInfo.Name & " with size " & fileInfo.Length & _
", permissions " & fileInfo.FilePermissions & _
" and last modification at " & fileInfo.LastWriteTime
Next
' Disconnect, clean up
session.Dispose
</script>
</job>
Other than that:
download the WinSCP .NET assembly package and extract it along with the script.
register the assembly for COM. Typically like:
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe WinSCPnet.dll /codebase /tlb:WinSCPnet32.tlb
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe WinSCPnet.dll /codebase /tlb:WinSCPnet64.tlb
Run the script (list.wsf) like:
cscript list.wsf
You can of course also just run winscp.com scripting like:
Set shell = CreateObject("WScript.Shell")
Set exec = shell.Exec("winscp.com /command ""open ftp://username:password#ftp.example.com/"" ""ls /remote/path"" ""exit""")
WScript.Echo(exec.StdOut.ReadAll())
For more details on this approach see guide to advanced FTP scripting from VB script.

Calling SVN post-lock only once

I've been trying to write a post-lock hook for my VisualSVN server on Windows, using batch files and VBS scripts. The end goal is to have the hook email a list of all the locked files to a collection of email addresses. However, the hook is called for every file. I'm hoping there's a way around this, or a clever way of waiting for all the information before sending the email. Also, I want a list of all the files, but currently only the repo path is passed in. I know the file paths are passed via stdin, but I haven't found a way to get that into a string to be passed to my VBS file. Any help would be great.
Batch File:
#echo off
pushd %~dp0
cscript email-bat.vbs %2 LOCKED %1
#pause 5
VBS:
Set emailObj = CreateObject("CDO.Message")
Set args = WScript.Arguments
emailObj.From = "mymail#gmail.com"
emailObj.To = "tomail#gmail.com"
emailObj.Subject = "SVN " + args.Item(1)
emailObj.TextBody = args.Item(0) + " has " + args.Item(1) + " the file(s) " + args.Item(2) + "."
Set emailConfig = emailObj.Configuration
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.gmail.com"
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 465
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = true
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/sendusername") = "mymail#gmail.com"
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "password"
emailConfig.Fields.Update
emailObj.Send

Resources