Powershell will not start or stop Windows service with nssm - powershell

i have a script made in powershell and i am using nssm to create as a service to be executed every "x" time, however when starting the service it generates error and does not execute.
I have full administrator rights and I even tried to run PowerShell as an administrator without success.
If I run the script directly it works, however using nssm it is not working.
The error that happens is this:
Start-Service: Service 'nice (nice)' start failed.
At C: \ Program Files \ NICE Systems \ nssm.ps1: 10 char: 14
Start-Service <<<< $ serviceName
CategoryInfo: OpenError: (System.ServiceProcess.ServiceController: ServiceController) [Start-Service],
ServiceCommandException
FullyQualifiedErrorId: StartServiceFailed, Microsoft.PowerShell.Commands.StartServiceCommand
nssm.ps1
$nssm = (Get-Command nssm.exe).Definition
$serviceName = 'nice'
$powershell = (Get-Command powershell.exe).Definition
$scriptPath = 'C:\Program Files\NICE Systems\script_delecao.ps1'
$arguments = '-ExecutionPolicy Bypass -NoProfile -File "{0}"' -f $scriptPath
& $nssm install $serviceName $powershell $arguments
& $nssm status $serviceName
Start-Service $serviceName
Get-Service $serviceName
script_delecao.ps1
$logPath = "C:\Program Files\NICE Systems\Logs\*\Archive\*"
# -------------------------------------------------------------------------------------------
# SET $NDAYS WITH THE NUMBER OF DAYS TO KEEP IN LOG FOLDER.
$nDays = 180
# -------------------------------------------------------------------------------------------
# SET $EXTENSIONS WITH THE FILE EXTENSION TO DELETE.
# YOU CAN COMBINE MORE THAN ONE EXTENSION: "*.LOG, *.TXT,"
$Extensions = "*.log*"
# -------------------------------------------------------------------------------------------
# PAY ATTENTION! IF YOU COMBINE MORE THAN ONE LOG PATH AND EXTENSIONS,
# MAKE SURE THAT YOU ARE NOT REMOVING FILES THAT CANNOT BE DELETED
# -------------------------------------------------------------------------------------------
$PathDelete = "C:\Program Files\NICE Systems\Delecoes"
while ($true) {
If(!(test-path $PathDelete))
{
New-Item -ItemType Directory -Force -Path $PathDelete
}
$LogDate = (Get-Date).ToString("dd_MM_yyyy")
$DateTime = (Get-Date).ToString("yyy-MM-ddThh:mm:ss")
$Files = Get-Childitem $LogPath -Include $Extensions -Recurse | Where `
{$_.LastWriteTime -le (Get-Date).AddDays(-$nDays)}
foreach ($File in $Files)
{
if ($File -ne $NULL)
{
$Log = $DateTime + " - O arquivo " + $File + " foi deletado "
$Log | Out-File -Append $PathDelete\DeleteLogFile_$LogDate.log
Remove-Item $File.FullName| out-null
}
}
# Add a sleep at the end of the loop to prevent the script from eating
# too much CPU time
$Log = $DateTime + " FINAL DO ARQUIVO "
$Log | Out-File -Append $PathDelete\DeleteLogFile_$LogDate.log
Start-Sleep -Seconds 300
}

I believe I have a similar scenario where I cannot back-up Bamboo file system while it's running. My back-up executes from a rundeck server via Remote PowerShell, and even though the user has local admin rights it cannot stop and start services using NSSM. So I use this function to run the command elevated
ELEVAT "nssm stop bamboo"
tar --exclude=./logs --exclude=./temp --exclude=*.log --exclude=*.jar --verbose -czf E:\dropfolder\bamboo-home.tar.gz --directory=E:\bamboo-home .
ELEVAT "nssm start bamboo"
the function itself...
function ELEVAT ($command) {
$scriptBlock = [scriptblock]::Create($command)
configuration elevated {
Import-DscResource -ModuleName 'PSDesiredStateConfiguration'
Set-StrictMode -Off
Node localhost {
Script execute {
SetScript = $scriptBlock
TestScript = {
if (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Verbose "Verified Elevated Session"
return $false
} else {
Write-Verbose "Not an Elevated Session!"
exit 9996
}
}
GetScript = { return #{ 'Result' = 'RUN' } }
}
}
}
$mof = elevated
Start-DscConfiguration ./elevated -Wait -Verbose -Force
if ( $error ) { Write-Host "[ELEVAT][WARN] `$Error[] = $Error" ; $Error.clear()
}
}

