Author Posts

September 13, 2018 at 6:18 pm

Hello POSH fam

Just wondering if I could get some clarification on why a file will not move using function Move-Item.

Premise of the script is to execute commands to modify a system setting and create/save a log of the script run using Out-File to create a logging of the script run.

I have multiple functions as you can see ūüôā

The goal of the script is accomplished thanks to the assistance provided in my previous post > https://powershell.org/forums/topic/search-string-in-powercfg-result/

I am not able to output/save my log file unto the desired location in "C:\Temp" when executing the script, however I am able to run the cmdlets in a Powershell session, just not when I try to execute the .ps1 file.

Additionally, As I am fairly new to POSH, for Powershell proper "etiquette" and/or best-practices, does creating multiple functions the way to go or ...some other way.

My apologies for the length of the script in advance.

Thanks,

Alex


< #
.SYNOPSIS
   Script to locate Disable_PC_Lock and remove
.DESCRIPTION
   
.PARAMETER 
   
.EXAMPLE
   
#>

# Function to check and/or create folder to store logs

function Test-FolderExist {

$Folder=Test-Path -Path 'c:\Temp\'

            if ($Folder -eq $false)
            {
                New-Item -Path 'c:\Temp\' -ItemType 'directory'
                
                Check-PowerPlan
                
            }
            else { exit }            
     
}

#Change PowerScheme/Plan

function ChangeActivePowerPlan {

"Changing Active Power Plan to Balanced.....................................`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append
	
		"> Locate additional power plan" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append
	
		$NotActivePlan= Get-WmiObject -Class win32_PowerPlan -Namespace root\cimv2\power -Filter "ElementName = 'Balanced'"
		$NotActiveGuid= $NotActivePlan.InstanceID.split('{')[1]
		$SetActivePlanGuid= $NotActiveGuid -replace '}',""
		
		"> Power Plan $($NotActivePlan.ElementName) with Guid $SetActivePlanGuid is non-active" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append
	
		#Set as active power plan
	
		powercfg /setactive "$SetActivePlanGuid"
	
		"> Power Plan $($NotActivePlan.ElementName) with Guid $SetActivePlanGuid has been set to active`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append
	
"Active Power Plan changed......................................`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append
	
	RemovePowerPlan
}

# Remove Disable_PC_Lock

function RemovePowerPlan {

"Removing Power Plan $($PowerScheme.ElementName)................`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append

    "> Removing Disable_PC_Lock Power Plan from $env:COMPUTERNAME" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append

    $RemoveDisablePCLock= Get-WmiObject -Class win32_PowerPlan -Namespace root\cimv2\power -Filter "ElementName = 'Disable_PC_Lock'"
    $RemovePlan= $RemoveDisablePCLock.InstanceID.split('{')[1]
    $RemovePlanGuid= $RemovePlan -replace '}',""

    #Remove power plan

    powercfg /delete "$RemovePlanGuid"

    "> Power Plan $($RemoveDisablePCLock.ElementName) with Guid $RemovePlanGuid has been removed`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append

sleep -Milliseconds 300

"List of all Power Plans present on $($env:COMPUTERNAME) after removal of (Disable_PC_Lock) power plan.....`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append

Get-WmiObject -Class win32_PowerPlan -Namespace root\cimv2\power | select ElementName,InstanceID,IsActive | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append

"Logging Process stopped......................................`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append
  
ShowScriptFooter | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append


Copy

}

# Footer

function ShowScriptFooter {

$FooterPurpose='Script Purpose: Locate and Remove Power Plan Disable_PC_Lock'
$FooterExecutionDetails='Script Execution: Executes at device startup via GPO'
$Team='Responsible Team: IT Collaboration Operations'
$Contact='For all inquiries please contact the Helpdesk'
$Date="Script ran on $((Get-Date).ToString())"
$message = @"

===================================================================================================

		    $FooterPurpose
		    $FooterExecutionDetails
		    $Team

===================================================================================================

		        $Contact

               		$Date

"@

$message

}

function Copy-File {

$file = "c:\REMOVAL_LOG.$env:COMPUTERNAME.log"

#Copy-Item $file -Destination c:\Temp -Verbose

Move-Item $file -Force


}

# Main Function

function Check-PowerPlan {
   
    $UniqueDate = Get-Date -UFormat %Y%m%d_%H%M%S
    
    "Logging process started........................................`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append
    
   
    "List of all Power Plans present on $($env:COMPUTERNAME)`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append

    Get-WmiObject -Class win32_PowerPlan -Namespace root\cimv2\power | select ElementName,InstanceID,IsActive | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append

    $PowerScheme=Get-WmiObject -Class win32_PowerPlan -Namespace root\cimv2\power -Filter "ElementName = 'Disable_PC_Lock'"

    if ($PowerScheme -eq $null) {

    #"Logging process started........................................`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append
    	
    	"> WARNING MESSAGE: Power plan 'Disable_PC_Lock' was not found on $($env:COMPUTERNAME)`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append
    	
    "Script stopped...............`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append
    
    ShowScriptFooter | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append
    	
    exit
    	
    } else {
    			
        Switch ($PowerScheme.IsActive) {
    				
    	    'True' {
                    
                    "> $($PowerScheme.ElementName) is the active plan and must be changed before continuing`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append                    
    							
                    ChangeActivePowerPlan
                             
            }
            
            'False'{
                            
                    "> $($PowerScheme.ElementName) is not the active plan`r`n> Ok to remove power plan`r`n" | Out-File "c:\$Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append
    				
                    RemovePowerPlan

                        
            }
        }
    			
    }
}

