I need to chain or pipe commands onto remote PS Session on servers. How can I pass arguments or commands to power shell remote sessions and automate the process of feeding command line arguments ?
If I log into a server locally and open a command prompt and type the commands\parameters it works fine. This is for windows 2012 server.
Open a cmd prompt.
1.) cd "D:\Oracle\Servers\AppSrv01\bin" //Type this in cmd prompt
2.) oraadmin.bat -user myuser -pwd mypwd //Type this in cmd prompt
oraadmin>oraadminctrl.invoke('clearlogs') //Type this in cmd prompt
oraadmin>oraadminctrl.invoke('stopserver') //Type this in cmd prompt
oraadmin> exit //This will exit the oraadmin in cmd prompt
3.)exit //Type this in cmd prompt, exits the cmd prompt
This works fine. Now I am trying to automate this in powershell by opening a session ($sess) object as below.
Tried this. But failed 'oraadminctrl.invoke' is not recognized as an internal or external command
$c = Invoke-Command -Session $sess {cmd.exe /c “cd D:\Oracle\Servers\AppSrv01\bin && oraadmin -user admin -password mypassword && oraadminctrl.invoke('clearlogs') && oraadminctrl.invoke('stopserver')" }
I just want to automate the process of feeding this username and password and running these commands one after other on the same command prompt process on the remote machine. I am also open to start-process or other forms of invoke-command. Writing a new batch file to be put on the server is not acceptable. Any idea how to go about this ?
I want to make a PowerShell script that can be used to connect computers to various client's SonicWall VPNs (specifically through Global VPN and NetExtender). I would like to have it be like a user interface to prompt the user (which will set the variables) and then use that information to pass through to command lines in the command prompt.
I want to be able to have information entered in be applied in the cmd line in the script.
I have tried using the MobileConnect connection through (Using the the app from the app store) and connecting with the Microsoft VPN client, but that does not grab all the network information; specifically DNS servers.
The best way is to install either Global VPN or NetExtender and connect through cmd line; that way will grab the entire network information.
This is the basic command to run it:
Function Connect-VPN {
Set-Location -Path "C:\Program Files (x86)\SonicWALL\SSL-VPN\NetExtender"
cmd /c "NECLI connect -s address:4433 -u Uname -p Password -d Domain -A"
Set-Location -Path C:\
}
Basically, you change the directory and execute the commands with those arguments.
I would like to prompt in POSH, create the variables with the user input, then have those arguments passed down.
What I have right now is:
param(
[string]$Testadd ,
[string]$Testun ,
[string]$TestPW ,
[string]$TestDom
)
If ($Testadd -eq "")
{$Testadd = (Read-Host "test")
}
If ($Testun -eq "")
{$Testun = (Read-Host "test")
}
If ($TestPW -eq "")
{$TestPW = (Read-Host "test")
}
If ($TestDom -eq "")
{$TestDom = (Read-Host "test")
}
Set-Location -Path "C:\Program Files (x86)\SonicWALL\SSL-VPN\NetExtender"
cmd /c "NECLI connect -s "$($Testadd)" -u "$($Testun)" -p "$($TestPW)" -d "$($TestDom)" -A"
Set-Location -Path C:\
The problem is that the all the arguments come out null. I do not know if it is possible, but I wanted to see.
You can try to build the string before running the cmd
param (
[string]$Testadd,
[string]$Testun,
[string]$TestPW,
[string]$TestDom
)
If ($Testadd -eq "")
{
$Testadd = (Read-Host "testadd")
}
If ($Testun -eq "")
{
$Testun = (Read-Host "testun")
}
If ($TestPW -eq "")
{
$TestPW = (Read-Host "testpw")
}
If ($TestDom -eq "")
{
$TestDom = (Read-Host "testdom")
}
Set-Location -Path "C:\Program Files (x86)\SonicWALL\SSL-VPN\NetExtender"
#build the string before
$cmd = "NECLI connect -s " + $($Testadd) + " -u " + $($Testun) + " -p " + $($TestPW) + " -d " + $($TestDom) + " -A"
# Or even like this
$cmd = "NECLI connect -s $Testadd -u $Testun -p $TestPW -d $TestDom -A"
# exec command
cmd /c $cmd
Set-Location -Path C:\
To add to #Desinternauta, I suspect it is how the command is interpreting the quotes and the variables. i.e. when you write out the string as you have it, it adds spaces:
$b = "b"
Write-Host "a"$($b)"c"
Outputs:
a b c
The good news is that double quoted strings allow you to embed the variables into the string:
cmd /c "NECLI connect -s $Testadd -u $Testun -p $TestPW -d $TestDom -A"
Calling external exe / commands that use cmd.exe, require special consideration and outing specifics. You also do not need to call cmd.exe directly, as that will just happen. This is a well documented this. For example:
PowerShell: Running Executables
The Call Operator &
Why: Used to treat a string as a SINGLE command. Useful for dealing
with spaces.
In PowerShell V2.0, if you are running 7z.exe (7-Zip.exe) or another
command that starts with a number, you have to use the command
invocation operator &.
The PowerShell V3.0 parser do it now smarter, in this case you don’t
need the & anymore .
Details: Runs a command, script, or script block. The call operator,
also known as the "invocation operator," lets you run commands that
are stored in variables and represented by strings. Because the call
operator does not parse the command,it cannot interpret command
parameters
# Example:
& 'C:\Program Files\Windows Media Player\wmplayer.exe' "c:\videos\my home video.avi" /fullscreen
Start-Process (start/saps)
Why: Starts a process and returns the .Net process object Jump if
-PassThru is provided. It also allows you to control the environment in which the process is started (user profile, output redirection
etc). You can also use the Verb parameter (right click on a file, that
list of actions) so thatyou can, for example, play a wav file.
Details: Executes a program returning the process object of the
application. Allows you to control the action on a file (verb
mentioned above) and control the environment in which the app is run.
You also have the ability to wait on the processto end. You can also
subscribe to the processes Exited event.
#Example:
#starts a process, waits for it to finish and then checks the exit code.
$p = Start-Process ping -ArgumentList "invalidhost" -wait -NoNewWindow -PassThru
$p.HasExited
$p.ExitCode
10. Stop-Parsing Symbol --%
Why: Its a quick way to handle program arguments that are not standard. Also its the new cool way to do it.
Details: The stop-parsing symbol (--%), introduced in Windows PowerShell 3.0, directs Windows PowerShell to refrain from interpreting input as Windows PowerShell commands or expressions. When calling an executable program in Windows PowerShell, placethe stop-parsing symbol before the program arguments.
After the stop-parsing symbol --% , the arguments up to the end of the line (or pipe, if you are piping) are passed as is.
#Examples:
# icacls in V2
# You must use escape characters to prevent PowerShell from misinterpreting the parentheses.
icacls X:\VMS /grant Dom\HVAdmin:`(CI`)`(OI`)F
# In V3 you can use the stop-parsing symbol.
icacls X:\VMS --% /grant Dom\HVAdmin:(CI)(OI)F
See also:
Using Windows PowerShell to run old command line tools (and their weirdest parameters)
Solve Problems with External Command Lines in PowerShell
Quoting
About Quoting Rules
A Story of PowerShell Quoting Rules
I have a dynamically generated batch file that I push out to a remote PC and then execute it using PsExec. The issue I am facing is that as soon as that line is called, the PowerShell script moves on and doesn't wait for it to finish. Here is what I have:
psexec -accepteula \\$Server -u Username -p Password-d -i 2 cmd /c C:\Call.bat
Call.bat calls an executable on the remote machine with a few parameters passed in. This file is dynamically generated and is different every time, but can look like this:
cd C:\20161212-175524
C:\20161212-175524\RE.exe /pa1 /pa2 /pa3 /pa4 /pa5 /pa6 /pa7 /pa8 /pa9 /pa10
The batch file needs to run as an interactive script as that specific user, but I need it to at least wait for the spawned process to finish. I have tried adding 2>&1 and | Out-Null
Ideally, I would like to retrieve the exit code returned by the spawned process, but that may be too much.
Previously i have used something like this to achieve the waiting you are after:
Start-Process -FilePath 'c:\tools\PSexec.exe' -ArgumentList "-u MyUserName -p $password \\$Computer .\Run.bat $Var >> C:\Temp\$Computer.log" -Wait -Passthru -WindowStyle Hidden
What you need to focus on the line above is by using the Start-Process cmdlet we can use the -Wait parameter.
Hope this answers your question
private static string ExecuteAndGetOutput(string command)
{
string resultFile = Path.GetTempFileName();
string commandFile = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(resultFile) + ".bat");
command += #" >""{0}""";
command = string.Format(command, resultFile);
File.WriteAllText(commandFile, command);
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = commandFile;
psi.WindowStyle = ProcessWindowStyle.Hidden;
Process p = Process.Start(psi);
p.WaitForExit();
int exitCode = p.ExitCode;
return File.ReadAllText(resultFile);
}
I was wondering if it would be possible to create PowerShell script that would link a certain file extension to an application.
For example:
The .ntb extension has to be opened using the following application by default:
C:\Program Files\SMART Technologies\Education Software\Notebook.exe
Why would I need a script for this you ask?
It could indeed be done by using Run With and then ticking the Default box. However I need to perform this on about 150+ computers. So I'd think to run the script when booting once.
I am a newbie when it comes to PowerShell, so if anyone could give a "small" start, I would be grateful.
For a scripted solution I'd use the cmd built-ins assoc and ftype:
$prg = 'C:\Program Files\SMART Technologies\Education Software\Notebook.exe'
$ext = '.ntb'
& cmd /c "ftype SMART.Notebook=`"$prg`" %1"
& cmd /c "assoc $ext=SMART.Notebook"
The above can be run on remote hosts via the Invoke-Command cmdlet:
Invoke-Command -Computer HostA,HostB,... -ScriptBlock {
$prg = 'C:\Program Files\SMART Technologies\Education Software\Notebook.exe'
$ext = '.ntb'
& cmd /c "ftype SMART.Notebook=`"$prg`" %1"
& cmd /c "assoc $ext=SMART.Notebook"
}
Otherwise you'll have to edit the registry, in which case the deployment via group policy would be preferable, as others have already pointed out.
I am trying to run a powershell command like this:
psexec \\MachineB "\\MachineB\drops\Func2WebSiteOnline.bat"
I get this error:
PsExec could not start \\MachineB\drops\Func2WebSiteOnline.bat on
MachineB: Access is denied.
I have tried the following things:
run powershell in "Administrator" mode
Run the powershell command with "-u Domain\user -p password" params
Neither of those help. However, I can run simple commands against machineB like this:
psexec \\MachineB net stop dcache
and that works just fine.
Any thoughts on how I can run that batch file above against MachineB?
Thanks
I found a somewhat unconventional way to solve it.
psexec \\MachineB -u domain\user -p password cmd /c "cd /d
I:\drops\Func2 && func2web.bat"