Installing a windows service through powershell - powershell

I have a batch script which install a windows service and I want to convert it to a powershell script or command to do the same job.
I have been trying to use the New-Service cmdlet without much success
The batch script is given below:
cd %~dp0%
set SERVICE_NAME=ESL_SERVICE
IF %PROCESSOR_ARCHITECTURE% == x86 (
set PR_INSTALL=%~dp0prunsrv_32.exe
) ELSE (
set PR_INSTALL=%~dp0prunsrv_64.exe
)
echo $PR_INSTALL
set PR_DESCRIPTION=ESL-Server
set PR_DISPLAYNAME=%SERVICE_NAME%
set PR_STARTUP=auto
set PR_CLASSPATH=server.jar
set PR_JVMOPTIONS="-Xmx1024M"
set PR_STARTMODE=jvm
set PR_STARTCLASS=at.mrdevelopment.esl.server.Server
set PR_STARTMETHOD=main
set PR_STOPMODE=jvm
set PR_STOPCLASS=at.mrdevelopment.esl.server.ServerServiceStarter
set PR_STOPMETHOD=stop
IF %PROCESSOR_ARCHITECTURE% == x86 (
prunsrv_32.exe //IS//%SERVICE_NAME%
) ELSE (
prunsrv_64.exe //IS//%SERVICE_NAME%
)
This is what I have done so far..and the service gets installed but it does not start the sevice
$PR_CLASSPATH = "server.jar"
$PR_JVMOPTIONS = '"-Xmx1024M"'
$PR_STARTMODE = "jvm"
$PR_STARTCLASS = "at.mrdevelopment.esl.server.Server"
$PR_STARTMETHOD = "main"
$PR_STOPMODE = "jvm"
$PR_STOPCLASS = "at.mrdevelopment.esl.server.ServerServiceStarter"
$PR_STOPMETHOD = "stop"
New-Service -Name ESL_SERVICE -binaryPathName "C:\imagotag\server\prunsrv_64.exe //RS//ESL_SERVICE" -Description "ESL-Server" -DisplayName ESL_SERVICE -StartupType Auto

Are you missing the Start-Service command, after the New-Service -Name ESL_SERVICE -binaryPathName ... line?
Start-Service -Name ESL_SERVICE
New-Service only creates the service. The -StartupType Automatic will only start this after next reboot.
From Get-Help New-Service -full:
-StartupType Automatic: The service is to be started (or was started) by the operating system, at system start-up.

Thanks for the help guys but I finally managed to figure it out..using a different way
I managed to write the procrun service by using command line parameters instead of variables (the batch script used variables to run the procrun service) and now its installing and working fine.
.\prunsrv_64.exe //IS//ESL_SERVICE --Description ESL-Server --DisplayName ESL_SERVICE --Startup auto --Classpath server.jar ++JvmOptions '"-Xmx1024M"' --StartMode jvm --StartClass at.mrdevelopment.esl.server.Server --StartMethod main --StopMode jvm --StopClass at.mrdevelopment.esl.server.ServerServiceStarter --StopMethod stop --LogPath $LOG_PATH
Start-Service -Name ESL_SERVICE

Related

Setting app pools to recycle at multiple specific times via powershell or appcmd does not display both times in GUI/IIS

