Many file extensions are associated with executables. You can then use Invoke-Item to open a document with this executable.
Finding out just which executable is responsible for a given file extension is not so trivial, though. You can read the Windows Registry, and try and figure this out yourself. If you take this route, beware of 32/64-bit issues.
Another approach is using the Windows API. The following sample illustrates how this works. If you take this approach, you can leave the heavy lifting to the operating system. The price you pay is a chunk of c# code that is calling the internal API function.
$Source = @" using System; using System.Text; using System.Runtime.InteropServices; public class Win32API { [DllImport("shell32.dll", EntryPoint="FindExecutable")] public static extern long FindExecutableA(string lpFile, string lpDirectory, StringBuilder lpResult); public static string FindExecutable(string pv_strFilename) { StringBuilder objResultBuffer = new StringBuilder(1024); long lngResult = 0; lngResult = FindExecutableA(pv_strFilename, string.Empty, objResultBuffer); if(lngResult >= 32) { return objResultBuffer.ToString(); } return string.Format("Error: ({0})", lngResult); } } "@ Add-Type -TypeDefinition $Source -ErrorAction SilentlyContinue $FullName = 'c:\Windows\windowsupdate.log' $Executable = [Win32API]::FindExecutable($FullName) "$FullName will be launched by $Executable"
A known limitation is that FindExecutable() requires the file to exist. You cannot ask for an executable based on file extension only.