Start process using wildcard for drive letter - powershell

I have a file which will always be located on a users desktop, however, depending on how the machine was set up, the desktop could be located on the C drive or D drive.
Below is what I have tried to use. On it's own, (Get-Location).Drive.Name will return the C drive on my machine. However, if I combine it into the full line of code to start the program, it does not work.
What am I doing wrong?
$userName = [Environment]::UserName
Start-Process ((Get-Location).Drive.Name)\Users\$($userName)\Desktop\VIPHorizon\Service_Desk.url

While the other answer is correct that you are missing a colon, simply adding that is not sufficient.
If you try running it with the colon, you will get another error like so:
Unexpected token ':\Users' in expression or statement.
In order to fix this, you need to wrap the whole thing in quote marks.
"((get-location).Drive.Name):\Users\$($userName)\Desktop\VIPHorizon\Service_Desk.url"
Then you will find that the ((get-location).Drive.Name) is written directly into the string, instead of being replaced. which can be fixed by prefixing the call with a dollar sign like you have already done for userName.
"$((get-location).Drive.Name):\Users\$($userName)\Desktop\VIPHorizon\Service_Desk.url"

You need to put a colon ( : ) right after your drive letter:
$userName = [Environment]::UserName
Start-Process ((get-location).Drive.Name):\Users\$($userName)\Desktop\VIPHorizon\Service_Desk.url

The proper way to get current users Desktop even if relocated is:
[Environment]::GetFolderPath('Desktop')
So use:
Start-Process (Join-Path [Environment]::GetFolderPath('Desktop') "VIPHorizon\Service_Desk.url")
To eumerate all special folders and current settings:
$SpecialFolders = [Environment+SpecialFolder]::GetNames([Environment+SpecialFolder])|Sort
ForEach ($SpecialFolder in $SpecialFolders) {
[PSCustomObject]#{
SpecialFolderName = $SpecialFolder
SpecialFolderLocation = ([Environment]::GetFolderPath($SpecialFolder))
}
}

The global Powershell variable $HOME will give you the home location for the active user.
Start-Process $HOME\Desktop\VIPHorizon\Service_Desk.url

Related

Powershell command to return Chrome's download folder as a string

