How to add -OutputPath parameter to Powershell script being called from batch file? - powershell

Using a batch file to call a Powershell script (this part is working and saving the output files locally):
PowerShell.exe -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File ""%~dpn0.ps1 -Update""' -Verb RunAs}"
Trying to add in a parameter to redirect the output of the script to a folder (per the code comments it can be to a local or UNC path):
-OutputPath Z:\Current
Have tried inserting it everywhere I can think of in the script, cannot get it to work; am thinking it should go in like this(?):
PowerShell.exe -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File ""%~dpn0.ps1 -OutputPath Z:\Current""' -Verb RunAs}"
Here is where the output path is determined in the code:
# If -OutputPath not specified, set default
If (-not($OutputPath)) {
Switch ($OSPlatform) {
"Windows" {
$OutputPath = "$env:PUBLIC\Documents\ Compliance"
if (!(Test-Path $OutputPath)) {
$null = New-Item -Path $(Split-Path -Path $OutputPath -Parent) -Name $(Split-Path -Path $OutputPath -Leaf) -ItemType Directory
}
}
"Linux" {
$OutputPath = "/opt/STIG_Compliance"
if (!(Test-Path $OutputPath)) {
sudo mkdir $OutputPath
}
}
}
}
From what I can find online, the -OutputPath Z:\Current should come immediately after the .ps1 command, but not sure where it should be inserted amongst the other options being used in the batch file.
The script is not throwing off any errors, but is running and saving the output in the default locatin. I am not that well-versed in Powershell; am I missing something?
Thanks in advance for your help!!

It seems like you're trying to pass the OutputPath parameter to your PowerShell script through the command line argument -File. I believe the correct way to pass parameters to a PowerShell script is to include them in the argument list of the PowerShell command.
You could update your command to include the OutputPath parameter in the argument list, like this:
PowerShell.exe -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File ""%~dpn0.ps1""', '-OutputPath', 'Z:\Current' -Verb RunAs}"
Also, make sure to update your PowerShell script to properly use the OutputPath parameter, like this:
# If -OutputPath not specified, set default
if (-not $OutputPath) {
switch ($OSPlatform) {
"Windows" {
$OutputPath = "$env:PUBLIC\Documents\Compliance"
if (!(Test-Path $OutputPath)) {
$null = New-Item -Path $(Split-Path -Path $OutputPath -Parent) -Name $(Split-Path -Path $OutputPath -Leaf) -ItemType Directory
}
}
"Linux" {
$OutputPath = "/opt/STIG_Compliance"
if (!(Test-Path $OutputPath)) {
sudo mkdir $OutputPath
}
}
}
}
# Redirect output to the specified output path
if ($OutputPath) {
$OutputFile = Join-Path -Path $OutputPath -ChildPath "output.txt"
Write-Output "Writing output to $OutputFile"
# Your code to generate output here
# ...
Out-File -FilePath $OutputFile -InputObject "Output data"
}
else {
# Your code to generate output here
# ...
}
Hopefully this helps ya.

Related

Self building powershell script