# Call function to start script execution

Test-FolderExist         

September 13, 2018 at 7:38 pm

You are using $Temp which an undefined variable. Define it or use like "c:\Temp\REMOVAL_LOG.$env:COMPUTERNAME.log" -Append.

Logging is an essential part of script in many scenarios. The normal practice is to have a logging function and use that function every where.

Function Log{
    Param(
        [string]$Message
        [string]$Path = "c:\Temp\REMOVAL_LOG.$env:COMPUTERNAME.log"
    )
    $Message | Out-File -FilePath $Path -Append
}

Function Whatever {
    Log "This is the first line"
}

September 13, 2018 at 8:10 pm

UPDATE:

I applied the "log" function and also modified the filepath and all is well. Appreciate the help once again!

Thanks @kvprasoon. I will try your suggestion and update this thread. Appreciate your time!

September 13, 2018 at 9:02 pm

Welcome to the club, but you have really over complicated this for yourself. So, this begs to question, what of the free PowerShell training have you leveraged to date. Look up 'beginning PowerShell' on Microsoft Virtual Academy, MS Channel9, and YouTube as well as take advantage of all the free ebooks available on this site and elsewhere.

As for this...

create/save a log of the script run using Out-File to create a logging of the script run.
I am not able to output/save my log file unto the desired location in "C:\Temp" when executing the script, however I am able to run the cmdlets in a Powershell session, just not when I try to execute the .ps1 file.

..., why not just use the built-in transcript cmdlets for this effort?

Get-Command -Name '*transcript*' | Format-Table -AutoSize

CommandType Name                        Version   Source
----------- ----                        -------   ------
Cmdlet      Start-Transcript            3.0.0.0   Microsoft.PowerShell.Host
Cmdlet      Stop-Transcript             3.0.0.0   Microsoft.PowerShell.Host

# get function / cmdlet details
(Get-Command -Name Start-Transcript).Parameters
Get-help -Name Get-ADUser -Examples
Get-help -Name Get-ADUser -Full
Get-help -Name Get-ADUser -Online

# get function / cmdlet details
(Get-Command -Name Stop-Transcript).Parameters
Get-help -Name Get-ADUser -Examples
Get-help -Name Get-ADUser -Full
Get-help -Name Get-ADUser -Online

All modules / functions you plan to use must be loaded first, before you can call them to do anything.

As for etiquette" and/or best-practices", here are a few references for you.

# Best Practices

PowerShell scripting best practices
'https://blogs.technet.microsoft.com/pstips/2014/06/17/powershell-scripting-best-practices'

The Unofficial PowerShell Best Practices and Style Guide
https://blogs.technet.microsoft.com/pstips/2014/06/17/powershell-scripting-best-practices

Using PSScriptAnalyzer to check your PowerShell code for best practices
'http://mikefrobbins.com/2015/11/19/using-psscriptanalyzer-to-check-your-powershell-code-for-best-practices'

You also have variables that are not properly declared. IN your dev effort, be sure to leverage the …

Set-StrictMode

https://blogs.technet.microsoft.com/heyscriptingguy/2014/12/03/enforce-better-script-practices-by-using-set-strictmode

… Option to help check yourself.

Running scripts in the ISE or VSCode editors, by clicking F5 to run everything to F8 to run only the selected text, of course is not the same thing as running from the console(s).

All your modules / functions / reference resources must be loaded first before you can use them.
Your PowerShell execution policy must be set for you to run scripts outside of the ISE/VSCode editors.

See the help files for:

Get-ExecutionPolicy
Set-ExecutionPolicy

You have a Copy-File function that is actually a move, so, that's really not needed and a move requires a destination, which you are not showing in your code.

$file = "c:\REMOVAL_LOG.$env:COMPUTERNAME.log"
Move-Item "c:\Temp\REMOVAL_LOG_$env:COMPUTERNAME.log" -Destination 'D:\Logs' -Force

You only need a force to force create a object if it does not already exist or you want to overwrite it.

In your RemovePowerPlan function, you all 'Copy', but you have not function called 'Copy' loaded or even defined to be loaded. Thus it will default to the built-in Copy-Item, since Copy is an alias for that and copy-item also must have a source and destination.

So, I am going to assume you did not mean to do this, or you meant to use the Copy-File function. Which as noted, is not really needed. Also why are you forcing the script to 'exit ' on your logic. Exit, means shutdown the script and do not process anything that follow.

So, others will have their take, however, my off the cuff changes, you'll have to test of course.




# Report Footer Message

