So I've got this pretty basic powershell script to backup files to our network drive:
Function Backup {
param ($backupSource)
#Define backup location
$backupTarget = '\\192.168.0.247\Public'
#Make sure we're targeting a folder
If (!(Test-Path $backupSource -pathtype container)) {
[System.Windows.Forms.MessageBox]::Show("Target must be a folder" , "Error", 0)
Exit
}
#Make sure we have access to the backup location
DO {
$test = Test-Path $backupTarget
If (!$test) {
$loop = [System.Windows.Forms.MessageBox]::Show("Is the WiFi on? I can't reach the public drive. Maybe try again in a second." , "Internet Connection Unavailable" , 5)
If ($loop -eq 'Cancel') {
Exit
}
}
} WHILE (!$test)
Copy-Item $backupSource $backupTarget -recurse
}
I'm trying to get it to work in a right click menu, making it show up is no problem, and it executes, but I can't figure out how to successfully feed it the $backupSource parameter.
I'm working out of HKEY_CLASSES_ROOT\Directory\shell\NASBackup\command with my default key. I've tried every combination of "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -File "C:\Windows\System32\Backup.ps1" "%1" I can think of. Can someone please help me out with the syntax here?
The script as provided doesn't work with command line arguments. i.e. calling the script as is doesn't work.
Try adding the call to the function passing the command line arguments.
At the end of your script add:
Backup $args[0]
I do it like this.
First I start cmd.exe from inside the registry. CMD window will appear briefly while it sends the powershell command.
Second I call powershell with the hidden switch so the rest of it runs invisibly.
Below is a working .reg file.
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Directory\shell\NASBackup\command]
#="cmd /c start /b /wait powershell.exe -nologo -WindowStyle Hidden -file C:\\Windows\\System32\\Backup.ps1"
;
Here is a powershell snip to set the same bits in the registry.
If ( -Not ( Test-Path "Registry::HKEY_CLASSES_ROOT\Directory\shell\NASBackup\command")){New-Item -Path "Registry::HKEY_CLASSES_ROOT\Directory\shell\NASBackup\command" -ItemType RegistryKey -Force}
Set-ItemProperty -path "Registry::HKEY_CLASSES_ROOT\Directory\shell\NASBackup\command" -Name "(Default)" -Type "String" -Value "cmd /c start /b /wait powershell.exe -nologo -WindowStyle Hidden -file C:\Windows\System32\Backup.ps1"
#
Related
I am so confused and actually also not so familiar with PS and bat after my troubles with them.
I want to set the Lockscreen in Windows 10 with Intune through an IntuneWin file (WIN32 application).
I have a folder with the image, which I want to set, a copy.bat which should copy the image in the directory and also execute the PS file for setting the login image and a del.bat for deleting the image.
copy.bat
md %AllUsersProfile%\sz
copy /Y Wallpaper.jpg %AllUsersProfile%\sz
powershell -ExecutionPolicy Bypass -File Set-Lockscreen.ps1 -verb RunAs
del.bat
del /Y %AllUsersProfile%\sz\Wallpaper.jpg
Set-Lockscreen.ps1
$RegKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationLS"
$LockScreenPath = "LockScreenImagePath"
$LockScreenStatus = "LockScreenImageStatus"
$LockScreenUrl = "LockScreenImageUrl"
$StatusValue = "1"
$path = "C:\ProgramData\Elinvar"
$LockScreenImageValue = "C:\ProgramData\sz\Wallpaper.jpg"
sIf ((Test-Path -Path $path) -eq $false)
{
New-Item -Path $path -ItemType directory
}
if (!(Test-Path $RegKeyPath))
{
Write-Host "Creating registry path $($RegKeyPath)."
New-Item -Path $RegKeyPath -Force | Out-Null
}
New-ItemProperty -Path $RegKeyPath -Name $LockScreenStatus -Value $StatusValue -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path $RegKeyPath -Name $LockScreenPath -Value $LockScreenImageValue -PropertyType STRING -Force | Out-Null
New-ItemProperty -Path $RegKeyPath -Name $LockScreenUrl -Value $LockScreenImageValue -PropertyType STRING -Force | Out-Null
RUNDLL32.EXE USER32.DLL, UpdatePerUserSystemParameters 1, True
I pack all these files with Microsoft Win32 Content Prep Tool and upload this in Intune as Win32 file.
Upload works, assigning to a group works, installation is successful. All good so far, I thought.
If I check the directory, the image is in %AllUsersProfile%\sz.
But when I check the reg, the entry is not set.
When I run the copy.bat file manually, It doesn't work. Only when I run it as administrator.
When I run the last line in cmd as administrator, so
powershell -ExecutionPolicy Bypass -File Set-Lockscreen.ps1 -verb RunAs
It works as well.
I think Intune is not running the script as administrator.
In Intune there is no configuration to say, run this command as administrator.
Maybe with a syntax? Does anyone know this?
Something like
copy.bat RunAs
I also export the reg file and import this with
reg import PersonalizationLS.reg
It didn't work.
I think there must be a way to execute the installation command in intune to run the script as admin.
It needs just for the last line the administrator privilege , md and copy work without administrator privileges. (same also for important reg file).
Hi I wrote a simple powershell script to:
Create a IE shortcut to a site
Disable Mixed Code Security Verification for Java control panel
Add a few sites as trusted sites
The script runs fine when I manually copy and paste it into powershell.
However, when I save it as a .ps1 file and 'Run with Powershell' - it doesn't seemingly execute (changes aren't made).
I tried changing execution policy to Bypass but it still does not execute.
Any thoughts on how I can get the .ps1 script to execute by using 'Run with Powershell'?
This is so my users can simply run this script without having to copy and paste into powershell.
Thank you,
Asif
Here is the full script for reference:
& powershell.exe -executionpolicy bypass -file C:\Users\AZahir\Desktop\ps2.ps1
$Shell = New-Object -ComObject ("WScript.Shell")
$ShortCut = $Shell.CreateShortcut($env:USERPROFILE + "\Desktop\Jacada.lnk")
$ShortCut.TargetPath = "C:\Program Files (x86)\Internet Explorer\iexplore.exe"
$ShortCut.Arguments = "http://facebook.com"
$ShortCut.WorkingDirectory = "C:\Program Files (x86)\Internet Explorer";
$ShortCut.WindowStyle = 1;
$ShortCut.IconLocation = "C:\Program Files (x86)\Internet Explorer\iexplore.exe"
$ShortCut.Save()
Add-Content -Path "$env:USERPROFILE\AppData\LocalLow\Sun\Java\Deployment\deployment.properties" -Value ('deployment.security.mixcode=DISABLE')
Set-Location "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
Set-Location ZoneMap\Domains
New-Item bpoazusargdb01d
Set-Location bpoazusargdb01d
New-ItemProperty . -Name http -Value 2 -Type DWORD
Set-Location "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
Set-Location ZoneMap\Domains
New-Item "172.30.1.3"
Set-Location "172.30.1.3"
New-ItemProperty . -Name http -Value 2 -Type DWORD
Set-Location "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
Set-Location ZoneMap\Domains
New-Item "172.30.1.49"
Set-Location "172.30.1.49"
New-ItemProperty . -Name http -Value 2 -Type DWORD
Set-Location "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
Set-Location ZoneMap\Domains
New-Item "172.30.1.89"
Set-Location "172.30.1.89"
New-ItemProperty . -Name http -Value 2 -Type DWORD
Leaving my original answer below but I've since found a more effective way without the file copy:
# 2>NUL & #powershell -nop -ep bypass "(gc '%~f0')-join[Environment]::NewLine|iex" && #EXIT /B 0
This is to be included as your first line of the powershell script, saved as a .cmd file.
Breakdown:
# 2>NUL &
This handles the batch part of our file so we can get that click-execution functionality. Since # isn't a filename or command, it throws an error we ignore with 2>NUL and skip to the next command with &.
#powershell ...
This is our call to powershell, grabbing the contents of the file (gc: Get-Content) and executing them (iex: Invoke-Expression). We use # so the command isn't echoed to the cli.
&& EXIT /B 0
This will exit the script gracefully if no errors were thrown.
If your only goal is to have a shortcut-clickable link for users to run your powershell script, you can accomplish that with this by pasting your script contents under this header (saved as myscript.cmd or whatever you want to name it):
::<#
#ECHO OFF
REM https://stackoverflow.com/questions/3759456/create-a-executable-exe-file-from-powershell-script#answer-4629494
REM https://blogs.msdn.microsoft.com/zainala/2008/08/05/using-0-inside-the-batch-file-to-get-the-file-info/
SET "pwsh=%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe"
SET "args=-NoProfile -NoLogo -ExecutionPolicy Bypass -Command"
SET "cmd="#(Get-Content -Path '%~f0') -replace '^^::'^|Set-Content -Path '%~dpn0.ps1';. '%~dpn0.ps1' %*""
%pwsh% %args% %cmd%
DEL "%~dpn0.ps1" /Q /F
EXIT
::#>
Simply put, it handles the execution policy and saves itself as a powershell script after replacing the batch-parts as a block comment.
This is so my users can simply run this script without having to copy
and paste into powershell.
Use a bat file side by.
include
PowerShell.exe -executionpolicy bypass -file "%~dp0ps2.ps1"
Remove below from your powershel script.
& powershell.exe -executionpolicy bypass -file C:\Users\AZahir\Desktop\ps2.ps1
When a user double clicks the bat file, they will run the ps2.ps1.
I don't see errors , when i run it . It creates the shortcut and the reg keys. In case, if you are trying to run it second time, it will generate errors saying the reg keys exists..
Also its wise to use """ instead of " more details How to pass msi ArgumentList with $ScriptDir with spaces in powershell?
or else your users may find difficulties running your script, if they put this script in a path with space such as c:\new folder\
I'm trying to create bat script that can start PowerShell script named the same as bat file in proper working directotry.
This is what I got:
#ECHO OFF
PowerShell.exe -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%~dpn0.ps1""' -WorkingDirectory '%~dp0' -Verb RunAs}"
PAUSE
Passing working directory this way does not work.
How to make script that will pass proper working directroy and also command line arguments?
The -WorkingDirectory parameter doesn't work when using -Verb RunAs. Instead, you have to set the working directory by calling cd within a -Command string.
This is what I use: (cmd/batch-file command)
powershell -command " Start-Process PowerShell -Verb RunAs \""-Command `\""cd '%cd%'; & 'PathToPS1File';`\""\"" "
If you want to make a "Run script as admin" right-click command in Windows Explorer, create a new registry key at HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Run with PowerShell (Admin)\Command, and set its value to the command above -- except replacing %cd% with %W, and PathToPS1File with %1 (if you want it to execute the right-clicked file).
Result: (Windows Explorer context-menu shell command)
powershell -command " Start-Process PowerShell -Verb RunAs \""-Command `\""cd '%W'; & '%1';`\""\"" "
EDIT: There's an alternative way to have the script be run as admin from Explorer, by using the "runas" sub-key: https://winaero.com/blog/run-as-administrator-context-menu-for-power-shell-ps1-files
If you want to run your script as admin from an existing powershell, remove the outer powershell call, replace %W with $pwd, replace %1 with the ps1 file-path, and replace each \"" with just ".
Note: The \""'s are just escaped quotes, for when calling from the Windows shell/command-line (it's quote-handling is terrible). In this particular case, just \" should also work, but I use the more robust \"" for easier extension.
See here for more info: https://stackoverflow.com/a/31413730/2441655
Result: (PowerShell command)
Start-Process PowerShell -Verb RunAs "-Command `"cd '$pwd'; & 'PathToPS1File';`""
Important note: The commands above are assuming that your computer has already been configured to allow script execution. If that's not the case, you may need to add -ExecutionPolicy Bypass to your powershell flags. (you may also want -NoProfile to avoid running profile scripts)
A workaround is to let the PowerShell script change the directory to it's own origin with:
Set-Location (Split-Path $MyInvocation.MyCommand.Path)
as the first command.
As per mklement0s hint: In PSv3+ use the simpler:
Set-Location -LiteralPath $PSScriptRoot
Or use this directory to open adjacent files.
$MyDir = Split-Path $MyInvocation.MyCommand.Path
$Content = Get-Content (Join-Path $MyDir OtherFile.txt)
I have to automate test cases.
Tasks:-
Step:-Open administrative command prompt from powershell.
Step:-Execute a batch file on the administrative command prompt.
Step:-Batch file includes some set of commands, including a execution of an exe.
For Example:- runas /user:administrator /savecred someCmd.exe >>D:\output.txt
Step:-Capture output of the exe in a variable for verification of the output.
i have used "
start-process -verb runas cmd.exe $param" cmdlet for opening administrative command prompt(Step 1).
Where $param contains the batch file to be executed.
Problem Statement:- When batch file executes the runas command mentioned above, it opens a new command prompt and the output is displayed in the prompt and it closes itself.
i am not able to capture the output(not getting written in the output.txt) based on which i have to do some verification.
you can use the the output redirection from the batch :
$params="/C ipconfig /all 2>&1 >>c:\temp\test.txt"
start-process -verb runas cmd.exe $params
gc c:\temp\test.txt
I ended up creating a wrapper batch file OutputWrapper.bat that takes at least two arguments:
1) output file
2) command
3) [optional] arguments
#ECHO OFF
IF "%2" == "" GOTO usage
SET OUTPUTFILE=%1
SET COMMAND=%2
SET ARGS=
SHIFT /2
:loop1
IF "%2"=="" GOTO exec
SET ARGS=%ARGS% %2
SHIFT
GOTO loop1
:exec
ECHO Command [%COMMAND%]
ECHO Arguments [%ARGS%]
ECHO Output file [%OUTPUTFILE%]
%COMMAND%%ARGS% > %OUTPUTFILE% 2>&1
GOTO end
:usage
ECHO Usage: %~nx0 outputfile command [arguments]
:end
and calling it from PowerShell like this:
$outFile = "C:\Temp\Deploy.out";
Start-Process -FilePath .\OutputWrapper.bat -ArgumentList "$outfile","whoami.exe","/priv" -Verb RunAs -Wait
Get-Content $outFile;
Solution
Open administrative command prompt from powershell.
executed a batch file in the runas command. For example: runas /user:administrator /savecred mybatch.bat
Batch file includes some set of commands, including a execution of an exe. For example someCmd.exe >>D:\output.txt
Capture output of the exe in a variable for verification of the output.
Now the output was captured and was written into a file. My target was to capture the output of the command and this was the solution through which I solved it.
I had the same problem and solved it by the use of gsudo. It let me run the elevated command and tunneled the output back from it.
gsudo {command-to-execute}
Improvement on Loïc MICHEL's answer, as without -Wait, it's likely that Get-Content will run before the process has finished. As the output isn't written until the process ends, Get-Content fails as the file does not exist.
$param = "ipconfig /all"
$args = "/C $param 2>&1 > C:\temp\test.txt"
Start-Process -FilePath cmd.exe -ArgumentList $args -Verb RunAs -Wait
Get-Content -Path C:\temp\test.txt
Alternatively, using powershell.exe instead and a random file in the temporary directory for the OS:
$CommandWithParameters = "gpresult /scope computer /z"
$OutputFile = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath ([System.IO.Path]::GetRandomFileName())
$Arguments = ("{0} 2>&1 > {1}" -f $CommandWithParameters, $OutputFile)
Start-Process -FilePath powershell.exe -ArgumentList $Arguments -Verb RunAs -Wait
Get-Content -Path $OutputFile
Using powershell.exe will save the output file using UCS-2 LE BOM encoding. If you use cmd.exe, the encoding will be ANSI.
I am trying to run this script in PowerShell. I have saved the below script as ps.ps1 on my desktop.
$query = "SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2"
Register-WMIEvent -Query $query -Action { invoke-item "C:\Program Files\abc.exe"}
I have made a batch script to run this PowerShell script
#echo off
Powershell.exe set-executionpolicy remotesigned -File C:\Users\SE\Desktop\ps.ps1
pause
But I am getting this error:
You need the -ExecutionPolicy parameter:
Powershell.exe -executionpolicy remotesigned -File C:\Users\SE\Desktop\ps.ps1
Otherwise PowerShell considers the arguments a line to execute and while Set-ExecutionPolicy is a cmdlet, it has no -File parameter.
I explain both why you would want to call a PowerShell script from a batch file and how to do it in my blog post here.
This is basically what you are looking for:
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& 'C:\Users\SE\Desktop\ps.ps1'"
And if you need to run your PowerShell script as an admin, use this:
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""C:\Users\SE\Desktop\ps.ps1""' -Verb RunAs}"
Rather than hard-coding the entire path to the PowerShell script though, I recommend placing the batch file and PowerShell script file in the same directory, as my blog post describes.
If you want to run from the current directory without a fully qualified path, you can use:
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& './ps.ps1'"
If you run a batch file calling PowerShell as a administrator, you better run it like this, saving you all the trouble:
powershell.exe -ExecutionPolicy Bypass -Command "Path\xxx.ps1"
It is better to use Bypass...
Small sample test.cmd
<# :
#echo off
powershell /nologo /noprofile /command ^
"&{[ScriptBlock]::Create((cat """%~f0""") -join [Char[]]10).Invoke(#(&{$args}%*))}"
exit /b
#>
Write-Host Hello, $args[0] -fo Green
#You programm...
Posted it also here:
How to run powershell command in batch file
Following this thread:
https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/converting-powershell-to-batch
you can convert any PowerShell script into a batch file easily using this PowerShell function:
function Convert-PowerShellToBatch
{
param
(
[Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
[string]
[Alias("FullName")]
$Path
)
process
{
$encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw -Encoding UTF8)))
$newPath = [Io.Path]::ChangeExtension($Path, ".bat")
"#echo off`npowershell.exe -NoExit -encodedCommand $encoded" | Set-Content -Path $newPath -Encoding Ascii
}
}
To convert all PowerShell scripts inside a directory, simply run the following command:
Get-ChildItem -Path <DIR-PATH> -Filter *.ps1 |
Convert-PowerShellToBatch
Where is the path to the desired folder. For instance:
Get-ChildItem -Path "C:\path\to\powershell\scripts" -Filter *.ps1 |
Convert-PowerShellToBatch
To convert a single PowerShell script, simply run this:
Get-ChildItem -Path <FILE-PATH> |
Convert-PowerShellToBatch
Where is the path to the desired file.
The converted files are located in the source directory. i.e., <FILE-PATH> or <DIR-PATH>.
Putting it all together:
create a .ps1 file (PowerShell script) with the following code in it:
function Convert-PowerShellToBatch
{
param
(
[Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
[string]
[Alias("FullName")]
$Path
)
process
{
$encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw -Encoding UTF8)))
$newPath = [Io.Path]::ChangeExtension($Path, ".bat")
"#echo off`npowershell.exe -NoExit -encodedCommand $encoded" | Set-Content -Path $newPath -Encoding Ascii
}
}
# change <DIR> to the path of the folder in which the desired powershell scripts are.
# the converted files will be created in the destination path location (in <DIR>).
Get-ChildItem -Path <DIR> -Filter *.ps1 |
Convert-PowerShellToBatch
And don't forget, if you wanna convert only one file instead of many, you can replace the following
Get-ChildItem -Path <DIR> -Filter *.ps1 |
Convert-PowerShellToBatch
with this:
Get-ChildItem -Path <FILE-PATH> |
Convert-PowerShellToBatch
as I explained before.
If you want to run a few scripts, you can use Set-executionpolicy -ExecutionPolicy Unrestricted and then reset with Set-executionpolicy -ExecutionPolicy Default.
Note that execution policy is only checked when you start its execution (or so it seems) and so you can run jobs in the background and reset the execution policy immediately.
# Check current setting
Get-ExecutionPolicy
# Disable policy
Set-ExecutionPolicy -ExecutionPolicy Unrestricted
# Choose [Y]es
Start-Job { cd c:\working\directory\with\script\ ; ./ping_batch.ps1 example.com | tee ping__example.com.txt }
Start-Job { cd c:\working\directory\with\script\ ; ./ping_batch.ps1 google.com | tee ping__google.com.txt }
# Can be run immediately
Set-ExecutionPolicy -ExecutionPolicy Default
# [Y]es
Another easy way to execute a ps script from batch is to simply incorporate it between the ECHO and the Redirection characters,(> and >>),
example:
#echo off
set WD=%~dp0
ECHO New-Item -Path . -Name "Test.txt" -ItemType "file" -Value "This is a text string." -Force > "%WD%PSHELLFILE.ps1"
ECHO add-content -path "./Test.txt" -value "`r`nThe End" >> "%WD%PSHELLFILE.ps1"
powershell.exe -ExecutionPolicy Bypass -File "%WD%PSHELLFILE.ps1"
del "%WD%PSHELLFILE.ps1"
Last line deletes the created temp file.
If your PowerShell login script is running after 5 minutes (as mine was) on a 2012 server, there is a GPO setting on a server - 'Configure Login script Delay' the default setting 'not configured' this will leave a 5-minute delay before running the login script.