I'm looking for a command for Powershell that will return a String containing the filepath used for its configured Downloads folder.
I'm trying to do something along the lines of a Get-Content for $settings.download.default_directory but not getting results, not sure what i'm doing wrong.
(EDIT: My other post has a working solution. I'll leave this one here in case you find it useful.)
I can get you some of the way there, but not all the way.
Assuming you're referring to Chrome on Windows, it typically stores its preferences in "C:\Users\[user]\AppData\Local\Google\Chrome\User Data\Default\Preferences". So you'd start with something like:
$prefs = Get-Content "C:\Users\[user]\AppData\Local\Google\Chrome\User Data\Default\Preferences"
(Replace "[user]" with your account name, obviously.)
"Preferences" is a text file consisting of a single, gigantic string of comma-separated data. This is where it specifies my download directory, for example:
,"download":{"default_directory":"C:\\Users\\Matt\\Desktop",
Your next step might be to do '$prefs | Select-String [something...]' to parse that file for that string. However, I don't know how to do that part. It's a matter of telling it: "look for ',"download":', then pull out everything from the comma before 'download' until the next comma."
Once you have that, you can then split on double quotes to isolate the directory path, then remove the double slashes. So, assuming you have the above string in a variable called "$download", it might be something like:
$download = $download.Split('"')[5]
$download = $download.Replace('\\','\')
$download
Or you can do the above in a single line like this:
($download.Split('"')[5]).Replace('\\','\')
Btw, be super careful with quotes on this task! Since Chrome uses double quotes extensively in that preferences file, be sure to always wrap stuff in single quotes otherwise it's not going to work.
Also, as side note: in PowerShell, text in single quotes isn't parsed whereas text in double quotes is. So that's another reason why we should be wrapping stuff in single quotes here: we want the text as a simple string. If the string happened to contain, say, "$path" and we wrapped it in double-quotes, it would interpret that as the existing system variable "$path" and try to do something with it, which would be...undesirable!
I just realized there's no need to mess around with 'Select-String' - the prefs file is already comma separated, so we can just split on commas and search for the download dir based on a partial string.
This should work (change '[user]' in the first line to your account):
$prefs = Get-Content 'C:\Users\[user]\AppData\Local\Google\Chrome\User Data\Default\Preferences' # Create variable containing Chrome's preferences file for [user]
$prefs = $prefs.Split(',') # Split the file on commas (this converts the comma-separated string into an array of values)
$downloadString = $prefs | Where-Object {$_ -like '*download":*'} # Locate the string we want by searching on part of it that we already know will be there (note the '-like' and the wildcard asterisks)
$downloadString = $downloadString.Split('"')[5] # Split the string on double quotes and select the sixth item in the resulting array (arrays produced by 'Split' start at zero), which is the path we're looking for
$downloadString = $downloadString.Replace('\\','\') # Replace the double slashes in the path with single slashes
$downloadString # Print the result to the screen
There are various ways you can compress that down to just a couple of lines, but I figured since you're new, this way would make it easier to see how it works.
Hope that helped!
Chrome uses a Preferences file (no extension) to store the downloads folder path in a setting called default_directory IF the user has set up a custom path in Chrome's settings.
This Preferences file is a JSON file and can be easily read by PowerShell.
When the user has not set up a custom path, this setting is not available in the Preferences file and Chrome will use whatever is set for the current user in Windows.
To get that you will either need to read the path from registry, or use the Shell.Application COM object.
Both are handled in the code below:
$prefsPath = "$env:localappdata\Google\Chrome\User Data\Default\Preferences"
if (Test-Path -Path $prefsPath -PathType Leaf) {
$prefs = Get-Content -Path $prefsPath | ConvertFrom-Json
$downloadFolder = $prefs.download.default_directory
}
if ([string]::IsNullOrWhiteSpace($downloadFolder)) {
# Chrome is using the download folder set in Windows for the current user
# read from registry:
# the Downloads property is stored under Guid instead of friendly name..
$regPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders'
$downloadFolder = Get-ItemPropertyValue -Path $regPath -Name '{374DE290-123F-4565-9164-39C4925E467B}'
# or use the Shell.Application COM object
# $downloadFolder = (New-Object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path
}
$downloadFolder

Powershell and registry key changing challenge

I make changes under hklm with a line like this:
Set-Location HKLM:\software\afilefolder\afilefolder
and it works. I also need to make a change to a current user key, I am told to do this by making a change to hkey_users, but i have about 5 machines that would run this script and based on what machine it is, i need to make a change to my location, because hkey_users has an sid as the next file folder and it changes for each user. so based on the user, i grab the sid, I have all of them. and i set my location like this:
$test = "hkey_users\" + $hkeypath + "\filefolder\filefolder"
Set-Location $test
I cannot put the concatenation in the Set-Location line, powershell no likey, but when I do it this way, it says the following path cannot be found: C:\windows\system32\HKEY_USERS\correctsid\filefolder\filefolder
why does it look in the system32 folder? how do i make changes to hkey_user. please advise
You can set the location just fine, with the string concatenation, just put the whole thing in the double quotes. You'll want to reference that it's in the registry just to be safe, try this out:
Set-Location "registry::hkey_users\$hkeypath\filefolder\filefolder"
That worked for me (well, I set my SID to $mysid and then did a Set-Location "registry::hk_users\$mysid\software" and that got me to my software key in the registry, under my SID).

Generating printer shortcuts from list

I am trying to generate a shortcut for every printer I have on a print server. The idea is to be able to email these shortcuts to people and when they click on them, it automatically installs that printer for them.
I've populated an array from a list of printer names exported from the print server:
$list = #((get-contnet $home\dekstop\plist.txt))
I then created a method to create a shortcut:
function Make-Shortcut
{
param ([string]$dest, [string]$source)
$WshShell = New-Object -comObject Wscript.Shell
$Shortcut = $WshShell.CreateShortcut($dest)
$Shortcut.TargetPath = $Source
$Shortcut.Save()
}
The function works fine. I was able to create standard shortcuts with no problem.
This next part is where I am getting stuck:
foreach ($i in $list)
{
Make-Shortcut "C:\pshort\$i.lnk" "C:\Windows\System32\rundll32.exe
printui.dll,PrintUIEntry /in /q /n\\printserver\$i"
}
When this runs, it does generate a shortcut with the same name as the printer for each printer on the list. However, the problem comes in at the target path. Instead of
C:\Windows\System32\rundll32.exe printui.dll,PrintUIEntry /in /q /n\\printserver\printername
it changes it to:
C:\Windows\System32\rundll32.exe printui.dll,PrintUIEntry \in \q \n\printserver\printername
The three problems with this are:
It is reversing the forward slash for the parameters
It is removing one of the backslashes preceding the server name
It is adding quotes to both sides. I need the quotes to come off for the shortcut to work properly.
I assume this is happening because Powershell thinks I am trying to make a standard shortcut and thinks I made mistakes while typing out the path.
I have tried putting a ` in front of each forward slash hoping the escape character would prevent it from reversing it, but no luck. I also tried using a hyphen for each parameter but that did not work either.
Is there anyway to stop this from happening? Or is there perhaps a better way to try to accomplish what I am trying to do?
You need to add arguments to the com object
Try adding a new param $arguments to your Make-Shortcut function and do:
Make-Shortcut "C:\pshort\$i.lnk" "C:\Windows\System32\rundll32.exe"
"printui.dll,PrintUIEntry /in /q /n\\printserver\$i"
add this in your function:
$Shortcut.Arguments = $arguments
So the link is created successfully ... but I have no idea if it works :)
Completely different answer but in a standard windows environment simply clicking a hyperlink to \printserver\printer will add a shared printer to someone's system?
So an email that simply lists :
\\PrintServer\Printer01
\\PrintServer\Printer02
\\PrintServer\Printer03
Would probably do the job just as well.

Insert Username in to file path Powershell

We are in the process of trying to tidy up our users home directories and speed up some office 2007 performance by moving all their templates in to a new directory on their user drive (U:). During my initial tests I can get the below script to work fine though it has the obvious problem of only working for my username. Is there a way to get it to take the currently logging in user? Before this would be handled by %username% and from a brief scan of the internet apparently:
$[Environment]::UserName
Should work. However I seem to be getting errors. Is there a better way to achieve the current logging in users name in to the file path?
if (!(Test-Path -path '\\SERVER\PATH\TO FILES\$[Environment]::UserName\Normal\'))
{
New-Item '\\SERVER\PATH\TO FILES\$[Environment]::UserName\Normal\' -type directory
##Move-Item \\SERVER\PATH\TO FILES\$env:username\Normal.dot \\\SERVER\PATH\TO FILES\$env:username\Normal\
## Move-Item \\SERVER\PATH\TO FILES\$env:username\*.dotm \\SERVER\PATH\TO FILES\%username%\Normal\
}
else
{
"No work to do"
}
Two problems. If you want variable/expression substitution to take place in a string, you need to use quotation-marks, not apostrophes, to enclose the string. In this case, you also need to add some parenthesis to denote an expression within the string.
"\\SERVER\PATH\TO FILES\$([Environment]::UserName)\Normal\"

Change path separator in Windows PowerShell

Is it possible to get PowerShell to always output / instead of \? For example, I'd like the output of get-location to be C:/Documents and Settings/Administrator.
Update
Thanks for the examples of using replace, but I was hoping for this to happen globally (e.g. tab completion, etc.). Based on Matt's observation that the separator is defined by System.IO.Path.DirectorySeparatorChar which appears in practice and from the documentation to be read-only, I'm guessing this isn't possible.
It's a good question. The underlying .NET framework surfaces this as System.IO.Path.DirectorySeparatorChar, and it's a read/write property, so I figured you could do this:
[IO.Path]::DirectorySeparatorChar = '/'
... and that appears to succeed, except if you then type this:
[IO.Path]::DirectorySeparatorChar
... it tells you that it's still '\'. It's like it's not "taking hold". Heck, I'm not even sure that PowerShell honours that particular value even if it was changing.
I thought I'd post this (at the risk of it not actually answering your question) in case it helps someone else find the real answer. I'm sure it would be something to do with that DirectorySeparatorChar field.
Replace "\" with "/".
PS C:\Users\dance2die> $path = "C:\Documents and Settings\Administrator"
PS C:\Users\dance2die> $path.Replace("\", "/")
C:/Documents and Settings/Administrator
You could create a filter (or function) that you can pipe your paths to:
PS C:\> filter replace-slash {$_ -replace "\\", "/"}
PS C:\> Get-Location | replace-slash
C:/