Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

New File Shortcut

Posted on March 18, 2010March 18, 2010

I've been looking at the File Server Resource Manager (FSRM) feature in Windows Server 2008 R2 a lot lately. One very nice part of FSRM is the ability to schedule typical file management tasks. One of the examples from the Microsoft storage team is to create a custom task to move old files to another server and leave a shortcut in place. The files are moved to a more appropriate server and the users can still find their files with practically no fuss. However, this requires Windows Server 2008 R2. If you aren't there yet, you can use my PowerShell function, New-FileShortCut in your archiving process.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

This will require PowerShell 2.0. But you should be able to run it from your Windows 7 desktop and manage a Windows Server 2003 file server.

   1: Function New-FileShortcut {

   2: #requires -version 2.0

   3:

   4: <#

   5: .Synopsis

   6:     Create a file link shortcut.

   7: .Description

   8:     This function will create a file shortcut link, a .lnk file. This can be useful when

   9:     moving files to another location and you want to leave a shortcut behind in place

  10:     of the orginal file. You must specify a shortcut name ending in .lnk and the target

  11:     file must already be in place.

  12:

  13:     This function fully supports -verbose, -confirm and -whatif.

  14:

  15: .Parameter Name

  16:     The full filename and path of the shortcut file. It must end in .lnk. You

  17:     should specify the complete path.

  18: .Parameter Target

  19:     The full filename and path of the target file. It must exist as it will be

  20:     verified during the validation process.

  21: .Parameter Passthru

  22:     By default nothing is written to the pipeline. Use -Passthru to write the shortcut

  23:     file object to the pipeline.

  24: .Example

  25:     PS C:\> New-FileShortcut \\file01\files\MyData.lnk \\file02\Archive\MyData.doc

  26:

  27:     This will create a shortcut file for MyData on FILE01 that points to the actual

  28:     file on FILE02.

  29: .Example

  30:     PS C:\>  dir H:\Files\*.csv | foreach {

  31:     $dest="\\File02\Archive\files"

  32:       Move-Item $_ -destination $dest

  33:       New-FileShortcut -name (Join-Path $_.Directory "$($_.basename).lnk" -target (Join-path $dest $_.name) -Passthru

  34:       }

  35:

  36:     This example will move all CSV files from H:\Files to the Archive folder on FILE02. After each file is moved

  37:     a new shortcut link is left in its place.  Join-Path is used to construct valid file paths and names.

  38:

  39: .Inputs

  40:     None

  41: .Outputs

  42:     File object if you use -Passthru

  43:

  44: .Link

  45:    Get-Item

  46:

  47: .Notes

  48:  NAME:      New-FileShortcut

  49:  VERSION:   1.1

  50:  AUTHOR:    Jeffery Hicks

  51:  LASTEDIT:  3/17/2010

  52:

  53: #>

  54:

  55: [cmdletBinding(SupportsShouldProcess=$True,ConfirmImpact="Low")]

  56:

  57: Param (

  58:     [Parameter(Mandatory=$True, ValueFromPipeline=$False,Position=0,

  59:     HelpMessage="Enter the name of the file shortcut. It must end in .lnk")]

  60:     [ValidateScript({$_.EndsWith(".lnk")})]

  61:     [string]$Name,

  62:

  63:     [Parameter(Mandatory=$True, ValueFromPipeline=$False,Position=1,

  64:     HelpMessage="Enter the full path to the target file shortcut. The file must already exist.")]

  65:     [ValidateScript({Test-Path $_})]

  66:     [string]$Target,

  67:

  68:     [Switch]$PassThru

  69:

  70: ) #end Parameter definition

  71:

  72: Begin {

  73:     write-verbose "Starting function"

  74:     write-verbose "Creating the shell COM Object"

  75:     $wshell=New-Object -ComObject "Wscript.Shell"

  76: } #end Begin scriptblock

  77:

  78: Process {

  79:     write-verbose "Creating a shortcut for $target as $name"

  80:     #shortcut will be saved in System32 folder unless a full path

  81:     #is specified. If the user just puts in a filename, assume

  82:     #they want the file in the current directory.

  83:

  84:     if (split-path $name -Parent) {

  85:         $linkpath=$name

  86:     }

  87:     else {

  88:         $linkpath=Join-path (get-location) $name

  89:         write-verbose "Adjusting link file to $linkpath"

  90:     }

  91:

  92:     $shortcut=$wshell.CreateShortcut($linkpath)

  93:     $shortcut.TargetPath=$target

  94:

  95:     if ($pscmdlet.ShouldProcess($Target)) {

  96:         write-verbose "Saving shortcut"

  97:         $shortcut.Save()

  98:

  99:         if ($passthru) {

 100:             write-verbose "Passing shortcut file object to the pipeline"

 101:             #write the new shortcut file object to the pipeline if -Passthru

 102:             Get-item $shortcut.fullname

 103:         }

 104:     }

 105:

 106:  } #end Process scriptblock

 107:

 108:  End {

 109:     write-verbose "Removing the shell object"

 110:     Remove-variable wshell -confirm:$false

 111:     write-verbose "Ending function"

 112:  } #end End scriptblock

 113:

 114: } #end Function

The function includes comment-based help to make it easier to understand and use.

image

I’ve also taken the liberty of including support for –Verbose, –WhatIf and –Confirm. Not that creating a shortcut is that serious but I thought it might be worthwhile as a demonstration. These are defined with the cmdletBinding statement.

[cmdletBinding(SupportsShouldProcess=$True,ConfirmImpact="Low")]

The Write-Verbose lines only execute if you use –Verbose. The SupportsShouldProcess setting is used when –WhatIf is specified. This block of code is configured to handle –WhatIf.

   1: if ($pscmdlet.ShouldProcess($Target)) {

   2:        write-verbose "Saving shortcut"

   3:        $shortcut.Save()

Using –WhatIf turns line 1 into a False statement so the shortcut is never saved.  The method value I’m using, $Target, is what PowerShell displays in the WhatIf statement. I could have used any variable. In my case it made more sense to show the target file. If –Whatif isn’t specified then this line is True and the file is saved.

The ConfirmImpact setting tells PowerShell to prompt me if –Confirm is passed. If you always want to be confirmed, you can set this value to “High”.

The function itself is a wrapper for the Wscript.Shell COM object that you use in VBScript. This object has a CreateShortcut() method. All my function is doing is creating a simple shortcut. By default the function doesn’t write anything to the pipeline, but you can use –Passthru to see the actual file. I couldn’t think of a good situation where you might want to use this in a pipelined expression so I kept it simple. Feel free to edit the function if you want to reverse this behavior.

Alright. Now that we have this function how can we use it in our file management task? Conceptually you would use Get-Childitem to retrieve what ever set of files you want to manage. Move them to the new location then create a shortcut in the original directory that points to the moved file.

   1: dir \\File01\Files\*.csv | foreach {

   2:   $dest="\\File02\Archive\files"

   3:   Move-Item $_ -destination $dest

   4:   $link=(Join-Path $_.Directory "$($_.basename).lnk"

   5:   $target=(Join-path $dest $_.name)

   6:   New-FileShortcut -name $link  -target $target -Passthru

   7:  }

   8:

In this example I’m getting all CSV files from \\File01\Files. Each file is moved to the new destination and to keep it easy to follow I' define values for the link file (did I mention it must end in .lnk?) and the target file. I want to make sure the link file keeps the same basename and is in the same directory. But just like that all the CSV files are moved, leaving shortcut links in their place. When the user goes to the share and double clicks the CSV icon, they’ll actually open the file from the other server.

You can download the script file here.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

2 thoughts on “New File Shortcut”

  1. Jeffery Hicks says:
    March 18, 2010 at 12:11 pm

    Oops. Wrong file attached.

  2. Jeffery Hicks says:
    March 18, 2010 at 12:18 pm

    Now I have the right file in the right formatting.

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d