How to Handle Blanks in %UserProfile% Batch File? - powershell

I have created a script that copies our work PowerPoint Presentation Template from DropBox and saves it as the default template.
Some user accounts have spaces, others do not, and I cannot get the Batch file used to trigger this script to run.
I have tried every type of formatting I can think of for this line {}""'' etc
"'%UserProfile%'\'Dropbox'\'Group Team Folder'\'Templates'\'PowerPoint Template.potx'"
The expected result would be for the Batch file to use the blank in the username "John Smith" as part of the path to the PowerPoint template instead of cutting it off.
it spits out an error stating the path "C:\Users\John" is not recognized.
Any help would be greatly appreciated
Edit
#ECHO OFF
If exist "%UserProfile%\Dropbox\Group Team Folder\Templates\PowerPoint Template.potx" (
PowerShell.exe -ExecutionPolicy Bypass -Command "%UserProfile%\Dropbox\Group Team Folder\Templates\Script\Powerpoint Template.ps1"
)
If exist "%UserProfile%\Dropbox (Group)\Group Team Folder\Templates\PowerPoint Template.potx" (
PowerShell.exe -ExecutionPolicy Bypass -Command "%UserProfile%\Dropbox\Group Team Folder\Templates\Script\Powerpoint Template.ps1"
)
PAUSE
Without single ticks, it does not work on the systems with a user profile with no spaces.
Note the reason the code is repeated is because there are 2 different directories for Dropbox on certain systems so it uses the PowerPoint template to determine if the path what path is correct for that system.
Edit 2
C:\Users\John\Dropbox\Group : The term 'C:\Users\John\Dropbox\Group' 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:1
+ C:\Users\John\Dropbox\Group Team Folder\Templates\ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
That is my command prompt error.
I have no idea why this isn't working.

These are the usual ways to run a powershell script;
using -File:
PowerShell.exe -ExecutionPolicy Bypass -File "%UserProfile%\Dropbox\Group Team Folder\Templates\Script\Powerpoint Template.ps1"
using -Command:
PowerShell.exe -ExecutionPolicy Bypass -Command "& '%UserProfile%\Dropbox\Group Team Folder\Templates\Script\Powerpoint Template.ps1'"

I had the same problem with some users trying to copy files from\to their profiles.
I end up using for windows 8.1 the $env variables.
$env:systemDrive\users\$env:USERNAME
but I see you want to run a PowerShell script there so Compo give you the hint on how to run those.

Related

Powershell Set-Location Auto truncate spaces error

I want to write a batch file named install.bat that will run a Powershell script file install.ps1 as Administrator. The content of the batch file install.bat as simple as below:
#echo off
PowerShell -NoExit -Command "Start-Process PowerShell -Verb RunAs '-NoExit -Command "Set-Location ''%cd%''; .\install.ps1"'"
In this batch script, I call a Powershell to run the Start-Process command. This Start-Process command would invoke another Powershell as Administrator. The second Powershell would run Set-Location command to set working directory to %cd% then invoke the install.ps1 script. An error happens with the Set-Location command if i run the install.bat file from a folder with more than 1 consecutive space characters in its name, for example:
D:\New folder
install.bat script will run normally with folder has 1 space character in its name, for example:
D:\New folder
but if a folder has more than 1 consecutive space character like:
D:\New folder
then Set-Location will searching for folder:
D:\New folder
and will show this error incase D:\New folder does not exist:
Can anyone explain this error and give me a solution?
The first thing that I looked with your script was the various control characters (single-quotes, double-quotes, etc.). Nothing obvious stood out.
I looked for other examples, but double-spaces in path names is not necessarily a common occurrence.
So I poked around and did some tests in a Command Prompt box, created a comparable test directory, and checked to see what outputs I could get.
First I sent the Current Directory variable to a PowerShell command to echo the value:
C:\temp\test\test 123>powershell -Command "Write-Host %cd%"
The output had stripped one of the space characters from the path name as you had described (double-quotes added for clarity):
"C:\temp\test\test 123"
Then I tried it with the variable within single-quotes:
C:\temp\test\test 123>powershell -Command "Write-Host '%cd%'"
This output preserved the space characters of the path name correctly (double-quotes added for clarity):
"C:\temp\test\test 123"
Then I tried it with the variable within two pairs of single-quotes as you had used in your script:
C:\temp\test\test 123>powershell -Command "Write-Host ''%cd%''"
This output also stripped one of the space characters from the path name, and it also added a space character to the front of the returned value (double-quotes added for clarity):
" C:\temp\test\test 123"
So it seems that your script might get corrected by changing to one pair of single-quotes surrounding the Current Directory variable call instead of the two pairs of single-quotes.
I'm not sure if you had another purpose for using the two pairs of single-quotes, and I suppose that most processes might not care about the extra leading space on the value return.
I hope that this helps with your script.

