I have multiple restarts between script blocks, the problem is on every restart the user is required to key in their credentials, and log in.
Is there any way where once the script is being executed it can login to system without username and password? We would want to hardcode username and password in the script itself.
The script helps in achieving the following:
Run Script Block
Restart
Run Next Script Block
But this requires user to log in after restart. Until then the process is under halt. I am looking for a way to automate the login process as well... I know it creates security threat, but this is something that is necessary for the process I am supposed to achieve.
#Code which will run script with admin privileges
If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
$arguments = "& '" + $myinvocation.mycommand.definition + "'"
Start-Process powershell -Verb runAs -ArgumentList $arguments
Break
}
# Temp Folder
if (!(Get-Item d:\temp -ea ignore)) { mkdir d:\temp }
$dropperscript = 'D:\temp\dropper.ps1'
$dropper = #'
#############################################
### Configuration Variables ###
#
# Put any variables you'll use here
#
### ###
#############################################
# Static Variables
$countfile = 'd:\temp\bootcount.txt'
$bootbatch = 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\dropper.bat'
$dropperscript = 'd:\temp\dropper.ps1'
#################
##### Setup #####
# Bootstrap Batch
if (!(Get-Item $bootbatch -ea ignore)) {
$x='PowerShell.exe -Command "& {Start-Process PowerShell.exe -ArgumentList '''
$y=' -ExecutionPolicy Bypass -File "D:\temp\dropper.ps1""'' -Verb RunAs}"'
$x+$y| Out-File $bootbatch -Encoding 'OEM'
}
# Boot Count
if (Get-Item $countfile -ea ignore) {
[int]$bootcount = Get-Content $countfile
if ($bootcount -match "^\d{1,2}$") { ([int]$bootcount) ++ }
else { $bootcount = 1 }
}
else { $bootcount = 1 }
$bootcount | Out-File $countfile
switch ($bootcount) {
1 {
$File="D:\temp\Log.txt"
Get-Date | Out-File $File -Append
Get-Process | Out-File $File -Append
Restart-Computer -Force
##################################################
############### --REBOOT-- ###############
}
2 {
$File="D:\temp\Log.txt"
Get-Date | Out-File $File -Append
Get-Process | Out-File $File -Append
Restart-Computer -Force
##################################################
############### --REBOOT-- ###############
}
3 {
$File="D:\temp\Log.txt"
Get-Date | Out-File $File -Append
Get-Process('\\itdsl\MSNPLAT\Gold\MSNPATCH\msnpatch.exe') | Out-File $File -Append
Restart-Computer -Force
##################################################
############### Restart ################
}
4{
$File="D:\temp\Log.txt"
Get-Date | Out-File $File -Append
Get-Process| Out-File $File -Append
Restart-Computer -Force
##################################################
############### --END-- ################
}
default {
# Dropper is complete; clean up
rm $countfile
rm $bootbatch
rm $dropperscript
}
}
'#
# Drop and run Dropper
$dropper | Out-File $dropperscript -Encoding 'OEM'
Invoke-Expression $dropperscript
Related
"System.Threading.Tasks.Task`1[System.String]" text comes on before the profile loading text
here is my
I changed my profile script to:
### PowerShell template profile
### Version 1.03 - Tim Sneath <tim#sneath.org>
### From https://gist.github.com/timsneath/19867b12eee7fd5af2ba
###
### This file should be stored in $PROFILE.CurrentUserAllHosts
### If $PROFILE.CurrentUserAllHosts doesn't exist, you can make one with the following:
### PS> New-Item $PROFILE.CurrentUserAllHosts -ItemType File -Force
### This will create the file and the containing subdirectory if it doesn't already
###
### As a reminder, to enable unsigned script execution of local scripts on client Windows,
### you need to run this line (or similar) from an elevated PowerShell prompt:
### Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
### This is the default policy on Windows Server 2012 R2 and above for server Windows. For
### more information about execution policies, run Get-Help about_Execution_Policies.
# Import Terminal Icons
Import-Module -Name Terminal-Icons
# Find out if the current user identity is elevated (has admin rights)
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal $identity
$isAdmin = $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
# If so and the current host is a command line, then change to red color
# as warning to user that they are operating in an elevated context
# Useful shortcuts for traversing directories
function cd... { Set-Location ..\.. }
function cd.... { Set-Location ..\..\.. }
# Compute file hashes - useful for checking successful downloads
function md5 { Get-FileHash -Algorithm MD5 $args }
function sha1 { Get-FileHash -Algorithm SHA1 $args }
function sha256 { Get-FileHash -Algorithm SHA256 $args }
# Quick shortcut to start notepad
function n { notepad $args }
# Drive shortcuts
function HKLM: { Set-Location HKLM: }
function HKCU: { Set-Location HKCU: }
function Env: { Set-Location Env: }
# Creates drive shortcut for Work Folders, if current user account is using it
if (Test-Path "$env:USERPROFILE\Work Folders") {
New-PSDrive -Name Work -PSProvider FileSystem -Root "$env:USERPROFILE\Work Folders" -Description "Work Folders"
function Work: { Set-Location Work: }
}
# Set up command prompt and window title. Use UNIX-style convention for identifying
# whether user is elevated (root) or not. Window title shows current version of PowerShell
# and appends [ADMIN] if appropriate for easy taskbar identification
function prompt {
if ($isAdmin) {
"[" + (Get-Location) + "] # "
} else {
"[" + (Get-Location) + "] $ "
}
}
$Host.UI.RawUI.WindowTitle = "PowerShell {0}" -f $PSVersionTable.PSVersion.ToString()
if ($isAdmin) {
$Host.UI.RawUI.WindowTitle += " [ADMIN]"
}
# Does the the rough equivalent of dir /s /b. For example, dirs *.png is dir /s /b *.png
function dirs {
if ($args.Count -gt 0) {
Get-ChildItem -Recurse -Include "$args" | Foreach-Object FullName
} else {
Get-ChildItem -Recurse | Foreach-Object FullName
}
}
# Simple function to start a new elevated process. If arguments are supplied then
# a single command is started with admin rights; if not then a new admin instance
# of PowerShell is started.
function admin {
if ($args.Count -gt 0) {
$argList = "& '" + $args + "'"
Start-Process "$psHome\powershell.exe" -Verb runAs -ArgumentList $argList
} else {
Start-Process "$psHome\powershell.exe" -Verb runAs
}
}
# Set UNIX-like aliases for the admin command, so sudo <command> will run the command
# with elevated rights.
Set-Alias -Name su -Value admin
Set-Alias -Name sudo -Value admin
# Make it easy to edit this profile once it's installed
function Edit-Profile {
if ($host.Name -match "ise") {
$psISE.CurrentPowerShellTab.Files.Add($profile.CurrentUserAllHosts)
} else {
notepad $profile.CurrentUserAllHosts
}
}
# We don't need these any more; they were just temporary variables to get to $isAdmin.
# Delete them to prevent cluttering up the user profile.
Remove-Variable identity
Remove-Variable principal
Function Test-CommandExists {
Param ($command)
$oldPreference = $ErrorActionPreference
$ErrorActionPreference = 'SilentlyContinue'
try { if (Get-Command $command) { RETURN $true } }
Catch { Write-Host "$command does not exist"; RETURN $false }
Finally { $ErrorActionPreference = $oldPreference }
}
#
# Aliases
#
# If your favorite editor is not here, add an elseif and ensure that the directory it is installed in exists in your $env:Path
#
if (Test-CommandExists nvim) {
$EDITOR = 'nvim'
} elseif (Test-CommandExists pvim) {
$EDITOR = 'pvim'
} elseif (Test-CommandExists vim) {
$EDITOR = 'vim'
} elseif (Test-CommandExists vi) {
$EDITOR = 'vi'
} elseif (Test-CommandExists code) {
#VS Code
$EDITOR = 'code'
} elseif (Test-CommandExists notepad) {
#fallback to notepad since it exists on every windows machine
$EDITOR = 'notepad'
}
Set-Alias -Name vim -Value $EDITOR
function ll { Get-ChildItem -Path $pwd -File }
function g { Set-Location $HOME\Documents\Github }
function Get-PubIP {
(Invoke-WebRequest http://ifconfig.me/ip ).Content
}
function uptime {
#Windows Powershell
Get-WmiObject win32_operatingsystem | Select-Object csname, #{
LABEL = 'LastBootUpTime';
EXPRESSION = { $_.ConverttoDateTime($_.lastbootuptime) }
}
}
function reload-profile {
& $profile
}
function find-file($name) {
Get-ChildItem -recurse -filter "*${name}*" -ErrorAction SilentlyContinue | ForEach-Object {
$place_path = $_.directory
Write-Output "${place_path}\${_}"
}
}
function unzip ($file) {
Write-Output("Extracting", $file, "to", $pwd)
$fullFile = Get-ChildItem -Path $pwd -Filter .\cove.zip | ForEach-Object { $_.FullName }
Expand-Archive -Path $fullFile -DestinationPath $pwd
}
function grep($regex, $dir) {
if ( $dir ) {
Get-ChildItem $dir | select-string $regex
return
}
$input | select-string $regex
}
function touch($file) {
"" | Out-File $file -Encoding ASCII
}
function df {
get-volume
}
function sed($file, $find, $replace) {
(Get-Content $file).replace("$find", $replace) | Set-Content $file
}
function which($name) {
Get-Command $name | Select-Object -ExpandProperty Definition
}
function export($name, $value) {
set-item -force -path "env:$name" -value $value;
}
function pkill($name) {
Get-Process $name -ErrorAction SilentlyContinue | Stop-Process
}
function pgrep($name) {
Get-Process $name
}
# Import the Chocolatey Profile that contains the necessary code to enable
# tab-completions to function for `choco`.
# Be aware that if you are missing these lines from your profile, tab completion
# for `choco` will not function.
# See https://ch0.co/tab-completion for details.
$ChocolateyProfile = "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
if (Test-Path($ChocolateyProfile)) {
Import-Module "$ChocolateyProfile"
}
Invoke-Expression (&starship init powershell)
I am a programming enthusiast and novice, I am using Powershell to try to solve the following need:
I need to extract the full path of files with extension .img. inside a folder with +/- 900 thousand folders and +/- million files. -/+ 900,000 img files.
Each img file must be processed in an exe. that is read from a file.
Which is better to store the result of the GetChildItem in a variable or a file?
I would greatly appreciate your guidance and support to optimize and / or find the best way to speed up processes vs. resource consumption.
Thank you un advance!!
This is the code I am currently using:
$PSDefaultParameterValues['*:Encoding'] = 'Ascii'
$host.ui.RawUI.WindowTitle = “DICOM IMPORT IN PROGRESS”
#region SET WINDOW FIXED WIDTH
$pshost = get-host
$pswindow = $pshost.ui.rawui
$newsize = $pswindow.buffersize
$newsize.height = 3000
$newsize.width = 150
$pswindow.buffersize = $newsize
$newsize = $pswindow.windowsize
$newsize.height = 50
$newsize.width = 150
$pswindow.windowsize = $newsize
#endregion
#
$out = ("$pwd\log_{0:yyyyMMdd_HH.mm.ss}_import.txt" -f (Get-Date))
cls
"`n" | tee -FilePath $out -Append
"*****************" | tee -FilePath $out -Append
"**IMPORT SCRIPT**" | tee -FilePath $out -Append
"*****************" | tee -FilePath $out -Append
"`n" | tee -FilePath $out -Append
#
# SET SEARCH FOLDERS #
"Working Folder" | tee -FilePath $out -Append
$path1 = Read-Host "Enter folder location" | tee -FilePath $out -Append
"`n" | tee -FilePath $out -Append
#
#
# SET & SHOW HOSTNAME
"SERVER NAME" | tee -FilePath $out -Append
$ht = hostname | tee -FilePath $out -Append
Write-Host $ht
Start-Sleep -Seconds 3
"`n" | tee -FilePath $out -Append
#
#
# GET FILES
"`n" | tee -FilePath $out -Append
#"SEARCHING IMG FILES, PLEASE WAIT..." | tee -FilePath $out -Append
$files = $path1 | Get-ChildItem -recurse -file -filter *.img | ForEach-Object { $_.FullName }
# SHOW Get-ChildItem PROCESS ON CONSOLE
Out-host -InputObject $files
"`n" | tee -FilePath $out -Append
Write-Output ($files | Measure).Count "IMG FILES FOUND TO PUSH" | tee -FilePath $out -Append
# DUMP Get-ChildIte into a file
$files > $pwd\pf
Start-Sleep -Seconds 5
# TIMESTAMP
"`n" | tee -FilePath $out -Append
"IMPORT START" | tee -FilePath $out -Append
("{0:yyyy/MM/dd HH:mm:ss}" -f (Get-Date)) | tee -FilePath $out -Append
"********************************" | tee -FilePath $out -Append
"`n" | tee -FilePath $out -Append
#
#
#SET TOOL
$ir = $Env:folder_tool
$pt = "utils\tool.exe"
#
#PROCESSING FILES
$n = 1
$pe = foreach ($file in Get-Content $pwd\pf ) {
$tb = (Get-Date -f HH:mm:ss) | tee -FilePath $out -Append
$fp = "$n. $file" | tee -FilePath $out -Append
#
$ep = & $ir$pt -c $ht"FIR" -i $file | tee -FilePath $out -Append
$as = "`n" | tee -FilePath $out -Append
# PRINT CONSOLE IMG FILES PROCESS
Write-Host $tb
Write-Host $fp
Out-host -InputObject $ep
Write-Host $as
$n++
}
#
#TIMESTAMP
"********************************" | tee -FilePath $out -Append
"IMPORT END" | tee -FilePath $out -Append
("{0:yyyy/MM/dd HH:mm:ss}" -f (Get-Date)) | tee -FilePath $out -Append
"`n" | tee -FilePath $out -Append
Try using parallel with PoshRSJob.
Replace Start-Process in Process-File with your code and note that there is no access to console. Process-File must return string.
Adjust $JobCount and $inData.
The main idea is to load all file list into ConcurrentQueue, start 20 background jobs and wait them to exit. Each job will take value from queue and pass to Process-File, then repeat until queue is empty.
NOTE: If you stop script, RS Jobs will continue to run until they finished or powershell closed. Use Get-RSJob | Stop-RSJob and Get-RSJob | Remove-RSJob to stop background work
Import-Module PoshRSJob
Function Process-File
{
Param(
[String]$FilePath
)
$process = Start-Process -FilePath 'ping.exe' -ArgumentList '-n 5 127.0.0.1' -PassThru -WindowStyle Hidden
$process.WaitForExit();
return "Processed $FilePath"
}
$JobCount = [Environment]::ProcessorCount - 2
$inData = [System.Collections.Concurrent.ConcurrentQueue[string]]::new(
[System.IO.Directory]::EnumerateFiles('S:\SCRIPTS\FileTest', '*.img')
)
$JobScript = [scriptblock]{
$inQueue = [System.Collections.Concurrent.ConcurrentQueue[string]]$args[0]
$outBag = [System.Collections.Concurrent.ConcurrentBag[string]]$args[1]
$currentItem = $null
while($inQueue.TryDequeue([ref] $currentItem) -eq $true)
{
try
{
# Add result to OutBag
$result = Process-File -FilePath $currentItem -EA Stop
$outBag.Add( $result )
}
catch
{
# Catch error
Write-Output $_.Exception.ToString()
}
}
}
$resultData = [System.Collections.Concurrent.ConcurrentBag[string]]::new()
$i_cur = $inData.Count
$i_max = $i_cur
# Start jobs
$jobs = #(1..$JobCount) | % { Start-RSJob -ScriptBlock $JobScript -ArgumentList #($inData, $resultData) -FunctionsToImport #('Process-File') }
# Wait queue to empty
while($i_cur -gt 0)
{
Write-Progress -Activity 'Doing job' -Status "$($i_cur) left of $($i_max)" -PercentComplete (100 - ($i_cur / $i_max * 100))
Start-Sleep -Seconds 3 # Update frequency
$i_cur = $inData.Count
}
# Wait jobs to complete
$logs = $jobs | % { Wait-RSJob -Job $_ } | % { Receive-RSJob -Job $_ }
$jobs | % { Remove-RSJob -Job $_ }
$Global:resultData = $resultData
$Global:logs = $logs
$Global:resultData is array of Process-File return strings
Which is better to store the result of the GetChildItem in a variable or a file?
If you're hoping to keep memory utilization low, the best solution is to not store them at all - simply consume the output from Get-ChildItem directly:
$pe = Get-ChildItem -Recurse -File -filter *.img |ForEach-Object {
$file = $_.FullName
$tb = (Get-Date -f HH:mm:ss) | tee -FilePath $out -Append
$fp = "$n. $file" | tee -FilePath $out -Append
#
$ep = & $ir$pt -c $ht"FIR" -i $file | tee -FilePath $out -Append
$as = "`n" | tee -FilePath $out -Append
# PRINT CONSOLE IMG FILES PROCESS
Write-Host $tb
Write-Host $fp
Out-host -InputObject $ep
Write-Host $as
$n++
}
When ran with elevated privileges, the code does what it is supposed to do by turning off the laptop's onboard microphone, but it needs to be totally silent. This will be sent out to over 1600 systems. It will be pushed via logon script to the local systems. So it needs to run as Admin and without any user intervention. How do I keep it running elevated and how to get it to run without the UAC prompt?
-TIA
$audioCaptureRegPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Capture"
$MICS = Get-Item $audioCaptureRegPath
$MICS.GetSubKeyNames() | % {`
if($(Get-ItemProperty -Path $audioCaptureRegPath"\"$_).DeviceState -eq 1 ){`
$systemNameData=$(Get-ItemProperty -Path $audioCaptureRegPath"\"$_\Properties).$systemNameVal
if(!($systemNameData -match "plant") -or !($systemNameData -match "HDX"))
{
$tmpFileFullPath = [System.io.Path]::getTempFileName()
"Windows Registry Editor Version 5.00" | Out-File -FilePath $tmpFileFullPath -Append
" " | Out-File -FilePath $tmpFileFullPath -Append
"[$($MICS.Name)\$_]" | Out-File -FilePath $tmpFileFullPath -Append
"`"DeviceState`"=dword:10000001" | Out-File -FilePath $tmpFileFullPath -Append
" " | Out-File -FilePath $tmpFileFullPath -Append
regedit.exe /S $tmpFileFullPath
}
}
}
I can't seem to find the correct syntax to pass 2 variables from the CALL-script to the execution script in order to have it executed on the remote server. I tried single quotes, double quotes, brackets, .. nothing I can fiind passes the $Target and $OlderThanDays parameters to the script.
Thank you for your help.
The CALL-Script:
#================= VARIABLES ==================================================
$ScriptDir = "\\Server\Scripts"
#================= BODY =======================================================
# Invoke-Command -ComputerName SERVER1 -FilePath $ScriptDir\"Auto_Clean.ps1"
Invoke-Command -FilePath .\Test.ps1 -ComputerName SERVER01 -ArgumentList {-Target ´E:\Share\Dir1\Dir2´,-OlderThanDays ´10´}
The execution Script:
#================= PARAMETERS =================================================
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$Target,
[Parameter(Mandatory=$True,Position=2)]
[string]$OlderThanDays
)
#================= BODY =======================================================
# Set start time & logname
$StartTime = (Get-Date).ToShortDateString()+", "+(Get-Date).ToLongTimeString()
$LogName = "Auto_Clean.log"
# Format header for log
$TimeStamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()+" |"
$Header = "`n$TimeStamp Deleting files and folders that are older than $OlderThanDays days:`n"
Write-Output "$Header" # to console
Out-File $Target\$LogName -inputobject $Header -Append # to log
# PS 2.0 Workaround (`tee-object -append`) // PS 4.0: `Write-Output "`nDeleting folders that are older than $OlderThanDays days:`n" | Tee-Object $LogFile -Append`
# Remove files older than
Get-ChildItem -Path $Target -Exclude $LogName -Recurse |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$OlderThanDays) } | ForEach {
$Item = $_.FullName
Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue
$Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()
# If folder can't be removed
if (Test-Path $Item)
{ "$Timestamp | FAILLED: $Item (IN USE)" }
else
{ "$Timestamp | REMOVED: $Item" }
} | Out-File $Target\$LogName -Append
# PS 4.0: ´| Tee-Object $Target\$LogName -Append` # Output folder names to console & logfile at the same time
# Remove empty folders
while (Get-ChildItem $Target -recurse | where {!#(Get-ChildItem -force $_.FullName)} | Test-Path) {
Get-ChildItem $Target -recurse | where {!#(Get-ChildItem -force $_.FullName)} | Remove-Item
}
# Format footer
$EndTime = (Get-Date).ToShortDateString()+", "+(Get-Date).ToLongTimeString()
$TimeTaken = New-TimeSpan -Start $StartTime -End $EndTime
Write-Output ($Footer = #"
Start Time : $StartTime
End Time : $EndTime
Total Runtime : $TimeTaken
$("-"*79)
"#)
# Write footer to log
Out-File -FilePath $Target\$LogName -Append -InputObject $Footer
# Clean up variables
$Target=$StartTime=$EndTime=$OlderThanDays = $null
The execution script:
you have got to use " or ' but not ´ :
-argumentlist #('E:\Share\Dir1\Dir2',10)
I am trying to run a powershell script on the task scheduler but am unable to understand the suitable logging command for my script. I want to get this to run on the schedule.
The script would delete the files and folders older than x days and would create an output log.
function Out-Log {
param (
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
[string]$message,
[switch]$Error
)
$logPath = $env:TEMP + "\Filedeletion.log"
$message | Out-File -FilePath $logPath -Append
}
trap
{
"error:" | Out-Log
$_.exception.message | Out-Log
break
}
$Error.Clear()
try
{
"Starting" | Out-Log
$DateToDelete = 1
$dateLimit = (Get-Date).AddDays(-$DateToDelete)
$StartFolder = "c:\TEST1"
Get-ChildItem -Recurse -Force -Path $StartFolder |
foreach {
$currentItemIsFolder = $_.PsIsContainer;
$curentItemIsOld = $_.LastWriteTime -lt $dateLimit
if ($curentItemIsOld -and (-not $currentItemIsFolder))
{
"Removing '$($_.fullname)'." | Out-Log
Remove-Item -Path ($_.fullname) -Force -WhatIf
}
}
}
finally
{
if ($Error)
{
"`$error stack:" | Out-Log
$error | foreach {$_.exception.ToString() | Out-Log}
}
"Stopping" | Out-Log
}
I was trying to use
Powershell -file "c:\Powershell\Filedeletion_logs_test.ps1"
via batch to run the powershell.
I've tried to check the commands in Powershell/? but did not find any suitable logging command working for my script.
Can anyone please help?
You do not need a separate batch file that runs the powershell in the task schedule. All you need is this nice tutorial. It is detailed step by step, but is very easy to setup.
http://community.spiceworks.com/how_to/show/17736-run-powershell-scripts-from-task-scheduler
Can't you do the same thing with SCHTASKS?
http://ss64.com/nt/schtasks.html
You should be able to pipe a list of servers through a TYPE command and add the tasks to the server set.
For example:
http://www.robvanderwoude.com/ntadmincommands.php
FOR /F %%A IN (servers.txt) DO (
SCHTASKS /CREATE /S %%A /U "system" /P "" /TN "Powershell Task" /TR "Powershell -file \"c:\my folder\script.ps1\""
)