Problems with running remote daemon (and not only) processes via PowerShell - windows

From my script I want to run some command in remote Windows box. So I googled a little and seems the most popular and somehow standard way to do that is to use PowerShell's Invoke-Command cmdlet which seems to use the same protocol as winrm and winrs. So, bellow are commands I've tried to call from my script (actually I've tried lots of other their modifications as well, but IMO these are enough to illustrate the problem):
PowerShell -Command "$encpass=ConvertTo-SecureString -AsPlainText mypass -Force;$cred = New-Object System.Management.Automation.PSCredential -ArgumentList myuser,$encpass; Invoke-Command -ComputerName REMOTE_COMPUTER_NAME -Credential $cred -ScriptBlock {<fullcommand>};"
PowerShell -Command "$encpass=ConvertTo-SecureString -AsPlainText mypass -Force;$cred = New-Object System.Management.Automation.PSCredential -ArgumentList myuser,$encpass; Invoke-Command -ComputerName REMOTE_COMPUTER_NAME -Credential $cred -ScriptBlock {Start-Process -FilePath <fullexepath> -ArgumentList <arguments> -Wait -NoNewWindow};"
PowerShell -Command "$encpass=ConvertTo-SecureString -AsPlainText mypass -Force;$cred = New-Object System.Management.Automation.PSCredential -ArgumentList myuser,$encpass;$session=new-PSSession -ComputerName "REMOTE_COMPUTER_NAME" -Credential $cred; Invoke-Command -Session $session -ScriptBlock {<fullcommand>};"
NOTE: The script is written in perl, but IMO here the language of the script doesn't matter, so you can suppose that I call the command from batch script, just note, that as commands should run from a script they should not require any interactive actions.
So, I have several problems with these commands, and need help to figure them out. Here they are:
Can't run processes of type configure and run daemon. Namely if I want to run configure_server.pl on remote box (<fullcommand> = "configure_server.pl <arguments>"), which should do some stuff, then run server.exe, it doesn't work, because as soon as configure_server.pl is done, full remote job is being killed including the server.exe which supposed to run as a daemon. (applies to points 1,2,3)
Get wrapped (length of each line is less or equal than 80 chars) standard output and standard error. (applies to point 1,3)
Don't get standard output and standard error. (applies to point 2)

Whew this is a tough one, your kind of all over the place so if I miss what your trying to do completely let me know.
1 . Stop trying to go the remote route. I know it seems like a great idea, but it's not. The only way you can get the process to persist is if you keep the powershell window up on the host computer. As you've probably noticed, you can create processes fine, but they're children of your powershell.exe, and are hosted by the wsmprovhost.exe process on the client computer. Once the parent is gone, all the children are killed
To fix this I suggest using a command line function : Schtasks.exe
schtasks.exe /create /sc ONCE /tn $taskName /tr $command /s $serverName /u $userName /p $pass /ru $userName /rp $pass /st $startTime
This command is going to create a scheduled task to run once and then remove itself after. It even takes computer name, so no remote-access required. You can also do a schtasks.exe /query and check the "Status" for running before you do a schtasks.exe /delete too.
2 . Use the ` (backtick) to specify carry execution to the next line in powershell
3 . I get standard output and error with this function, sometimes not output when executed in a big script, but can always use $? to capture error.
Note: You cannot pass in PSCredentials to this command. I suggest making a GUI that just prompts for userName and and password, without converting to secure string. I try to stay away from remoting in my scripts, since it always just makes everything so slow. Sometimes you do not have a choice, but in this case I believe you do.

Related

Powershell: Can't run script as different user in same window?

I am running a script that involves writing to a database only certain users have access to, so we are running the script as a different user (passing in those user credentials) on our corporate network.
Despite trying things like -NoNewWindow or -WindowStyle Hidden, it always seems to pop up in a new window. This is an issue because when we launch the script from our Jenkins builder with a powershell build step, Jenkins doesn't like the second window and really appears to need it all in the main window.
We are using Start-Process, and the script call looks similar to this (I cut some of the details out):
Start-Process -NoNewWindow powershell.exe -Credential $credential -ArgumentList “Start-Process powershell.exe 'path\script.ps1 -param1 xxx -param2 yyy' -Verb runAs”
Any ideas as to how to get this to actually run without a popup window?
Thanks!
one of these should do the trick to you
Invoke-Command -ComputerName 'Same computer Name' -Credential '(PAss Cred object here)' -ScriptBlock {'Your Scripts Here'}
Invoke-Command -ComputerName 'Same computer Name' -Credential '(PAss Cred object here)' -FilePath 'FilePAthHere'

PSExec on Windows Server Startup Script

I'm programatically launching a Google Cloud Compute Instance running Windows Server 2016 with a start up script.
The executable in the start up script requires to be launched as a specific user, so I'm trying to launch it with psexec to simulate said user:
C:/psexec.exe \\\\WIN-SERVER-2016 -u WIN-SERVER-2016\\customuser -p custompassword -accepteula -w "c:/app" cmd /c node index.js
c:/app/index.js contains a simple hello world, which should write to a file.
If I log in as any user and launch this exact command from cmd, the file is written. Launching from the startup script (supplied as windows-startup-script-cmd in the Google Cloud Compute Engine Instance) results in no file written.
What could be the solution? Is there a more efficient way to execute a start-up script as a specific user?
Looking at the concern , I would not recommend you to use PSEXEC .
NOrmally, we use PSExec in order to invoke a GUI in the remote system which PS doesn't support by native.
In your case, I would suggest you to run using the Invoke-Command
Something like this:
$username = 'WIN-SERVER-2016\customuser'
$password = "custompassword"
$secstr = New-Object -TypeName System.Security.SecureString
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr
$Script_block = {cmd /c node index.js}
Invoke-Command -ComputerName WIN-SERVER-2016 -Credential $cred -ScriptBlock $Script_block
This should also take it from the Metadata key if you are using windows-startup-script-cmd
Note: I have not considered the accepteula -w "c:/app" part. Please incorporate the placeholders accordingly.
Hope it helps...!!!

Run code block locally as a different user in powershell script

This is something incredibly simple, but I just can't get anything to work. I want to run a block code in a powershell script under a specific user. The keyword is locally and I'm using powershell 2.0.
Invoke-Command seems to require a remote host? I run the following and the error message that I see seems to suggest as much:
$strScriptUser = "DOMAIN\USER"
$strPass = "PASSWERD"
$PSS = ConvertTo-SecureString $strPass -AsPlainText -Force
$cred = new-object system.management.automation.PSCredential $strScriptUser,$PSS
Invoke-Command -ComputerName "." -scriptblock {
write-output "HI!"
} -Credential $cred
Start-Job with -ScriptBlock isn't supported with powershell 2.0? I run the following and the error message that I see seems to suggest as much:
$strScriptUser = "DOMAIN\USER"
$strPass = "PASSWERD"
$PSS = ConvertTo-SecureString $strPass -AsPlainText -Force
$cred = new-object system.management.automation.PSCredential $strScriptUser,$PSS
Start-Job -ScriptBlock {
write-output "HI!"
} -Credential $cred
Am I doing something wrong, or is there an alternative way?
Added: Here is what I'm trying to do in the first place. I'm making a scheduled task that runs when a user logs into/unlocks a terminal that writes logon information to a file. The scheduled task runs as the local user in order to get at the username, profile, etc. information. The logon information is then written to a log file using a different user account, which is the only account that can modify the file. To deter access to the logon credentials in the script I convert the script to an EXE using PS2EXE.
Here is another way.
# Get the other user's credentials
$credential = Get-Credential
# Execute a scriptblock as another user
$commands = #'
$env:username
# ... more commands ...
'#
Start-Process -FilePath Powershell -LoadUserProfile -Credential $credential -ArgumentList '-Command', $commands
# Execute a file as another user
$script = '.\path\name.ps1'
Start-Process -FilePath Powershell -LoadUserProfile -Credential $credential -ArgumentList '-File', $script
With the -LoadUserProfile switch, this has the added benefit of creating the user's profile if it does not already exist.
Another approach is impersonation, it is good option if you are not willing to enable remoting.
Check this and this out.
You should just put your code between
Push-ImpersonationContext $credential
and
Pop-ImpersonationContext
It would help to see the error messages you're not showing us, but I think the answer to your question is to use PowerShell Remoting as you tried with Invoke-Command. The computer name . is fine as is localhost but you do have to have remoting enabled on your machine to do it.
To enable remoting, run Enable-PSRemoting within powershell, or run winrm quickconfig in a regular command prompt.
If you already have remoting enabled, then you might be trying to do the remoting with a non-administrative user. If that's the case, take a look at the output of Get-PSSessionConfiguration. You'll get a list of endpoints and the permissions that are applied.
The endpoint you're connecting to by default is called Microsoft.Powershell and you could change the permissions with Set-PSSessionConfiguration (be sure to use the -ShowSecurityDescriptorUI parameter unless you want to mess with SDDL).
But instead of doing that, there should already be a group given access called BUILTIN\Remote Management Users which you can add your limited user to.
If none of this helps, give more details and error messages.
Edit
After seeing the explanation of what you're ultimately trying to accomplish, I have another suggestion for you.
Your existing scheduled task writes the information to a known location.
A different scheduled task running under the privileged user account picks up that information and puts it into the file that the limited user cannot access.
Bonus: start the second task from the first task.
This could be a quick compromise to do what you want without remoting and without exposing the credentials of the privileged user.
Issues with the current approach:
The major problem I have with your original idea is that you're going to need to embed the credentials into the script, so the limited user will have access to the credentials of the account that can modify the file anyway.
Ideally:
You would have a web service that you could invoke with your limited-user powershell script in which you can only give it the login information and not get anything back. So you'd hit a URL and do a POST or whatever with the data that you want to log, but that user can't ever retrieve any info. It might be a bit beyond what you're willing to do for this.

How to keep remote powershell command alive after session end?

I use the following command to run setup_server.exe on remote Windows box:
powershell -command "$encpass=convertto-securestring -asplaintext RPASSWORD -force;$cred = New-Object System.Management.Automation.PSCredential -ArgumentList RUSER,$encpass; invoke-command -computername RCOMPUTERNAME -scriptblock {setup_server.exe} -credential $cred;"
setup_server.exe's task is to create some configuration files and start my_server.exe (some daemon process), then it finishes. And I want my_server.exe to keep running after setup_server.exe is finished.
So when I do it via CMD on local box (i.e. just run setup_server.exe from CMD) it works, but when I do it via powershell on remote host it doesn't work. Namely the my_server.exe gets started, but right after setup_server.exe is closed the server also gets closed(killed).
So the question is following:
Which powershell flags/cmdlets should I use to make the described scenario to work as in local mode?
NOTE: I want synchronously get output of setup_server.exe, so running remote command with -AsJob flag, probably wouldn't work for me, though I even don't know if it will keep the server alive after setup_server.exe's end.
The way to keep the remote PowerShell session running after the command has finished is to use a PSSession e.g.:
$s = new-PSSession computername
Invoke-Command -session $s { ..script.. }
... do other stuff, remote powershell.exe continues to run
Remove-PSSession $s # when you're done with the remote session
Generally though exes should run independently from the app that launched them.
Why are you using Invoke-Command. If you want a persistent Session, use Enter-PSSession.
$s = New-PSSession -Computername "Computername";
Enter-PSSession -Session $s;
setup_server.exe
# Once you are finnished
Exit-PSSession
With 'Enter-PSSession' you are not just Invoking some Command on the Server, you are directly logged-in like you probably know from SSH.
If you want your powershell session to keep running because you are running an exe, try using the -InDisconnectedSession switch. From what I understand, it will run the executable on the remote machine in a session that isn't actually connected to your computer. In essence, your computer will not destroy the session, when it disconnects, allowing the exe to continue to run.
invoke-command -computername RCOMPUTERNAME -scriptblock {start-process setup_server.exe} -InDisconnectedSession
If you need to do this on multiple computers. Setup an array of all the computer names.
Note: I don't believe this works with sessions that are already created.
In order to keep a powershell code running on the session exit it should be a process. And the windows way to keep the process is running a .exe or a windows service.
To keep a Powershell shell open after executing a command, I use the -NoExit switch, e.g. this script starts a remote interactive PS session on servername with user administrator
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoExit
-Command "Enter-PSSession -ComputerName servername -Credential administrator"
http://powershell-guru.com/powershell-tip-13-prevent-powershell-from-exiting-once-script-finished/

How to run processes with Invoke-WMIMethod on remote computer in foreground

I am running this command
Invoke-WmiMethod -ComputerName $machine -Credential $cred -Impersonation 3 -Path Win32_process -Name create -ArgumentList "powershell.exe -ExecutionPolicy Unrestricted -File C:\Windows_Updates.ps1" -Verbose
The only problem is in the remote machine, it getting created as a background process. When I open the task manager, I am able to see powershell.exe, but I have no way to identify what is going on. I have looked nearly everywhere but unable to find a solution.
Basically I need to execute the powershell file remotely. I am open to using other solutions where I can see the script running.
I dont think that is possible. Try psexec instead
http://blogs.technet.com/b/heyscriptingguy/archive/2005/09/06/how-can-i-remotely-start-an-interactive-process.aspx
sysinternals psexec
http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx

Resources