how to get rid of present working directory in powershell - windows

I am working on a project that is buried deep beneath the folders and directories and because of that my powershell's line is half filled with the path to the directory. I want to know if it is possible to get rid of the long string of directory path that is constantly showing.

Add this to your script, then call the function after starting your script.
function prompt {
$p = Split-Path -leaf -path (Get-Location)
"$p> "
}
This way only the "leaf" folder will be shown for the prompt placeholder.

Building on the last answer I usually put the current path in the title bar of the console window and use the history ID for the prompt. Something like:
Function Prompt
{
$cwd = (get-location).Path
$LastHist = ( Get-History)[-1].Id + 1
$Host.UI.RawUI.WindowTitle = "SPoSh_$($PSVersionTable.PSVersion.Major) - $cwd | User: $($env:USERNAME)"
$Host.UI.Write("Green", $Host.UI.RawUI.BackGroundColor, "SPoSh_$($PSVersionTable.PSVersion.Major)")
" #$LastHist : "
}
So this would look like:
"SPoSh_5 #1 : "
I leave a space at the end which makes it easier to double click select a previous command without capturing any of the prompt itself.
Note: If you are working in the regular console the title bar additions let you know where you are without crowding the prompt.
The title bar stuff doesn't show in some of the other non-colsole PowerShell hosts, like VSCode's integrated console, but during script dev the location is usually fairly static, so it's not too much trouble.

Related

Windows PowerShell - Input file name, output file path

I've just started using PowerShell and I have a task where I need to be able to have the file path displayed on screen when I enter the file name.
Is there a script that allows me to do the below ? :
Ex 1: I enter "test.txt" and I get "C:\Program Files...."
Ex 2: I enter a file name "My Documents" and I also get its path.
I have searched online on how to do this but I didn't quite find what I was looking for and all the queries/answers were too complicated for me to understand.
Can anyone help me out, please?
Thanks in advance!
Here is a starter sample for you.
This example search only within the confine of the paths present is the Path system environment variable. It also only looks for files and do not recurse through these path.
So anything you could access directly from the command line should be available to you through it.
Now, if you want to search the whole drive, you could replace the $DefaultPaths assignment with Get-ChildItem -Path 'C:' -Recurse but doing that each time won't be super efficient.
You could do it and it will work... but it will be slow.
To search on the whole drive or whole filesystem, there are alternative methods that might work better. Some examples of what might entice:
Using a database which you have to buld & maintain to index all the files so that when you search, results are instantaneous and / or very fast
Parsing the MFT table (if using Windows / NTFS filesystem only) instead of using Get-ChildItem (This is not somehting natively doable through a simple cmdlet though) .
Relying on a third party software and interface with (For example, Void Tools Everything search engine already parse MFT and build its own database, allowing users to search instantly through a Windows NTFS filesystem. It also have its own SDK you can plug in through Powershell and retrieve what you seek instantly. The caveats is that you need the software installed first for that solution to work.)
Example: Searching through all paths defined in the Path variable
# What you are looking for. Accept wildcards characters (*)
$Filter = 'notepad.exe'
# Get the System Environment Path variable in an array
$DefaultPaths = $env:Path -split ';'
$Paths =
Foreach ($P in $DefaultPaths) {
# Search for files matching the specified filter. Ignore errors (often if the path do not exist but is sin the Path)
$MatchingFiles = Get-ChildItem -Path $P -Filter $Filter -File -ErrorAction SilentlyContinue
if ($MatchingFiles.count -gt 0) {
$MatchingFiles.Directory.FullName
}
}
$Paths | out-string | Write-Host -ForegroundColor Cyan
Output for Notepad.exe search using this method.
C:\Windows\system32
C:\Windows

Admin vs Non-Admin Mode - Cannot overwrite variable because the variable has been optimized

