Hey All,<\/p>\n
I’m in no means a power-shell guru but ive been tasked with identifying shortcut paths for users at our company. I put together this script to try to check a .csv for a username and then search the user directory for the shortcut paths. The script works to get the paths when i run it right to the user directory but i wanted to sort of automate this by having a list of users and it searching said user directory and then outputting the result into another csv. My issue is i cant seem to get it to take the user from the .csv and search in only that user directory. Ive tried using this variable but it searches my local pc instead and errors out. Anyone have any tips or other variables that may help? Hopefully i don’t sound to confusing. Thanks all<\/p>\n
\\UNCPATHTOUSERPROFILES$env:USERNAME<\/p>\n
$Users= (Get-Content C:\\temp\\Users.csv) -notmatch ‘^\\s*$’<\/p>\n
foreach ($User in $Users){<\/p>\n
function Get-StartMenuShortcuts{
\n$Shortcuts = Get-ChildItem -Recurse \\UNCPATHTOUSERPROFILES$env:USERNAME -Include *.lnk
\n$Shell = New-Object -ComObject WScript.Shell
\nforeach ($Shortcut in $Shortcuts)
\n{
\n$Properties = @{
\nShortcutName = $Shortcut.Name;
\nShortcutFull = $Shortcut.FullName;
\nShortcutPath = $shortcut.DirectoryName
\nTarget = $Shell.CreateShortcut($Shortcut).targetpath
\n}
\nNew-Object PSObject -Property $Properties
\n}<\/p>\n
[Runtime.InteropServices.Marshal]::ReleaseComObject($Shell) | Out-Null
\n}<\/p>\n
$Output = Get-StartMenuShortcuts
\n$Output.Target
\n}<\/p>","upvoteCount":7,"answerCount":8,"datePublished":"2020-02-11T13:00:24.000Z","author":{"@type":"Person","name":"richiesilva","url":"https://community.spiceworks.com/u/richiesilva"},"suggestedAnswer":[{"@type":"Answer","text":"
Hey All,<\/p>\n
I’m in no means a power-shell guru but ive been tasked with identifying shortcut paths for users at our company. I put together this script to try to check a .csv for a username and then search the user directory for the shortcut paths. The script works to get the paths when i run it right to the user directory but i wanted to sort of automate this by having a list of users and it searching said user directory and then outputting the result into another csv. My issue is i cant seem to get it to take the user from the .csv and search in only that user directory. Ive tried using this variable but it searches my local pc instead and errors out. Anyone have any tips or other variables that may help? Hopefully i don’t sound to confusing. Thanks all<\/p>\n
\\UNCPATHTOUSERPROFILES$env:USERNAME<\/p>\n
$Users= (Get-Content C:\\temp\\Users.csv) -notmatch ‘^\\s*$’<\/p>\n
foreach ($User in $Users){<\/p>\n
function Get-StartMenuShortcuts{
\n$Shortcuts = Get-ChildItem -Recurse \\UNCPATHTOUSERPROFILES$env:USERNAME -Include *.lnk
\n$Shell = New-Object -ComObject WScript.Shell
\nforeach ($Shortcut in $Shortcuts)
\n{
\n$Properties = @{
\nShortcutName = $Shortcut.Name;
\nShortcutFull = $Shortcut.FullName;
\nShortcutPath = $shortcut.DirectoryName
\nTarget = $Shell.CreateShortcut($Shortcut).targetpath
\n}
\nNew-Object PSObject -Property $Properties
\n}<\/p>\n
[Runtime.InteropServices.Marshal]::ReleaseComObject($Shell) | Out-Null
\n}<\/p>\n
$Output = Get-StartMenuShortcuts
\n$Output.Target
\n}<\/p>","upvoteCount":7,"datePublished":"2020-02-11T13:00:24.000Z","url":"https://community.spiceworks.com/t/shortcut-path-identifier/750732/1","author":{"@type":"Person","name":"richiesilva","url":"https://community.spiceworks.com/u/richiesilva"}},{"@type":"Answer","text":"
$env:Username is an automatic variable that contains the username of the user logged into the current session (i.e., the Powershell console). You need to use your own $User variable instead.<\/p>\n
$Users= (Get-Content C:\\temp\\Users.csv) -notmatch '^\\s*$'\n\nforeach ($User in $Users){ \n\nfunction Get-StartMenuShortcuts{\n $Shortcuts = Get-ChildItem -Recurse \\\\UNCPATHTOUSERPROFILES\\$User -Include *.lnk\n $Shell = New-Object -ComObject WScript.Shell\n foreach ($Shortcut in $Shortcuts)\n {\n $Properties = @{\n ShortcutName = $Shortcut.Name;\n ShortcutFull = $Shortcut.FullName;\n ShortcutPath = $shortcut.DirectoryName\n Target = $Shell.CreateShortcut($Shortcut).targetpath\n }\n New-Object PSObject -Property $Properties\n }\n\n[Runtime.InteropServices.Marshal]::ReleaseComObject($Shell) | Out-Null\n}\n\n$Output = Get-StartMenuShortcuts\n$Output.Target\n}\n<\/code><\/pre>","upvoteCount":1,"datePublished":"2020-02-11T13:33:22.000Z","url":"https://community.spiceworks.com/t/shortcut-path-identifier/750732/2","author":{"@type":"Person","name":"Evan7191","url":"https://community.spiceworks.com/u/Evan7191"}},{"@type":"Answer","text":"Ahh of course! Thank you so much for your reply, i’m going to change it when i get in.<\/p>\n
@techadmin8<\/a><\/p>","upvoteCount":0,"datePublished":"2020-02-11T13:39:33.000Z","url":"https://community.spiceworks.com/t/shortcut-path-identifier/750732/3","author":{"@type":"Person","name":"richiesilva","url":"https://community.spiceworks.com/u/richiesilva"}},{"@type":"Answer","text":"Ugh.<\/p>\n
First off, never put function definitions inside a loop, that defeats the purpose of the function altogether.<\/p>\n
Second, you are still calling an environment variable instead of the loop variable:<\/p>\n
# Wrong\nforeach ($User in $Users){\n $Shortcuts = Get-ChildItem -Recurse \\\\UNCPATHTOUSERPROFILES\\$env:USERNAME -Include *.lnk\n...\n}\n\n# Right\nforeach ($User in $Users){\n $Shortcuts = Get-ChildItem -Recurse \\\\UNCPATHTOUSERPROFILES\\$User -Include *.lnk\n...\n}\n<\/code><\/pre>\nThird, you never call the function. Each iteration you only define the function and don’t do anything with it. In all honesty the code is short enough that a function is not really justified, just put the code inside the loop:<\/p>\n
$Users = (Get-Content C:\\temp\\Users.csv) -notmatch '^\\s*$'\n\nforeach ($User in $Users) {\n $Shortcuts = Get-ChildItem -Recurse \\\\UNCPATHTOUSERPROFILES\\$User -Include *.lnk\n $Shell = New-Object -ComObject WScript.Shell\n $data = foreach ($Shortcut in $Shortcuts) {\n [PSCustomObject]@{\n ShortcutName = $Shortcut.Name;\n ShortcutFull = $Shortcut.FullName;\n ShortcutPath = $shortcut.DirectoryName\n Target = $Shell.CreateShortcut($Shortcut).targetpath\n # Always useful to know the user\n User = $User\n } \n }\n [Runtime.InteropServices.Marshal]::ReleaseComObject($Shell) | Out-Null\n}\n$data | Export-Csv report.csv -NoTypeInformation\n<\/code><\/pre>","upvoteCount":3,"datePublished":"2020-02-11T13:52:56.000Z","url":"https://community.spiceworks.com/t/shortcut-path-identifier/750732/4","author":{"@type":"Person","name":"tulioarends","url":"https://community.spiceworks.com/u/tulioarends"}},{"@type":"Answer","text":"As a further improvement, you can move the shell instantiation and disposal outside of the loop. There is no need to do this multiple times.<\/p>","upvoteCount":1,"datePublished":"2020-02-11T14:36:02.000Z","url":"https://community.spiceworks.com/t/shortcut-path-identifier/750732/5","author":{"@type":"Person","name":"tulioarends","url":"https://community.spiceworks.com/u/tulioarends"}},{"@type":"Answer","text":"
add more?<\/p>\n
Function Check-Shortcut{\n\t[CmdletBinding()]\n\t\tParam(\n\t\t\t[Parameter(\n\t\t\t\tMandatory=$True,\n\t\t\t\tHelpMessage=\"Please enter Path of Shortcut, Example c:\\folder\",\n\t\t\t\tPosition=1\n\t\t\t)][string]$path\n\t\t )\n$ErrorActionPreference='Silentlycontinue'\n$Shortcuts = Get-ChildItem -Recurse $path -Include *.lnk -Force\n$Shell = New-Object -ComObject WScript.Shell\n Foreach ($Shortcut in $Shortcuts)\n {\n $checks=$shell.CreateShortcut($Shortcut).TargetPath \n \nForeach($check in $checks){\n $pathcheck=Test-Path $($check)\n if($pathcheck -eq $false){\n [Pscustomobject]@{\n Status ='Failed'\n Shortcut =$Shortcut.name\n FailedTopath =$($check)\n }\n }\n elseif($pathcheck -eq $True){\n [Pscustomobject]@{\n Status ='Sucess'\n Shortcut =$Shortcut.name\n Workingpath =$($check)\n }\n }\n }\n }\n }\n \n $Users = (Get-Content C:\\temp\\Users.csv) -notmatch '^\\s*$'\nforeach ($User in $Users) {\n $User=$($User)\n Check-Shortcut -path \\\\UNCPATHTOUSERPROFILES\\$User \n }\n<\/code><\/pre>\nExport<\/p>\n
Function Check-Shortcut{\n\t[CmdletBinding()]\n\t\tParam(\n\t\t\t[Parameter(\n\t\t\t\tMandatory=$True,\n\t\t\t\tHelpMessage=\"Please enter Path of Shortcut, Example c:\\folder\",\n\t\t\t\tPosition=1\n\t\t\t)][string]$path\n\t\t )\n$ErrorActionPreference='Silentlycontinue'\n$Shortcuts = Get-ChildItem -Recurse $path -Include *.lnk -Force\n$Shell = New-Object -ComObject WScript.Shell\n Foreach ($Shortcut in $Shortcuts)\n {\n $checks=$shell.CreateShortcut($Shortcut).TargetPath \n \nForeach($check in $checks){\n $pathcheck=Test-Path $($check)\n if($pathcheck -eq $false){\n [Pscustomobject]@{\n Status ='Failed'\n Shortcut =$Shortcut.name\n FailedTopath =$($check)\n }\n }\n elseif($pathcheck -eq $True){\n [Pscustomobject]@{\n Status ='Sucess'\n Shortcut =$Shortcut.name\n Workingpath =$($check)\n }\n }\n }\n }\n }\n \n $Users = (Get-Content C:\\temp\\Users.csv) -notmatch '^\\s*$'\n$data=foreach ($User in $Users) {\n $User=$($User)\n Check-Shortcut -path \\\\UNCPATHTOUSERPROFILES\\$User \n }\n$data|export-csv c:\\results.csv -notype\n<\/code><\/pre>","upvoteCount":0,"datePublished":"2020-02-11T14:37:03.000Z","url":"https://community.spiceworks.com/t/shortcut-path-identifier/750732/6","author":{"@type":"Person","name":"jitensh","url":"https://community.spiceworks.com/u/jitensh"}},{"@type":"Answer","text":"Seriously thank you guys so much, just crazy how knowledgeable y’all are. i’m sorry for my noob moment of putting the function definitions inside a loop but you guys showed me something today! Thanks Jiten too for the improvements, i’m working on trying those out now<\/p>\n
@tulioarends<\/a> @jitensh<\/a><\/p>","upvoteCount":0,"datePublished":"2020-02-11T14:48:15.000Z","url":"https://community.spiceworks.com/t/shortcut-path-identifier/750732/7","author":{"@type":"Person","name":"richiesilva","url":"https://community.spiceworks.com/u/richiesilva"}},{"@type":"Answer","text":"