Cause TFS InvokeProcess Build Activity to run under other credentials - tfs

We have customized the build process with a InvokeProcess action that runs a powershell script that deploys our sln.
Problem is that this script must be run under a given user (not the tfsbuild user).
How can we achive this?
Alternative 1: Make the InvokeProcess
run as a different user -
Alternative 2: Make the powershell script itself
run as different user
Problem is that I have no idea of how to do any of this.

I have created a blog post on this how you can achieve this: Customize Team Build 2010 – Part 9: Impersonate activities (run under other credentials)

A pure PowerShell option, assuming you have PowerShell 2.0 on your TeamBuild machine, is to use a background job. Start-Job allows you to specify the credentials of another account to perform the work. After spinning up the background job in your script you will probably want to wait for the job to finish and grab the results to output from the main script e.g.:
$cred = Get-Credential
$job = Start-Job -ScriptBlock { ls c:\windows\system32 -r *.sys } -Cred $cred
Wait-Job $job
Receive-Job $job
With respect to capturing, storing and retrieving the credentials, see this blog post for a good treatise on the subject.

Related

Invoking batch script with specific user from TFS build server

I'm new to TFS and need help to overcome following problem.
I have a desktop which has a licensed testing tool and automated tests developed using that tool. The license of the tool is tied up to the user logged in to that desktop.
Now I have created a batch file for my automated tests and I want to call this batch file from TFS. I've installed TFS agent on the desktop where that tool is and on TFS server configured a build definition which runs this batch file, everything working well till here.
The problem is, when the batch script is called by the TFS agent (I think) it is involved as SYSTEM user and not the user which is tied up to the license. Due to this the license check fails and my tests are unable to run.
Is there any way to tell TFS to run the batch script using a specific user ?
The batch scripts are run using the build service account. If you want to run the batch script using a specific account, you need to change your build agent service account.
For TFS 2015 Build agent, run the command:
C:\Agent\Agent\VsoAgent.exe /ChangeWindowsServiceAccount
Please refer to this document to change the account: https://www.visualstudio.com/en-us/docs/build/actions/agents/v1-windows
If you use TFS 2017 Build agent, just re-configure it and specify that account when you reconfigure it.
You can use a PowerShell wrapper script to start a executable with different identity.
param (
[Parameter(Mandatory=$True)]
    [string]$username,
[Parameter(Mandatory=$True)]
    [string]$password,
[Parameter(Mandatory=$True)]
    [string]$executable,
[Parameter(Mandatory=$False)]
    [string[]]$arguments,
[Parameter(Mandatory=$False)]
    [string]$workingDirectory
)
$secpassword = $password | ConvertTo-SecureString -asPlainText -Force
$password = $null
$credentials = New-Object System.Management.Automation.PSCredential($username,$secPassword)
$workingDirectory = if([string]::IsNullOrEmpty($workingDirectory)){(Get-Item -Path ".\").FullName}
Start-Process $executable -ArgumentList $arguments -WorkingDirectory $workingDirectory -Credential ($credentials)
Create a hidden variable 'password' in your build or release definition with the password and set the visibility to hidden.
Call this script with the powershell step:
-username "username" -password = $(password) -executable "myExecutable" -arguments '-param "param1"','-param2 "param2"','-param3"d:\directory\with blanks in a path\"'

Jenkins - kill process before delete workspace action starts

I am having a Jenkins job that runs Nunit tests on remote machine.
I am using Jenkins's Workspace Cleanup Plugin pluggin (https://wiki.jenkins-ci.org/display/JENKINS/Workspace+Cleanup+Plugin) to clean my workspace.
the problem is that I want to task kill some process on my machine (because otherwise I could not delete the workspace - some files will be in use and threfore could not be deleted) and I want to do it before the delete action takes place (it is always the first action on the job).
I know that there is an option in the pluggin- "External Deletion Command" - but this runs the command on all the files in the workspace where as I need it to run only once (not on a the sepsific workspace files - i.e. only this command: "c:/workspace/taskill nunit")
is there a way to do so?
Thanks
If I can suggest a different approach to use an app called LockHunter which has an API to unlock and delete your workspace. It's much more "sergical" than removing a random task and hope it's the one you meant to.
You can trigger it from command line using "run before SCM" and it'll handle the deletion and unblocking of your specific workspace.
You can also use:
"cmd /c wmic /INTERACTIVE:OFF Path win32_process Where \\"CommandLine Like '%workspace%'\\" call terminate"
Where %workspace% is your current workspace. This will go over all the tasks that are currently running and check the command line path, then it'll call terminate for anything it found.
Good luck!

Start Selenium test cases using jenkins

I have prepared a test cases using selenium webdriver and I ran locally using MSTEST and it works fine and now I would like to move my test cases to JENKINS, and when i run from JENKINS it says Starting execution... and its more than 15 mnts and still the same status so I have to stop it manually.
here is my console output:
Started by user anonymous
Started by user anonymous
Building in workspace D:\Jenkins\jobs\Selenium_Script\workspace
[workspace] $ cmd /c call C:\Users\XXXXXXX\AppData\Local\Temp\hudson4765437871038045571.bat
D:\Jenkins\jobs\SelScript\workspace>call "D:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\mstest" /testcontainer:D:\Sel\EmployeeTest\test.emp.admin.dll
Microsoft (R) Test Execution Command Line Tool Version 10.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.
Loading D:\Sel\EmployeeTest\test.emp.admin.dll...
Starting execution...
Build was aborted
Finished: ABORTED
I wanted to execute the test case on Jenkins and check the result of execution
and here is my code I'm using just in case.
This is what I am using to instantiated my driver, do I have to use RemoteDriver?
public static IWebDriver GetDriver()
{
string _url = new Uri(Common.Url).DnsSafeHost.ToString();
switch (Common.BrowserSelected)
{
case "ff":
FirefoxProfile profile = new FirefoxProfile();
profile.SetPreference("network.http.phishy-userpass-length", 255);
profile.SetPreference("network.automatic-ntlm-auth.trusted-uris", _url);
drv = new FirefoxDriver(profile);
break;
case "ie":
var options = new InternetExplorerOptions();
options.IntroduceInstabilityByIgnoringProtectedModeSettings = true;
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.SetCapability(CapabilityType.AcceptSslCertificates, true);
drv = new InternetExplorerDriver(options);
break;
case "chrome":
//_driver = new ChromeDriver();
break;
}
return drv;
}
You can run your Selenium scripts in the Build section of Jenkins.
Click on Add Build Step and select Execute Shell, over there you can directly run your commands as you would type in a Linux environment.
All of this assuming you are running your Jenkins of a Linux environment.
#Do I have to use RemoteDriver?
Depends do you have xvfb installed to run your tests in a headless mode?
If not, then yes, you can redirect your tests to run remotely on a windows/mac machine.
UPDATE
If you have a windows machine, you do not need xvfb. So forget about that.
Shell script (defaults to sh, but this is configurable) for building the project. The script will be run with the workspace as the current directory. Type in the contents of your shell script. If your shell script has no header line like #!/bin/sh —, then the shell configured system-wide will be used, but you can also use the header line to write script in another language (like #!/bin/perl) or control the options that shell uses.
By default, the shell will be invoked with the "-ex" option. So all of the commands are printed before being executed, and the build is considered a failure if any of the commands exits with a non-zero exit code. Again, add the #!/bin/... line to change this behavior.
As a best practice, try not to put a long shell script in here. Instead, consider adding the shell script in SCM and simply call that shell script from Jenkins (via bash -ex myscript.sh or something like that), so that you can track changes in your shell script.
Example -
You can run a ruby command like so
ruby testscripts.rb
or a shell script like so
./testscripts.sh
Jenkins is super easy. Just do this:
1. Allow Jenkins to check-out your code into the Jenkins workspace.
2. Navigate to that workspace on your Windows computer and manually run
the tests by executing the script that starts them.
By doing it this way Jenkins is temporarily out of the picture and is therefore no longer the cause of your problem. Then, you can focus on what the real actual problem is. Once you have resolved the problem, check your changes into your source code repo, then run the Jenkins build again and try to run manually again. If that also works, THEN finally, you are clear to setup a build task in Jenkins to run your test.

MSDeploy to install windows service?

We have a website which publishes events using NServiceBus. The site is deployed using msdeploy. We also have the NServiceBus.exe which should run as a windows service to subscribe to these events, and we'd like to deploy that as well.
Is there any way to package the service as well as the website, so that it can be installed as well? Is it possible to package separately so we can deploy it to another server?
Any tips on where to find information on how to do this would be great, as we can do automated deployments for the website now.
I recently did this using MSDeploy, Phantom and installUtil.exe
You just basically need to modify your installer class and elevate your remote wmsvc service privileges if needed.
Link to blog
What we wound up doing was creating a 'controller' layer that coordinates deployment tasks, even one that could use msdeploy. Essentially, msdeploy is not the highest level of abstraction in our deployment system.
We chose to use MSBuild to coordinate those tasks of deploying items from a 'package'.
In our deployment process, a web application deployed with msdeploy is just another deployment item, just as is a Windows service.
In all disclosure, we have not actually created msdeploy deployment tasks yet, though it should/would drop in nicely to what we've already created, as MSBuild would invoke the msdeploy. We currently use MSBuild community tasks for webapp deployment automation, coordinated via MSBuild.
You can read a little more about how we 'generalized' our deployments via a blog post I did called "PANDA - Packaging ANd Deployment Automation".
Here is a msdeploy cmd line I used to sync an archivedir that is created from a post-build step in my Windows Service.proj file.
It is syncing from my build server to my app server on a different network. I have pre and post build steps that start and stop the services on the remote server. You must wrap the powershell script in a vb script due to a bug with powershell and msdeploy. The -verbose option is very helpful.
I also have the vbscript and ps1 script below. Be careful with the VB sleep and the pre and post msdeploy timeouts.
msdeploy -verb:sync -source:archivedir=\\qa-xxxxx1.qa.lan\deployment\backups\FreddieMacDelivery\FreddieMacDelivery.zip,tempAgent='True',computerName=qa-xxxxx1.qa.lan,userName=QA\xxxxx,password=xxxx,authtype=NTLM,includeAcls='False' -dest:dirpath=\\qa-xxxxxx1.qa.lan\protk\Services\FreddieMacDelivery\1.4.1.test -useCheckSum -verbose -preSync:runCommand="cscript.exe c:\temp\stop_win_svc.vbs" -postSync:runCommand="c:\temp\start_win_svc.vbs",waitInterval=15000,waitAttempts=1
VB script:
Option Explicit
Dim oShell, appCmd,oShellExec
Set oShell = CreateObject("WScript.Shell")
appCmd = "powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ""&c:/temp/Get_Win_SVC.ps1"" "
Set oShellExec = oShell.Exec(appCmd)
WScript.Sleep 1000
oShellExec.StdIn.Close()
Powershell script:
$username = 'QA\xxxxx'
$password = 'xxxxx'
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList #($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
(Get-WmiObject -computer qa-xxxx1.qa.lan -Credential $cred Win32_Service -Filter "Name='ProTeck.FreddieMac.DeliveryService'")
$svc = (Get-WmiObject -computer qa-xxxxx1.qa.lan -Credential $cred Win32_Service -Filter "Name='ProTeck.FreddieMac.DeliveryService'")
Write-Host $svc
$svc.InvokeMethod("StartService", $null)
(Get-WmiObject -computer qa-xxxxx1.qa.lan -Credential $cred Win32_Service -Filter "Name='ProTeck.FreddieMac.DeliveryService'")> c:\temp\win_stat_post.txt

Creation of InstallAnywhere installer inside of Hudson CI

My company is trying to automate the creation of a nightly installer with Hudson. Our license to install anywhere is running on a separate server. We have an ANT build script set up to call the InstallAnywhere jar file which creates the installer automatically, and that works great when ran from the command prompt.
However when we try to run it inside of Hudson, Hudson is not able to connect to that license server. InstallAnywhere spits out The evaluation period has expired. Does anyone know what we can do to solve this issue?
I'm assuming it's a Hudson issue since our ANT script works fine when used outside of Hudson.
My best guess is that you need to set up some environment variables required by the InstallAnywhere process; I'm not very familiar with that product, but maybe it needs a home directory for the product, the location of the license file, the license key value, etc.
One easy way to debug this would be to check if Hudson is running under the same user that you are using to run the Ant script from the command line, then check the environment settings for the command line user if they are different.
Since I'm running Hudson as a service I had to use the "Default User" user. The solution was to copy the InstallAnywhere folder tree from "C:\Documents and Settings\MyUser" to "C:\Documents and Settings\Default User"
I just had the same issue, so I thought I would share my solution. You can also register the CI build user so you can continue using the automated user rather than switching it to your own user account: http://www.flexerasoftware.com/downloads/instructions/productlicensing/en/InstallAnywhereProductLicensing.pdf#page=15
Set up a bat file to execute:
<PATH_TO_IA>\build.exe -registerNodeLocked <PATH_TO_IA>\License.lic
Note, the License will be your mac address.lic, and you only have to do this once.
My bat was:
C:\Progra~2\Instal~2\build.exe -registerNodeLocked C:\Progra~2\Instal~2\[MAC].lic
Then I added a bat task to jenkins, and ran the job:
You should see something like:
Trying to checkout IAEE version=12.0
InstallAnywhere is successfully registered.

Resources