Related

Problem with downloading language local experience file using Powershell script

I use a fantastic script to download LXP files from microsoft and install them. This script works fine with languages like: en-us, pl-pl, zh-tw, zh-cn, fr-fr, ja-jp and maybe more BUT there is a strange issue with languages like italian (it-it), spanish (es-es) and portuguese (pt-pt). The script shows an error that the Invoke-WebRequest can't connect to the server and the rest of script fails because next variables are empty. Maybe sb will have an idea how to solve it.
There is a script I am talking about with es-es language:
# the language we want as new default
$language = "es-ES"
Start-Transcript -Path "$env:TEMP\LXP-SystemContext-Installer-$language.log" | Out-Null
# https://www.microsoft.com/de-de/p/deutsch-local-experience-pack/9p6ct0slw589
$applicationId = "9NWVGWLHPB1Z" # spanish
$webpage = Invoke-WebRequest -UseBasicParsing -Uri "https://bspmts.mp.microsoft.com/v1/public/catalog/Retail/Products/$applicationId/applockerdata"
$packageFamilyName = ($webpage | ConvertFrom-JSON).packageFamilyName
$skuId = 0016
$geoId = 217 # Spain
$inputLanguageID = "0c0a:0000040a" # es-es
# custom folder for temp scripts
"...creating custom temp script folder"
$scriptFolderPath = "$env:SystemDrive\ProgramData\CustomTempScripts"
New-Item -ItemType Directory -Force -Path $scriptFolderPath
"`n"
$languageXmlPath = $(Join-Path -Path $scriptFolderPath -ChildPath "MUI.xml")
# language xml definition for intl.cpl call to switch the language 'welcome screen' and 'new user' defaults
$languageXml = #"
<gs:GlobalizationServices xmlns:gs="urn:longhornGlobalizationUnattend">
<!-- user list -->
<gs:UserList>
<gs:User UserID="Current" CopySettingsToDefaultUserAcct="true" CopySettingsToSystemAcct="true"/>
</gs:UserList>
<!-- GeoID -->
<gs:LocationPreferences>
<gs:GeoID Value="$geoId"/>
</gs:LocationPreferences>
<!-- UI Language Preferences -->
<gs:MUILanguagePreferences>
<gs:MUILanguage Value="$language"/>
</gs:MUILanguagePreferences>
<!-- system locale -->
<gs:SystemLocale Name="$language"/>
<!-- input preferences -->
<gs:InputPreferences>
<gs:InputLanguageID Action="add" ID="$inputLanguageID" Default="true"/>
</gs:InputPreferences>
<!-- user locale -->
<gs:UserLocale>
<gs:Locale Name="$language" SetAsCurrent="true" ResetAllSettings="false"/>
</gs:UserLocale>
</gs:GlobalizationServices>
"#
$userConfigScriptPath = $(Join-Path -Path $scriptFolderPath -ChildPath "UserConfig.ps1")
# we could encode the complete script to prevent the escaping of $, but I found it easier to maintain
# to not encode. I do not have to decode/encode all the time for modifications.
$userConfigScript = #"
`$language = "$language"
Start-Transcript -Path "`$env:TEMP\LXP-UserSession-Config-`$language.log" | Out-Null
`$geoId = $geoId
"explicitly register the LXP in current user session (Add-AppxPackage -Register ...)"
`$appxLxpPath = (Get-AppxPackage | Where-Object Name -Like *LanguageExperiencePack`$language).InstallLocation
Add-AppxPackage -Register -Path "`$appxLxpPath\AppxManifest.xml" -DisableDevelopmentMode
# important for regional change like date and time...
"Set-WinUILanguageOverride = `$language"
Set-WinUILanguageOverride -Language `$language
"Set-WinUserLanguageList = `$language"
#Set-WinUserLanguageList `$language -Force
# changed handling due to new knowledge :-)
# https://oliverkieselbach.com/2021/01/13/company-portal-stuck-in-a-different-language/
`$OldList = Get-WinUserLanguageList
`$UserLanguageList = New-WinUserLanguageList -Language `$language
`$UserLanguageList += `$OldList | where { `$_.LanguageTag -ne `$language }
"Setting new user language list:"
`$UserLanguageList | select LanguageTag
""
"Set-WinUserLanguageList -LanguageList ..."
Set-WinUserLanguageList -LanguageList `$UserLanguageList -Force
"Set-WinSystemLocale = `$language"
Set-WinSystemLocale -SystemLocale `$language
"Set-Culture = `$language"
Set-Culture -CultureInfo `$language
"Set-WinHomeLocation = `$geoId"
Set-WinHomeLocation -GeoId `$geoId
Stop-Transcript -Verbose
"#
Set-WinUserLanguageList -LanguageList $language -Force
$userConfigScriptHiddenStarterPath = $(Join-Path -Path $scriptFolderPath -ChildPath "UserConfigHiddenStarter.vbs")
$userConfigScriptHiddenStarter = #"
sCmd = "powershell.exe -ex bypass -file $userConfigScriptPath"
Set oShell = CreateObject("WScript.Shell")
oShell.Run sCmd,0,true
"#
"...set reg key: BlockCleanupOfUnusedPreinstalledLangPacks = 1"
& REG add "HKLM\Software\Policies\Microsoft\Control Panel\International" /v BlockCleanupOfUnusedPreinstalledLangPacks /t REG_DWORD /d 1 /f /reg:64
"`n"
$packageName = "Microsoft.LanguageExperiencePack$language"
# check for installed Language Experience Pack (LXP), maybe already installed?
$status = $(Get-AppxPackage -AllUsers -Name $packageName).Status
# create CIM session here as we need it for Store updates as well
$session = New-CimSession
try {
if ($status -ne "Ok")
{
try {
$namespaceName = "root\cimv2\mdm\dmmap"
$omaUri = "./Vendor/MSFT/EnterpriseModernAppManagement/AppInstallation"
$newInstance = New-Object Microsoft.Management.Infrastructure.CimInstance "MDM_EnterpriseModernAppManagement_AppInstallation01_01", $namespaceName
$property = [Microsoft.Management.Infrastructure.CimProperty]::Create("ParentID", $omaUri, "string", "Key")
$newInstance.CimInstanceProperties.Add($property)
$property = [Microsoft.Management.Infrastructure.CimProperty]::Create("InstanceID", $packageFamilyName, "String", "Key")
$newInstance.CimInstanceProperties.Add($property)
$flags = 0
$paramValue = [Security.SecurityElement]::Escape($('<Application id="{0}" flags="{1}" skuid="{2}"/>' -f $applicationId, $flags, $skuId))
$params = New-Object Microsoft.Management.Infrastructure.CimMethodParametersCollection
$param = [Microsoft.Management.Infrastructure.CimMethodParameter]::Create("param", $paramValue, "String", "In")
$params.Add($param)
# we create the MDM instance and trigger the StoreInstallMethod to finally download the LXP
$instance = $session.CreateInstance($namespaceName, $newInstance)
$result = $session.InvokeMethod($namespaceName, $instance, "StoreInstallMethod", $params)
"...Language Experience Pack install process triggered via MDM/StoreInstall method"
}
catch [Exception] {
write-host $_ | out-string
$exitcode = 1
}
}
if (($result.ReturnValue.Value -eq 0) -or ($status -eq "Ok")) {
if ($status -ne "Ok")
{
"...busy wait until language pack found, max 15 min."
$counter=0
do {
Start-Sleep 10
$counter++
# check for installed Language Experience Pack (LXP)
$status = $(Get-AppxPackage -AllUsers -Name $packageName).Status
} while ($status -ne "Ok" -and $counter -ne 90) # 90x10s sleep => 900s => 15 min. max wait time!
}
# print some LXP package details for the log
Get-AppxPackage -AllUsers -Name $packageName
if ($status -eq "Ok") {
"...found Microsoft.LanguageExperiencePack$language with Status=Ok"
"...trigger install for language FOD packages"
# add Windows capabilities / FODs to avoid UAC dialog after restart
# Parameter -Online will reach out to Windows Update to get the latest correct source files
Get-WindowsCapability -Online | Where-Object Name -ilike "Language.*~~~$($language)~*" | ForEach-Object {
if ($_.State -ine "Installed") {
"Adding windows capability '$($_.Name)'..."
$_ | Add-WindowsCapability -Online | Out-Null
}
else {
"Windows capability '$($_.Name)' is already installed.`n"
}
}
"`n"
"...trigger language change for current user session via ScheduledTask = LXP-UserSession-Config-$language"
Out-File -FilePath $userConfigScriptPath -InputObject $userConfigScript -Encoding ascii
Out-File -FilePath $userConfigScriptHiddenStarterPath -InputObject $userConfigScriptHiddenStarter -Encoding ascii
# REMARK: usag of wscript as hidden starter may be blocked because of security restrictions like AppLocker, ASR, etc...
# switch to PowerShell if this represents a problem in your environment.
$taskName = "LXP-UserSession-Config-$language"
$action = New-ScheduledTaskAction -Execute "wscript.exe" -Argument "$userConfigScriptHiddenStarterPath"
$trigger = New-ScheduledTaskTrigger -AtLogOn
$principal = New-ScheduledTaskPrincipal -UserId (Get-CimInstance –ClassName Win32_ComputerSystem | Select-Object -expand UserName)
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries
$task = New-ScheduledTask -Action $action -Trigger $trigger -Principal $principal -Settings $settings
Register-ScheduledTask $taskName -InputObject $task
Start-ScheduledTask -TaskName $taskName
Start-Sleep -Seconds 30
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false
# trigger 'LanguageComponentsInstaller\ReconcileLanguageResources' otherwise 'Windows Settings' need a long time to change finally
"...trigger ScheduledTask = LanguageComponentsInstaller\ReconcileLanguageResources"
Start-ScheduledTask -TaskName "\Microsoft\Windows\LanguageComponentsInstaller\ReconcileLanguageResources"
Start-Sleep 10
# change 'welcome screen' and 'new user' language defaults
"...trigger language change for welcome screen and new user defaults"
Out-File -FilePath $languageXmlPath -InputObject $languageXml -Encoding ascii
# check eventlog 'Microsoft-Windows-Internationl/Operational' for troubleshooting
& $env:SystemRoot\System32\control.exe "intl.cpl,,/f:`"$languageXmlPath`""
# trigger store updates, there might be new app versions due to the language change
"...trigger MS Store updates for app updates"
Get-CimInstance -Namespace "root\cimv2\mdm\dmmap" -ClassName "MDM_EnterpriseModernAppManagement_AppManagement01" | Invoke-CimMethod -MethodName "UpdateScanMethod"
$exitcode = 0
}
}
else {
$exitcode = 1
}
"...cleanup and finish"
try {
$session.DeleteInstance($namespaceName, $instance) | Out-Null
Remove-CimSession -CimSession $session
} catch {}
Remove-Item -Path $scriptFolderPath -Force -Recurse -ErrorAction SilentlyContinue
}
catch [Exception] {
# maybe a left over to clean, but prevent aditional errors and set exitcode
try {
$session.DeleteInstance($namespaceName, $instance) | Out-Null
} catch {}
$exitcode = 1
}
if ($exitcode -eq 0) {
$installed = 1
}
else {
$installed = 0
}
# IME app install runs by default in 32-bit so we write explicitly to 64-bit registry
& REG add "HKLM\Software\MyIntuneApps" /v "SetLanguage-$language" /t REG_DWORD /d $installed /f /reg:64 | Out-Null
Stop-Transcript -Verbose
exit $exitcode
I tried to find my mistakes in ID etc also checking if the requested language is available (and it is!). I tried to run the invoke-webrequest alone and it also works.
The error msg:
PS>TerminatingError(Invoke-WebRequest): "Unable to connect to remote server"
Invoke-WebRequest : Unable to connect to remote server
At C:\Windows\IMECache\ffa6ea3b-604e-41c3-98b9-dd30e2f9c714_1\languagechange.ps1:47 char:12
+ $webpage = Invoke-WebRequest -UseBasicParsing -Uri "https://bspmts.mp ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExcep
tion
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Invoke-WebRequest : Unable to connect to remote server
At C:\Windows\IMECache\ffa6ea3b-604e-41c3-98b9-dd30e2f9c714_1\languagechange.ps1:47 char:12
+ $webpage = Invoke-WebRequest -UseBasicParsing -Uri "https://bspmts.mp ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc
eption
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
ConvertFrom-Json : Cannot bind argument to parameter 'InputObject' because it is null.
At C:\Windows\IMECache\ffa6ea3b-604e-41c3-98b9-dd30e2f9c714_1\languagechange.ps1:48 char:34
+ $packageFamilyName = ($webpage | ConvertFrom-JSON).packageFamilyName
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertFrom-Json], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFromJs
onCommand
ConvertFrom-Json : Cannot bind argument to parameter 'InputObject' because it is null.
At C:\Windows\IMECache\ffa6ea3b-604e-41c3-98b9-dd30e2f9c714_1\languagechange.ps1:48 char:34
+ $packageFamilyName = ($webpage | ConvertFrom-JSON).packageFamilyName
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertFrom-Json], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFrom
JsonCommand

Set-Content : The process cannot access the file 'C:\WINDOWS\system32\drivers\etc\hosts' because it is being used by another process

I have the following PowerShell script:
param([switch]$Elevated)
function Test-Admin
{
$currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
$currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}
if ((Test-Admin) -eq $false) {
if ($elevated) {
# tried to elevate, did not work, aborting
} else {
Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -noexit -file "{0}" -elevated ' -f ($myinvocation.MyCommand.Definition))
}
exit
}
function UpdateHosts {
param ($hostName)
Write-Host $hostName
try {
$strHosts = (Get-Content C:\WINDOWS\system32\drivers\etc\hosts -Raw)
if([string]::IsNullOrEmpty($strHosts)) {
Write-Error "Get-Content hosts empty"
exit
}
} catch {
Write-Error "Unable to read hosts file"
Write-Error $_
exit
}
try {
$strHosts -replace "[\d]+\.[\d]+\.[\d]+\.[\d]+ $hostName","$ipAddress $hostName" | Set-Content -Path C:\WINDOWS\system32\drivers\etc\hosts
} catch {
Write-Error "Unable to write hosts file"
Write-Error $_
exit
}
}
$ipAddress = "127.0.0.1"
UpdateHosts -hostName local.pap360.com
Sometimes, when I run it, I get the following error:
Set-Content : The process cannot access the file 'C:\WINDOWS\system32\drivers\etc\hosts' because it is being used by another process.
When I open up C:\WINDOWS\system32\drivers\etc\hosts in Notepad it's then blank. ie. all the data I had in it is wiped.
My question is... how can I prevent this from happening?
Like if Set-Content can't access the hosts file to write to it then how is it able to wipe it's contents? And why isn't the catch block working?
Here's the full error:
Set-Content : The process cannot access the file 'C:\WINDOWS\system32\drivers\etc\hosts' because it is being used by
another process.
At C:\path\to\test.ps1:36 char:92
+ ... $hostName" | Set-Content -Path C:\WINDOWS\system32\drivers\etc\hosts
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (C:\WINDOWS\system32\drivers\etc\hosts:String) [Set-Content], IOException
+ FullyQualifiedErrorId : GetContentWriterIOError,Microsoft.PowerShell.Commands.SetContentCommand
I also don't understand why it's so intermittent. Is there some Windows process that opens the hosts file up for 1s once a minute or some such?
First of all, check if your Firewall or AV software isn't restricting access to the file.
If that is not the case and 'some' other process is currently locking the hosts file, perhaps add a test before reading or writing the file can help:
function Test-LockedFile {
param (
[parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[Alias('FullName', 'FilePath')]
[ValidateScript({Test-Path $_ -PathType Leaf})]
[string]$Path
)
$file = [System.IO.FileInfo]::new($Path)
# old PowerShell versions use:
# $file = New-Object System.IO.FileInfo $Path
try {
$stream = $file.Open([System.IO.FileMode]::Open,
[System.IO.FileAccess]::ReadWrite,
[System.IO.FileShare]::None)
if ($stream) { $stream.Close() }
return $false # file is not locked
}
catch {
return $true # file is locked
}
}
Then use like this:
function UpdateHosts {
param ($hostName)
Write-Host $hostName
$path = 'C:\WINDOWS\system32\drivers\etc\hosts'
# test if the file is readable/writable
# you can of course also put this in a loop to keep trying for X times
# until Test-LockedFile -Path $path returns $false.
if (Test-LockedFile -Path $path) {
Write-Error "The hosts file is currently locked"
}
else {
try {
$strHosts = (Get-Content $path -Raw -ErrorAction Stop)
if([string]::IsNullOrEmpty($strHosts)) {
Write-Error "Get-Content hosts empty"
exit
}
}
catch {
Write-Error "Unable to read hosts file:`r`n$($_.Exception.Message)"
exit
}
try {
$strHosts -replace "[\d]+\.[\d]+\.[\d]+\.[\d]+\s+$hostName", "$ipAddress $hostName" |
Set-Content -Path $path -Force -ErrorAction Stop
}
catch {
Write-Error "Unable to write hosts file:`r`n$($_.Exception.Message)"
exit
}
}
}

Executing XMLA with AMO PowerShell does not create measures

I wrote a PowerShell script to automate deployment of SSAS Cubes. I use the Deployment Wizard to generate an XMLA file and then PowerShell AMO command to deploy it. However, when I run it the tabular database gets created but all measures are missing. Running the same XMLA from SQL Management Studio or using Invoke-ASCmd produce the correct database with all measures in it. Am I missing an option or something in the "Invoke" command?
[CmdletBinding()]
Param(
# InputDir is required
[Parameter(Mandatory=$True,Position=1)]
[string]$InputDir,
# Server is optional
[Parameter(Mandatory=$False,Position=2)]
[string]$Server=$env:computername
)
# Output execution parameters.
"Executing with the following parameters:"
" InputDir: $InputDir"
" AS Database Server: $Server`n"
$XmlaDir = Resolve-Path($InputDir)
$Xmla = Join-Path -Path $XmlaDir -ChildPath '\Model.xmla'
$ASFiles = Get-ChildItem -Recurse -Path $InputDir -Filter *.asdatabase
$Count = $ASFiles.Count
If($Count -ne 1)
{
Write-Host("`ERROR: Count asdatabase file(s) found at $inputdir")
Exit 1
}
$ASDatabase = $ASFiles[0].FullName
Write-Host("`nUsing $ASDatabase for deployment.")
Write-Host("`nAttempting to create $Xmla ...`n")
# Use Analysis Services Deployment Utility to generate XMLA file from
.asdatabase file
$Script:ASDeployWizard = "E:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\ManagementStudio\Microsoft.AnalysisServices.Deployment.exe
"
$Arguments = #("`"$ASDatabase`"", "/s", "/o:`"$Xmla`"")
Start-Process -FilePath $Script:ASDeployWizard -ArgumentList $Arguments -Wait
If ((-Not $?) -Or -Not (Test-Path $Xmla))
{
"Cannot generate deployment descriptor. Deployment aborted."
Exit 1
}
Write-Host("XMLA deployment descriptor generated.`n")
Try {
Import-Module SQLPS -DisableNameChecking
# Deploy Cube
"Invoking deployment script. This may take several minutes...`n"
$AS = New-Object Microsoft.AnalysisServices.Server
$AS.connect($Server)
$CubeDescriptor = [string](Get-Content $Xmla)
$Results = $AS.Execute($CubeDescriptor)
Foreach ($r in $Results) {
$r.Messages.Description
}
"Done.`n"
} Catch {
Write-Host($_.Exception.GetType().FullName + "`n" + $_.Exception.Message + "`n")
Write-Host("Deployment FAILED.`n")
}
Exit 0

Powershell Msdeploy command error

I am trying to invoke Msdeploy in powershell , which is part of a teamcity build task.
My script is like this below
$folderName = "packageTmp"
$packagePath = (gci -path %teamcity.build.checkoutDir%\extract -filter $foldername -Recurse | Select-Object -Expand FullName) |Out-String
$azureSite ="%azureSite%"
$azurePublishUrl = "%azurePublishUrl%"
$azureUsername ="%azureUsername%"
$azurePassword = "%azurePassword%"
$localPath =$packagePath
$server ="https://$azurePublishUrl/msdeploy.axd?site=$azureSite,UserName=$azureUsername,Password=$azurePassword,AuthType=Basic"
$remotePath="%azureSite%"
$env:Path += ";C:\Program Files\IIS\Microsoft Web Deploy V3"
function PushToTarget() {
param([string]$server, [string]$remotePath, [string]$localPath)
cmd.exe /C $("msdeploy.exe -verb:sync -source:contentPath=`"{0}`" -dest:computerName=`"{1}`",contentPath=`"{2}`" -whatif" -f $localPath, $server, $remotePath )
}
echo "Server: " $server
echo "remote path: " $remotePath
echo "local path: " $localPath
PushToTarget "$server" "$remotePath" "$localPath"
while i run this i get following error , error stack follows
Error: A '-dest' argument must be specified with the 'sync' verb.
As error says i have included sync keyword already.
what i am doing wrong and how can i rectify it ?
i tried to use following solutions
solution1
stackoverflow post
I don't see a problem in your script but PS can be particular.
Here is how the new ASP.NET 5 PS-based deployment executes MSDeploy.exe maybe this will work better for you:
$webrootOutputFolder = (get-item (Join-Path $packOutput $webroot)).FullName
$publishArgs = #()
$publishArgs += ('-source:IisApp=''{0}''' -f "$webrootOutputFolder")
$publishArgs += ('-dest:IisApp=''{0}'',ComputerName=''{1}'',UserName=''{2}'',Password=''{3}'',IncludeAcls=''False'',AuthType=''Basic''{4}' -f
$publishProperties['DeployIisAppPath'],
(Get-MSDeployFullUrlFor -msdeployServiceUrl $publishProperties['MSDeployServiceURL']),
$publishProperties['UserName'],
$publishPwd,
$sharedArgs.DestFragment)
$publishArgs += '-verb:sync'
$publishArgs += '-enableLink:contentLibExtension'
$publishArgs += $sharedArgs.ExtraArgs
$command = '"{0}" {1}' -f (Get-MSDeploy),($publishArgs -join ' ')
if (! [String]::IsNullOrEmpty($publishPwd)) {
$command.Replace($publishPwd,'{PASSWORD-REMOVED-FROM-LOG}') | Print-CommandString
}
Execute-Command -exePath (Get-MSDeploy) -arguments ($publishArgs -join ' ')

Get an progress output for Export-VM

I recently created a script that's able to create a chosen number of Hyper-V VMs from a "template", by exporting one VM and import it with different ids and names.
Everything is working smoothly, but the export takes quite some time. Is there any way to get an progress output from the export-vm? If I look in the hyper-v command center, I see that my VM is exported after i started the script, and it has a progress value, too, so somehow there seems to be a way to get the current progress...
It would also be nice to have a progress output for Import-VM, too, but that's not really important.
If you are interested, here is my current script. I know that the hard-coded paths and other ascpects aren't really nice, so please don't tell me anything about code style or something like this. First comes a working script, then comes nice code.
param(
[int]$Anzahl = 0,
[string]$BasisVM = 'Schulung',
[string]$ExportDir = 'C:\VMConf\Export\',
[string]$ExportConf = 'Schulung\Virtual Machines\0D444AF2-3E63-4ACF-867E-34440AA99C42.xml',
[string]$VMDir = 'C:\VMs\',
[string]$VMNamePrefix = 'Schulung'
)
if ($Anzahl -eq 0) {
$Anzahl = Read-Host "Bitte Anzahl der benötigten VMs eingeben"
}
"`nStarte Export der Vorlage..."
if (-Not(Test-Path $ExportDir)) {
New-Item -ItemType directory -Path $ExportDir | out-null
}
Export-VM -Name $BasisVM -Path $ExportDir
"Abgeschlossen.`n"
if (Test-Path $VMDir) {
$err = $null
$i = 1
while (-not($err)) {
if ($i -gt 1) {
"Alte VM Nummer $($i - 1) wurde gelöscht."
}
Remove-VM -Name $($VMNamePrefix + ("{0:D2}" -f $i)) -Force -ErrorVariable err -ErrorAction SilentlyContinue
$i++
}
Remove-Item -r $VMDir | out-null
New-Item -ItemType directory -Path $VMDir | out-null
}
"`n$Anzahl VMs werden erstellt..."
for ($i=1; $i -le $Anzahl; $i++) {
"`tErstelle VM Nummer $i..."
$name = ($VMNamePrefix + ("{0:D2}" -f $i))
$path = ($VMDir + $name)
$VM = Import-VM -Path $($ExportDir + $ExportConf) -VhdDestinationPath $($path + "/Virtual Hard Discs") -VirtualMachinePath $path -Copy -GenerateNewId
Rename-VM -VM $VM -NewName $name
"`t$VM Nummer $i wurde erzeugt."
}
"Abgeschlossen.`n"
"Aufräumen..."
if (Test-Path $ExportDir) {
Remove-Item -r $ExportDir | out-null
}
"Abgeschlossen."
You could start the export (and even imports) as a background job and then log the progress of the job. Sample code:
$ExportJob = Export-VM -Name $BasisVM -Path $ExportDir -AsJob;
while( $ExportJob.State -eq "Running" -or $ExportJob.State -eq "NotStarted")
{
Write-Output ("[Export] " + $($ExportJob.Progress.PercentComplete) + "% complete");
sleep(5);
}
if($ExportJob.State -ne "Completed")
{
Write-Error ("Export Job did not complete: " +$ExportJob.State);
throw $ExportJob.Error;
}