During some testing today I came across an unexpected issue and I do not understand why it is happening. Below is the code I am using to duplicate the issue. It is only a very small portion of the larger project.
Testing is being cone on Windows 10 Build 1709, if that helps
Both the PS1 File and the BAT File are named the same.
Ways to cause the errors
Running the PS1 File via Right-Click - Run with PowerShell will cause the error
Opening PowerShell ISE in Non-Admin Mode, then opening/running the script will cause the error
Running BAT File as Admin or Non-Admin will cause the error
Ways to avoid the errors
Opening PowerShell ISE in Admin Mode, then opening/running the script will not cause the error
Adding Script: in front of the variables on the last 2 lines of code will not cause the error no matter how the script is executed
Using VSCode, it will work as shown below. Running it in the integrated terminal, it will see it not running as an Admin, it will launch PowerShell.exe outside of VSCode and work without issue
-
Why do I have Script: in front of the variables in the functions? It was the only way I could get variables set in the functions to be used outside the functions. The other 25 or so variables not listed in this post do not have an issue, however, they are not modified like these two are after they are set.
The Questions
Why, if running the ISE in Admin Mode, it will work?
Why would it not work if it relaunches as an Administrator?
Why does VSCode not care and it works regardless?
Something isn't making sense and I cannot pinpoint it.
Here are the errors
Cannot overwrite variable NetFX3 because the variable has been optimized. Try using the New-Variable or Set-Variable
cmdlet (without any aliases), or dot-source the command that you are using to set the variable.
At C:\Users\a502690530\Desktop\Testing2.ps1:14 char:5
+ [string]$Script:NetFX3 = $BAT_Files_Path + "NetFX3.zip"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (NetFX3:String) [], SessionStateUnauthorizedAccessException
+ FullyQualifiedErrorId : VariableNotWritableRare
Cannot overwrite variable Power_Plan because the variable has been optimized. Try using the New-Variable or
Set-Variable cmdlet (without any aliases), or dot-source the command that you are using to set the variable.
At C:\Users\a502690530\Desktop\Testing2.ps1:15 char:5
+ [string]$Script:Power_Plan = $BAT_Files_Path + "Power_Plan.zip"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (Power_Plan:String) [], SessionStateUnauthorizedAccessException
+ FullyQualifiedErrorId : VariableNotWritableRare
Here is the code
# Checks if running as an administrator. If not, it will relaunch as an administrator
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
}
[string]$ErrorActionPreference = "Continue"
[string]$BAT_Files = $Root_Path + "BAT_Files\"
Function Set-FilePaths ([string]$BAT_Files_Path) {
# BAT Files Paths (ZIPs only!!!)
[string]$Script:NetFX3 = $BAT_Files_Path + "NetFX3.zip"
[string]$Script:Power_Plan = $BAT_Files_Path + "Power_Plan.zip"
Set-Lists
}
function Set-Lists {
# List of BAT Files (ZIPs)
[System.Collections.ArrayList]$Script:List_Of_BAT_Files = #(
$NetFX3
$Power_Plan
)
}
Set-FilePaths `
-BAT_Files_Path $BAT_Files
PAUSE
$NetFX3 = ((Split-Path $NetFX3 -Parent) + "\NetFX3\")
$Power_Plan = ((Split-Path $Power_Plan -Parent) + "\Power_Plan\")
BAT File to launch
REG ADD "HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" /T REG_SZ /V ExecutionPolicy /D Unrestricted /F
Start PowerShell.exe -Command "& '%~dpn0.ps1'"
I have no specific answer, but a pointer:
Your issue sounds like a PowerShell bug related to the DLR (Dynamic Language Runtime), a technology PowerShell uses behind the scenes (since v3); there's at least one open bug report on GitHub that sounds related.
Aside from the workaround you already know of - using scope modifier script consistently - I suggest avoiding variable access across scope boundaries as a general best practice, which should also avoid the problem.
PowerShell is very flexible in what it can return (output) from a function, so it's better to set variables in the caller's scope based on a function's output.
Specifically, I suggest refactoring your code as follows:
Function Get-FilePaths ([string]$BAT_Files_Path) {
# Output the paths as an *array*.
($BAT_Files_Path + "NetFX3.zip"), ($BAT_Files_Path + "Power_Plan.zip")
}
# Call the function in the script scope and capture its output in variables.
$List_Of_BAT_Files = Get-FilePaths
# Use a destructuring assignment to store the elements of the array
# in individual variables
$NetFX3, $Power_Plan = $List_Of_BAT_Files
If there are a lot of individual variables to set, you can make the function output a hash table instead, and use the hash table's named entries instead of individual variables (requires PSv3+, due to use of [ordered] to create a hash table with ordered keys):
Function Get-FilePaths ([string]$BAT_Files_Path) {
# Output the paths as a *hash table*, using its
# entries for named access instead of individual variables.
$outHash = [ordered] #{
NetFX3 = $BAT_Files_Path + "NetFX3.zip"
Power_Plan = $BAT_Files_Path + "Power_Plan.zip"
}
# Add a 'List' entry that contains all values added above as an array.
# Note the need to use #(...) to force creation of a new array from the
# hash table's value collection.
$outHash.List = #($outHash.Values)
# Output the hash table.
$outHash
}
# Call the function in the script scope and capture its output in
# a single variable that receives the hash table.
$hash = Get-FilePaths
# Now you can access the invididual values by name - e.g., $hash.NetFX3 -
# or use $hash.List to get all values.

split an argument and add include the items in url

I'm trying to solve a problem at work, where it's required to access project folders on a shared drive.
However the naming convention is a bit tricky. The URLs on the server start with the static FS\XXX\00 followed by the project number (6 digits long) which is split into pieces of two and between slashes. For example the project folder for project 123456 would look like FS\XXX\00\12\34\56.
What I'm trying to sort out is how to create a .bat file, put it in the environment path and call it with the Run command, so for example I would call the file ex.bat by entering the following sequence in the Run console:
ex 123456
Then the program should split the number, build up and open the following URL:
FS\XXX\00\12\34\56
Any ideas?
%1 is the first parameter. Save it to a variable (%p%) do be able to do substring substitution (see set /?) and build and output the desired string:
#echo off
set p=%1
echo FS\XXX\00\%p:~0,2%\%p:~2,2%\%p:~4,2%
pause
Because powershell was tagged, here's a powershell implementation. Save this as a script in the environment path somewhere:
[CmdLetBinding()]
param
(
[string] $ProjectNumber = '123457'
)
$root = 'FS\XXX\00\'
# Create a string with backslashes every 2 chars
$out = (&{for ($i = 0;$i -lt $ProjectNumber.length;$i += 2)
{
$ProjectNumber.substring($i,2)
}}) -join '\'
# Create final path
$path = Join-Path -Path $root -ChildPath "$out\"
# Run explorer with the path
explorer $path
and call from run/cmd like this:
powershell "& "Script.ps1 -ProjectNumber 123456""

Windows Batch script to read pom.properties file within .jar

I'm looking for a simple way to read the 2nd line of the pom.properties file that is placed within the META-INF folder of a compiled .jar. (see here: http://maven.apache.org/guides/getting-started/index.html#How_do_I_add_resources_to_my_JAR). I often need to know the date in that file and it's just a pain to have to open the jar every time and dig down into it. I want a Windows batch script that I can run via right-clicking on a .jar (so I'll need help with the Windows registry command as well). The result of the batch command can just be displayed in a cmd window (a nice bonus would be the value being copied to the clipboard, too).
In short: I want to be able to right-click on a .jar file in Windows Explorer > select 'Get Maven Generated Date' (or whatever) > and have the 2nd line of the pom.properties file printed to the console (and copied to the clipboard).
I know this can't be too hard, I just don't know quite what to look for :).
Thanks in advance for any help.
Note that .NETv4.5 is required to use the System.IO.Compression.FileSystem class.
Add-Type -As System.IO.Compression.FileSystem;
$sourceJar = <source-jar-here>;
$jarArchive = [IO.Compression.ZipFile]::OpenRead($sourceJar).Entries
try
{
foreach($archiveEntry in $jarArchive)
{
if($archiveEntry.Name -like "*pom.properties")
{
$tempFile = [System.IO.Path]::GetTempFileName()
try
{
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($archiveEntry, $tempFile, $true)
$mavenDate = Get-Content $tempFile -First 2
Write-Host $mavenDate
}
finally
{
Remove-Item $tempFile
}
}
}
}
finally
{
$jarArchive.Dispose
}

open UNC path with spaces in windows explorer with perl

Hello stackoverflowers,
i'm afraid i can't figure out how to open an UNC path with spaces within Windows Explorer in perl.
Purpose is, i want the user to put a file within the path. To make it more comfortable, the path should open in explorer automatically. Which it does for any local drives.
The UNC path that should open is: \\srvr1\mean space dir
My code so far:
use strict
use warnings
my $sourceDir = "\\\\srvr1\\mean space dir";
system("start $sourceDir");
Which gives the error: "Win can't access \\srvr1\mean."
Ok, so i tried to quote the string:
my $sourceDir = "\\\\srvr1\\\"mean space dir\"";
Which lead to: "Win can't access \\srvr1\"mean space dir"."
Next thing i tried was:
my $sourceDir = q{"\\\srvr1\\mean space dir"}
Which lead to an cmd window being opened with the correct path within the title?!
Is maybe the system call itself wrong?
I really appreciate any help. Thanks.
The second form is correct, but then you have to account for the fact that the start command treats its first quoted argument as a window title. If you want to start a quoted path, you need to give a window title argument too (the empty string is fine).
Like so:
my $sourceDir = q{\\\\srvr1\\mean space dir};
system(qq{start "" "$sourceDir"});
For this kind of thing the array style system call is a good fit. You don't need to worry about quoting the path or escaping as much.
$path = '\\\\srvr1\mean space dir';
system('start', '', $path);
Quoting (or forgetting to quote) paths in system calls is a significant source of bugs where I've worked. A habit of doing it as above means you never need to worry about it.

Resources