how to edit a file in powershell remoting session (powershell) - powershell

I am connecting to another computer using powershell remoting, really nice. can do lots, but how do I edit a file?
PS C:\Users\guutlee> Enter-PSSession -ComputerName appprod
[appprod]: PS C:\Users\guutlee\Documents> cd \myapp
[appprod]: PS C:\myapp>
what can I do to open a file editor on a file on the remote machine?
[appprod]: PS C:\myapp> edit app.config
so edit "filename" just seems to hang, from powershell.exe or from powershell_ise.exe
The only thing I can think of is back out of the pssession and "start \webprod\c$\inetpub\myapp\web.config", which would open visual studio.
[appprod]: PS C:\myapp> exit
PS C:\Users\guutlee> start \agobuild\c$\myapp\app.config
PS C:\Users\guutlee> Enter-PSSession -ComputerName appprod
[appprod]: PS C:\Users\guutlee\Documents> cd \myapp
[appprod]: PS C:\myapp> myapp.exe
Of course with this I have to re-find the file, hope that the c$ share is available and accessible, and the reconnect my pssession and re-find my working directory when I want to go on. It doesn't seem very elegant.
I could maybe wrap this is a function, but having a hard time wrapping my head around that..
so how do I conveniently edit a file with a remote pssession?
EDIT
kbrimington's post got me thinking me about the -X option to ssh. probably would be an awesome thing for powershell sessions to be able to forward windowed apps back to the original windowing environment...
but still I'd be happy just to edit the file.
EDIT
tests using vi, emacs, cmd and edit
PS C:\Users\Meredith> Enter-PSSession -ComputerName appprod
[appprod]: PS C:\Users\guutlee\Documents> C:\vim\vim72\vim filename.txt
[appprod]: PS C:\Users\guutlee\Documents> C:\emacs-23.2\bin\emacs.exe -nw filename.txt
emacs.exe : emacs: standard input is not a tty
+ CategoryInfo \: NotSpecified: (emacs: standard input is not a tty:String) [], RemoteException
+ FullyQualifiedErrorId \: NativeCommandError
[appprod]: PS C:\Users\guutlee\Documents> cmd
Microsoft Windows [Version 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\guutlee\Documents>
[appprod]: PS C:\Users\guutlee\Documents> edit filename.txt
vi and edit hang (Control-C to get a prompt back)
cmd runs, producing a prompt, but immediately exits back to the powershell prompt
emacs produces the error (standard input is not a tty)
EDIT
Jered suggests pulling the file back locally to edit. I embellished his answer to copying using pssessions rather than UNCs (perhaps this is what he intended)
PS C:\Users\Meredith> Invoke-Command -Session $ps -ScriptBlock {get-content c:/inetpub/myapp/web.config} > web.config
edit web config
PS C:\Users\Meredith> get-content web.config | Invoke-Command -Session $ps -ScriptBlock {set-content c:/inetpub/myapp/web.config}
Potentially we could run the invoke-commands in either direction, local to remote or remote back to local.

If you are using Powershell 5, you can use command called PSEdit. It only works from ISE.
So first, open PowerShell ISE
Then open remote session to the remote computer using Enter-PSSession
Then edit the file using PsEdit 'filename'
The remote file will be opened in a new tab in your (local) ISE window.
Actually I found this answer from the comments section of this SO question , but I think it will be helpful for others if I post it as answer here.

Can you not pull the file locally, edit it and post it? I know this is tedious and not elegant but it seems editors are presently having issue with remote sessions.
E.g.,
Get-Content REMOTE\Filename.txt > LOCAL\Filename.txt
Make your changes locally and then
Set-Content -path REMOTE\Filename.txt -value (get-content LOCAL\Filename.txt)
EDIT
Also if you are only replacing certain instances you can do this pretty easily.
E.g.,
Get-Content REMOTE\Filename.txt | foreach-object { $_ -replace "OLD", "NEW" } | Set-Content REMOTE\Filename.txt

After much digging around, I found something that seems relevant in the powershell help documentation. At the powershell prompt, type:
help about_remote_troubleshooting
At the very end of the help file that is displayed, there is a section entitled 'TROUBLESHOOTING UNRESPONSIVE BEHAVIOUR', which states:
TROUBLESHOOTING UNRESPONSIVE BEHAVIOR
This section discusses remoting problems that prevent a command from
completing and prevent or delay the return of the Windows PowerShell
prompt.
HOW TO INTERRUPT A COMMAND
Some native Windows programs, such as programs with a user interface,
console applications that prompt for input, and console
applications that use the Win32 console API, do not work
correctly in the Windows PowerShell remote host.
When you use these programs, you might see unexpected behavior, such
as no output, partial output, or a remote command that does not
complete. To end an unresponsive program, type CTRL + C. To view any
errors that might have been reported, type "$error" in the
local host and the remote session.
Thus it would seem even non-GUI console applications such as VIM won't work unfortunately. Anyone
care to shed a little light on why this might be the case and/or whether it can be worked
around? I would REALLY love it if I could use vim over powershell remoting.

First, create a temp folder on the local machine (LOCALTEMPFOLDER). Then, use the following function:
function vimrem {param([parameter(position=0,mandatory=$true)][string]$Session, [parameter(position=1,mandatory=$true)][string]$Path)
$TempFile = split-path -path $Path -leaf
copy-item -fromsession $Session -path $Path -destination LOCALTEMPFOLDER\$TempFile
vim $LOCALTEMPFOLDER\$TempFile
copy-item -tosession $Session -path LOCALTEMPFOLDER\$TempFile -destination $Path
remove-item -path LOCALTEMPFOLDER\$TempFile
}
This should work, but you will have leave an interactive session before using this function.

PowerShell_ISE.exe \\REMOTE\...\File.txt
will load and edit the file directly and save it back to the remote computer in one step and, since its command line, easy to build functions using it. Doesn't get around sharing problems, but the easiest way I've found.

Try it out using a console-based editor such as VI or Emacs. As in my comment, I think the problem is that the edit command is bound to a windowed application which, in turn, is not virtualized across a remote session.

I try all the above suggestion and even other microsoft related solution but none works the way you and I want --"full interactive and responsive shell"--. If you really want to have the ssh experience that unix users have from the beggining of time i recomend you install an ssh server. I personally use freesshd, you can find it here http://www.freesshd.com and instructions of how to configure it here http://www.windowsnetworking.com/articles_tutorials/install-SSH-Server-Windows-Server-2008.html. After you make all that it says in the instructions you only need to use any ssh client app to connect to your computer and use powershell full interactive. Vim, edit, emacs or whatever you use to edit a file is going to work without any problem.
i encourage you to not waste your time with psremoting, telnet, winrs, psexec, trying to achieve what a real interactive shell provide (i already lost it, T_T). Try that ssh server an see for your self.

Inspired by the answer provided by #chenz, this can also be done using Visual Studio Code when inside the Powershell Integrated Shell. I tried this with Powershell 7 over SSH remoting, but should also work with WinRM remoting as well.
Enter-Session ...
[RemoteSystem] PS> psedit service.log
The filename will follow this pattern:
C:\users\dev\appdata\local\temp\2\pses-15960\remotefiles\1702137071\winboxname\service.log

I got nano to work easily over SSH to PowerShell. It's available in Chocolatey so you can just do...
choco install nano -y
Then you can just do...
nano filename

I've been looking into this quite thoroughly given the limitations of PSRemoting and the possible work arounds or solutions.
Console editors do not work as they are native (exe) commands and are character based. (I'm wondering if cmd over ssh works with these) It needs to be a cmdlet to properly interact with the console host over a psremote session.
A PSRemote session is line based. You edit the line locally push enter and then it is sent to the remote end, the command is executed and the result returned. So it does support line interactivity but not character interactivity.
Given all these limitations, GNU's ed appears to be a perfect fit. I'm surprised that no one has looked at implementing it as a cmdlet.
I decided to investigate this further, I checked that the powershell cmdlet read-host works and then the C# equivalent PSHostUserInterface.ReadLine() work over a PSRemote session and they do, which is all that is needed to make a working line editor.
So here's what I've done so far. I could probably use some help on the more exotic regex code.
https://github.com/silicontrip/ps-ed
I've used this to edit files via a psremote session. (I wouldn't go editing large source files with it, but for the odd small config file or ps1 script it is perfect.)
Make sure you are familiar with GNU ED before using this cmdlet. It'd be like trying to use VI for the very first time, otherwise.

Related

Is anybody having this Powershell "Update-Help" command, issue?

I am trying to download and install Help files for all the commands but it won't work. I am using Powershell 7.1.1 inside the Windows Terminal.
Update-Help: Failed to update Help for the module(s) 'ConfigDefender, PSReadline' with UI culture(s) {en-US} : One or more errors occurred. (Response status code does not indicate success: 404 (The specified blob does not exist.).).
English-US help content is available and can be installed using: Update-Help -UICulture en-US.
This is exactly what the out-put looks like
Solved, thanks to another post I've found on stackoverflow.
According to Microsoft, the below command should work in case of errors regarding the cmdlet: Update-Help.
Update-Help -Verbose -Force -ErrorAction SilentlyContinue
The issue is the capitalization of PSReadline, which changed to PSReadLine with PowerShell 6.
Fix is easy:
Close all PowerShell windows
From TaskMgr make sure to kill any remaining PowerShell processes.
Open Admin Cmd prompt (not PowerShell) and run the following:
ren "C:\Program Files\WindowsPowerShell\Modules\PSReadline" PSReadLine
ren "%APPDATA%\Microsoft\Windows\PowerShell\PSReadline" PSReadLine
That's it. Now you can close the Cmd prompt window, open a PowerShell window and do a normal Update-Help.
See this blog for some additional context:
https://devblogs.microsoft.com/powershell/updating-help-for-the-psreadline-module-in-windows-powershell-5-1/

Which program to edit a file in powershell and just the powershell?

I see a lot of questions about this but the answers are only about get function and replace function.
Isn't there anyway to edit a file simple a nano or vi in linux, already pre-installed in powershell?
I could think about a thousand of usecase where you don't want to use function to do that. One among many is that you are remoting on a nanoserver and you want to do several changes in a single script file.
With PowerShell ISE (pre-installed on Windows clients) and vscode with PowerShell Extension and Integrated Console, you can open files in Remote PowerShell Sessions with psEdit $filetoopen.
Example
Enter-PSSession -ComputerName nanoserver
psedit C:\nanofile.txt

Why does Chocolatey hang when using Powershell ISE without the `-y` switch?

When using PowerShell ISE with Chocolatey to install applications, if I forget the -y switch, it hangs waiting on some sort of "confirmation" that's not popping up anywhere?
I have to Ctrl+Alt+Del to kill PowerShell ISE and Chocolatey and it leaves things in half-way state.
This is what it looks like below:
In addition to the comments to the OP above, regarding PowerShell ISE not supporting (most) interactive console applications...
It is worth remembering that the REPL window in PowerShell_ISE.exe is not just some sort of docked PowerShell.exe console. Most of the time the user experience is the same, but this hides a number of differences:
https://blogs.msdn.microsoft.com/powershell/2009/04/17/differences-between-the-ise-and-powershell-console/
Both these executables are host applications that run a PowerShell runspace (engine). You can even write your own application that "hosts" PowerShell. It is the host application that determines the user experience.
PowerShell.org: The Shell vs The host
Spiceworks.com: The Shell vs The Host
Writing a Windows PowerShell Host
And finally, for the most curious:
How PowerShell works
I think I wrote this answer more for my own benefit; it's a useful refresher for me as I get asked this by colleagues every now and again...
It's simply because PoSH ISE is not a thing to use for user interactive .exe commands.
If you .exe or whatever expects a response, when in the ISE you have to provide it.
You can easily prove this is not a Chocolatey thing by trying any other .exe that kicks out interactive stuff. For example, just type:
nslookup in the script pane and F8 to run it, or type it in the console pane and hit enter
Either way, the console will just hang, waiting for a interactive response that you cannot provide.
You can still use interactive commands like nslookup in the PoSH ISE, but you have to provide all parameters. For example:
nslookup microsoft.com
nslookup -type=mx microsoft.com
nslookup -q=soa microsoft.com
PS 5.1 even kicks out an error message now.
nslookup
Cannot start "nslookup". Interactive console applications are not supported.
To run the application, use the Start-Process cmdlet or use "Start PowerShell.exe" from the File menu.
To view/modify the list of blocked console applications, use $psUnsupportedConsoleApplications, or consult online help.
At line:0 char:0
You can easily shell out to the PowerShell console host temporarily this way.
Here is a function I have in my profile for such efforts.
Function Start-ConsoleCommand
{
[CmdletBinding()]
[Alias('scc')]
Param
(
[string]$ConsoleCommand,
[switch]$PoSHCore
)
If ($PoSHCore)
{Start-Process pwsh -ArgumentList "-NoExit","-Command &{ $ConsoleCommand }" -Wait}
Else
{Start-Process powershell -ArgumentList "-NoExit","-Command &{ $ConsoleCommand }" -Wait}
}
So, just type
scc -ConsoleCommand choco install winmerge
It'll pop the console host and stay open until you close it.
Update
As per request of - Alex Kwitny
PoSHGet default has only two repositories,
nuget
PSGallery
but you can add your own or another.
You use the below cmdlets to make this happen.
I have not had to use Chocolatey in a while, but taking a quick look and my archives, the below is what I used
Set up chocolatey repository
Find-Module
Get-Module
Find-Package
Get-Package
Get-PackageProvider
Get-PackageSource
Get-PackageSource -Provider chocolatey
Register-PackageSource -Name chocolatey -Provider Chocolatey -Trusted -Location http://chocolatey.org/api/v2/ -Verbose
Find-Module
Get-Module
Find-Package
Get-Package

Is it possible to/how do you stop powershell using certain cmdlets?

Powershell is clearly a lot better than cmd but it hides basic functionality. I normally use it to figure out how to use commands that I want in scripts but it breaks a large number of basic things and I end up using both side by side if I hit a sticky spot.
Today this was removing a directory - rd or rmdir - both of which are broken in powershell in favour of one it's undocumented (from the commandline) cmdlets Remove-Item. I seem to run into it all the time though - sc (for mucking around with services); where for finding what program is being called when you type a command etc etc.
Hilariously I actually got the problem with sc and then googled to find out the command where only to discover that didnt work in powershell either! That was a confusing day
In some cases once you know this is what's going on you can type the full exe name (for instance 'where.exe' will work whereas 'where' on its own wont).
This isn't the case with rmdir however. Although interestingly typing 'where rmdir' in cmd doesnt work.
So... my question is this - Is there a way of turning off (preferably all) cmdlets in powershell and just getting the normal stuff instead?
There is no need to turn off cmdlets in powershell as that would destroy the very reason for having it.
Most of the "normal" stuff is there anyway, which you can find by using the get-alias command.
C:\> get-alias
CommandType Name
----------- ----
Alias % -> ForEach-Object
Alias ? -> Where-Object
Alias ?? -> Invoke-NullCoalescing
Alias ac -> Add-Content
Alias asnp -> Add-PSSnapin
Alias cat -> Get-Content
Alias cd -> Set-Location
Alias chdir -> Set-Location
.....
..... AND A WHOLE LOT MORE!
If you are missing a command that you really, really want to have, then you can easily add a new alias:
Set-Alias python2 "C:\Python27\python.exe"
In order to avoid having to do this every single time, you can simply add this into your startup profile. Just type in $PROFILE into the command prompt and it will show you the file path. If it doesn't exist, simply create it, and any powershell commands you add to the top will be automatically invoked when you start a new session.
And last thing. All of the commands are documented, and you can get to them easily using just two.
Just type this into your command prompt and you will be on your way to Powershell enlightenment!
get-help get-command
get-command -noun Item
get-command -verb get
I just realised the answer to my question was buried in the comments to the other answer:
To remove a cmdlet in powershell you run
Remove-Item alias:something.
I can confirm you can do this by using the profile mentioned in Josh's post, however there are a couple more steps:
By default you cant run scripts in powershell. You have to change this using set-ExecutionPolicy.
I changed this by using an admin powershell and typing
set-executionpolicy bypass
This will let you run any script you like
Then in my profile script I have lines like:
Remove-Item -force alias:sc
You wont see errors from this script when it runs and it wont do anything unless you have force.

powershell v2 remote features?

Just listened to Hansellminutes podcast. He had a talk with two Microsoft PS developers. They mentioned PS V2 remoting features.
I have some scripts based on PS v1. In terms of remoting commands or executions, I installed PS on local and a remote machines. Then I use PsExec.exe to push bat on remote to execute PS scripts. Now I am thinking to take advantage of PS V2.
To simple questions I have, to get a list of files on local, I can use the following codes:
$fs = Get-Item -Path $Path | Where { !$_.PSIsContainer ... } # more constrains in ...
if ( $fs -ne $null )
{
# continue to work on each file in the collection
...
}
What is the equivalent command to get a collection of files from a remote? I prefer to get a similar collection of file objects back so that I can access to their properties.
The second question is how to exec a command on remote with external application? I tried to use WIM Process before, but I could not get WMI class working on a case of Windows 2008 server. Then I used PsExec.exe to push a bat to a remote to execute PS script. It works in the cases. However, the problem I have to install PS on the remote as well. I am going to working another remote. I'll try to avoid to install PS on the remote. Can I take PS V2 advantage to execute a command on a remote Windows? What's the new commands?
By the way, normally, I have to pass user name and pwd to a remote. I guess in PS I have to pass user/pwd as well.
You can either put your code above in a script file and invoke it on a remote computer using V2 remoting like so:
PS> Invoke-Command remotePCName -file c:\myscript.ps1
You will need to be running with admin privs (elevated if UAC enabled) in order to use remoting. The command above will copy the script to the remote machine, execute it and return deserialized objects. These objects are essentially property bags. They are not "live" objects and setting properties on them like IsReadOnly will not affect the remote file. If you want to set properties then do it in your script that executes on the remote PC.
The option if you have a little bit of script is to use a scriptblock like so:
PS> Invoke-Command remotePCName { Get-Item C:\*.txt | Where {$_.IsReadOnly }
You can execute native commands (EXE) on the remote computer in either script or a scriptblock. You only need to make sure the EXE is available on the remote PC.
Regarding credentials, if you're on a domain and you have admin privs on the remote computer you won't need to pass credentials as your default credentials should work. If you need to run as a specific user then use the -Credential parameter on Invoke-Command like so:
PS> $cred = Get-Credential
PS> icm remotePCName { gci c:\windows\system32 -r *.sys } -credential $cred
Regarding your last comment, no PowerShell will use Windows integrated security so you should not have to pass any username or password unless you wanted to run it as a different user.
If you haven't yet enabled PS remoting, every time I've tried I've had to actually turn off UAC while I was enabling remoting (then I could re-enable UAC once remoting was enabled). Running Enable-PSRemoting from an elevated command prompt was not enough and the error message was not at all useful.
EDIT: I've just confirmed in a fresh Windows 7 VM that this is not an issue. It could have been a beta issue that I am no longer experiencing as I've been using beta/rc/ctp of PowerShell and Windows 7 for a long time.