I am attempting to set app pools to recycle at multiple times in the day in iis 8.5, I've tried using powershell and app command and when testing on a server that has no sites/applications in the pool it seems to work perfectly, however when trying to set using either method on a server that has sites in the app pools I'm seeing strange behavior, It seems to work however in the GUI of IIS if i look at the recycling settings of the app pool it only shows one of the times specified.
Powershell script initially tried using is:
function Set-ApplicationPoolRecycleTimes {
param (
[string]$ApplicationPoolName,
[string[]]$RestartTimes
)
Import-Module WebAdministration
Write-Output "Updating recycle times for $ApplicationPoolName"
# Delete all existing recycle times
Clear-ItemProperty IIS:\AppPools\$ApplicationPoolName -Name Recycling.periodicRestart.schedule
Clear-ItemProperty IIS:\AppPools\$ApplicationPoolName -Name Recycling.periodicRestart.time
foreach ($restartTime in $RestartTimes) {
Write-Output "Adding recycle at $restartTime"
# Set the application pool to restart at the time we want
New-ItemProperty -Path "IIS:\AppPools\$ApplicationPoolName" -Name Recycling.periodicRestart.schedule -Value #{value=$restartTime}
Set-ItemProperty -Path "IIS:\AppPools\$ApplicationPoolName" -Name Recycling.periodicRestart.time -Value "00:00:00"
} # End foreach restarttime
} # End function Set-ApplicationPoolRecycleTimes
$apppoolname1 = "app pool's name"
$restartat = #("1:45", "18:45")
Set-ApplicationPoolRecycleTimes -ApplicationPoolName $apppoolname1 -RestartTimes $restartat
Again this seems to work perfectly unless there are sites in the application pool. When sites exist it seems to work except that the gui only shows one of the times set:
however querying the value show's both times:
Import-Module WebAdministration
(Get-ItemProperty ('IIS:\AppPools\app pool name') -Name Recycling.periodicRestart.schedule.collection) | select value
value
-----
18:45:00
01:45:00
also attempted using appcmd but finding the same results, works perfectly on a server with no sites in the app pool, but when run against servers with sites, missing one of the times in the gui, querying shows both times. I have turned logging on for app pool recycles to confirm it's happening at both times but wondering if I'm just overlooking something obvious.
appcmd script:
CD C:\windows\System32\inetsrv
$V1 = "app pool name"
#clears any existing schedule
cmd.exe /c appcmd.exe set apppool /apppool.name: $V1 /-recycling.periodicRestart.schedule
#setting desired recycles
cmd.exe /c appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='$v1'].recycling.periodicRestart.schedule.[value='01:45:00']" /commit:apphost
cmd.exe /c appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='$v1'].recycling.periodicRestart.schedule.[value='18:45:00']" /commit:apphost
I tried your PowerShell script with the application pool which contains a site or without site.in both the condition your posted script is working.
you could try to use the below script:
function Set-ApplicationPoolRecycleTimes {
param (
[string]$ApplicationPoolName,
[string[]]$RestartTimes
)
Import-Module WebAdministration
Write-Output "Updating recycle times for $ApplicationPoolName"
# Delete all existing recycle times
Clear-ItemProperty IIS:\AppPools\$ApplicationPoolName -Name Recycling.periodicRestart.schedule
foreach ($restartTime in $RestartTimes) {
Write-Output "Adding recycle at $restartTime"
# Set the application pool to restart at the time we want
New-ItemProperty -Path "IIS:\AppPools\$ApplicationPoolName" -Name Recycling.periodicRestart.schedule -Value #{value=$restartTime}
} # End foreach restarttime
} # End function Set-ApplicationPoolRecycleTimes
$apppoolname = "abcsite"
$restartat = #("05:55", "12:55", "17:00")
Set-ApplicationPoolRecycleTimes -ApplicationPoolName $apppoolname -RestartTimes $restartat
or
appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='test1'].recycling.periodicRestart.schedule.[value='07:00:00']" /commit:apphost
appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='test1'].recycling.periodicRestart.schedule.[value='18:25:00']" /commit:apphost
or
Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/applicationPools/add[#name='test1']/recycling/periodicRestart/schedule" -name "." -value #{value='07:00:00'}
Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/applicationPools/add[#name='test1']/recycling/periodicRestart/schedule" -name "." -value #{value='18:25:00'}
The above scripts are tested with the IIS 10 (Windows 10) and IIS 8.5(windows server 2012r2)

Install Windows HotFix using Terraform on AWS

I have a very simple PowerShell script that uploads a generated test file to an AWS S3 bucket from a Windows 2008 R2 Datacenter server (clean AWS instance). If I run the script remotely on the server using Terraform (remote-exec provisioner), the script fails on the S3 upload with a StackOverflowException. When I run the script directly on the server, it runs fine and uploads the file.
I've experimented with different sizes for the file and 14.5MB seems to be about the maximum that works before the StackOverflowException occurs. Just about any size works fine when I RDP into the server and run the script directly. I've tested 200MB and it works fine.
Any idea why this is happening or what I can do to fix it? The actual file I need to upload is 50MB.
Here are the essential parts to recreate the problem. terraform.tf file:
resource "aws_instance" "windows" {
count = "1"
ami = "ami-e935fc94" #base win 2008 R2 datacenter
instance_type = "t2.micro"
connection {
type = "winrm"
user = "<username>"
password = "<password>"
timeout = "30m"
}
provisioner "file" {
source = "windows/upload.ps1"
destination = "C:\\scripts\\upload.ps1"
}
provisioner "remote-exec" {
inline = [
"powershell.exe -File C:\\scripts\\upload.ps1"
]
}
}
The PowerShell script is very simple. upload.ps1:
$f = new-object System.IO.FileStream C:\Temp\test.dat, Create, ReadWrite
$f.SetLength(40MB) # change this to 14.5MB and it works!
$f.Close()
Write-S3Object -BucketName "mybucket" -Folder "C:\Temp" -KeyPrefix "20180322" -SearchPattern "*.dat"
The error that I receive when launching the script from Terraform (remote-exec provisioner):
aws_instance.windows (remote-exec): Process is terminated due to StackOverflowException.
Running upload.ps1 from RDP on the server itself works fine, including larger files (tested up to 200MB).
Here is the version information:
Microsoft Windows Server 2008 R2 Datacenter
Powershell Version: 3.0
AWS Tools for Windows PowerShell, Version 3.3.245.0
Amazon Web Services SDK for .NET, Core Runtime Version 3.3.21.15
This problem results from a Windows bug. This is all fine and good for a standard Windows server -- you can patch and move on. But, things are more tricky with AWS automation using Terraform.
The ideal solution would allow 1) use of the base AMI, 2) apply the hotfix to itself, and 3) then run the WinRM remote-exec, all from Terraform. Another solution would be to create an AMI with the hotfix installed and have Terraform generate instances using that AMI. However, then you're stuck maintaining AMIs.
Normally, I grab the Microsoft-provided base AMI using a filter:
data "aws_ami" "windows2008" {
most_recent = true
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "name"
values = ["Windows_Server-2008-R2_SP1-English-64Bit-Base*",]
}
owners = ["801119661308", "amazon"]
}
Then I use that AMI to create the AWS instance:
resource "aws_instance" "windows" {
count = "1"
ami = "${data.aws_ami.windows2008.id}"
...
}
But, the base AMI doesn't have the hotfix installed allowing you to avoid this WinRM/Windows bug. This is were it gets tricky.
You can use a userdata script to perform a multi-phase setup. In the first boot of the instance (Phase 1), we'll block the instance so that the remote-exec doesn't come in before we're ready. Then, we'll download and install the hotfix and we'll reboot (thanks to Niklas Akerlund, Micky Balladelli and Techibee). On the second boot (in method described here), we'll unblock the instance (enable WinRM) so that the remote-exec can connect.
Here's my userdata/PowerShell script:
$StateFile = "C:\Temp\userdata_state.txt"
If(-Not (Test-Path -Path $StateFile))
{
# PHASE 1
# Close the instance to WinRM connections until instance is ready (probably already closed, but just in case)
Start-Process -FilePath "winrm" -ArgumentList "set winrm/config/service/auth #{Basic=`"false`"}" -Wait
# Set the admin password for WinRM connections
$Admin = [adsi]("WinNT://./Administrator, user")
$Admin.psbase.invoke("SetPassword", "${tfi_rm_pass}")
# Create state file so after reboot it will know
New-Item -Path $StateFile -ItemType "file" -Force
# Make it so that userdata will run again after reboot
$EC2SettingsFile="C:\Program Files\Amazon\Ec2ConfigService\Settings\Config.xml"
$Xml = [xml](Get-Content $EC2SettingsFile)
$XmlElement = $Xml.get_DocumentElement()
$XmlElementToModify = $XmlElement.Plugins
Foreach ($Element in $XmlElementToModify.Plugin)
{
If ($Element.name -eq "Ec2HandleUserData")
{
$Element.State="Enabled"
}
}
$Xml.Save($EC2SettingsFile)
# Download and install hotfix
# Download self-extractor
$DownloadUrl = "https://hotfixv4.trafficmanager.net/Windows%207/Windows%20Server2008%20R2%20SP1/sp2/Fix467402/7600/free/463984_intl_x64_zip.exe"
$HotfixDir = "C:\hotfix"
$HotfixFile = "$HotfixDir\KB2842230.exe"
mkdir $HotfixDir
(New-Object System.Net.WebClient).DownloadFile($DownloadUrl, $HotfixFile)
# Extract self-extractor
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($HotfixFile, $HotfixDir)
# Install - NOTE: wusa returns immediately, before install completes, so you must check process to see when it finishes
Get-Item "$HotfixDir\*.msu" | Foreach { wusa ""$_.FullName /quiet /norestart"" ; While (#(Get-Process wusa -ErrorAction SilentlyContinue).Count -ne 0) { Start-Sleep 3 } }
# Reboot
Restart-Computer
}
Else
{
# PHASE 2
# Open WinRM for remote-exec
Start-Process -FilePath "winrm" -ArgumentList "quickconfig -q"
Start-Process -FilePath "winrm" -ArgumentList "set winrm/config/service #{AllowUnencrypted=`"true`"}" -Wait
Start-Process -FilePath "winrm" -ArgumentList "set winrm/config/service/auth #{Basic=`"true`"}" -Wait
Start-Process -FilePath "winrm" -ArgumentList "set winrm/config #{MaxTimeoutms=`"1900000`"}"
}

