New-Object not recognized - powershell

I want to run a script that will continue executing even when I close the terminal window.
I use the following command on PowerShell 2.0 to download files from the Internet:
$fyle = New-Object System.Net.WebClient;
$fyle.DownloadFile($url, $dest);
The following script downloads and runs a .ps1 script, and I can close the window, but not immediately since I have to wait for the file to download..
$fyle = New-Object System.Net.WebClient;
$fyle.DownloadFile($url, $dest_filename);
Start-Process cmd -ArgumentList " /c start /min powershell -Exec Bypass $dest_filename" -NoNewWindow
To try to fix that, all I did was put $fyle inside the Start-Process block:
$url = "https://google.com";
$dir = "$env:userprofile/adir";
$dest_filename = "$dir/script.ps1";
Start-Process cmd -ArgumentList " /c start powershell -Exec Bypass mkdir $dir; $fyle=New-Object System.Net.WebClient; $fyl.DownloadFile($url,$dest_filename); $dest_filename"
However, I get this error:
The term '=New-Object' 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.
At line:1 char:40
+ mkdir C:\Users\IEUser/adir; =New-Object <<<< System.Net.WebClient; .DownloadFile(https://google.com,C:\Users\IEUser/adir/script.ps1); C:\Users\IEUser/adir/script.ps1
+ CategoryInfo : ObjectNotFound: (=New-Object:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

The typo in your code aside, if you take a closer look at the statement throwing the error it becomes pretty much apparent what is happening:
+ mkdir C:\Users\IEUser/adir; =New-Object <<<< System.Net.WebClient; .DownloadFile(https://google.com,C:\Users\IEUser/adir/script.ps1); C:\Users\IEUser/adir/script.ps1
^^ ^^
The variable you intend to use is missing at the positions I indicated above. Without the variable the statements become incomplete commands, thus throwing the error you observed.
The reason for this is that you're passing the arguments for CMD in a double-quoted string. PowerShell's parser expands all variables in that string before passing it to Start-Process. Undefined variables are expanded to empty strings, leaving you with an incomplete commandline to execute. The variable expansion also leads to another issue with your code, because the variables that serve as the arguments for DownloadFile() are also expanded before the string is passed to Start-Process. However, DownloadFile() expects strings not bare words as its arguments.
You can fix this by escaping the $ in variables you define inside your argument string and adding quotes around the arguments for DownloadFile():
Start-Process cmd -ArgumentList " /c start powershell -Exec Bypass mkdir $dir; `$fyle=New-Object System.Net.WebClient; `$fyle.DownloadFile('$url','$dest_filename'); $dest_filename"
# ^ ^ ^ ^ ^ ^
Better yet, define your argument list as an array before passing it to Start-Process:
$params = '/c', 'start', 'powershell', '-Exec Bypass',
"mkdir $dir;",
'$fyle=New-Object System.Net.WebClient;',
"`$fyle.DownloadFile('$url','$dest_filename');",
"$dest_filename"
Start-Process cmd -ArgumentList $params

Related

Powershell - How to pass arguments with apostrophes in them?

I'm using a third party tool to do some AD manipulation. I run a powershell script and pass arguments to it.
Everything works except if that argument contains an apostrophe in it like Jerry O'Connor. I've tried lots of different escape combinations without any luck.
Here is my command: script.ps1 -name "'%name%'" and name contain is Jerry O'Connor.
The error is
Result:The string is missing the terminator: '.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
I've tried:
script.ps1 -name "'%name%'"
script.ps1 -name \"%name%\"
script.ps1 -name ''name''
all with same error.
If you run this at the PS CMD level you'll see the error
powershell echo -name "'Jerry O'Connor'"
Anyone know how to pass an argument to script.ps1 -name "name" where that argument contains an apostrophe?
Cheers
You need to escape any ' chars. inside the value of %name% as '' to make them work inside a single-quoted PowerShell string, which from cmd.exe you can do with %name:'=''%:
From cmd.exe / a batch file:
powershell.exe -Command ./script.ps1 -name "'%name:'=''%'"
If %name% contains verbatim Jerry O'Connor, the above expands to the following, which should work as intended:
powershell.exe -Command ./script.ps1 -name "'Jerry O''Connor'"
However, you can simplify quoting if you use the -File CLI parameter instead of -Command:
powershell.exe -File ./script.ps1 -name "%name%"
See also:
For guidance on when to use -Command vs. -File, see this answer
For a comprehensive overview of the PowerShell CLI, see this answer
Try the escape character as shown here:
$Test = "`'test`'"
$Test

How to pass path with spaces to script

I am trying to use PowerShell to call an EXE that is at a location/path containing spaces. When I call the script from the command line, the EXE's full path is not being passed to the script. Any ideas as to why this is happening?
PowerShell Script Contents (Untitled1.ps1)
Here is the entire script that gets called from the command line:
param(
[string] $ParamExePath
)
function Run-CallThisExe {
param(
[string] $ThisExePath
)
Write-Host "ThisExePath: " "$ThisExePath"
start-process -FilePath $ThisExePath
}
write-host "ParamExePath: " $ParamExePath
Run-CallThisExe -ThisExePath "$ParamExePath"
Command Line String
Here is the command line string being run from the PowerShell script's parent folder:
powershell -command .\Untitled1.ps1 -NonInteractive -ParamExePath "C:\path with spaces\myapp.exe"
Output
Here is what is output after running the script
ParamExePath: C:\path
ThisExePath: C:\path
start-process : This command cannot be run due to the error: The system cannot
find the file specified.
At C:\sample\Untitled1.ps1:11 char:5
+ start-process -FilePath $ThisExePath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
Just change this:
powershell -command .\Untitled1.ps1 -NonInteractive -ParamExePath "C:\path with spaces\myapp.exe"
To This:
powershell -file .\Untitled1.ps1 -NonInteractive -ParamExePath "C:\path with spaces\myapp.exe"
The -Command Parameter used to execute commands for example {Get-Date}
The -File Parameter used to Run .ps1 Script File
-Command
Executes the specified commands (and any parameters) as though they were
typed at the Windows PowerShell command prompt, and then exits, unless
NoExit is specified. The value of Command can be "-", a string. or a
script block.
-File
Runs the specified script in the local scope ("dot-sourced"), so that the
functions and variables that the script creates are available in the
current session. Enter the script file path and any parameters.
File must be the last parameter in the command, because all characters
typed after the File parameter name are interpreted
as the script file path followed by the script parameters.
Type Powershell /? to get full details on each Parameter
A couple of other ways to call it:
powershell -command .\Untitled1.ps1 -NonInteractive "-ParamExePath 'C:\path with spaces\myapp.exe'"
powershell -command ".\Untitled1.ps1 -ParamExePath 'C:\path with spaces\myapp.exe'" -NonInteractive
Note that if you pass a folder path to Powershell that has a trailing backslash it cannot handle it. e.g. -ParamFolder "C:\project folder\app\bin debug\". The parameter string ends up with a double quote at the end. So when you try to append the name of a file to it you end up with something like C:\project folder\app\bin debug"Filename.txt. In this case you have to send in a second backslash at the end.

PowerShell Start-Process -redirectStandardOutput throws: The system cannot find the file specified

In a PowerShell window I am executing:
Start-Process XXXXX.exe -ArgumentList "some valid arguments" -wait
-redirectStandardOutput "D:\\test1.txt"
And getting:
Start-Process : This command cannot be executed due to the error: The system cannot find the file specified.
At line:1 char:14
+ Start-Process <<<< XXXXX.exe -ArgumentList "some valid arguments here" -redirectStandardOutput "D:\\test1.txt"
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
I have checked that the start-process works as expectedif I omit the -redirectStandardOutput argument (it does).
The test1.txt is a NEW file, not trying to append.
The suprising thing is that the test1.txt file on D:\ is created when I run the line, it just remains empty.
Has anyone any idea what is happening here?
Thanks.
EDIT
I discovered that if I run:
Start-Process XXXXX.exe -ArgumentList "some valid arguments" -wait
-redirectStandardOutput "D:\\test1.txt"
it fails (as originally posted)
If I run:
Start-Process XXXXX.exe -ArgumentList "some valid arguments" -wait
it works fine but doesnt save the console output to a file
and if I run
Start-Process .\XXXXX.exe -ArgumentList "some valid arguments" -wait
-redirectStandardOutput "D:\\test1.txt"
It works pretty much as expected.
So why do I need to specify the path when I am using the redirection but when I am not it runs happily?
EDIT
To recapitulate the problem; there appears to be some inconsistancy regarding the requirement that scripts/exes in the current directory require a ./ prefix to be allowed to run. When I am not redirecting the output the ./ is NOT required. Anyone know if this is expected behavior?
RichyRoo,
The issue you're seeing is most likely because your XXXXX.exe location isn't registered inside your PATH environment variable.
If you try to run your command using an application registered inside one of the folders defined inside your PATH environment variable, it should work without the trailing .\
ie:
Start-Process cmd.exe -ArgumentList "/c ping 127.0.0.1" -redirectStandardOutput "D:\ABC\test.txt" -Wait
I tried a 2nd example using a sample batch file and it doesn't work without prefixing the path by .\ - It replicates your behavior.
So it works on your end by qualifying your .exe location by prefixing your xxxxx.exe with .\ as I assume your current directory in your shell is your .exe location.
I haven't looked up why current path isn't being looked at the command execution level though.

Powershell opening file path with whitespaces

I'm my PS script I want to be able to run another script in another PS instance by doing the following:
$filepath = Resolve-Path "destruct.ps1"
start-process powershell.exe "$filepath"
destruct.ps1 is in the same folder as this script.
However when running this script in a location which includes spaces ("C:\My Scripts\") I will get the following error:
The term 'C:\My' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.
I know by using a '&' with the Invoke-Expression method solves this problem, how can I do the same but by using the start-process method?
try this:
start-process -FilePath powershell.exe -ArgumentList "-file `"$filepath`""
edit after comments:
start-process -FilePath powershell.exe -ArgumentList "-file `"$($filepath.path)`""
side note:
$filepath is a [pathinfo] type and not a [string] type.
You can add escaped double quotes so that you pass a quoted argument:
"`"$filepath`""
I am answering here for a general scenario.
If you need to navigate to a folder for example C:\Program Files from the Powerhsell, the following command won't work as it has white space in between the path.
cd C:\Program Files
Instead embed the path with double quotes as like the below.
cd "C:\Program Files"
File name might contain spaces, so preserve spaces in full path:
Notepad++ exec command:
"C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe" "& \"$(FULL_CURRENT_PATH)\""
same from command prompt:
"C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe" "& \"C:\a_work\Systems\name with spaces.ps1\""
Just in case [string]$shipno (which is path & file name) comes in including spaces the following allows it to be passed to -FilePath successfully:
if ($shipno.contains(" ") -eq $true) {
$shipno = """" + $shipno + """"
}

Powershell to open hta in background

I'm doing a project with not enough time to rewrite what is written in HTA.
I need to call a HTA using cmd.exe /C (so it closes the window after it formulates, generating a flashing hta box). I am able to do this in an invoke-expression fashion, but I'm trying to get it as a start-job with a mixture of variables.
$RunHTA = {
param(
[string]$FP, ### filepath to hta
[string]$output) ### output
Invoke-Expression -command 'cmd.exe /C $FP /H:`"$output`"' ### this line works alone. the /H is the save report feature and the double quotes are needed by the hta
}
$fp="C:\Path\To\HTA\file.hta"
$output = "C:\Output\path"
$j = Start-job $RunHTA -ArgumentList $FP,$output
$j | Receive-job
The filename, directory name, or volume label syntax is incorrect.
+ CategoryInfo : NotSpecified: (The filename, d...x is incorrect.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
I've done some testing and the variables are getting passed through correctly. Using returns to see the full variables.
Seems simple and probably something that should work without hassle.
Any ideas?
Try wrapping command in double quotes instead
Invoke-Expression -command "cmd /c $FP /H:`"$output`""