Attempt to run a PowerShell script from a batch file is failing

The following batch-file is generating the exception:
& : The term '.\Run-Regression.ps1' 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:3
+ & '.\Run-Regression.ps1' -InputCSV '..\Desktop\tests\V10MWB.csv' -CAR ...
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (.\Run-Regression.ps1:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
What am I doing wrong? and/or how do I resolve this issue?
I do want to preserve relative paths because powershell has additional dependencies.
#ECHO OFF
:: Enable PowerShell script execution
PowerShell Set-ExecutionPolicy Unrestricted
:: Navigate to the 'Common' directory (preserves relative paths)
PUSHD %~dp0\..\Common
:: Prepare the 'logs' directory
IF NOT EXIST ..\logs (MD ..\logs)
DEL /Q ..\logs\*.log 1>NUL 2>&1
:: Execute script
PowerShell "& 'Run-Regression.ps1' -InputCSV '..\Desktop\tests\%1.csv' -CARS_ID 0 -RunOnDesktop -Log -Email -Progress -Archive 2>&1" 1>"..\logs\%1.log";
:: Navigate back to original directory
POPD
According to the error message, it can't find the script in the current directory as you are invoking it. Either change to the correct directory, or invoke it with the fully-qualified path.
Working with relative paths there can be a misunderstanding with what is a startup folder where your batch file is started.
If your batch and PowerShell scripts located in the same folder and you don't want to care about startup folder, try %~dp0 instruction - it'll point to the folder, where batch file is located.
For example, this will execute Run-Regression.ps1 script located in the same folder with bat\cmd file without taking into account execution policy and startup folder.
PowerShell.exe -ExecutionPolicy Bypass -File %~dp0Run-Regression.ps1
You can find more useful thing in this thread: What does %~dp0 mean, and how does it work?
Your error message does not match the actual invocation command that is part of your batch file:
PowerShell "& 'Run-Regression.ps1' ..." ...
fails, because PowerShell by design does not permit running executables and scripts by mere file name from inside PowerShell (whether invoked directly or via &, the call operator).
Instead, you must prepend .\ to explicitly signal the intent to run a script from the current directory.
PowerShell "& .\Run-Regression.ps1 ..." ...
If your *.ps1 isn't actually in the current directory, but in the batch file's, see Vladimir Dronov's helpful answer
However, consider using the -File CLI parameter instead of the (implied) -Command parameter, in which case the .\ prefix isn't needed and which simplifies the syntax in general:
PowerShell -File Run-Regression.ps1 -InputCSV ..\Desktop\tests\%1.csv -CARS_ID 0 -RunOnDesktop -Log -Email -Progress -Archive 2>&1 1>"..\logs\%1.log";
Note:
There are many subtle differences between using -File and -Command; for more information, see this answer.
PowerShell [Core], whose executable name is pwsh.exe, defaults to -File, not -Command, a change that was needed to support scripts with shebang lines on Unix-like platforms.
Thank you all for your responses, because they helped me bring together the following solution which is working very well for my situation:
PUSHD %~dp0..\Common
...
PowerShell "& '%CD%.\Run-Regression.ps1' ...
POPD
Thanks again,
Allan G.

Open a file with a PowerShell script in explorer

I wanted to use Windows built-in table viewer to open CSV file, like this SO answer shows.
So I want that when I double click on a CSV file in Explorer, the following command is run:
Import-Csv [CSV-FILE] |Out-GridView
I ended up creating two script files. One file name "read_csv.bat" which contains:
powershell.exe -ExecutionPolicy ByPass -noexit -File %~dp0read_csv.ps1 -csvfile %1
pause
Another file name "read_csv.ps1" which contains the actual script
param (
[Parameter(Mandatory=$true)][string]$csvfile
)
Import-Csv $csvfile |Out-GridView
Is there now way to do it more efficiently, so with only one script file? If I set explorer to open the CSV file with the POwerShell script directly, a blue message appears
This app can't run on your PC
To find a version for your PC, check with your published
Note:
Since powershell.exe is ultimately called, a console window will invariably (also) open when a CSV file is opened, because powershell.exe is a console-subsystem application.
Providing an alternative, GUI-subsystem executable to avoid creating a console window is the subject of this feature request on GitHub; in the meantime, there are workarounds:
A VBScript-based solution is shown in this answer.
A script-less, but complex and potentially AV-software-triggering alternative is used in this answer.
You'll need to use an adapted version of the powershell.exe command from your batch file, because *.ps1 files are by design not directly executable.
That is, in the registry definition for the CSV file type, use the following command to define the action for the Open verb (see below):
powershell.exe -ExecutionPolicy ByPass -NoExit -File c:\path\to\read_csv.ps1 -csvfile "%1"
Be sure to substitute the real path to your *.ps1 script for c:\path\to\read_csv.ps1 (double-quote it, if necessary); you can either use a literal path, or one based on cmd.exe-style environment-variable references (e.g., "%USERPROFILE%\read_csv.ps1").
Alternatively, you can make do without a script file altogether, using the PowerShell CLI's -Command parameter:
powershell.exe -ExecutionPolicy ByPass -NoExit -Command Import-Csv \"%1\" | Out-GridView
To automate the process of configuring this command for opening CSV files via File Explorer / the desktop:
The code below modifies the registry as follows:
defines a new file type, PsCsvViewer, with an Open verb (operation) that invokes the PowerShell command defined above.
associates the .csv filename extension with that new file type.
Note: The first time you open a CSV file after the redefinition, you may be prompted to confirm the intent to use a PowerShell command from now on.
creates the definitions above for the current user only, which means that you don't need admin privileges to run the code (which writing to subkeys of HKEY_CLASSES_ROOT\ would require).
# Note the need for *3* "\", because an extra layer of escaping is
# needed for reg.exe.
$cmd = 'powershell.exe -ExecutionPolicy ByPass -NoExit -Command Import-Csv \\\"%1\\\" | Out-GridView'
# Create a new file type for the PowerShell command.
reg.exe add HKCU\Software\Classes\PsCsvViewer\Shell\Open\command /ve /d $cmd /f
# Associate .csv files with the new file type.
reg.exe add HKCU\Software\Classes\.csv /ve /d PsCsvViewer /f

How do I run powershell scripts without admin rights?

If I try to change the execution policy, I get a message that says I can't modify the registry because I'm not an administrator.
It seems like this should be possible, since I can run batch files and other .exe and .com programs.
If your domain administrator hasn't forbidden it, you can do this:
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser
This changes the default execution policy for PowerShell sessions run under the current user, rather than setting it for all users on the machine.
If you instead want to change the execution policy for just the current PowerShell session, you can use this command:
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
However, if your domain administrator is using the "Turn on Script Execution" group policy, you will not be able to change your execution policy at all. The group policy setting makes the Set-ExecutionPolicy cmdlet ineffective.
You can try and set the policy of the process itself.
powershell.exe -ExecutionPolicy bypass
if you want to have an easy way to run a script myscript.ps1 from the windows shell then all you need is a bat Runmyscript.bat with the following contents:
type myscript.ps1 | powershell -
So simple it makes me wonder why you can't just run the ps1 in the first place, but there we go.
A generic version that prompts for userinput to type the name of the script would be:
set /p filename="Type name of script here: "
type %filename% | powershell -
I suppose if you wanted to, you could also write a generic vbscript script that opens any file in powershell using a dialogue box using this http://todayguesswhat.blogspot.co.uk/2012/08/windows-7-replacement-for.html
how about
$script = Get-Content .\test.ps1
Invoke-Expression $script
This works for me. Try this: cmd /min /C "set __COMPAT_LAYER=RUNASINVOKER && start "" %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
The third technique I've found elsewhere on the internet is to use
powershell.exe -EncodedCommand XXXXXXX
where XXXXXXX is the result of
$code = {
#powershell script goes here.
}
}
[convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($code))
Ref:
http://dmitrysotnikov.wordpress.com/2008/06/27/powershell-script-in-a-bat-file/