Resume powershell script after reboot [duplicate]

This question already has answers here:
Powershell - Reboot and Continue Script
(7 answers)
Closed 5 years ago.
I have a lot of articles about this subject but none of it is understandable.
My request is very simple. I have two part of my codes ; First of all Code 1 should be work and windows should be restarted. After reboot completion, Code 2 should be work. This process should be done silently at background. Powershell version is 4.0 ( Win 2012 R2 )
CODE 1 - This code is changing Computer Primary DNS Suffix.
$computerName = $env:computername
$DNSSuffix = "abc.com"
$oldDNSSuffix = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\" -Name "NV Domain")."NV Domain"
#Update primary DNS Suffix for FQDN
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\" -Name Domain -Value $DNSSuffix
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\" -Name "NV Domain" -Value $DNSSuffix
#Update DNS Suffix Search List - Win8/2012 and above - if needed
#Set-DnsClientGlobalSetting -SuffixSearchList $oldDNSSuffix,$DNSSuffix
#Update AD's SPN records for machine if part of an AD domain
if ((gwmi win32_computersystem).partofdomain -eq $true) {
$searchAD = new-object System.DirectoryServices.DirectorySearcher
$searchAD.filter = "(&(objectCategory=computer)(cn=$($computerName)))"
$searchADItem = $searchAD.FindAll() | select -first 1
$adObj= [ADSI] $searchADItem.Path
$oldadObjSPN = $searchADItem.Properties.serviceprincipalname
$adObj.Put('serviceprincipalname',($oldadObjSPN -replace $oldDNSSuffix, $DNSSuffix))
$oldadObjDNS = $searchADItem.Properties.dnsHostName
$adObj.Put('dnsHostName',($oldadObjDNS -replace $oldDNSSuffix, $DNSSuffix))
$adObj.setinfo()
#$adObj.Get('serviceprincipalname')
#$adObj.Get('dnsHostName')
}
CODE 2 - Installing Terminal Services on this computer
Import-Module RemoteDesktop
Add-WindowsFeature -Name RDS-RD-Server -IncludeAllSubFeature
Add-WindowsFeature -Name RDS-Licensing -IncludeAllSubFeature
If you don’t want to roll your own with log files to check where it left off, you can look into powershell workflows which allows recovery after reboot. See https://technet.microsoft.com/en-us/library/jj574130(v=ws.11).aspx
powershell commands are very complicated, i decided to do this with batch file.
Resume batch script after computer restart

