Start-job resulting in null parameter - powershell

I'm trying to execute the following two lines of code in PowerShell v2.0 as a job, and am having trouble. I think I have the syntax right, but I can't get it to do what I think it should do, so I clearly am doing something wrong...
$report = <command line thing>
invoke-expression $report
These two lines work in PowerShell. But when I try to put it into a start-job command:
start-job -scriptblock {invoke-expression $report} -argumentlist $report | wait-job | receive-job
I get the following error:
Cannot bind argument to parameter 'Command' because it is null.
+ CategoryInfo : InvalidData: (:) [Invoke-Expression], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.InvokeExpre
ssionCommand
+ PSComputerName : localhost
I understand that error as saying that the argument I'm passing the invoke-expression is null, but, I'd thought that by passing $report in the -argumentlist param, it'd get through?

You cannot access $report directly unless you do:
-scriptblock {param($report) invoke-expression $report}
The param($report) part captures the $report variable passed in via -ArgumentList and makes it available for use inside the scriptblock.

Related

retrieve vhdx path from a remote server

hi i' m trying to retrieve the vhdx of specified vmname from the remote host server
here part of the script
$pth="C:\path\resize-vm"
$list=gc $pth\list-host.txt
foreach ($hostserver in $list) {
$vm=(Invoke-Command -ComputerName $hostserver -ScriptBlock {Get-VM}).VMName
Write-Host -NoNewline " here the vm installed in " $hostserver `r`n $vm
$vmname=Read-Host -Prompt "please chose a vmname to resize "
#the issue in the last line
$pathvhd=Invoke-Command -ComputerName $hostserver -ScriptBlock {(Get-VMHardDiskDrive -VMName $vmname).path}
When I launch this command $vmname="dc-kozhan"
I am getting this error
Cannot validate argument on parameter 'VMName'. The argument is null
or empty. Provide an argument that is not null or empty, and then try
the command again.
+ CategoryInfo : InvalidData: (:) [Get-VMHardDiskDrive], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.HyperV.PowerShell.Commands.GetVMHardDiskDrive
Command
+ PSComputerName : h-uludag-3
But when I specified dc-kozhan literally it work
PS C:\Users> Invoke-Command -ComputerName $hostserver -ScriptBlock {(Get-VMHardDiskDrive -VMName "DC-KOZAHAN")
.path}
V:\DC-KOZAHAN\DC-KOZAHAN-SYSTEM.vhdx
V:\DC-KOZAHAN\DC-KOZAHAN-DIRECTORY.vhdx
V:\DC-KOZAHAN\DC-KOZAHAN-SYSVOL.vhdx
V:\DC-KOZAHAN\DC-KOZAHAN-BACKUP.vhdx
does anyone have an idea why it does not work when it's specified in a variable
You need to understand how to pass arguments inside the scriptblock. The scope is different when you try to pass the value inside the scriptblock. As a result, $VMname is becoming null in your first statement.
Kindly change your existing Invoke-command statement to the below one:
Invoke-Command -ComputerName $hostserver -ScriptBlock {Param([string]$vmname)(Get-VMHardDiskDrive -VMName $vmname)} -ArgumentList $vmname
Also, my suggestion for you to read about the argumentlist in powershell in case invoke-command
Hope it helps.

invoking command while copying file over ps remote session fails

I have a question regarding how to properly structure a command with powershell.
Here is the code where I am having the issue.
$python_command =
{
param($script)
C:\Python27\python.exe $script
return $lastexitcode
}
$exit_code = Invoke-Command Copy-Item -Path C:\TestWare\jsonStuff.json -Destination
C:\Tunnel\Tunneling\jsonStuff.json -ToSession $Session - ScriptBlock $python_command -ArgumentList $exec_script
#Clean up
ExitWithCode($exit_code)
I'm assuming there there is an issue with how $exit_code is formatted because when it has this value
Copy-Item -Path C:\TestWare\jsonStuff.json -Destination C:\Tunnel\Tunneling\jsonStuff.json -ToSession $Session
there are no issues. I want the python command to run as well though. Can these commands be separated or how would they work as one? At the moment, I am getting the following error
Invoke-Command : A parameter cannot be found that matches parameter name 'Path'.
At C:\TestWare\run-test3.ps1:122 char:39
+ $exit_code = Invoke-Command Copy-Item -Path C:\TestWare\ ...
+ ~~~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-Command], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.InvokeCommandCommand
Any ideas on how to fix? I am on Powershell version 5 as well.
(EDIT) Here is my ExitWithCode function
function ExitWithCode
{
param
(
$exitcode
)
$host.SetShouldExit($exitcode)
exit
}
Invoke-Command has many different parameter sets, but just two fundamental ways to specify what command to invoke [remotely]:
via the -FilePath parameter, which expects a local script's path whose content is converted to a script block, which is then executed on the target machine.
via the -ScriptBlock parameter, which accepts a script block ({ ... })
Therefore, your attempt to pass a script block and a Copy-Item call directly cannot work.
It looks like you need 2 statements:
The Copy-Item call to copy something to session $Session with -ToSession.
The Invoke-Command statement to execute script block $python_command in session -Session $Session.
You could only get away with a single Invoke-Command call if you read the content of C:\TestWare\jsonStuff.json into memory and passed it as an argument to the script block and acted on that argument accordingly.

