I'm trying to set the Inno Setup IDE "Sign Tools" command to use a relative path.
I made a sign.bat script which calls signtool.exe following the file structure below:
code_sign\
+ sign.bat
+ signtool.exe
+ cert.pfx
script.iss
If I set the Sign Tool (Tools / Configure Sign Tools...) command to code_sign\sign.bat $p, I got the following error message:
Sign Tool command failed (Failed to execute Sign Tool.
Error 2: The system cannot find the file specified). Will retry (2 tries left).
Running Sign Tool command: sign.bat "(...)\uninst.e32.tmp"
Sign Tool command failed (Failed to execute Sign Tool.
(...)
What is the working path when the sign tool is called?
Sadly I cannot use an absolute path (which works) as the code_sign folder is meant to be a submodule shared with other applications and other users.
What I'm doing wrong here? Should I use the command line version?
Edit: as requested, the sign.bat contents:
SET script_path=%~dp0
SET stool=%script_path%signtool.exe
SET pfx=%script_path%cert.pfx
SET ntp=http://timestamp.globalsign.com/scripts/timstamp.dll
SET pwd=12345
"%stool%" sign /f %pfx% /p %pwd% /tr %ntp% /td SHA256 %1
Configure your sign tool command as only $p.
And then in your .iss, set the SignTool directive as follows (assuming the sign tool command is named custom), with a use of SourcePath preprocessor predefined variable.
[Setup]
SignTool=custom {#SourcePath}\code_sign\sign.bat $f
Related
I'm trying to set up Jenkins to build and deploy one of the applications I'm working on.
I created a stage where it signs the application.
It does sign the application, but immediately after it tries to execute the different options as separate commands.
13:07:16 + bash
13:07:16 + cd Wrap.UI
13:07:16 + 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86\signtool.exe' sign /f './Service.pfx' /p password ./bin/x64/Test/Wrap.UI.exe
13:07:16 Done Adding Additional Store
13:07:16 Successfully signed: ./bin/x64/Test/Wrap.UI.exe
13:07:16
13:07:16 Number of files successfully Signed: 1
13:07:16 Number of errors: 4
13:07:16 SignTool Error: File not found: F:/
13:07:16 SignTool Error: This file format cannot be signed because it is not recognized.
13:07:16 SignTool Error: An error occurred while attempting to sign: ./Service.pfx
13:07:16 SignTool Error: File not found: P:/
13:07:16 SignTool Error: File not found: password
The string in the Jenkins script looks like this
sh '''
bash
cd Wrap.UI
"C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.19041.0\\x86\\signtool.exe" sign /f "./Service.pfx" /p password ./bin/x64/''' + CONFIGURATION + '''/Wrap.UI.exe
cd ..
'''
I apologies for the weird spacing in the code section.
I'm guessing here is I need to encapsulate the command with its parameters somehow, but I'm not very familiar with bash scripts and could use some help with that.
If you are on Windows, perhaps try to use a bat command instead of a sh command. (I never thought I was going to suggest this, but it looks like your sh support is buggy.)
bat """
cd Wrap.UI
"C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.19041.0\\x86\\signtool.exe" sign /f "./Service.pfx" /p password ./bin/x64/${CONFIGURATION}/Wrap.UI.exe
"""
Notice also that there is no need to cd .. at the end; the command runs in a separate environment, and its current working directory will not be reflected back in the parent.
Tangentially, the lone bash wasn't doing anything useful. If you want to run a command in Bash instead of sh, the syntax for that is sh '''bash -c 'commands; more commands'; '''. But nothing here requires Bash; cd behaves the same in bash and sh, and besides that, you are just running an external Windows command. The lone bash would start and exit an interactive Bash shell.
I am using following batch file to download and unzip the google-cloud-sdk,
file name: download.bat
set home=%USERPROFILE%
echo %home%
%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe -Command "(New-Object Net.WebClient).DownloadFile('https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-179.0.0-windows-x86_64-bundled-python.zip', '%home%/google-cloud-sdk.zip');& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('%home%/google-cloud-sdk.zip', '%home%/google-cloud-sdk'); }"
and I am using following batch file to install the SDK silently on windows,
file name: install_win.bat
call %USERPROFILE%\google-cloud-sdk\google-cloud-sdk\install.bat --path-update=true --usage-reporting=false --command-completion=false
After these steps are completed successfully when I try to authorize my serice account from another batch file using the following command,
gcloud auth activate-service-account --key-file {json fila path}
It fails and tells me that the glcoud is not recognized internal or external command.
Can anyone please help me solve this error?
I think the error is because of the lack of environment variable in windows with the bin file of SDK.
How to set that from the batch file?
The ...cloud...\install.bat routine is called, hence it inherits the calling routine's environment. It does not communicate any changes back to the calling routine.
Since I'd assume that the install.bat is supplied by a 3rd party, hence cannot be altered, then you would need to retrieve the new path for the current cmd instance.
call %USERPROFILE%\...\install.bat ...
FOR /f "delims=" %%a IN ('echopath') DO SET "newpath=%%a"
where echopath.bat is simply one line:
echo %path%
Provided echopath.bat is reachable - and it must be a separate file, not an internal routine - the new path should be returned (to newpath in this instance - I'll let you guess what changes you'd need to make to change that to path...)
Since executing an external batch loads the environment anew, the modified environment path will be reported by echopath and hence assigned to the variable nominated.
I've created a post build event to do code signing of the application after a successful build with the following post build script.
copy $(TargetPath) $(TargetDir)SignedApp.exe
signtool sign /t http://timestamp.verisign.com/scripts/timestamp.dll /a $(TargetDir)SignedApp.exe
I get the error 'signtool' is not recognized as an internal or external command.
So it seems the path used for the build event doesn't point to the signtool utility. When I run the VS2013 x86 Native Tools Command Prompt I can run signtool as it includes a path which points to:
C:\Program Files (x86)\Windows Kits\8.1\bin\x86
I could hard-code this path into my build event
"C:\Program Files (x86)\Windows Kits\8.1\bin\x86\signtool" sign /t http://timestamp.verisign.com/scripts/timestamp.dll /a $(TargetDir)SignedApp.exe
However that seems non-portable. How do I get the same path defined for the Native Command Prompt to be used by my post build event without hard coding it? I've looked at the list of macros but haven't found any that would be useful.
I found this question first so I'll post the answer I eventually went with.
Along the way I looked at this other answer and some docs:
Path to SignTool.exe or "Windows Kits" directory when using Visual Studio 2012
https://learn.microsoft.com/en-us/visualstudio/msbuild/property-functions?view=vs-2017
My solution ended up being this big PropertyGroup added into the csproj file:
<PropertyGroup>
<!-- Find Windows Kit path and then SignTool path for the post-build event -->
<WindowsKitsRoot>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot10', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
<WindowsKitsRoot Condition="'$(WindowsKitsRoot)' == ''">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot81', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
<WindowsKitsRoot Condition="'$(WindowsKitsRoot)' == ''">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
<SignToolPath Condition="'$(SignToolPath)' == '' And '$(Platform)' == 'AnyCPU' and Exists('$(WindowsKitsRoot)bin\x64\signtool.exe')">$(WindowsKitsRoot)bin\x64\</SignToolPath>
<SignToolPath Condition="'$(SignToolPath)' == '' And Exists('$(WindowsKitsRoot)bin\$(Platform)\signtool.exe')">$(WindowsKitsRoot)bin\$(Platform)\</SignToolPath>
<SignToolPathBin Condition="'$(SignToolPath)' == ''">$([System.IO.Directory]::GetDirectories('$(WindowsKitsRoot)bin',"10.0.*"))</SignToolPathBin>
<SignToolPathLen Condition="'$(SignToolPathBin)' != ''">$(SignToolPathBin.Split(';').Length)</SignToolPathLen>
<SignToolPathIndex Condition="'$(SignToolPathLen)' != ''">$([MSBuild]::Add(-1, $(SignToolPathLen)))</SignToolPathIndex>
<SignToolPathBase Condition="'$(SignToolPathIndex)' != ''">$(SignToolPathBin.Split(';').GetValue($(SignToolPathIndex)))\</SignToolPathBase>
<SignToolPath Condition="'$(SignToolPath)' == '' And '$(SignToolPathBase)' != '' And '$(Platform)' == 'AnyCPU'">$(SignToolPathBase)x64\</SignToolPath>
<SignToolPath Condition="'$(SignToolPath)' == '' And '$(SignToolPathBase)' != ''">$(SignToolPathBase)$(Platform)\</SignToolPath>
</PropertyGroup>
I need lots of the extra intermediary properties because the Windows SDK on my machine doesn't install signtool.exe in <root>\bin\x64\signtool.exe but rather under another directory level that is the version of the SDK which I definitely do not want to hard-code.
And then in the post-build I can use this "$(SignToolPath)signtool.exe"
The solution I decided on was:
REM If SIGNTOOL environment variable is not set then try setting it to a known location
if "%SIGNTOOL%"=="" set SIGNTOOL=%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86\signtool.exe
REM Check to see if the signtool utility is missing
if exist "%SIGNTOOL%" goto OK1
REM Give error that SIGNTOOL environment variable needs to be set
echo "Must set environment variable SIGNTOOL to full path for signtool.exe code signing utility"
echo Location is of the form "C:\Program Files (x86)\Windows Kits\8.1\x86\bin\signtool.exe"
exit -1
:OK1
echo Copying $(TargetFileName) to $(TargetDir)SignedApp.exe
copy $(TargetPath) $(TargetDir)SignedApp.exe
"%SIGNTOOL%" sign /t http://timestamp.verisign.com/scripts/timestamp.dll /a $(TargetDir)SignedApp.exe
This was a variation on #Dennis Kuypers suggestion #4. The developer must set environment variable SIGNTOOL to the correct location. If they fail to do so then one known possible location is attempted. If that fails then error is reported instructing them to set SIGNTOOL env var appropriately.
I did discover there is an environment variable WindowsSdkDir
WindowsSdkDir=C:\Program Files (x86)\Windows Kits\8.1\
But again, this was set only when running the Native Command Prompt and thus was not defined when running the post build event script.
I've been looking at a lot of posts of various vintages today, and the problem with most of them is that they haven't been consistently working after a couple of years, or they involved a lot of registry reads followed by a lot of conditional hard coded paths.
I finally hit on something that (I think) will work for a while. At least 2019 going forward until something breaks.
I make my Post Build event something to the effect of
call "$(VSAPPIDDIR)..\Tools\VsDevCmd.bat"
signtool.exe sign /p <whatever> /f <whatever>.pfx "$(TargetFileName)"
The first line gets all the environment variables set up as though you were in the Developer Command Prompt. The second does the signing using that environment
I had the same issue in Visual Studio 2012 and found an easier way to resolve this. Instead of starting Visual Studio direct start "Developer Command Prompt for VS2012" and then type 'devenv' in the command prompt to start Visual Studio. After that signtool worked fine for me.
I recently made a game in Unity3D and I am trying to sign the code with a certificate I bought from Comodo (saved in a pfx file). I have done a ton of research on how to use it and have settled to running these commands:
doskey signtool="C:\Program Files (x86)\Windows Kits\10\Tools\bin\i386\signtool.exe"
signtool sign /f "C:\...[path to cert on desktop]...\cert.pfx" "C:\...[path to exe on desktop]...\Game.exe"
No matter what I do, or slight variations I try, or anything, I always get the same error:
SignTool Error: A required paramter is missing.
Usage: signtool <command> [options]
Even running "signtool sign /?" gives me this same error. I don't understand why the program won't do or even tell me anything useful. Some sources I've seen say I need to add a "/p passwordHere" after the /f option, but that gives the same error message as all others.
You must let doskey know that the macro signtool expects parameters, which are to be passed onto the real signtool.exe. This is done by appending $* at the end of the definition.
doskey signtool="C:\Program Files (x86)\Windows Kits\10\Tools\bin\i386\signtool.exe" $*
From the official Doskey docs (highlight mine):
To run a macro, type the macro name at the command prompt, starting at the first position. If the macro was defined with $* or any of the batch parameters $1 through $9, use a space to separate the parameters.
I am trying to run a batch file script from Microsoft Test Manager using Test Settings, but it gives an error.
TestOutcome 'Error'; Message 'The setup batch file exited with error code 1.'
My batch file:
setx SERVERTEST "TEST" -m
Running setx /? shows some examples of using the command, one of them is SETX MACHINE "COMPAQ COMPUTER" /M. This follows the Windows style that options start with a /. The code in your question ends with -m.
Try replacing the -m with /m or with /M.