PowerShell - Console Input using Explorer - powershell

Scenario: User is trying to upload a document from a PowerShell 3.0 script.
Current mechanism: Read-Host. Simple string prompt to request path/file.ext.
Desired behavior: A prompt ('Please choose the file to upload') and
Explorer is launched. The path/file the user selects is passed along to my script.
I can see how to launch Explorer of course, just can't figure how to tie the command line
prompt and the file selection with Explorer together.
Kind Regards,
Paul

Here's a simple script to do what you're wanting to do. Also you can use PowerGUI To compile the script and have the Powershell Window close Automatically close the powershell window after it's finished, but that's not needed.
$DestinationFolder = "L:\Users\caleb.berger\Desktop";
function Get-FileName($initialDirectory) {
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog;
$OpenFileDialog.initialDirectory = $initialDirectory;
$OpenFileDialog.filter = "All files (*.*)| *.*";
$OpenFileDialog.ShowDialog() | Out-Null;
$OpenFileDialog.filename;
}
Write-Host "Please Select The File To Upload:";
$SourceFile = Get-FileName -initialDirectory "c:\";
Write-Host "Copying File...";
Copy-Item -LiteralPath $SourceFile -Destination $DestinationFolder -Force;
Write-Host "Finished.";
Read-Host "Press Any Key To Continue";
You can learn more about how this works at:
http://blogs.technet.com/b/heyscriptingguy/archive/2009/09/01/hey-scripting-guy-september-1.aspx
His script is what I built this application off of.

Related

How to write progress bar for a script in powershell that finds specific files and deletes them with Get-ChildItem, Remove-Item

I'm new with powershell.
I'm trying to write a script that:
will search in a specific path and delete specific files
write in a log file all files that were deleted and their paths
write in a log file all files that script could not delete, the
reason and their path
progress bar that shows:
*current path that script is working on
*how much time script running
*the amount files that were deleted
*the amount of files that script could not delete
What I've succeeded by now**:
1,2 - log file made after script stops, but i want to be able to check and refresh it to see if new information was added.
here is my code:
#files you want to find, include all in array
$file_names = #('*file1.exe', '*file2.exe', '*file3.exe')
Clear-Host
Write-Host "Hello. A scrip is going to search and delete the following files: $($file_names)." -ForegroundColor Black -BackgroundColor Green
Write-Host "Edit file names in the script if needed." -ForegroundColor Black -BackgroundColor Green
#input the right path were to find a files
$search_path = Read-Host "Please enter the path (for an example: C:\workday\*)"
while(-Not (Test-Path $search_path)){
$search_path = Read-Host "The path $($search_path) is incorrect, please input another one)" }
#path to the log file
Write-Host "The output will be saved to a log file in the disk C:\" -ForegroundColor Black -BackgroundColor Green
$log = "C:\deleted_files_$((get-date).ToString("yyyyMMdd_HHmm")).log"
$log
#search parameters, -recurse: find in subdirectories, -force: grab hidden and system files, SilentlyContinue - continue if there error
try{$search = Get-ChildItem -Path $search_path -include $file_names -Recurse -force -ErrorAction SilentlyContinue | Remove-Item -Force -Verbose 4>&1 | Add-Content $log
$search }
catch [System.UnauthorizedAccessException]{
Write-Warning "Access denied: $search_path"}
Read-Host -Prompt "Press Enter to exit"

System.IO.FileSystemWatcher and mapped network drives

