I have a batch script which generates a WinSCP upload script to upload a file to an SFTP location. Now when I run the batch file via command prompt - it runs successfully and loads it. I called the same thru SSIS Execute process task - it runs successfully and loads it. Now when I put the same on SQL Agent - I tried the following two options:
Using Operating System (CmdExec) - cmd.exe /c "\.bat"
Added the SSIS package to SSISDB and added it as a job step.
With both the above options the job showed a successful run. However the file is not uploaded! Any ideas on what is happening?
Here's my batch script:
echo off
SET winscp=C:\"Program Files (x86)"\WinSCP\WinSCP.com
SET stagingDirectory=\\<staging path>\
SET scriptPath=\\<ScriptPath>\UploadScript.txt
SET ftpHost=xx.xx.xx.xx
SET ftpUser=user
SET ftpPass=password
SET fileName=Test.xlsx
SET ftpFlags=
#REM ftpFlags: -explicit
echo deleting uploadScript if it already exists
IF EXIST %scriptPath% del /F %scriptPath%
IF EXIST %scriptPath% exit 1
echo Generating WINSCP Upload Script
>>%scriptPath% echo option batch abort
>>%scriptPath% echo option confirm off
>>%scriptPath% echo open sftp://%ftpUser%:%ftpPass%#%ftpHost% %ftpFlags%
>>%scriptPath% echo option transfer binary
>>%scriptPath% echo put %stagingDirectory%%fileName% /
>>%scriptPath% echo close
>>%scriptPath% echo exit
echo Launching WINSCP upload
start /wait %winscp% /console /script=%scriptPath%
As you start the WinSCP via the start (why?), the exit code is not propagated to the SSIS. So, you never learn, if the script fails. And it most probably fails.
You also should enable logging, so that you can see what's wrong.
You should use this code to propagate the WinSCP exit code to SSIS and to enable logging:
%winscp% /log=\\<ScriptPath>\UploadScript.log /script=%scriptPath%
exit /b %ERRORLEVEL%
(Note that the winscp.com does not have the /console parameter)
Anyway, one clear problem is that you do not specify an expected SSH host key in the script. When you run the script manually, you probably have the key cached in the registry of your Windows account. But under the SSIS a different account is used, and its host key cache is likely empty. You should add the -hostkey switch to the open command in the script to make the script independent on the cache. See Where do I get SSH host key fingerprint to authorize the server?
When testing the script, add the /ini=nul parameter to isolate the script from your configuration.
For this and other hints, when debugging WinSCP running under SSIS, see My script works fine when executed manually, but fails or hangs when run by Windows Scheduler, SSIS or other automation service. What am I doing wrong?
And finally, see WinSCP SFTP Task for SSIS.
Your variable seems set incorrectly. To manage with a space in the path and into the variable you have to put in quotes the whole path or the whole variable.
i.e.
set "winscp=C:\Program Files (x86)\WinSCP\WinSCP.com"
echo start "%winscp%"
:: output: start "C:\Program Files (x86)\WinSCP\WinSCP.com"
or
set winscp="C:\Program Files (x86)\WinSCP\WinSCP.com"
echo start %winscp%
:: output: start "C:\Program Files (x86)\WinSCP\WinSCP.com"
Another point, you have to check this file: UploadScript.txt because your script adds new lines rather than remake the file.
change this line to >%scriptPath% echo option batch abort instead of >>%...
Ah, I did not pay attention to the IF EXIST.
Related
I am currently creating an improvised installer for a cople software packages. To do this I have to install a couple MSI packages first before doing a couple file operations.
To install an MSI package I am using the following command:
start /wait msiexec /i "Myinstaller V2.1.msi" /qb
This command works and installs the package instantly and witout any problems via CMD.
But when I put this command in my batch file and execute it as an administrator, I get the following error:
This installation package could not be opened. Contact the application vendor to verify that this is a valid Windows Installer package
What cold be the problem? Using the same command via the console works flawlessly, only the batch file throws the error...
EDIT: I have also tried the /a parameter in order to install it as an administrator and it does not work either. Full command in batch file:
start /wait msiexec /qn /a "Myinstaller V2.1.msi"
EDIT2: I just realized that it only does not work when I start the batch file with Right click > Run as administrator
When I open a console with administrative rights and start my batch file it works for some reason...
Is there a way to make it work with the Right click > Run as administrator method?
SOLUTION: Thanks to RGuggisberg's answer I now know that the directory changes once the file is executed as an administrator. With a small change the installer gets fired up as an admin and works perfectly starting the installer from a relative path in the same directory:
#echo off
pushd %~dp0
start /wait msiexec /i "Myinstaller V2.1.msi" /qb
pause
I've now also implemented a feature to detect wether or not the installation fails or not:
#echo off
pushd %~dp0
start /wait msiexec /i "Myinstaller V2.1.msi" /qb
if %ERRORLEVEL% EQU 0 echo SUCCESSFULL
if NOT %ERRORLEVEL% EQU 0 echo MyProgram installation FAILED
pause
The current directory changes when you run as administrator. If you want to prove that to yourself, see this post
Difference between "%~dp0" and ".\"?
Include the full path to your filename and it will work.
I have an issue where the files I am uploading to a vendor are being consumed before they are finished uploading. To get around it the vendor has provided me with a location underneath where I can upload the files first then requested I move them once the upload is done.
Stripping out sensitive information, I am referencing this file in my sftp command in batch myfile.scr
cd /from_client/payments/upload
lcd E:/uploadfiles
mput uploadfiles.xml.*
quit
That would upload the files to the remote directory upload. I know need to get them into the level above. The theory is this will then process as normal and the files will already exist so the application won't consume them before they are done uploading.
I would assume I need to do a job to build a list of the files and then a 2nd to loop through them to do a rename on the remote folder to get them to go up a level.
Any ideas on how this could work? The vendor is unable to do anything here.
already tried various solutions to see if I could use mv but thats not an option as its not using Winscp. We can only use batch scripts and then native sftp commands.
You can generate put and rename commands for each file using a batch file like this:
set SOURCE=E:\uploadfiles
set SCRIPT=myfile.scr
(
echo cd /from_client/payments/upload
echo lcd %SOURCE%
for %%F in (%SOURCE%\*) do (
echo put %%~nF
echo rename %%~nF /final/path/%%~nF
)
echo quit
) > %SCRIPT%
sftp user#host -b %SCRIPT%
It should generate a script like this:
cd /from_client/payments/upload
lcd E:\uploadfiles
put one.txt
rename one.txt /final/path/one.txt
put two.txt
rename two.txt /final/path/two.txt
put three.txt
rename three.txt /final/path/three.txt
quit
Though with a more capable client, it would be easier. For example my WinSCP supports wildcards with mv command, so you can simply do:
WinSCP.com /ini=nul /log=winscp.log /command ^
"open sftp://user:password#host/ -hostkey=""...""" ^
"put E:\uploadfiles\* /from_client/payments/upload/" ^
"mv /from_client/payments/upload/* /final/path/" ^
"exit"
I'm aware that you wrote that you cannot use other clients, because:
"It's not using WinSCP" – What "it"? It's you! Use the best tool for your task.
"We can only use ... native sftp commands" – There are no "native sftp commands". There are only commands of the client you are using. Currently you are using OpenSSH sftp client. But that's not set in stone. It's easy to switch (you do not even to read it, everything is already in my code above).
I am trying to automate a call to a remote server using WinSCP which is a redundant everyday task. I want the batch file to call remote machine - provide username and password, and later check for if files exist.
So far I am able to start a WinSCP server but still the batch file does not consume username and password - it is still asking for them and/or providing an error regarding too many arguments.
chdir /d D:\Program Files\WinSCP\
winscp.com 172.18.186.39 username password
Your syntax does not even remotely resemble WinSCP command-line syntax for scripting.
See WinSCP article on Checking file existence using scripting:
#echo off
set REMOTE_PATH=/home/user/test.txt
winscp.com /command ^
"open ftp://username:password#ftp.example.com/" ^
"stat %REMOTE_PATH%" ^
"exit"
if %ERRORLEVEL% neq 0 goto error
echo File %REMOTE_PATH% exists
rem Do something
exit /b 0
:error
echo Error or file %REMOTE_PATH% not exists
exit /b 1
The above example is for FTP protocol. You didn't tell use what protocol are you using. If not FTP, you have to change the open command accordingly.
You can have WinSCP GUI generate the open command for you.
Once you have the batch file ready, use Windows Scheduler to call it regularly.
I have configured NUnit tests to run after build completed.(Jenkins)
I added following on Excecute windows batch command window in Jenkins.
rmdir ClickOnceInstall /Q /S
mkdir ClickOnceInstall
CD BuildScripts
Start.bat
"C:\Program Files (x86)\NUnit 2.6.2\bin\nunit-console-x86.exe" AA.Tests\bin\x86\Release\AA.Tests.dll /xml=nunit-result.xml
It seems Execute unit test command doesn't create result file as specified name and marked as failed. However, when I run the nunit test command manually it creates the file. Next time build through Jenkins, result xml file does not seem to be updated but it doesn't fail.
am I missing any configuration or something else?
It would help if you would paste the console log.
However, my first guess is to ask you to add call to your batch file statement:
call Start.bat
If that batch file has an exit /b statement (even with 0), it will quit the whole calling step (i.e. "Execute windows batch command") without getting to your last statement (i.e nunit command).
Using call in front of the batch file will make sure that control is returned to the calling step.
I am having some trouble creating a batch file, I need it to remove a .msi file first and then run a .exe file this is what I have so far.
echo on
title remove mimecast 3.5.6
if exist c:\windows\mimecastrem.tag goto alldone
msiexec.exe /x {86C4653D-E9B2-4421-8578-D2B953FFAEDA} /qn /L "C:\windows\mimecast.log"
start \\fcmsvr2\MimecastMSO\deploymimecast.exe /zap
echo. >c:\windows\mimecastrem.tag
:alldone
rem exit
If I run this in DOS logged on the pc it runs ok, I have tried to add this to a GPO startup and shutdown and the batch runs but only removes the .msi file and won't start the .exe, is there a way to add logging to this so I can see why it isn't running?
Thanks
David
Create a Wrapper Script to Capture the Output
When I try to run batch commands from a GPO, I usually have two batch files:
One batch file does all the work.
One to call the other and redirect all the output.
This way, if the important batch file has syntax problems (usually due to the contents of variables or other conditions on the machine), I still see something in the log.
batch_worker.cmd
#ECHO OFF
SETLOCAL
#ECHO Proceeding with important tasks...
REM do other stuff (delete, install, etc.)
batch_wrapper.cmd
CALL %~dp0batch_worker.cmd > C:\Windows\TEMP\batch_worker.log 2>&1
Self-Wrapping
Another option that I occasionally employ is to have the script invoke itself, redirecting the output.
batch_worker.cmd
#ECHO OFF
SETLOCAL
IF NOT "%_LOGGING%"=="1" (
SET _LOGGING=1
CALL "%0" %* > C:\Windows\TEMP\batch_worker.log 2>&1
EXIT /B %ERRORLEVEL%
)
#ECHO Proceeding with important tasks...
REM do other stuff (delete, install, etc.)
Network Files from GPO
Any startup scripts that run on a Windows machine will have the network identity of the computer account (COMPUTERNAME$). This account doesn't usually have access to most network resources. The one exception is the GPO. All computer accounts have access to the GPO (which is stored as files).
If your script needs other files:
Store them in a world-readable network location (or grant any domain member RX access).
Store them with the GPO.
When you create/add a startup script, the GPMC snap-in gives you access to the network location (under SYSVOL) where the script should reside. Use that UNC path to save any other files the script needs access to.