Powershell signcode.exe Innosetup [duplicate] - inno-setup

This question already has answers here:
Inno Setup - Signing fails with "Sign Tool failed with exit code 0x1"
(2 answers)
Closed 4 years ago.
EDITED:
I have problems with InnoSetup and signtool. The following works perfectly from the Command Line (I reverted from PowerShell in my original post to CMD).
"c:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86\signtool.exe" sign /f certificate.p12 /p password /t http://timestamp.verisign.com/scripts/timstamp.dll MyApp.exe
However, if I put the same line in InnoSetup IDE (adding $f at the end as requested by InnoSetup), it fails with "sign tool failed with exit code 0x1". I have already seen the following answer, however as on the command line it works fine, it doesn't help.
Without the codetool line "SignTool=signtool", InnoSetup compiles correctly.

In PowerShell, use the & symbol (aka call operator or invocation operator) to execute a command name that contains quotes and whitespace.
& "c:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86\signtool.exe" sign /f certificate.p12 /p password /t http://timestamp.verisign.com/scripts/timstamp.dll MyApp.exe
Why? Because PowerShell interprets a quoted string (first on the line) as a string, rather than a command. The & operator means "the string that follows is a command."
Read the PowerShell help topic about_Operators for more information.

Related

Signing with full path with spaces to signtool.exe fails with “Sign Tool failed with exit code 0x1” in Inno Script Studio

