PowerShell Enter Session find path bug - powershell

I have some automation scripts, but I had to split them down because of what appears to be an interesting bug. I've stripped it to its simplest form below:
Enter-PSSession [SERVER]
cd D:\
If I run the above in one go, I get the below error
cd : Cannot find drive. A drive with the name 'D' does not exist.
However, if I run the lines individually, they run fine. I have tried putting a sleep in for a second, a pause line, but still no luck. Is anyone else aware of this, and the way around it?

Use Invoke-Command instead of enter-pssession.
Example:
$ReturnValue = Invoke-Command -ComputerName $Server -ScriptBlock{
Set-Location D:
# DO STUFF
Return $ReturnValue # Return your stuff
}

Related

Invoke remote .exe on server with argument list

I'm quite new to PowerShell and I'm hoping to ask a question about a command I'm attempting to run.
I've read and read everything I can find on this so apologies in advance if I'm asking the impossible or something dumb.
From the Windows CLI on the remote computer I can run the following command;
'c:\config-files\app.exe foo /o /last' the exe generates an output file by reading the foo files and saves it as foo.txt.
app.exe doesn't exist in within the c:\config-files, when running it
on the computer the app.exe is in the local env path within
c:\main-app.
- The above is one of the key points here which has been addressed in replies below.
I've tried adding a path to the exe but that seems to be ignored when performing the following;
path='c:\main-app\'
& Invoke-Command -ComputerName foo -ScriptBlock { & cmd.exe /c "c:\config-files\app" } -ArgumentList 'foo', '/last', '/o'
The above fails (probably obvious to some!)
If I run:
Invoke-Command foo -ScriptBlock {& cmd.exe /c "c:\main-app\app" }
The application runs in the PowerShell window, I just then seem to be unable to send Arguments to the application.
Invoke-Command -Computername foo -ScriptBlock {param ($myarg) "cmd.exe /c c:\main-app\app" $myarg } -ArgumentList 'foo', '/last', '/o'
This is the closest I think I've got, but it only reads one argument and that's being invoked from the documents and setting folder of the user attempting to execute the command and not that path of the binary.
I've tried many, many things to make this work but still don't seem to be able to get past this point, any help you can provide on this would be hugely appreciated.
Thanks in advance for your time.
You don't need cmd /c to invoke a console application (or any external program).
To access arguments passed to a script block from within the script, either use the automatic $Args array or declare parameters explicitly (as you've attempted with a single parameter).
You can use an array directly for passing its elements as individual arguments to an external program.
Invoke-Command -Computername foo -ScriptBlock {
c:\main-app\app $Args # invoke app.exe, passing arguments through
} -ArgumentList 'foo', '/last', '/o'
Additionally, you mention wanting to interpret arguments that are file paths as relative to the directory in which the application is located; the simplest solution is to use a Set-Location command first:
Invoke-Command -Computername foo -ScriptBlock {
Set-Location c:\main-app
.\app $Args
} -ArgumentList 'foo', '/last', '/o'

Loading .exe using PowerShell's Invoke-Command but exe does not read .config file

I am currently running an exe using the command below. The .exe runs fine, however, it doesn't read a config file associate with the program. I used this solution and it works. However, I would like to add something like "-WorkingDirectory" but using invoke-command. My end goal is to be able to run the exe as part of the tfs build using this script.
$file = 'C:\test.exe'
Invoke-Command -ScriptBlock { Param($myarg) & $file }
Pass the directory as an argument and use Set-Location to change the working directory inside the scriptblock:
$file = 'C:\test.exe'
Invoke-Command -ScriptBlock {
Param($exe, $wd)
Set-Location $wd
& $exe
} -ArgumentList $file, 'C:\working\directory'
With that said, there's no point in using Invoke-Command unless you want to run something on a different computer, with different credentials, or as a background job (or any combination of the aforementioned). Otherwise you could just as well change the directory and run the command directly:
Set-Location 'C:\working\directory'
& $file

Powershell Quotes Use asisstance

Need some expert help from you guru's out there (after 3 days of trying on my own lol). Here the portion of my script that's failing:
$yy=(get-date).Year
Invoke-Command -ComputerName *ipaddress* -Credential $moveitcred {
move-item -path "C:\iCApps\Dev\LetterGenerator\Letters\FTS\EDMS\*.txt" -destination "C:\Moveitft\Dev\Letters\Outbound" -force
Start-Process -FilePath "C:\Program Files\7-Zip\7z.exe" -ArgumentList "a -y C:\Moveitft\Dev\Letters\archive\Letters$yy_.zip C:\Moveitft\Dev\Letters\Outbound\*.*"
}
The move works fine. AND the zip works fine, except when I want to include the the year varible ($yy) in the argument list. Powershell doesn't want to populate the variable to adjust the file name. Either it bombs out citing a $null, or the job completes with just a blank where the $yy should be.
If i run just $yy from the prompt, it does return the correct year value, so I'm guessing it an improper use of quotes. But after 3 days of googling and trying various combinations on my own, I'm throwing in the towel. Any help/guidance would be so GREATLY appreciated :)
Change Letters$yy_.zip to either
Letters$($yy)_.zip
or
Letters${yy}_.zip.
Both of them work.
See: PowerShell subexpression and PowerShell variable names.
The problem is not about quoting is about variable scope. Inside the scriptblock you are executing, powershell knows nothing about the $yy var. So you need to tell it where to obtain the value. You could do that using the argumentList parameter. I see that you already are doing that but you are doing it wrong (move-item doesn't support that parameter). Look the following examples to grasp the concept, I think with that you will solve your problem:
# this is fine and simple
$yy="Hello scriptblocks!"
Invoke-Command -ScriptBlock { "whatever you want to run that use the an external var. $yy" } -ArgumentList $yy
# this is incorrect
Invoke-Command -ScriptBlock { "whatever you want to run that use the an external var. $yyCarefulWithThisText" } -ArgumentList $yy
# this shows how you could resolve the variable when you want to put text around
Invoke-Command -ScriptBlock { "whatever you want to run that use the an external var. $($yy)CarefulWithThisText" } -ArgumentList $yy
# output1: whatever you want to run that use the an external var. Hello scriptblocks!
# output2: whatever you want to run that use the an external var.
# output3: whatever you want to run that use the an external var. Hello scriptblocks!CarefulWithThisText
Tried the above, thank you! I think this might boil down to powershell version. I'm trying to execute this on a server running powershell v2.0, against another 2012 Server.
I've shortened down the code to just the line in question (so I can "F8" it to test the results) Here it is:
Invoke-Command -ComputerName ipaddress -Credential $moveitcred {
Start-Process -FilePath "C:\Program Files\7-Zip\7z.exe" -argumentlist "a -y C:\Moveitft\Dev\Letters\archive\Letters${yy}.zip C:\Moveitft\Dev\Letters\Outbound*.*"
}
Both of your suggestions "work", in that the command processes, however its still not reading the variable correctly. Here's what I get as a resultant .zip
The reason I'm thinking its powershell, is becuase if I copy/paste the same command into powershell v4.0 on my own production machine, you can instantly see by the color coding that the "$yy" is being considered a variable because it turns red - and then the code works ok on from my PS4.0 machine.
On the PSv2.0 server i'm trying to get this to run from, that same line for "-argumentlist" appears all maroon/brown - including the $yy portion. So its kind of a hint whether it will work or not for me.

what is wrong with this Start-Job command?

Edit: Ok, that's weird. Maybe I just screwed up my testing. The command that I indicated does work. What doesn't is using it within a Foreach loop within the ISE (version 4). Within a regular Powershell console, it also does work.
foreach ($computer in #("2008R2-test","anotherServer")) { Start-Job -name $computer -ScriptBlock { Invoke-Command -computerName $computer -scriptBlock {$?} } }
The job never stops running, never is "completed". I don't get the cursor back. It hangs and I have to kill the ISE with task manager to get it back. The "$?" is just an example of running anything. I'm trying to do it this way because I want to run some commands that will display stuff to the screen, then do stuff that can happen in the background including a command that runs at the remote machine. I guess it's just another case of not being able to use the ISE.

Use Powershellscript to start remote Powershellscrhipt with Parameters

I have a Powershell Script (PS1), which gets Events from a Remote Computer.
When there is a special Event, it (PS1) should start a Powershell Script (PS2) which is on the remote Computer. The 2nd Script gets 2 Parameter from the first and the first should not wait for the 2nd (it will copy some files with robocopy and this will need some time)
PS1:
icm -ComputerName $Computer {param ($source, $location)
'G:\RoboCopyScript_271113.ps1'} -ArgumentList $source, $location
-Credential $credWinLog
PS2: param ( [Parameter(Position=0)]$source,
[Parameter(Position=1)]$location )
Someone knows how i make the PS2... something like a Child Process?
and where my Errors ware with the Parameters, i tried so much :/