Property is empty when run through Invoke-Command

I am trying to individually monitor memory usage of a process (w3wp.exe) that has multiple instances of itself by filtering out a string found in the process' CommandLine property.
It works when I run this script locally:
$proc = (WmiObject Win32_Process -Filter "Name = 'w3wp.exe'" | Where-Object {$_.CommandLine -like "*SomeTextFromCl*"})
$id = $proc.ProcessId
$ws = [math]::round((Get-Process -Id $id).WS/1MB)
Write-Host $ws
However, when I try to run it remotely through Invoke-Command, I get an error telling that the Id property's value is null:
Cannot bind argument to parameter 'Id' because it is null.
+ CategoryInfo : InvalidData: (:) [Get-Process], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetProcessCommand
+ PSComputerName : RemoteServerName
My Invoke-Command syntax is:
Invoke-Command -ComputerName RemoteServerName -FilePath script.ps1 -Credential $mycredential
I'm sure it's simple but I'm back to PS after a long absence and I had a look around but couldn't find anything really helpful.
You are writing the answer to the console. You use the ps1 as a function, so you should use:
return $ws
instead of
write-host $ws

Powershell: Capture process id of a background job

I want to start a background job and capture it's process id into a .pid file. I was able to do it with the Start-Process as follows:
Start-Process C:\process.bat -passthru | foreach { $_.Id } > start.pid
Now, I want to wrap Start-Process with Start-Job, to run it in the background, like this:
$command = "Start-Process C:\process.bat -passthru | foreach { $_.Id }"
$scriptblock = [Scriptblock]::Create($command)
Start-Job -ScriptBlock $scriptblock
Unfortunatelly, this doesn't work and Receive-Job gives me the following error:
The term '.Id' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
+ CategoryInfo : ObjectNotFound: (.Id:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : localhost
Looks like it's something wrong with the $_ variable. Maybe it gets overwritten by the Start-Job.
Any clues greatly welcome!
That is because the variable is being expanded when using double quotes. If you want to keep the $_, then you need to use single quotes.
$command = 'Start-Process C:\process.bat -passthru | foreach { $_.Id }'
$scriptblock = [Scriptblock]::Create($command)
Start-Job -ScriptBlock $scriptblock

Removing multiple apps using powershell?

I want to create a script to remove a bunch of apps. I want to do this without user interaction once I've started the script.
This is the script I have so far; it doesn't work but hopefully you can see what I'm trying to do:
$App = Get-Content "C:\ListOFApps.txt" #get a list of apps
$args= '/quiet /norestart' # stores arguments for start-process
#gwmi gets the list of applications
# where selects just the apps im interested in removing
# start-process removes each app using msiexec with quiet and norestart options
gwmi win32_product | where { $App -contains $_.Name } | foreach {Start-Process 'msicexec /uninstall ' $_.IdentifyingNumber -ArgumentList $args -wait}'
This is the error that occurred:
ForEach-Object : Cannot process command because of one or more missing mandatory parameters: Process.
At C:\Users\username\AppData\Local\Temp\406f96a1-19b4-4e0d-af1b-b1ac2e32a6ba.ps1:3 char:62
+ gwmi win32_product| where { $App -contains $_.Name }| foreach <<<<
+ CategoryInfo : InvalidArgument: (:) [ForEach-Object], ParameterBindingException
+ FullyQualifiedErrorId : MissingMandatoryParameter,Microsoft.PowerShell.Commands.ForEachObjectCommand
$_.IdentifyingNumber
Start-Process 'msicexec /uninstall $_.IdentifyingNumber' -ArgumentList $args -wait
You have an unbalanced single quote on the end of the line with the "foreach." I suspect fixing that is only the start of your problems. Good luck.
Also you have the Process misspelled. Should be "msiexec" not "msicexec"