Powershell - Copying File to Remote Host and Executing Install exe using WMI

EDITED: Here is my code now. The install file does copy to the remote host. However, the WMI portion does not install the .exe file, and no errors are returned. Perhaps this is a syntax error with WMI? Is there a way to just run the installer silently with PsExec? Thanks again for all the help sorry for the confusion:
#declare params
param (
[string]$finalCountdownPath = "",
[string]$slashes = "\\",
[string]$pathOnRemoteHost = "c:\temp\",
[string]$targetJavaComputer = "",
[string]$compname = "",
[string]$tempPathTarget = "\C$\temp\"
)
# user enters target host/computer
$targetJavaComputer = Read-Host "Enter the name of the computer on which you wish to install Java:"
[string]$compname = $slashes + $targetJavaComputer
[string]$finalCountdownPath = $compname + $tempPathTarget
#[string]$tempPathTarget2 =
#[string]$finalCountdownPath2 = $compname + $
# say copy install media to remote host
echo "Copying install file and running installer silently please wait..."
# create temp dir if does not exist, if exist copy install media
# if does not exist create dir, copy dummy file, copy install media
# either case will execute install of .exe via WMII
#[string]$finalCountdownPath = $compname + $tempPathTarget;
if ((Test-Path -Path $finalCountdownPath) )
{
copy c:\hdatools\java\jre-7u60-windows-i586.exe $finalCountdownPath
([WMICLASS]"\\$targetJavaComputer\ROOT\CIMV2:win32_process").Create("cmd.exe /c c:\temp\java\jre-7u60-windows-i586.exe /s /v`" /qn")
}
else {
New-Item -Path $finalCountdownPath -type directory -Force
copy c:\hdatools\dummy.txt $finalCountdownPath
copy "c:\hdatools\java\jre-7u60-windows-i586.exe" $finalCountdownPath
([WMICLASS]"\\$targetJavaComputer\ROOT\CIMV2:win32_process").Create("cmd.exe /c c:\temp\java\jre-7u60-windows-i586.exe /s /v`" /qn")
}
I was trying to get $Job = Invoke-Command -Session $Session -Scriptblock $Script to allow me to copy files on a different server, because I needed to off load it from the server it was running from. I was using the PowerShell Copy-Item to do it. But the running PowerShell script waits until the file is done copying to return.
I want it to take as little resources as possible on the server that the powershell is running to spawn off the process on another server to copy the file. I tried to user various other schemes out there, but they didn't work or the way I needed them to work. (Seemed kind of kludgey or too complex to me.) Maybe some of them could have worked? But I found a solution that I like that works best for me, which is pretty easy. (Except for some of the back end configuration that may be needed if it is is not already setup.)
Background:
I am running a SQLServer Job which invokes Powershell to run a script which backups databases, copies backup files, and deletes older backup files, with parameters passed into it. Our server is configured to allow PowerShell to run and under the pre-setup User account with SQL Server Admin and dbo privileges in an Active Directory account to allow it to see various places on our Network as well.
But we don't want it to take the resources away from the main server. The PowerShell script that was to be run would backup the database Log file and then use the another server to asynchronously copy the file itself and not make the SQL Server Job/PowerShell wait for it. We wanted it to happen right after the backup.
Here is my new way, using WMI, using Windows Integrate Security:
$ComputerName = "kithhelpdesk"
([Wmiclass]'Win32_Process').GetMethodParameters('Create')
Invoke-WmiMethod -ComputerName RemoteServerToRunOn -Path win32_process -Name create -ArgumentList 'powershell.exe -Command "Copy-Item -Path \\YourShareSource\SQLBackup\YourDatabase_2018-08-07_11-45.log.bak -Destination \\YourShareDestination\YourDatabase_2018-08-07_11-45.log.bak"'
Here is my new way using passed in Credentials, and building arg list variable:
$Username = "YouDomain\YourDomainUser"
$Password = "P#ssw0rd27"
$ComputerName = "RemoteServerToRunOn"
$FromFile = "\\YourShareSource\SQLBackup\YourDatabase_2018-08-07_11-45.log.bak"
$ToFile = "\\YourShareDestination\SQLBackup\YourDatabase_2018-08-07_11-45.log.bak"
$ArgumentList = 'powershell.exe -Command "Copy-Item -Path ' + $FromFile + ' -Destination ' + $ToFile + '"'
$SecurePassWord = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $Username, $SecurePassWord
([Wmiclass]'Win32_Process').GetMethodParameters('Create')
Invoke-WmiMethod -ComputerName $ComputerName -Path win32_process -Name create -ArgumentList $ArgumentList -Credential $Cred
We think that this above one is the preferred one to use.
You can also run a specific powershell that will do what you want it to do (even passing in parameters to it):
Invoke-WmiMethod -ComputerName RemoteServerToRunOn -Path win32_process -Name create -ArgumentList 'powershell.exe -file "C:\PS\Test1.ps1"'
This example could be changed to pass in parameters to the Test1.ps1 PowerShell script to make it more flexible and reusable. And you may also want to pass in a Credential like we used in a previous example above.
Help configuring WMI:
I got the main gist of this working from: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/invoke-wmimethod?view=powershell-5.1
But it may have also needed WMI configuration using:
https://helpcenter.gsx.com/hc/en-us/articles/202447926-How-to-Configure-Windows-Remote-PowerShell-Access-for-Non-Privileged-User-Accounts?flash_digest=bec1f6a29327161f08e1f2db77e64856b433cb5a
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/enable-psremoting?view=powershell-5.1
Powershell New-PSSession Access Denied - Administrator Account
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/invoke-wmimethod?view=powershell-5.1 (I used to get how to call Invoke-WmiMethod).
https://learn.microsoft.com/en-us/powershell/scripting/core-powershell/console/powershell.exe-command-line-help?view=powershell-6 (I used to get syntax of command line)
I didn't use this one, but could have: How to execute a command in a remote computer?
I don't know for sure if all of the steps in the web articles above are needed, I suspect not. But I thought I was going to be using the Invoke-Command PowerShell statement to copy the files on a remote server, but left my changes from the articles above that I did intact mostly I believe.
You will need a dedicated User setup in Active Directory, and to configure the user accounts that SQL Server and SQL Server Agent are running under to give the main calling PowerShell the privileges needed to access the network and other things to, and can be used to run the PowerShell on the remote server as well. And you may need to configure SQLServer to allow SQL Server Jobs or Stored Procedures to be able to call PowerShell scripts like I did. But this is outside the scope of this post. You Google other places on the internet to show you how to do that.

Running setup in background with msdeploy

We're deploying build directly from TFS build to servers with msdeploy. There are many components and some of those need setup (multiple nservicebus services that take ~1min each to start/install/stop). Also this "gateway" server runs msdeploy itself to "fanout" deployment binaries to other servers that run similar setup tasks depending on their role.
It doesn't make sense for build server to be hung up on this task for a long time so we need some way to make this setup run in "background"/detached from build server perspective.
We're using powershell as deployment script engine.
So here is what we've tried:
Jobs started with start-job are killed as soon as original msdeploy -started powershell exits.
Jobs started with start-process hang up the msdeploy connection until they finish
We can't loop with invoke-command -ComputerName localhost -InDisconnectedSession (this worked from shell on same machine but not through msdeploy; I don't care for passing credentials around because we don't have DA creds and deployed machines are in multiple networks)
I post my solution below, I ended up using scheduled task that is launched immediately. But I hope somebody would know a cleaner solution.
This program will schedule itself to run immediately, this can be "triggered" with msdeploy runCommand and not block output.
This is our msdeploy using trigger script:
param([string]$dest = "fully.qualified.example.com",
[string]$serviceMachine = "windowsmachine",
[string]$deployUser = "webdeploy",
[string]$deployPass = "***",
[string]$localPath = "c:/temp/source",
[string]$remotePath = "c:/temp"
);
$deployCommand = "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe"
$depArgs = #('-verb:sync'
"-source:dirpath=$localPath"
"-dest:computerName=https://${dest}/msdeploy.axd,userName=$servicemachine\$deployUser,password=$deployPass,authType=basic,dirPath=$remotePath"
"-postSync:runCommand='powershell -inputformat none $remotePath/starter.ps1',waitInterval=30000"
"-enableRule:DoNotDeleteRule"
"-allowUntrusted")
$command = "& '$deployCommand' --% $depArgs"
& $ExecutionContext.InvokeCommand.NewScriptBlock($command)
and here is the starter.ps1 triggered in above:
param([switch] $fg)
$scheduledJobName = "starter_v1"
$localPath = (Get-Location).Path
$logfile = "c:\temp\starterlog.txt"
function startBGJob() {
try {
Get-ScheduledJob -Name $scheduledJobName -ErrorAction Stop
"[BGJ] Found job $scheduledJobName, starting."
# no way in PS to start the job as actual scheduled task
schtasks /run /tn "\Microsoft\Windows\PowerShell\ScheduledJobs\$scheduledJobName"
} catch {
"[BGJ] Job not found, creating and starting new"
$jobsb = {
param($lp, $logfile);
& "$lp\starter.ps1" -fg | out-file $logfile
}
$option = New-ScheduledJobOption -RunElevated
Register-ScheduledJob -name $scheduledJobName -ScriptBlock $jobsb -ArgumentList ($localPath, $logfile) -ScheduledJobOption $option -RunNow
}
}
function Main() {
if ($fg -eq $true) {
# actual work done here
} else {
startBGJob
}
}
Main
I had to extract some things from those, so typos may be within.