I use following PowerShell script to monitor a mapped drive for newly created files and write these changes to a csv file.
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = 'Z:\'
$action =
{
$path = $event.SourceEventArgs.FullPath
$changetype = $event.SourceEventArgs.ChangeType
Write-output "$path was $changetype at $(get-date)" >> C:\temp\HostFileList.csv
}
Register-ObjectEvent $watcher 'Created' -Action $action
Get-EventSubscriber
while($true){ sleep -seconds 1 }
The computer I'm running this script on is heavily used by multiple users. Each user will log onto the computer with their own profile, click a desktop batch file to map a network drive folder and save their work there. My script is set up in Local Group Policy to be ran at start up. From what I can tell the script doesn't have any issues running in the background and listening to the mapped drive folder. My problem is that the script refuses to write an output file to the designated location. If I manually run the script, it creates the output file just fine. Also, when I manually run the script with the local GP startup script enabled, I get two entries in my file, which makes me believe the script is running fine from the local GP. Could anyone advise why my script creates an output file when I run it manually, but not when it is ran at startup? Any feedback is much appreciated.
As for this...
Write-output
Write-Output (Microsoft.PowerShell.Utility)
Sends the specified objects to the next command in the pipeline. If
the command is the last command in the pipeline, the objects are
displayed in the console.
Use the file cmdlets
Export-Csv
Out-File
... and the -append parameter. So, collect your properties and pipe to one of them.
| Export-Csv -Path 'C:\temp\HostFileList.csv' -Append -NoTypeInformation
Export-Csv (Microsoft.PowerShell.Utility)
Converts objects into a series of comma-separated value (CSV) strings
and saves the strings to a file.
$AppService = (Get-Service -DisplayName *Application* | Select-Object -Property DisplayName, Status)
$AppService | Export-Csv -Path .\Services.Csv -NoTypeInformation
Get-Content -Path .\Services.Csv
$WinService = (Get-Service -DisplayName *Windows* | Select-Object -Property DisplayName, Status)
$WinService | Export-Csv -Path ./Services.csv -NoTypeInformation -Append
Get-Content -Path .\Services.Csv
"DisplayName","Status"
"Application Layer Gateway Service","Stopped"
"Application Identity","Running"
"Windows Audio Endpoint Builder","Running"
"Windows Audio","Running"
"Windows Event Log","Running"
Out-File (Microsoft.PowerShell.Utility) - PowerShell
Sends output to a file.
-Append Adds the output to the end of an existing file.

Passing a password into a script

I am currently using the below PowerShell script to update an autologon value in the registry, it also checks that if the value isn't there that it is created.
Rather than opening up the script, changing the defaultpassword value in there and then running the script I'd like to be able to run the script in PowerShell and for it to prompt for the user to enter the value that is going to update.
I am new to parameters within PowerShell and can't say I'm 100% sure that is the solution.
Can anyone help? it's the 'passwordvalue' I'm looking to have inputed from a prompt and to be subsequently replaced in the script before the script runs. Let me know if I'm not being clear!
$RegKey = “HKLM:\SOFTWARE\MICROSOFT\WINDOWS NT\CURRENTVERSION\WINLOGON”
if (-Not(Test-Path “$RegKey”)) {
New-Item -Path “$($RegKey.TrimEnd($RegKey.Split(‘\’)[-1]))” -Name “$($RegKey.Split(‘\’)[-1])” -Force | Out-Null
}
Set-ItemProperty -Path “$RegKey” -Name “DefaultPassword” -Type String -Value “passwordvalue”
Just use the Read-Host cmdlet:
# ....
Set-ItemProperty -Path "$RegKey" -Name "DefaultPassword" -Type String -Value (Read-Host -Prompt 'Enter the password')

copying a new file each way and reporting a message to the screen

