I'm seeing some peculiar behaviour in a TeamCity step that uses a cmd script.
In the example below, %USERPROFILE%\myfile.txt contains only the text "abc123" without quotes.
set /p myFileContent=<"%env.USERPROFILE%\myfile.txt"
echo "%%myFileContent%%"
set /p myFileContentTwo=<"%env.USERPROFILE%\myfile.txt"
echo "%%myFileContentTwo%%"
Output:
"abc123"
""
What is going on here? The file is read correctly first time, but not the second time. It works fine if I run the equivalent cmd script outside of TeamCity:
#echo off
set /p myFileContent=<"%USERPROFILE%\myfile.txt"
echo "%myFileContent%"
set /p myFileContentTwo=<"%USERPROFILE%\myfile.txt"
echo "%myFileContentTwo%"
Output:
"abc123"
"abc123"
I first observed this problem when reading the same file in two separate steps, with a wait of several seconds between reads, suggesting it's not a sharing violation. The file is intact and has the expected content after all steps have run.
I'm on TeamCity Enterprise 2021.2.1 (build 99602) on Windows 10.
Related
In my Jenkins post build email (using extended email plugin), I want to use a variable identified in a build step (windows batch) using the EnvInject plugin. The plugin requires a properties file to be created using a shell script. I am having difficulties converting the following batch lines to shell:
svn log --limit 1 > Change_Request.txt
set "ChangeRequest="
for /f "skip=3 delims=" %%i in (Change_Request.txt) do if not defined ChangeRequest set "ChangeRequest=%%i"
echo ChangeRequest=%ChangeRequest% > export.properties
The situation: There is a Jenkins plugin named EnvInject that allows variables to be passed from a build step to a post build step. The variable was not being passed between the steps.
Perceived issue at the time: After reading the error log message and instructions on using the plugin, I thought the plugin only worked with a shell script.
Real issue: I was trying to read the properties file from a different location than where it was written.
Solution: Initially resolved by using a shell script to write the variable to a properties file:
echo ChangeRequest=$(svn log --limit 1|sed '4q;d')>export.properties
This resolved the issue as it created the properties file in the expected location.
But if I had properly identified the issue, it could have been resolved in the initial batch script.
When updating the Jenkins job to pass a second variable, I realized the real reason my initial effort failed. I updated my first batch script to pass the variables to a properties file, in the expected location. I ran my svn command from the repository directory, then returned to my job's workspace directory to write the properties file.
svn log --limit 1 > ..\..\..\Change_Request.txt
for /f "skip=3 delims=" %%i in (..\..\..\Change_Request.txt) do if not defined >ChangeRequest set ChangeRequest=%%i
for /f "delims=: tokens=1,2" %%a in ('svn info %Repository_URL%') do (
if "%%a"=="Revision" (
set /a RevisionNumber=%%b
)
)
CD D:\Jenkins\workspace\JOB_Folder\
echo ChangeRequest=%ChangeRequest% > export.properties
echo RevisionNumber=%RevisionNumber% >> export.properties
Having no svn I can't test this, but it might work.
Coming from windows I'm quite new to shell/bash.
First version quite simmilar:
svn log --limit 1 > Change_Request.txt
ChangeRequest=$(sed '4q;d' Change_Request.txt)
echo ChangeRequest=$ChangeRequest>export.properties
Shorter no var:
svn log --limit 1 > Change_Request.txt
echo ChangeRequest=$(sed '2q;d' Change_Request.txt)>export.properties
Shortest no intermediate file (maybe required)
echo ChangeRequest=$(svn log --limit 1|sed '4q;d')>export.properties
PowerShell variant
svn log --limit 1 > Change_Request.txt
"ChangeRequest=$((gc Change_Request.txt)[4])" > export.properties
I have a post-build script in Visual Studio that I am trying to run so that we can make remote deployments easier. Earlier in this script (you don't see it here), we hard-code the user in the net use execution below. So all we're doing here is having the user input the server name and database to deploy to and then connect to the network share of that server.
What I've found though is that the code below works fine only if you run it with Command Prompt. It opens up a new window and has the user put in the server and database and then the net use command will correctly show the server the user input, all in the same window.
If you try to use this in a batch file or in Visual Studio though, the net use command shows blank for the server name.
I appreciate any insight anyone might have on this!
START CMD /C "CALL SET /P SERVERNAME=Please Enter The Server Name: & CALL SET /P DATABASE=Please Enter The Database Name: & CALL CMD /C net use \\%SERVERNAME%\d$ /persistent:no * /user:%user%"
Follow advise of #bgalea. Where is %user% defined? Did you mean %username%? Of course this scheme will not work if you plan to have builds done by a build agent later.
The reason it is not working is that variables are expanded at load time. Consequently, %SERVERNAME% is expanded when the line is loaded...BEFORE the user has entered a value. Try changing to this:
SETLOCAL ENABLEDELAYEDEXPANSION SET /P SERVERNAME=Please Enter The Server Name: & SET /P DATABASE=Please Enter The Database Name: & \\!SERVERNAME!\d$ /persistent:no * /user:%username%"
That way you will be using the run time value of SERVERNAME.
I have an exe program that uses a command line GUI and would like to set up a batch script to run a few commands automatically, so here are the sort of commands that the GUI uses:
? = help
s = start
l = status
r = reset
x = exit
I would like to create a batch file that automatically runs the start command I have tried a few things to no avail such as the below.
using a cannedreponsesfile as the input:
#echo off
START /b <path>\service.exe < <path>\cannedreponses.txt
And I receive the following error:
The system cannot find the path specified.
The path referenced in the batch script seems to be ok I checked with dir /s /b
I have also attempted this command
echo s |START /b service.exe
This seems to have better results, but it seems to keep repeating input.
Any idea what is going on, or how I can do this in a batch file.
Thanks in advance
You appear to have overcensored your question.
In all probability, the problem is with <path>
If the real string you are using contains separators (especially spaces) or some other special characters, then you need "enclose the string in quotes".
There's a quirk with start however - the very first string quoted encountred is interpreted as a "window title" so you may need to use
start /b "" "whatever 1" "whatever 2"
The start is unnecessary here and only introduces a source for errors. Just say
Echo s|service.exe
My goal is copying an .exe file from a bin folder of solution A to another solutions B resource folder on the post build event of solution A.
I created the necessary xcopy command and tried it out in powershell: It works perfectly.
Whenever I add any command to the actions in VS build fails with: "#command# exited with code 1", where #command# is, for example, the xcopy command.
I tried running VS as admin and currently I tried just running a .bat file that contains "#echo off #exit 0". That too leads to "#command# exited with code 1".
Have some example of what I tried out as VS post/pre-build command:
call "projdir\test.bat"
call projdir\test.bat
"projdir\test.bat"
projdir\test.bat... I tried projdir as "$(ProjectPath)" and manual path.
I put output to verbose and found the following:The command "C:\Users\Traubenfuchs\AppData\Local\Temp" is written incorrectly or couldn't be found. (That folder actually exists but I don't know what it wants to do it.)The same thing happens when I put an xcopy command in pre/post build.
Anyone knows what I am doing wrong?
Recently I met similar problem.
About your "hello world" post-build event :
try to call powershell directly
powershell -command "write-output 'hello world'; exit 0"
=================
My pre-build event looks like :
powershell -file scriptPath.ps1
My scriptPath.ps1 looks like :
<my epic powershell code>
...
exit 0
Note that without "exit 0" at the end I recieved return code 1 from my script.
We had this issue because of a "Software Restriction Policy" set up in a domain GPO. It appears that pre and post builds create a .cmd batch file in the temp folder. Here's what the logging showed me:
cmd.exe (PID = 8456) identified
C:\Users\brian\AppData\Local\Temp\tmp733425d2c0604973a90a0a175c13353e.exec.cmd
as Disallowed using default rule, Guid =
{11015445-d282-4f86-96a2-9e485f593302}
To fix this we modified the GPO that controlled the SRP so that it did not include .cmd files. After all, the goal of SRP is to block executable malware, not batch files. I may get some security blowback because of this. Hopefully someone knows a better way to fix this issue.
One possible issue is that you have to use $(ProjectDir) instead of $(ProjectPath)
When you use $(ProjectPath) it is actually: "C:\Users\....\Project\MyProject.csproj"
Versus $(ProjectDir) which is: "C:\Users\....\Project\"
Notice, that the first version is actually pointing to your project solution file... which would cause everything to fail.
Another is that that $(ProjectDir) automatically adds the trailing slash to the path. i.e. "$(ProjectDir)\test.bat" would actually translate to: "C:\Users\....\Project\\test.bat"
Also you have to make sure that you enclose all your file paths in double quotes
So the correct call would look like this:
call "$(ProjectDir)test.bat"
Other things to check out would be to make sure that the directory that the script is executing from is correct. See SO: visual studio 2012, postbuild event, bat file not creating new file (not executing)
Have you checked out the suggestions in this StackOverflow? Post Build exited with code 1
Edit
Try this:
echo Hello World
#exit 0
You need to end any commands with #exit 0 otherwise it doesn't think that it finished properly
Edit 2
Why do we use #exit 0 instead of exit 0? #Sunny has a good explanation of the At symbol - # here:
The # symbol tells the command processor to be less verbose; to only
show the output of the command without showing it being executed or
any prompts associated with the execution. When used it is prepended
to the beginning of the command, it is not necessary to leave a space
between the "#" and the command.
Essentially if you call xyz.bat by default every command in the .bat file is echoed back along with the actual output of the command. e.g.:
test.bat
echo Hello World
exit 0
Will output:
C:\>call test.bat
C:\>echo Hello World
Hello World
C:\>exit 0
C:\>
When we add a # in front of the commands, we only get the output of the commands themselves.
test2.bat
#echo Hello World
#exit 0
Will output:
C:\>call c.bat
Hello World
C:\>
#echo off is also a way to turn this off for the rest of the script. We typically do this simply to make the logs easier to read, as the text of the commands muddies the log output.
I am trying to run this .bat script
set target_path =\\remoteserver\c$\newfolder\newfolder1\logs >log.txt
findstr /m "ERROR" "%target_path%\file1.txt" >> log.txt
The expected output from this .bat file is that it will pick up "ERROR" string from file1.txt from the "remoteserver" and will show as output in log.txt.
But,once when i run this script it shows me the following error
FINDSTR: Cannot open \remoteserver\c$\newfolder ...
Kindly, suggest me the flaws or correct script so that the above script gets executed successfully with the expected output .
thanks for your quick update and sorry for acknowledging late. I tried executing the batch script with the necessary corrections you mentioned needed in the script , but still i face the same problem . I am unable to fetch the "ERROR" from log file and get the expected output. Is there any other field to be added to "FINDSTR" to pull up the ERROR ??.. Kindly, assist me for the same.
Thanx in advance.
Not at all sure how you achieved that response given the scant 2 lines of code you've posted.
You are setting the variable "target_path ", not "target_path" according to your first line. Batch is sensitive to spaces in a set statement.
Since "target_path" is not set, it's a total mystery how your response is Cannot open \remoteserver\c$\newfolder ... unless the variable "target_path" had been previously set in the environment. The findstr should, with the posted code, have been executed against the file "\file1.txt" - not as reported.