In Inno Setup, my sign tool is defined as:
cmd /k "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\signtool.exe" sign /t http://timestamp.comodoca.com /n "My Company" $f
Prepending cmd /k (as suggested at Inno Setup - Signing fails with "Sign Tool failed with exit code 0x1") reveals that there is not actually a problem with the sign tool itself, but rather how Inno Setup is calling it, generating the following message:
'C:\Program' is not recognized as an internal or external command, operable program or batch file.
Clearly, it's chopping off the path to signtool at the first space, even though I put it in quotes. I even tried replacing the quotes with $q to see if that made any difference. (It didn't.) I would think this is improper behavior for the parser to dishonor the quotes, since the instructions clearly say to paste the exact text you'd use on the command line, and the example itself includes quotation marks (https://revolution.screenstepslive.com/s/revolution/m/10695/l/563371-signing-installers-you-create-with-inno-setup).
Everything works beautifully from the command line. For some reason, Inno Setup just isn't properly calling signtool.
ADDED 2020-07-14:
Inno Setup's example, copied from their website:
"C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin\signtool.exe" sign /f "C:\MY_CODE_SIGNING.PFX" /t http://timestamp.comodoca.com/authenticode /p MY_PASSWORD $f
My version, used without the cmd /k:
"C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\signtool.exe" sign /t http://timestamp.comodoca.com /n "My Company" $f
As you can see, we use quotes in the same manner. I will check for updates - I probably should have done that first. When I get some time, I'll revert the signtool definition and see if maybe the update fixes it.
Also, I should have been more clear. I am new to Inno Setup and it didn't occur to me to clarify this. I am compiling via Inno Script Studio. It occurs to me that there's some possibility this has to do with a behavior in a specific version of Script Studio and not the compiler itself, but I don't know enough about the inner workings to do any more than speculate.
Having done a bit more tinkering, I'm now fairly certain this must be a bug with Inno Setup. I implemented a work-around as follows:
Open a command window with elevated privileges
Change to a directory I created with no space in the name: cd \bin
Create a 'spaceless' symbolic link to the directory where signtool.exe is located: mklink /d "Windows10SDK" "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64"
Enter new sign tool definition that uses the symbolic link:
C:\bin\Windows10SDK\signtool.exe sign /t http://timestamp.comodoca.com /n "My Company" $f
And that's it! Because there is no longer a space character in the path to signtool.exe, Inno Setup now performs the signing correctly and everything works beautifully.
I'll report this as a bug and update if needed.
I use:
#define SignedDesc "$q" + MSA + "$q"
#define SignedPfx "$qd:\My Certificate\2018\My Certificate.pfx$q"
#define SignedTimeStamp "$qhttp://timestamp.verisign.com/scripts/timestamp.dll$q"
#define SignedPw "$q~~~~~~~$q"
SignTool=SignTool /d {#SignedDesc} /du $q{#AppURL}$q /f {#SignedPfx} /p {#SignedPw} /t {#SignedTimeStamp} /v $f
My sign tool is configured as:
$qC:\Program Files (x86)\Windows Kits\10\bin\10.0.16299.0\x86\Signtool.exe$q sign $p
You have to use $q which is a quote mark.

Why is an error output on parsing a line within a FOR loop? [duplicate]

This question already has an answer here:
Variables are not behaving as expected
(1 answer)
Closed 4 years ago.
I'm currently trying to write a batch file to automatically detect if a VPN is logged in or not. However, the code is not working as expected.
set VAR=SUCCESS
for /f "delims=: tokens=1" %%i in ('"C:\Program Files (x86)\F5 VPN\f5fpc.exe" -info') do (
set str=%%i
set rep=%str:logged out=%
echo %str%
echo %rep%
if not "%str%"=="%rep%" (
set VAR=FAIL
)
echo %VAR%
)
echo %VAR%
Running "C:\Program Files (x86)\F5 VPN\f5fpc.exe" -info will give exactly the following (will have spaces before the start of each line):
Command arguments:
INFO result:
session: code: status:
xxxxxx 64 logged out
There is 1 active session(s)!
The status can be either logged out or session established. What I'm trying to determine is that I'd have run the VPN. If the user has successfully logged into the VPN, then I need to do something, otherwise, have to execute some other code.
VAR=FAIL means the VPN failed to log in successfully and would be in logged out state. The problem I'm facing is that the str and rep variables are not assigned any value. I can determine it by the echo statements.
Can somebody help me out in this?
There is a much more simple way to work around this. The way you have the for statement setup will cause it to perform echo's and set strings for each new line of the output string.
A very easy way is to use the | FIND /I after your command. This will filter and search for a statement or text your looking for without any loops.
"C:\Program Files (x86)\F5 VPN\f5fpc.exe" -info | FIND /I "logged out">Nul && (Echo.logged out) || (Echo.session established)
To use the setup, simply put your command in the front (Before the pipe) and use the find /I "" to search for that within the output. Please keep in mind that >Nul will silence the command from being shown on console, which is great for this use.

Sign the exe file using NSIS script

I am using NSIS script to generate the exe file.
Now i have to sign the exe and what i am doing is using NSIS , create the exe file first. Then i open the command prompt in admin mode and run the Signtool.exe file along with parameters like path to pfx file, timestamp url etc to sign the exe and its getting signed without any issues
But i found that using Finalize http://nsis.sourceforge.net/Docs/Chapter5.html#finalize in NSIS we can call the Signtool command from NSIS script itself
So for doing do i tried to make a .bat file with code for Signing the exe in it and saved the bat file in the same location of nsis script and i called this line of code in the end
!finalize 'signfile.bat'
But this resulted in the below message
Finalize command: signfile.bat 'signfile.bat' is not recognized as
an internal or external command, operable program or batch file.
Finalize command returned 1
I tried with direct signing like below
Signtool.exe sign /f k:\---.pfx /p ????? /tr http://timestamp.----.com /td sha256 /fd sha256 "%1"
and
Signtool.exe sign /f k:\--.pfx /p ????? /tr http://timestamp.---.com /td sha256 /fd sha256 filename.exe
Then i get this error
!finalize expects 1-3 parameters, got 13.
Usage: !finalize command_with_%1 []
So anyone can helps to find out the proper syntax to use for signing the exe file from nsis script directly
The error message you get when running the .bat is from cmd.exe because it cannot find the file. You could try !finalize dir to find out what the current directory actually is.
The quote syntax is !finalize '"c:\path\to\app.exe" "par am 1" param2 "par am 3"'

Start Excel file from Windows batch script in safemode, use default file association

Question Summary:
Can I start Excel file Installer.xlsm from Windows batch script in safemode, without providing EXCEL.EXE installation path?
Details
I have a windows batch script which downloads the latest versions of a family of Excel Add-ins from a remote server, places them in a directory (C:\appname\AddIns) and calls the Excel file Installer.xlsm.
Upon loading, Installer.xlsm executes a VBA macro, which uninstalls older versions of the add-ins and installs their newer version.
Currently I start Installer.xlsm using the command:
start "Launching installer file" /wait "<Path to file>\Installer.xlsm"
What's great about it is that it uses Windows' file association to open Excel, and I don't have to provide the EXCEL.EXE installation path (multiple users with different machine images and MS Office versions).
Now I'd like to load Installer.xlsm in safemode, to make sure that no add-ins are loaded and no other code is run while Installer.xlsm tries to work with the add-ins.
I know I can use "<PathToExcel>excel" /safemode "<PathToXls>Installer.xlsm" as described in this answer, but this method doesn't use Windows' file association and requires that I provide a path.
We have users with various machine images, using different versions of MS Office, so I do not want to get into hardcoding all possible Excel installation locations.
Can I do something of the following form:
start "Launching installer file" /wait "<Path to file>\Installer.xlsm /safemode"
I tried different possible combinations without success. How would you do it?
First I suggest to read the Microsoft documentation page Application Registration. It explains how the installer of an application or an application suite like Microsoft Office should register the installed application(s) so that the executable(s) of the application(s) can be found by other applications.
Recommended is creating under registry key
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
a subkey with name of the executable file like excel.exe with default string value being name of the executable with full path and optionally adding one more string value with name Path containing just the path to the executable. The Path string can but most not exist and it can but must not end with a backslash.
The command START uses also this key to find an application as explained in answer on Where is “START” searching for executables?
The installers of the various versions of Microsoft Office register excel.exe key under this key too.
So the easiest method on Windows Vista and later Windows versions to get installation location of Microsoft Excel is:
#echo off
for /F "skip=1 tokens=2*" %%A in ('%SystemRoot%\System32\reg.exe QUERY "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\excel.exe" /ve 2^>nul') do set "ExcelApp=%%~B"
echo ExcelApp=%ExcelApp%
pause
But on Windows XP the output of reg.exe is different and requires for that reason this batch code:
#echo off
for /F "skip=3 tokens=3*" %%A in ('%SystemRoot%\System32\reg.exe QUERY "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\excel.exe" /ve 2^>nul') do set "ExcelApp=%%~B"
echo ExcelApp=%ExcelApp%
pause
The different outputs are explained in answer on Read words separated by space & string value also contains space in a batch script in batch code written to get string value of a default string of a registry key containing spaces.
And it is good coding practice to add extra code which handles an error case like registry key does not exist at all because Microsoft Excel is not installed at all.
But is it possible with batch code to do what command START respectively the Windows shell function ShellExecuteEx does on using in a command prompt window the command line?
start "Launching installer file" "C:\Path to file\Installer.xlsm"
Yes, it is possible as the commented batch code below demonstrates.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem First query default string value of HKEY_CLASSES_ROOT\.xlsm from registry.
call :GetDefaultRegValue "HKCR\.xlsm"
rem Is there no key HKEY_CLASSES_ROOT\.xlsm or was the default string empty?
if not defined RegValue goto GetFromAppPaths
SET RegValue
rem Get the shell command line used for opening a *.xlsm file.
call :GetDefaultRegValue "HKCR\%RegValue%\shell\open\command"
rem Could the command line not read successfully from Windows registry?
if not defined RegValue goto GetFromAppPaths
SET RegValue
rem The command line contains as first string usually enclosed in double
rem quotes EXCEL.EXE with full path enclosed in double quotes. And there
rem can be even more arguments on the command line which are not needed
rem here. The command line below is used to get just first string of
rem the command line which should be EXCEL.EXE with full path.
for %%I in (%RegValue%) do set "RegValue=%%~I" & goto CheckExcelExistence
rem It is not good when both registry queries above fail. This means
rem either Microsoft Excel is not installed at all or a version of
rem Excel is installed which does not support *.xlsm files like Excel
rem of MS Office 2003, MS Office 2000 or MS Office 97.
rem However, perhaps just *.xlsm is not correct registered and therefore
rem get full path to excel.exe from application registration key.
:GetFromAppPaths
call :GetDefaultRegValue "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\excel.exe"
if defined RegValue goto CheckExcelExistence
echo Failed to determine installation location of Microsoft Excel.
echo/
endlocal
pause
goto :EOF
:CheckExcelExistence
SET RegValue
rem Remove surrounding double quotes if the Excel executable file name
rem read from Windows registry is still enclosed in double quotes.
set "RegValue=%RegValue:"=%"
if exist "%RegValue%" goto :RunInstall
echo Registered "%RegValue%" does not exist.
echo/
endlocal
pause
goto :EOF
:RunInstall
SET RegValue
ECHO start "Launching installer file" /wait "%RegValue%" "%~dp0Installer.xlsm" /safemode
endlocal
goto :EOF
rem This subroutine queries from Windows registry the default string value of
rem the key passed to the subroutine as first and only parameter and assigns
rem this value to environment variable RegValue. Environment variable RegValue
rem is deleted and therefore is not defined after subroutine exits on failure
rem to get the registry value or when the default value is an empty string.
rem This subroutine works for Windows XP and all later versions of Windows.
:GetDefaultRegValue
set "TypeToken=2"
:Reg3Run
for /F "skip=1 tokens=%TypeToken%*" %%A in ('%SystemRoot%\System32\reg.exe QUERY "%~1" /ve 2^>nul') do (
if "%%A" == "REG_SZ" (
if not "%%~B" == "" (
set "RegValue=%%B"
goto :EOF
)
) else if "%%A" == "NAME>" (
set "TypeToken=3"
goto Reg3Run
)
)
set "RegValue="
goto :EOF
This batch code is just a demonstration. It does not start Excel when really found. Instead it just outputs the command line which would start Excel because of ECHO left of start ... in block below label RunInstall.
Further this batch code contains 4 lines with just SET RegValue. Those 4 lines output just the string value queried successfully from Windows registry and stored in environment variable RegValue. Those 4 commands help to understand what happens on execution of the batch file. Those four command lines should be deleted finally from batch file and also the single ECHO written in upper case.
Note: It is quite easy to test what happens if an expected registry key does not exist or its default value is an empty string. Just insert a single character like # before last double quote on a line starting with call :GetDefaultRegValue and the modified registry key is not found anymore.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg /?
reg query /?
rem /?
setlocal /?
start /?
Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded reg.exe command line with using a separate command process started in background.

How to open a *.xlsx file containing a space in file name found by command DIR in Excel?

I have a batch file that opens an Excel file with a space as well as date in its file name.
For example: Book 1-27Aug2016
Currently, I am having trouble disabling the delimiters so that command start doesn't try to open two files: Book.xlsx and 1-27Aug2016.xlsx
Here is my code:
for /f "delims=*" %%# in ('dir /tw /o-d /b "Book 1-*"') do (start excel %%#& exit)
I referenced the web page in SS64 Windows CMD Shell forum below for disabling/modifying delimiters, but I still have yet to experience success.
For /f documentation
Lastly, once I remove the space from the file name, the batch runs without any issues.
What do I need to modify in the single line batch code to open also an Excel file with a space in file name in Excel?
Open a command prompt window, run in this window for /? and read very carefully all output help pages.
Command FOR with option /F splits up a string by default on spaces/tabs. It can be either used "tokens=*" or "delims=" to avoid this string splitting. The usage of "delims=*" works also for file names because the name of a file without or with path can't contain an asterisk. But "delims=*" is usually not used to prevent splitting up a string into tokens because a string read from a text file, output of an application or an environment variable could contain 1 or more asterisks as well.
Next run in a command prompt window cmd /? and read at least last output help page on which is explained on which characters in name of a file/folder without or with path the file/folder name string must be enclosed in double quotes. In general it is advisable to enclose file/folder names without/with path always in double quotes.
The command DIR returns with the used options just the names of the files without path and always without surrounding double quotes as it can be seen on running in a command prompt window in directory with Book 1-* files
dir "Book 1-*" /A-D /B /O-D /TW
after first running dir /? to get displayed the help for command DIR.
So used should be:
for /F "delims=" %%# in ('dir "Book 1-*" /A-D /B /O-D /TW 2^>nul') do ( start "" excel.exe "%%#" & exit /B )
2^>nul is 2>nul whereby the redirection operator > is escaped with ^ to apply this redirection on running command DIR instead of being interpreted as redirection of command FOR at an invalid position in command line. The command DIR outputs the error message File not found to handle STDERR if it can't find any file in current directory matching the pattern Book 1-*. This error message is suppressed by redirecting it to device NUL.
It is advisable to specify the application to start with file extension if well known even if the path is not known. Read answer on Where is “START” searching for executables? for an explanation.
In the batch command line above there are after command START also two double quotes before the name of the executable to start. Usage of "" is highly recommended as command START interprets often first double quoted string in arguments list as optional title string. By specifying explicitly an in this case empty title string helps to avoid unexpected application execution. For details on command START run in command prompt window start /?.
And last it is better to use command EXIT with parameter /B to exit just processing of current batch file and not exit entire command process. If this batch file is called with command CALL from another batch file or started from within a command prompt window and command EXIT is used without parameter /B, the processing would not continue on parent batch file respectively command prompt window would be closed by EXIT, too. There is no difference between usage of exit and exit /B if this batch file is executed by a double click on the batch file. For details on command EXIT run in a command prompt window exit /?.
By the way: The command START uses file association registration data if it can find an executable or script with given name to open the specified file with the registered application for the file extension.
So it would be also possible to use:
for /F "delims=" %%# in ('dir "Book 1-*" /A-D /B /O-D /TW 2^>nul') do ( start "" "%%#" & exit /B )
Now command START opens the *.xslx file with whatever application is associated with this file extension as default application for opening it.
Add double quotes around the last variable.
for /f "delims=*" %%# in ('dir /tw /o-d /b "Book 1-*"') do (start excel "%%#"& exit)

Resources