I'm currently trying to make ps1 script that creates another ps1 script via echo, add-content, clip and so forth.
What I'm trying to do is write a ps1 script that gets a folder, stores it in a variable ($VBS) and writes the new ps1 to a file in that folder to afterwards run it from that folder. Here's my code so far:
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe -windowstyle hidden "-NoProfile -ExecutionPolicy RemoteSigned -File `"$PSCommandPath`"" -Verb RunAs; exit }
cd \
$VBS = gci -Recurse -Filter "Folder" -Directory -ErrorAction SilentlyContinue -path "C:\"
cd "$env:USERPROFILE\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
echo $VBS | ForEach-Object { $_.FullName } > KickStart.ps1
cat KickStart.ps1 | set-clipboard
echo '"if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe -windowstyle hidden "-NoProfile -ExecutionPolicy RemoteSigned -File `"$PSCommandPath`"" -Verb RunAs; exit }' > KickStart.ps1
add-content KickStart.ps1 "`ncd \"
add-content KickStart.ps1 "`ncd"
add-content KickStart.ps1 ' "'
add-content KickStart.ps1 | get-clipboard
add-content KickStart.ps1 '"'
add-content KickStart.ps1 '`nstart File.vbs'
add-content KickStart.ps1 '`n cd \'
add-content KickStart.ps1 '`ncd "$env:USERPROFILE\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"'
add-content KickStart.ps1 'rm KickStart.ps1'
The final product (KickStart.ps1) should look like this:
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe -windowstyle hidden "-NoProfile -ExecutionPolicy RemoteSigned -File `"$PSCommandPath`"" -Verb RunAs; exit }
cd \
cd "C:\PATH\TO\FOLDER"
start file.vbs
cd \
cd "$env:USERPROFILE\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
rm KickStart.ps1
Instead my current scripts generates this:
"if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe -windowstyle hidden "-NoProfile -ExecutionPolicy RemoteSigned -File `"$PSCommandPath`"" -Verb RunAs; exit }
cd \
cd
"
"
`nstart File.vbs
`n cd \
`ncd "$env:USERPROFILE\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
rm KickStart.ps1
I seriously don't know what I'm doing wrong, I've put in almost 12 hours finding the solutions, help would be appreciated.
Although not entirely sure what you are trying to achieve, but looking at the desired output, why not build the content using a Here-String like this:
#'
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")) {
Start-Process powershell.exe -WindowStyle Hidden -NoProfile -ExecutionPolicy RemoteSigned -File "$PSCommandPath" -Verb RunAs
exit
}
Set-Location \
Set-Location "C:\PATH\TO\FOLDER"
Start-Process file.vbs
Set-Location \
Set-Location "$env:USERPROFILE\AppData\Roaming\Microsoft\Windows\Start-Process Menu\Programs\Startup"
Remove-Item KickStart.ps1
'# | Set-Content -Path 'THE PATH FOR THE KickStart.ps1 FILE'
Result:
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")) {
Start-Process powershell.exe -WindowStyle Hidden -NoProfile -ExecutionPolicy RemoteSigned -File "$PSCommandPath" -Verb RunAs
exit
}
Set-Location \
Set-Location "C:\PATH\TO\FOLDER"
Start-Process file.vbs
Set-Location \
Set-Location "$env:USERPROFILE\AppData\Roaming\Microsoft\Windows\Start-Process Menu\Programs\Startup"
Remove-Item KickStart.ps1

Calling a Batch File into a Powershell Script

Everytime my Powershellscript is calling the Batchfile, a new Powershell Window opens. How can i modify the script in order to avoid the new window opens? I've tried with -windowstyle hidden and NoNewWindow, but nothing works.
Here is the Batchfile that starts my Powershell Script:
#echo off
set scriptFileName=%~n0
set scriptFolderPath=%~dp0
set powershellScriptFileName=test.ps1
powershell.exe -windowstyle hidden -Command "Start-Process powershell \"-ExecutionPolicy Bypass -NoProfile -NoExit -Command `\"cd \`\"C:\Temp\`\"; & \`\".\test.ps1\`\"`\"\" -Verb RunAs"
And here is my Powershell Script:
$Source = "C:\Program Files\Planmeca\Romexis\client\cephmodule\analyses"
$Destination = "\\PRENCIPE-THINK\PDATA\analyses" #<------ UNC PFAD FUER DEN SERVER ANPASSEN!!
New-Item -ItemType directory -Path $Destination -Force
Copy-Item -Path $Source\*.* -Destination $Destination -Force -Recurse
(ROBOCOPY $Source $Destination /MIR /W:30 /R:10)
# Ueberpruefe den Ordner auf veraenderungen
# Fuehre den Script aus bei Aenderung oder Umbennenung
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = 'C:\Program Files\Planmeca\Romexis\client\cephmodule\analyses'
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $false
$watcher.NotifyFilter = [System.IO.NotifyFilters]::LastWrite -bor [System.IO.NotifyFilters]::FileName
while($TRUE){
$result = $watcher.WaitForChanged([System.IO.WatcherChangeTypes]::Changed -bor [System.IO.WatcherChangeTypes]::Renamed -bOr [System.IO.WatcherChangeTypes]::Created, 1000);
if($result.TimedOut){
continue;
}
write-host "Change in " + $result.Name
$A = Start-Process -WindowStyle Hidden -FilePath c:\temp\Bypass.bat -Wait -passthru ;$a.ExitCode
}
Try the '-NoNewWindow' switch. I'm running PS Version 5.1 on Windows 7 and it's available. If you're running an earlier iteration if WMF, you may want to update your machines to 5 or better.

"Open Admin Powershell here" Windows Explorer Context Menu

