Manage IIS Remotely through TFS2015 - powershell

Currently using TFS 2015 update 3 for deployments and I have added "PowerShell on target machine" task, which calls for PowerShell script saved on IIS server to stop website before deployments:
icm -ComputerName $server -ScriptBlock {Import-Module WebAdministration; Stop-Website -Name $app}
with session variables as: $server = abc.xyz.com, $app = DefaultWebSite
The error I get is:
The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: Cannot validate argument on parameter 'Name'. The argument is null. Provide a valid value for the argument, and then try running the command again.”
The same script works if I hard code the server & application name.

With a scriptblock, you can't use the variables from your script scope unless you use param with an argument list or with PowerShell 3+ use the using: scope modifier.
icm -ComputerName $server -ScriptBlock {Import-Module WebAdministration; Stop-Website -Name $using:app}

Related

$using in powershell to execute a script on remote machine

I am trying to run a particular script out on a remote machine
$script:remoteSession = New-PSSession -ComputerName $script:currentnode -Credential $script:cred -ErrorAction Stop
Invoke-Command -Session $script:remoteSession -ScriptBlock {
. "$($using:RemotedriveLetter):\SilentInstaller\configureWindows.ps1" -driveLetter $using:RemotedriveLetter
}
but the above code gives the below error
"A Using variable cannot be retrieved. A Using variable can be used only with Invoke-Command, Start-Job, or InlineScript in the script workflow. When it is used with Invoke-Command, the Using variable is valid only if the script block is invoked on a remote computer."

Passing a script with Invoke-Command

I have a script which uses a set of cmdlets which are on a Windows 2012 Domain Controller. I am using a Windows 7 machine which does not have these (Get-DHCPServerV4Lease for example).
At first I created a script module and applied it like this:
Invoke-Command -Computername <Server> -scriptblock {Get-ComputerStatus}
I then get an error message stating that the cmdlet is not recognised. Then I just converted it into a straight-forward PS1 script:
icm -cn <server> -FilePath .\ComputerInfo.ps1 -ArgumentList "Computer"
After running this I get an error saying that the various cmdlets I am using in the script are not recognised.
Get-DnsServerResourceRecord : The term 'Get-DnsServerResourceRecord'
is not recognized as the name of a cmdlet,......
How can I run my script against a DC using Invoke-Command?
Adding to Frode F's comment, you need to first install the corresponding module on the target machine, which you specify as <server> in your Invoke-Command cmdlet. Then within your script, you need to import that module before you can execute cmdlets which are available via that module.
Invoke-Command -Computername <Server> -scriptblock
{
Import-Module <moduleName> -ErrorAction SilentlyContinue
Get-ComputerStatus
#<Any othe cmdlets from the module>
}

PowerShell Invoke-Command on an advanced function

I have an advanced function Copy-FilesHC that is available in a module file. This function copies some files from the Source to the Destination folder and generates some output for in a log file.
The function works fine locally:
Copy-FilesHC -Source $Src -Destination $Des *>> $Log
It also works on a remote machine:
# For remote use we need to make it available first
Import-Module (Get-Command Copy-FilesHC).ModuleName
Invoke-Command -Credential $Cred -ComputerName $Host -ScriptBlock ${Function:Copy-FilesHC} -ArgumentList $LocalSrc, $LocalDes
However, I can't seem to figure out how I can have it pass the output to a log file like in the first command. When I try the following, it fails:
Invoke-Command -Credential $Cred -ComputerName $Host -ScriptBlock ${Function:Copy-FilesHC *>> $Log} -ArgumentList $LocalSrc, $LocalDes
Invoke-Command : Cannot validate argument on parameter 'ScriptBlock'. The argument is null. Provide a vali
d value for the argument, and then try running the command again.
As indicated here I thought the $ sign for the ScriptBlock was incorrect. But this way I don't need to put my advanced function in a ScriptBlock to copy it over as it now happens automatically while it's only available within the module. So I just need to find out how to capture the output in the log file.
Thank you for your help.
Found the solution just a few minutes ago:
# For remote use we need to make it available first
Import-Module (Get-Command Copy-FilesHC).ModuleName
Invoke-Command -Credential $Cred -ComputerName $Host -ScriptBlock ${Function:Copy-FilesHC} -ArgumentList $LocalSrc, $LocalDes *>> $Log

Mapping drive on a remote machine in powershell

I am working on a remote machine from my desktop and I have the following script :
Invoke-Command -computername $name -authentification default
-credential $creds1
-scriptblock {net use \share $password2 /user:otherdomain\otheruser}
Then I get A specified logon session does not exist. It may have already been terminated. This thing is frustrating because if I run net use \\share $password2 /user:otherdomain\otheruser directly on the remote machine it works perfectly. Is there a workaround or did I miss something ?
You need to pass the variable $password2 into the script block, otherwise its value will be empty:
Invoke-Command -Computer $name ... -ScriptBlock {
net use \\host\share $args[0] /user:otherdomain\otheruser
} -ArgumentList $password2

Can the Invoke-Item cmdlet launch an executable with parameters?

I'm trying to install some custom Windows services using PowerShell, and I've been unable to run InstallUtil without getting the following error:
A positional parameter cannot be found that accepts argument ''
Here's what I've run that causes the error above:
Invoke-Command -ComputerName <remote machine> -ScriptBlock {Invoke-Item C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe "<path to service exe>"}
From the docs:
The Invoke-Item cmdlet performs the default action on the specified item.
I don't believe commandline arguments can be used with a default action.
However...
In this example, invoke-item shouldn't be necessary to invoke the executable.
Invoke-Command -ComputerName <remote machine> -ScriptBlock { C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe "<path to service exe>"}