Set up PowerShell Script for Automatic Execution

I have a few lines of PowerShell code that I would like to use as an automated script. The way I would like it to be able to work is to be able to call it using one of the following options:
One command line that opens PowerShell, executes script and closes PowerShell (this would be used for a global build-routine)
A file that I can double-click to run the above (I would use this method when manually testing components of my build process)
I have been going through PowerShell documentation online, and although I can find lots of scripts, I have been unable to find instructions on how to do what I need. Thanks for the help.
From http://blogs.msdn.com/b/jaybaz_ms/archive/2007/04/26/powershell-polyglot.aspx
If you're willing to sully your beautiful PowerShell script with a little CMD, you can use a PowerShell-CMD polyglot trick. Save your PowerShell script as a .CMD file, and put this line at the top:
#PowerShell -ExecutionPolicy Bypass -Command Invoke-Expression $('$args=#(^&{$args} %*);'+[String]::Join(';',(Get-Content '%~f0') -notmatch '^^#PowerShell.*EOF$')) & goto :EOF
If you need to support quoted arguments, there's a longer version, which also allows comments. (note the unusual CMD commenting trick of double #).
##:: This prolog allows a PowerShell script to be embedded in a .CMD file.
##:: Any non-PowerShell content must be preceeded by "##"
##setlocal
##set POWERSHELL_BAT_ARGS=%*
##if defined POWERSHELL_BAT_ARGS set POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=\"%
##PowerShell -ExecutionPolicy Bypass -Command Invoke-Expression $('$args=#(^&{$args} %POWERSHELL_BAT_ARGS%);'+[String]::Join(';',$((Get-Content '%~f0') -notmatch '^^##'))) & goto :EOF
Save your script as a .ps1 file and launch it using powershell.exe, like this:
powershell.exe .\foo.ps1
Make sure you specify the full path to the script, and make sure you have set your execution policy level to at least "RemoteSigned" so that unsigned local scripts can be run.
Run Script Automatically From Another Script (e.g. Batch File)
As Matt Hamilton suggested, simply create your PowerShell .ps1 script and call it using:
PowerShell C:\Path\To\YourPowerShellScript.ps1
or if your batch file's working directory is the same directory that the PowerShell script is in, you can use a relative path:
PowerShell .\YourPowerShellScript.ps1
And before this will work you will need to set the PC's Execution Policy, which I show how to do down below.
Run Script Manually Method 1
You can see my blog post for more information, but essentially create your PowerShell .ps1 script file to do what you want, and then create a .cmd batch file in the same directory and use the following for the file's contents:
#ECHO OFF
SET ThisScriptsDirectory=%~dp0
SET PowerShellScriptPath=%ThisScriptsDirectory%MyPowerShellScript.ps1
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%PowerShellScriptPath%'"
Replacing MyPowerShellScript.ps1 on the 3rd line with the file name of your PowerShell script.
This will allow you to simply double click the batch file to run your PowerShell script, and will avoid you having to change your PowerShell Execution Policy.
My blog post also shows how to run the PowerShell script as an admin if that is something you need to do.
Run Script Manually Method 2
Alternatively, if you don't want to create a batch file for each of your PowerShell scripts, you can change the default PowerShell script behavior from Edit to Run, allowing you to double-click your .ps1 files to run them.
There is an additional registry setting that you will want to modify so that you can run scripts whose file path contains spaces. I show how to do both of these things on this blog post.
With this method however, you will first need to set your execution policy to allow scripts to be ran. You only need to do this once per PC and it can be done by running this line in a PowerShell command prompt.
Start-Process PowerShell -ArgumentList 'Set-ExecutionPolicy RemoteSigned -Force' -Verb RunAs
Set-ExecutionPolicy RemoteSigned -Force is the command that actually changes the execution policy; this sets it to RemoteSigned, so you can change that to something else if you need. Also, this line will automatically run PowerShell as an admin for you, which is required in order to change the execution policy.
Source for Matt's answer.
I can get it to run by double-clicking a file by creating a batch file with the following in it:
C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe LocationOfPS1File
you can use this command :
powershell.exe -argument c:\scriptPath\Script.ps1