I wanted to add an item to the windows explorer context menu, that would open a PowerShell as Admin.
I found this command which starts the powershell in the cmd:
PowerShell -windowstyle hidden -Command `"Start-Process cmd -ArgumentList '/s,/k,pushd,%V && PowerShell' -Verb RunAs`"
The problem with this is that the window is the cmd window and not the powershell one.
So I tried to make a command on my own and came up with this:
PowerShell.exe -WindowStyle Hidden -NoExit -Command "Start-Process PowerShell.exe -Verb RunAs -ArgumentList #(`'-NoExit`',`'-Command`',`'Set-Location -LiteralPath `"%V`"`')";
which works fine when executed in the cmd or powershell, but when i put it into the registry (HKEY_CLASSES_ROOT\Directory\shell\PowershellMenu (Administrator)\command\(Default)) the powershell window flashes shortly.
I tried to...
...use the full PowerShell path:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -WindowStyle Hidden -NoExit -Command "Start-Process -FilePath 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' -Verb RunAs -ArgumentList #(`'-NoExit`',`'-Command`',`'Set-Location -LiteralPath `"%V`"`')";
...add a sleep to see if the -NoExit is ignored:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -WindowStyle Hidden -NoExit -Command "Start-Process -FilePath 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' -Verb RunAs -ArgumentList #(`'-NoExit`',`'-Command`',`'Set-Location -LiteralPath `"%V`"; Sleep 10`')";
without any success.
Execute in PowerShell as administrator:
'Directory',
'Directory\Background',
'Drive' | ForEach-Object {
$Path = "Registry::HKEY_CLASSES_ROOT\$_\shell\runas";
New-Item -Path $Path -Name 'command' -Force | Out-Null;
Set-ItemProperty -Path "$Path\command" -Name '(default)' -Value "PowerShell -WindowStyle Maximized -NoExit -NoLogo -Command Set-Location '%V'";
Set-ItemProperty -Path $Path -Name '(default)' -Value 'PowerShell';
Set-ItemProperty -Path $Path -Name 'HasLUAShield' -Value '';
Set-ItemProperty -Path $Path -Name 'Icon' -Value "${Env:WinDir}\System32\WindowsPowerShell\v1.0\powershell.exe,0";
}

Install msi using Start-Process with /q switch?

I want to install an msi with a /q switch, I look online and the examples don't have the /q switch and I keep getting errors.
I need something like:
$WorkingDirectory = (Split-Path $myinvocation.mycommand.path -Parent)
Start-Process -FilePath msiexec /i "$WorkingDirectory\LAPS.x64.msi" -ArgumentList /q
Don't bother with Start-Process. Use the call operator:
& msiexec.exe /i "$WorkingDirectory\LAPS.x64.msi" /q
put the whole command in the brackets
Example(Python msi):
Start-Process msiexec.exe -Wait -ArgumentList "/I $($LocalPython.FullName) /passive ALLUSERS=1 ADDLOCAL=Extensions"
replace /passive with /q
Not all installers are the same. To find the installer switches for your .msi use:
.\LAPS.x64.msi /?
.\LAPS.x64.msi -?
I would also store the msi path in a variable, and use an ArrayList for the arguments, something like this has worked for me in my scripts:
# Path to .msi
$msiPath= 'C:\LAPS.x64.msi'
# Define arguments
[System.Collections.ArrayList]$arguments =
#("/i `"$msiPath`"",
"/quiet")
# Start installation
Start-Process -FilePath msiexec.exe -ArgumentList "$arguments" -Wait -NoNewWindow
$path="C:\Dat\install.msi"
$parameters="/q"
$packageinstall=(split-path $path -leaf) + ' ' + $parameters
write-host $packageinstall
$computers = get-content c:\com.txt
$computers | where{test-connection $_ -quiet -count 1} | ForEach-Object {
copy-item $path "\\$_\c$\windows\temp" -Force -Recurse
$newProc=([WMICLASS]"\\$_\root\cimv2:win32_Process").Create("C:\windows\temp\$packageinstall")
If ($newProc.ReturnValue -eq 0) {
Write-Host $_ $newProc.ProcessId
} else {
write-host $_ Process create failed with $newProc.ReturnValue
}
}

How to capture windows command result from Start-Process?

$features = Start-Process powershell -Verb runAs -ArgumentList "Get-WindowsOptionalFeature –Online"
$features
How can I get the result back into my $feature variable?
Quick & dirty workaround: you can use temporary clixml file to store results of Get-WindowsOptionalFeature cmdlet:
$tempFile = [System.IO.Path]::GetTempFileName()
try
{
Start-Process powershell -Wait -Verb runAs -ArgumentList "-Command Get-WindowsOptionalFeature -Online | Export-Clixml -Path $tempFile"
$features = Import-Clixml -Path $tempFile
# Use $features
}
finally
{
if (Test-Path $tempFile)
{
Remove-Item -Path $tempFile -Force -ErrorAction Ignore
}
}