function ShowScriptFooter 
{
    $FooterPurpose='Script Purpose: Locate and Remove Power Plan Disable_PC_Lock'
    $FooterExecutionDetails='Script Execution: Executes at device startup via GPO'
    $Team='Responsible Team: IT Collaboration Operations'
    $Contact='For all inquiries please contact the Helpdesk'
    $Date="Script ran on $((Get-Date).ToString())"
    $message = @"
===================================================================================================

		    $FooterPurpose
		    $FooterExecutionDetails
		    $Team

===================================================================================================

		        $Contact

               		$Date

"@

$message

}

#Change PowerScheme/Plan

function ChangeActivePowerPlan 
{

"Changing Active Power Plan to Balanced....................................."
	
		"> Locate additional power plan"
	
		$NotActivePlan= Get-WmiObject -Class win32_PowerPlan -Namespace root\cimv2\power -Filter "ElementName = 'Balanced'"
		$NotActiveGuid= $NotActivePlan.InstanceID.split('{')[1]
		$SetActivePlanGuid= $NotActiveGuid -replace '}',""
		
		"> Power Plan $($NotActivePlan.ElementName) with Guid $SetActivePlanGuid is non-active"
	
		#Set as active power plan
	
		powercfg /setactive "$SetActivePlanGuid"
	
		"> Power Plan $($NotActivePlan.ElementName) with Guid $SetActivePlanGuid has been set to active`r`n"
	
"Active Power Plan changed......................................"
	
	RemovePowerPlan
}


function RemovePowerPlan
 {

"Removing Power Plan $($PowerScheme.ElementName)................"

    "> Removing Disable_PC_Lock Power Plan from $env:COMPUTERNAME"

    $RemoveDisablePCLock= Get-WmiObject -Class win32_PowerPlan -Namespace root\cimv2\power -Filter "ElementName = 'Disable_PC_Lock'"
    $RemovePlan= $RemoveDisablePCLock.InstanceID.split('{')[1]
    $RemovePlanGuid= $RemovePlan -replace '}',""

    #Remove power plan

    powercfg /delete "$RemovePlanGuid"

    "> Power Plan $($RemoveDisablePCLock.ElementName) with Guid $RemovePlanGuid has been removed"

sleep -Milliseconds 300

"List of all Power Plans present on $($env:COMPUTERNAME) after removal of (Disable_PC_Lock) power plan....."

Get-WmiObject -Class win32_PowerPlan -Namespace root\cimv2\power | select ElementName,InstanceID,IsActive

"Logging Process stopped......................................"
  
ShowScriptFooter


Move-Item $file -Destination 'D:\Logs' -Force

}


# Main Function

function Check-PowerPlan 
{
   
   # Force create log folder if it does not already exist
    New-Item -Path 'c:\Temp\' -ItemType 'directory' -Force


    $UniqueDate = Get-Date -UFormat %Y%m%d_%H%M%S
    
    "Logging process started........................................"
    
   
    "List of all Power Plans present on $($env:COMPUTERNAME)"

    Get-WmiObject -Class win32_PowerPlan -Namespace root\cimv2\power | 
    select ElementName,InstanceID,IsActive

    $PowerScheme = Get-WmiObject -Class win32_PowerPlan -Namespace root\cimv2\power -Filter "ElementName = 'Disable_PC_Lock'"

    if ($PowerScheme -eq $null) {

    "Logging process started........................................" 
    	
    	"> WARNING MESSAGE: Power plan 'Disable_PC_Lock' was not found on $($env:COMPUTERNAME)`r`n"
    	
    "Script stopped..............."
    
    ShowScriptFooter   	
    } 
    else 
    {
    			
        Switch ($PowerScheme.IsActive) {
    				
    	    'True' {
                    
                    "> $($PowerScheme.ElementName) is the active plan and must be changed before continuing"
    							
                    ChangeActivePowerPlan
                             
            }
            
            'False'{
                            
                    "> $($PowerScheme.ElementName) is not the active plan`r`n> Ok to remove power plan"
    				
                    RemovePowerPlan
                        
            }
        }
    			
    }
}

# Call function to start script execution and log all using transcription
Start-Transcript -Path "c:\Temp\REMOVAL_LOG_$env:COMPUTERNAME.log" -Force

Check-PowerPlan

Stop-Transcript

September 13, 2018 at 9:29 pm

Thanks @postannote. I really appreciate the detailed feedback and all the useful information. My apologies that I did not post the correct test ps1 that I was working on. The one I posted was one that I was applying changes to. I should have reviewed the post before posting.

I forced the script to exit if the folder exists, as (from what I was trying to accomplish) if the folder exist, then the script already ran on the computer and therefore no longer needs to run. Reasoning is that this PS1 will be pushed via GPO and I only need to run it once and log only that instance. Whether the powerscheme was found/removed and/or non-existent, the initial run of the script on the PC will tell create that folder. I did not want to have a log created for every time the PC goes into a startup cycle.

Nonetheless, I truly appreciate all the help and time you all put in to assist a fellow Posh enthusiast.

Take care all!

September 13, 2018 at 11:56 pm

No worries.
We all do what we can.