The main idea is to copy new files from server to client and copy logs from the client to the server only if the files are
1. older than the client version
2. if the client does not have the file
Notify the user with write out to text box advising of new update and restart required
I am trying to copy a config update another issue is folder structure
would i need to have the complete folder structure in the script all this will be completed without user interaction so silently
I have adapted the code below
display message to only to say if restart required
server layout roughly server>config files
-update
-config
-other config folder
-another config folder
client layout client>program>logs
-log1
-log2
Ssource = "\\server\Tmp\Test.cfg"
$destination = "\\anyclient\Tmp\Destination\"
$TestPath = Test-Path $destination
IF (!$TestPath)
{Copy-Item $source $destination -Verbose write-host "restart required"
PC1 - no file found. Copying}
ELSE
{
IF (((Get-ChildItem $source).Length -ne (Get-ChildItem
$destination).Length) -or ((Get-ChildItem $source).LastWriteTime -ne (Get- ChildItem $destination).LastWriteTime))
{Copy-Item $source $destination -Force -Verbose}
write-host = "restart required"
ELSE
{"PC2 - exact file found, nothing copied"}
}
Any help greatly appreciated my only problem is this must be powershell v2 compatible
I am not sure wheter you use sharepoint and that stuff but normally there are webservices provided which can be used for up and downloading files like:
$webclient = New-Object System.Net.WebClient
$webclient.UseDefaultCredentials = $true
$credentials =$webclient.Credentials
(just to initialize the webclient) and here is up and download function:
$webclient.DownloadFile($source, $destination)
and as a report box I am using a Message Box Method a friend told me about:
function Show-MessageBox {
param(
[parameter(Mandatory=$true)]
[string]$Message,
[Validateset('Error', 'Warning', 'Information')]
[string]$Type
)
[System.Windows.Forms.MessageBox]::Show($Message, $Type, `
[System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::$Type)
}
this method above can be called like this:
Show-MessageBox -Type Information -Message "Error or info code"
Type (information means a little icon which will be displayed on the message box and it looks like a blue circle with a white 'i' in it) :D

Persist current directory between PowerShell sessions

Is there a way to make PowerShell Console remember the current directory from the last time it was run and use that as the default location for the next instance?
eg.
Open PowerShell Console
Set-Location c:\tmp
Close PowerShell
Open PowerShell Console
Get-Location returns c:\tmp
You could change the prompt function to save location changes to a user environment variable:
$Function:prompt = {
if([System.Environment]::GetEnvironmentVariable("LocationMemory",[System.EnvironmentVariableTarget]::User) -ne $PWD){
[System.Environment]::SetEnvironmentVariable("LocationMemory",$PWD,[System.EnvironmentVariableTarget]::User)
}
"PS $($ExecutionContext.SessionState.Path.CurrentLocation)$('>' * ($NestedPromptLevel + 1))"
}
And then check if the environment variable exists and is valid when powershell starts
if(($LastLocation = [System.Environment]::GetEnvironmentVariable("LocationMemory",[System.EnvironmentVariableTarget]::User))){
if((Test-Path $LastLocation -PathType Container)){
Set-Location $LastLocation
}
}
Put both snippets in your profile to make it work. You probably want to limit it to $Profile.CurrentUserCurrentHost
I don't know if this is perfect but testing on my machine it seems to work. First check out this question/answer, this is the icing of the cake. You are basically going to have to log the current path of your session through an exiting event with PowerShell.
You can add this bit of code to your $PROFILE so it will always register the exit event and then set the path.
Register-EngineEvent PowerShell.Exiting -Action {(Get-Location).Path | Out-File 'C:\Users\wshaw\Documents\WindowsPowerShell\LastPath.txt' -Force}
$lastPath = 'C:\Users\wshaw\Documents\WindowsPowerShell\LastPath.txt'
if (Test-Path $lastPath) {
Set-Location (Get-Content $lastPath)
}
Thanks to #Shawn and #Mathias for both giving great answers. I ended up combining your approaches to come up with the following:
Register-EngineEvent PowerShell.Exiting -Action {
Write-Warning "Saving current location"
[System.Environment]::SetEnvironmentVariable("LocationMemory", (Get-Location).Path, [System.EnvironmentVariableTarget]::User)
} | Out-Null
$lastPath = [System.Environment]::GetEnvironmentVariable("LocationMemory",[System.EnvironmentVariableTarget]::User)
if (($lastPath -ne $null) -and (Test-Path $lastPath)) {
Set-Location $lastPath
}
There is around a 4 second delay for me when SetEnvironmentVariable is called, which is why I added the Write-Warning (otherwise you might think that the console window isn't closing after you exited or clicked on the Close Window control)