teamcity powershell - unable to run batch file - powershell

I've spent quite a bit of time banging my head on this one. A little StackOverflow help please, good folks!
Scenario: We are trying to run a custom .bat file located on the CI server via the TeamCity Powershell step.
When powershell script is run on local box manually, it kicks off .bat file correctly.
When powershell script is run through TeamCity, it successfully 'sees' the .bat file (validated by receiving a 'cannot find file' response when I rename the .bat file it is expecting)
HOWEVER, we have not seen any indication that the .bat file was actually kicked off.
What we've tried:
We've added the 'RedirectStandardOutput' and 'RedirectStandardError' for attempt to diagnose, but although the log file is created, it is returned blank.
We've granted filepath permissions and tried two different credentials including the credential of the TC build agent
Added "-wait" at one point to see if we needed to 'tell' PS to wait on the .bat file.
Two questions...
What is preventing us from running this .bat file?
How do we diagnose issues like this? ATM it is a 'blackbox' to us.
TeamCity Powershell settings:
Powershell Run Mode: Version 1.0; Bitness x64 (tried x86 as well)
Working Directory: Tried as blank, and specific filepath of .bat file (so, 'D:\folder\folder2\')
Script: Source Code
Script Execution: Execute .ps1 from external file (tried with 'Put script into PowerShell stdin with "-Command -" argument' as well)
Add -NoProfile argument (tried both)
Powershell script:
#Predefine necessary information
$Username = "DOMAIN\username"
$Password = "password"
$ComputerName = "CI Build Server Name"
#Create credential object
$SecurePassWord = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $Username, $SecurePassWord
#Start batch file
Start-Process "testbat.bat" -WorkingDirectory D:\file\path\ -Credential ($Cred)-NoNewWindow -RedirectStandardError stderr.txt -RedirectStandardOutput stdout.txt
Write-Host "Executed powershell."
UPDATE 1: If we remove the '-Credential ($Cred)' portion we are able to kick off the testbat.bat file from TeamCity, as expected. The problem must lie with that "-Credential ($Cred)" argument, somehow. Any thoughts?
UPDATE 2: If we set the '-Credential ($Cred)' portion to the credential of the build agent user we are able to kick off the test.bat file from TeamCity. The problem only occurs when we set the credential to a user other than the one running the build agent. This seems to indicate that credential syntax is fine.
UPDATE 3: Tried running with PowerShell executionpolicy set to 'RemoteSigned' and 'Unrestricted'. Problem persists.
UPDATE 4: Gave the BuildAgent user, and the user of whom we want to run this as, full permissions to powershell via 'Set-PSSessionConfiguration'. Problem persists.

$credential = New-Object System.Management.Automation.PsCredential(".\user", (ConvertTo-SecureString "pass" -AsPlainText -Force))
Start-Process powershell -Credential $credential -ArgumentList '-noprofile -command &{Start-Process D:\file\path\test.bat -NoNewWindow -RedirectStandardError stderr.txt -RedirectStandardOutput stdout.txt }'
note:
first i get credential "user" ur user then convert your pass to plain text
then start-process with your credential set

If agent is running as service under Local System account, then it's not possible to run PowerShell under specified account. The workarounds are:
Run agent via command line.
Try to run agent service under another account (not Local System) with administrator rights, probably it will help.
Try RunAs plugin. It provides an ability to run builds under the specified user account.

Related

How do I run a command on localhost with saved credentials? -Powershell

I want to run one command with saved credentials on powershell, i have the following script
$user = "test"
$passwd = ConvertTo-SecureString -String "ExtremelyStrongPassword" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList $user, $passwd
Copy-Item -Path "C:\Temp\*" "C:\Program Files\Test\" -Credentials $cred
The user doesn't have administrator permissions, but in the localhost we have an user with administrator permissions to run these process.
The error returned is "Access Denied"
How do i pass these parameters to run a command with elevation?
Never pass plain text credentials in a script. Use the Get-Credential cmdlet to collect and use them. Even doing this, the user will get prompted for a password.
This is what the -RunAs switch of Start-Process is for
Or set your script to auto elevate
Or use the credential switch of a cmdlet
Or use a scheduled task with whatever creds you need, and let the user run it.
Use the Requires statement at the top of your script
Store the need creds in the Windows Credential Store and call them
from there
about_Requires - PowerShell | Microsoft Docs
Short description Prevents a script from running without the required
elements.
#Requires -RunAsAdministrator
Start-Process
Example 5: Start PowerShell as an administrator This example starts
PowerShell by using the Run as administrator option.
Start-Process -FilePath "powershell" -Verb RunAs
Using what you have this way:
Copy-Item -Path 'C:\Temp\*' 'C:\Program Files\Test\' -Credentials (Get-Credential -Credential 'Domain\UserName')
With exception of the scheduled task approach, each will prompt the user for a password, which sounds like what you wanting to avoid. So, consider the following:
Accessing Windows Credentials Manager from PowerShell
This simple PowerShell class can be used for working with Credentials
Manager and Password Vault in Windows: checking if account information
is present in the vault, saving credentials to the vault and reading
stored login and password information from the vault.
https://gallery.technet.microsoft.com/scriptcenter/Accessing-Windows-7210ae91
Using the registry to store credentials:
Save Encrypted Passwords to Registry for PowerShell

Looking to map an Azure Fileshare as a mapped network drive on an Azure Windows VM via another machine/Custom Script Execution

I'm attempting to provision a Windows VM and I need to map some Azure fileshares to drives for the VM user that will be interacting with the VM.
I've been trying to make "az vm extension set"/Custom Script Execution work for me by calling some PowerShell scripts to setup the mapping to the fileshare, but since the process runs as NT AUTHORITY\SYSTEM, the mappings aren't working, obviously. I've tried to switch user contexts in my scripts via having an intermediate script that changes context to my VM user and then calling another script that does the work, but that doesn't seem to be working.
$scriptFile = $args[0]
$username = $args[1]
$password = $args[2]
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username,
$securePassword
Start-Process Powershell.exe -Credential $credential $scriptFile
Unfortunately it seems nothing gets run in the $scriptFile that I call, and I can't get any errors out of standard out/err, so I'm at a loss as to how this can be done.
Certainly someone out there has had to run scripts as another user via the Custom Script Execution method before, I'm hoping they happen to read this post.
Is there a way to set what user the Custom Script Execution runs as?
No, there is no way of setting a user under which script extension runs.
You also should use -PassThru and -Wait and\or -RedirectStandardError\-RedirectStandardInput to your command invocation. Also, add -ErrorAction Stop to your commands to propagate errors.

Run PowerShell script as different user and hidden window from another PowerShell script

I need to run a PowerShell script from another PowerShell script as different user and hidden window.
What do I have so far:
Start-Process powershell '& C:\test.ps1' -WindowStyle Hidden -Credential $cred
where $cred is a PSCredential object. The test.ps1 script is for testing purposes one line with Remove-Item. As I can still see the file not being removed I can tell that the script is not being run.
EDIT
My original intention is to run regedit script but when I was implementing Start-Job answer (below) I've got this error:
Start-Job : The value of the FilePath parameter must be a Windows PowerShell script file. Enter th
e path to a file with a .ps1 file name extension and try the command again.
You could use jobs for this. As the Powershell documentation says
A Windows PowerShell background job runs a command without interacting
with the current session.
PS> $myJob = Start-Job -FilePath C:\test.ps1 -Credential $cred
To get the result/output of the job, use Receive-Job
PS> $myJob | Receive-Job -Keep
You can run the PowerShell scripts through task scheduler. I'm not sure if it is your goal, but it will let you execute PowerShell scripts on a user's session using their credentials.
I'll let you Google the how to, to fit your needs.

Start-Process powershell credentials don't work but when using cmd it does

I am trying to run a powershell script from another powershell script passing in the credentials of a different user and then using the credentials:
Start-Process powershell.exe -Credential "LON\my-user" -NoNewWindow -ArgumentList "-file C:\DevopsScripts\stuckApps.ps1"
I have this is numerous different ways all get the same error. I have tried setting the username and password before the command:
$username = "LON\my-user"
$password = "pass"
$PSS = ConvertTo-SecureString $password -AsPlainText -Force
$cred = new-object system.management.automation.PSCredential $username,$PSS
$env:USERNAME
Start-Process powershell.exe -Credential $cred -NoNewWindow -ArgumentList "-file C:\DevopsScripts\stuckApps.ps1"
But everything I try gets the error:
Start-Process : This command cannot be run due to the error: The user name or password is incorrect.
I know the username and password are correct as they have been tested on the cmd which it works fine:
C:\Users\ADM-me>runas /noprofile /user:LON\my-user"powershell.exe C:\DevopsScripts\stuckApps.ps1"
What am I doing wrong here and how could I fix this, preferably by setting the password beforehand, so this can be automated. Also this does not need to be done using Start-Process, just this is the closest thing I could find to working.
I think the problem I am having is this, in stuck apps it has this:
$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = "Server = mssql.co.uk; Database = mydata; Integrated Security = true;"
$conn.Open()
I need this to run the credentials that I am trying to pass through it or else I get this error.
`Exception calling "Open" with "0" argument(s): "Login failed. The login is from an untrusted domain and cannot be used with Windows authentication."
But I can't pass the credentials through as the only ones that work are admin ones, (which I have but then that will throw the error above). Is it possible for me to use the admin logins to access stuck apps then use the logins needed to connect on stuck apps as an AD login.
Your first attempt with -Credential "LON\my-user" can't work, but your second attempt is correct, building the object of class PSCredential, as required (see the type in Get-Help Start-Process -Parameter Credential, it is PSCredential and not String). I tried the same with some reused code here, and it works here both or CMD and PS1 calling a PS1 test script via Powershell.exe, using a local test account (sorry, no domain #home).
So even though my code ist not identical and the domain of the user is the local machine, the approach is the same compared to yours and - sorry that this does not solve your problem - I don't see that you are doing sth. wrong.
To play safe, please make sure though to test with the same Powershell version, the below scripts executed under W10 1607 (so Powershell 5.1.14393.1198), all scripts in the same directory.
testscript.ps1
write-host "Testscript is run with user: $($env:USERNAME)"
Start-Sleep 2
testrun.cmd
runas /noprofile /user:%COMPUTERNAME%\myaccount "powershell.exe -NoProfile -ExecutionPolicy ByPass -file %~dp0testscript.ps1"
testrun.ps1
$Username = "$($env:COMPUTERNAME)\myaccount"
$Password = 'mypassword'
$SecurePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
$ScriptFile = Join-Path -Path $PSScriptRoot -ChildPath 'testscript.ps1'
$Credential = New-Object System.Management.Automation.PSCredential( $Username, $SecurePassword)
$StartOpts = #{ 'FilePath' = 'powershell.exe'
'Credential' = $Credential
'NoNewWindow' = $false
'ArgumentList' = #( '-f', $ScriptFile,
'-ExecutionPolicy', 'Bypass',
'-NoProfile'
)
}
Start-Process #StartOpts
Some remarks on testrun.ps1
Don't mind the parameters for Start-Process being passed as a hashtable, it's just better readable for me, otherwise it makes not difference
The ArgumentList is being passed as a string array here - I prefer it this way so that it is automatically taken care for double qouting parameters, e.g. when the pathname of the script directory would contain spaces
The parameter -NoNewWindow passed to Start-Process seems not to have any effect here - a new window is opened
I always recommend to add the parameters -Noprofile and -ExecutionPolicy Bypass when using Powershell.exe to launch scripts or execute commands, just to make sure it works despite of the Execution Policy set or any present user or machine profile scripts.
However, at least the parameter -NoProfile seems not to work the same when Powershell.exe is being called fom the above CMD or PS1. Called from PS1, my machine profile gets nevertheless executed, but not fom CMD... interesting! The MSDN: PowerShell.exe Command-Line Help just says about this parameter: "Does not load the Windows PowerShell profile." Funny! There are six of them, see Technet: Understanding the Six PowerShell Profiles. I use "Current User, Current Host – console" and "All Users, Current Host – console". Lesson learned, but I am not sure if it's a bug or a feature.

How do I execute a powershell script under a specified credential without a prompt?

I'm writing an 'Action Script' in VMWare AppDirector 'AppD' which installs MS Dynamics. (My action script is actually a powershell script). The way this works is that AppD will execute a powershell script on a newly deployed server, using a builtin administrator account. This script is one of the last steps in a highly orchestrated deployment. At this stage my SQL server has been deployed, the databases loaded, and I'm performing the final deployment.
When I run my script logged in as myself, everything works great. But of course that's executing under 'mydomain\myusername' which has access to the SQL server etc. However, when AppD executes this script under a local builtin account, it doesn't have the credentials needed by setup to authenticate against SQL, and make proper connections for install to succeed.
My first attempt was to just call a script, that invokes my actual deployment script, so I can pass credentials;
$user = "mydomain\myusername"
$pword = ConvertTo-SecureString -String "mypassword" -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $pword
Invoke-Command -FilePath "C:\Scripts\DeployAOS.ps1" -Credential $credential -Computer localhost
This looked like it might have worked, but when reviewing the install log I see the following error;
2015-03-09 13:15:19Z Property DbSqlServer set to: 'SQLSERVER001'
2015-03-09 13:15:23Z Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'.
My original DeployAOS.ps1 script contains this line, which kicks off the install;
# Perform AOS Installation
Start-Process -FilePath $exeAOSSetup -ArgumentList $cfgAOS -Wait
I have also tried just modifying my DeployAOS.ps1 to set the 'System.Management.Automation.PSCredential' object w\ Username\Password, and doing something like this;
# Perform AOS Installation
Start-Process -FilePath $exeAOSSetup -ArgumentList $cfgAOS -Credential $credentials -Wait
And it really didn't like that. It feels like the AOS setup needs to be executed under a domain user, that has access to the SQL server, and maybe even have a user profile loaded while setup runs (So it can create a desktop shortcut, etc.)
Any ideas how I might go about solving this problem? I'm fairly new to scripting in powershell, so any help would be appreciated.