none
Launching Windows Photo Viewer RRS feed

  • Question

  • I'm trying to launch Windows Photo Viewer programmatically. I've tried several methods that are professed to work but none of them do. I don't get any errors but I don't get the viewer either. I've tried (hardcoded paths just to illustrate):

    var process = new Process( );
    process.StartInfo.FileName = "c:\\windows\\system32\\rundll32.exe ";
    process.StartInfo.Arguments = "\"c:\\program files\\windows photo viewer\\photoviewer.dll\",ImageView_Fullscreen c:\\myimg.png";
    
    process.Start( );
    

    Also:

    var psi = new ProcessStartInfo( );
    psi.FileName = "c:\\windows\\system32\\rundll32.exe ";
    psi.Arguments = "\"c:\\program files\\windows photo viewer\\photoviewer.dll\", ImageView_Fullscreen c:\\myimg.png";
    psi.UseShellExecute = false;
    psi.CreateNoWindow = true;
    Process.Start( psi );
    
    This is on Win7 x64 VS2012. Any ideas?

    Friday, August 2, 2019 3:15 PM

Answers

  • I'm trying to launch Windows Photo Viewer programmatically. I've tried several methods that are professed to work but none of them do. I don't get any errors but I don't get the viewer either. I've tried (hardcoded paths just to illustrate):

    var process = new Process( );
    process.StartInfo.FileName = "c:\\windows\\system32\\rundll32.exe ";
    process.StartInfo.Arguments = "\"c:\\program files\\windows photo viewer\\photoviewer.dll\",ImageView_Fullscreen c:\\myimg.png";
    
    process.Start( );


    This is on Win7 x64 VS2012. Any ideas?

    Do you have Admin rights when running this?

    FWIW, I tried your first example on Win7 64 using VS 2017 after changing the
    image file to myimg.jpg and it works fine. 

    - Wayne

    • Marked as answer by D A M Monday, August 5, 2019 3:29 PM
    Friday, August 2, 2019 3:36 PM
  • It also works for me (Windows 10, VS 2015)

    You can try if it works with the Shell =>

    HRESULT hr = HRESULT.E_FAIL;
    uint rgflnOut = 0;
    System.Runtime.InteropServices.ComTypes.IDataObject pDataObject;
    IntPtr pidlParent = IntPtr.Zero, pidlFull = IntPtr.Zero, pidlItem = IntPtr.Zero;
    var aPidl = new IntPtr[255];
    
    hr = SHILCreateFromPath("E:\\test.jpg", out pidlFull, ref rgflnOut);
    if (hr == HRESULT.S_OK)
    {
        pidlItem = ILFindLastID(pidlFull);
        aPidl[0] = ILClone(pidlItem);
        ILRemoveLastID(pidlFull);
        pidlParent = ILClone(pidlFull);
        ILFree(pidlFull);
    
        hr = SHCreateFileDataObject(pidlParent, 1, aPidl, null, out pDataObject);
        if (hr == HRESULT.S_OK)
        {
            //Guid CLSID_PrintPhotosDropTarget = new Guid("60fd46de-f830-4894-a628-6fa81bc0190d");
            Guid CLSID_PhotoViewerDropTarget = new Guid("ffe2a43c-56b9-4bf5-9a79-cc6d4285608a");
            //Type DropTargetType = Type.GetTypeFromCLSID(CLSID_PrintPhotosDropTarget, true);
            Type DropTargetType = Type.GetTypeFromCLSID(CLSID_PhotoViewerDropTarget, true);
            object DropTarget = Activator.CreateInstance(DropTargetType);
            IDropTarget pDropTarget = (IDropTarget)DropTarget;
            int pdwEffect = DROPEFFECT_NONE;
            POINT pt;
            pt.x = 0;
            pt.y = 0;
            hr = pDropTarget.Drop(pDataObject, 0, pt, pdwEffect);
        }
    
        if (pidlParent != IntPtr.Zero)
            ILFree(pidlParent);
        if (aPidl[0] != IntPtr.Zero)
            ILFree(aPidl[0]);                
    }

    Declarations =>

    	public enum HRESULT : int
            {
                S_OK = 0,
                S_FALSE = 1,
                E_NOINTERFACE = unchecked((int)0x80004002),
                E_NOTIMPL = unchecked((int)0x80004001),
                E_FAIL = unchecked((int)0x80004005),
            }
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern HRESULT SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)]string pszPath, out IntPtr ppIdl, ref uint rgflnOut);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "#740")]
            public static extern HRESULT SHCreateFileDataObject(IntPtr pidlFolder, uint cidl, IntPtr[] apidl, System.Runtime.InteropServices.ComTypes.IDataObject pdtInner, out System.Runtime.InteropServices.ComTypes.IDataObject ppdtobj);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern IntPtr ILFindLastID(IntPtr pidl);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern IntPtr ILClone(IntPtr pidl);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern Boolean ILRemoveLastID(IntPtr pidl);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern void ILFree(IntPtr pidl);
    
            public const int DROPEFFECT_NONE = (0);
            [ComImport]
            [Guid("00000122-0000-0000-C000-000000000046")]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            public interface IDropTarget
            {
                HRESULT DragEnter(
                    [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
                    [In] int grfKeyState,
                    [In] POINT pt,
                    [In, Out] ref int pdwEffect);
    
                HRESULT DragOver(
                    [In] int grfKeyState,
                    [In] POINT pt,
                    [In, Out] ref int pdwEffect);
    
                HRESULT DragLeave();
    
                HRESULT Drop(
                    [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
                    [In] int grfKeyState,
                    [In] POINT pt,
                    [In, Out] ref int pdwEffect);
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct POINT
            {
                public int x;
                public int y;
    
                public POINT(int X, int Y)
                {
                    this.x = X;
                    this.y = Y;
                }
            }


    • Edited by Castorix31 Friday, August 2, 2019 9:52 PM
    • Marked as answer by D A M Monday, August 5, 2019 3:29 PM
    Friday, August 2, 2019 9:51 PM

All replies

  • I'm trying to launch Windows Photo Viewer programmatically. I've tried several methods that are professed to work but none of them do. I don't get any errors but I don't get the viewer either. I've tried (hardcoded paths just to illustrate):

    var process = new Process( );
    process.StartInfo.FileName = "c:\\windows\\system32\\rundll32.exe ";
    process.StartInfo.Arguments = "\"c:\\program files\\windows photo viewer\\photoviewer.dll\",ImageView_Fullscreen c:\\myimg.png";
    
    process.Start( );


    This is on Win7 x64 VS2012. Any ideas?

    Do you have Admin rights when running this?

    FWIW, I tried your first example on Win7 64 using VS 2017 after changing the
    image file to myimg.jpg and it works fine. 

    - Wayne

    • Marked as answer by D A M Monday, August 5, 2019 3:29 PM
    Friday, August 2, 2019 3:36 PM
  • I also tried it using VS 2012 Express and myimg.png and it works fine.

    - Wayne
    Friday, August 2, 2019 3:44 PM
  • Which method did you use? Yes, I have admin rights and launch VS as admin. Not sure why I would need those rights as this is a read operation. I guess it's possible this is machine specific, I'll try it on another machine to see if it works. Thanks.
    Friday, August 2, 2019 4:47 PM
  • Which method did you use?  I guess it's possible this is machine specific, I'll try it on another machine to see if it works. 

    >Which method did you use? 

    As I said: the first one you listed and which I quoted in my reply.
    Here it is as copy/pasted *from* the VS 2012 IDE:

    static void Main(string[] args)
    {
        var process = new Process();
        process.StartInfo.FileName = "c:\\windows\\system32\\rundll32.exe ";
        process.StartInfo.Arguments = "\"c:\\program files\\windows photo viewer\\photoviewer.dll\",ImageView_Fullscreen c:\\myimg.png";
    
        process.Start();
    }
    

    >I guess it's possible this is machine specific

    Could be. User rights? Policy settings? UAC? Security software blocking?

    I'm running Win7 Home Premium 64-bit.

    - Wayne

    Friday, August 2, 2019 6:58 PM
  • It also works for me (Windows 10, VS 2015)

    You can try if it works with the Shell =>

    HRESULT hr = HRESULT.E_FAIL;
    uint rgflnOut = 0;
    System.Runtime.InteropServices.ComTypes.IDataObject pDataObject;
    IntPtr pidlParent = IntPtr.Zero, pidlFull = IntPtr.Zero, pidlItem = IntPtr.Zero;
    var aPidl = new IntPtr[255];
    
    hr = SHILCreateFromPath("E:\\test.jpg", out pidlFull, ref rgflnOut);
    if (hr == HRESULT.S_OK)
    {
        pidlItem = ILFindLastID(pidlFull);
        aPidl[0] = ILClone(pidlItem);
        ILRemoveLastID(pidlFull);
        pidlParent = ILClone(pidlFull);
        ILFree(pidlFull);
    
        hr = SHCreateFileDataObject(pidlParent, 1, aPidl, null, out pDataObject);
        if (hr == HRESULT.S_OK)
        {
            //Guid CLSID_PrintPhotosDropTarget = new Guid("60fd46de-f830-4894-a628-6fa81bc0190d");
            Guid CLSID_PhotoViewerDropTarget = new Guid("ffe2a43c-56b9-4bf5-9a79-cc6d4285608a");
            //Type DropTargetType = Type.GetTypeFromCLSID(CLSID_PrintPhotosDropTarget, true);
            Type DropTargetType = Type.GetTypeFromCLSID(CLSID_PhotoViewerDropTarget, true);
            object DropTarget = Activator.CreateInstance(DropTargetType);
            IDropTarget pDropTarget = (IDropTarget)DropTarget;
            int pdwEffect = DROPEFFECT_NONE;
            POINT pt;
            pt.x = 0;
            pt.y = 0;
            hr = pDropTarget.Drop(pDataObject, 0, pt, pdwEffect);
        }
    
        if (pidlParent != IntPtr.Zero)
            ILFree(pidlParent);
        if (aPidl[0] != IntPtr.Zero)
            ILFree(aPidl[0]);                
    }

    Declarations =>

    	public enum HRESULT : int
            {
                S_OK = 0,
                S_FALSE = 1,
                E_NOINTERFACE = unchecked((int)0x80004002),
                E_NOTIMPL = unchecked((int)0x80004001),
                E_FAIL = unchecked((int)0x80004005),
            }
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern HRESULT SHILCreateFromPath([MarshalAs(UnmanagedType.LPWStr)]string pszPath, out IntPtr ppIdl, ref uint rgflnOut);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "#740")]
            public static extern HRESULT SHCreateFileDataObject(IntPtr pidlFolder, uint cidl, IntPtr[] apidl, System.Runtime.InteropServices.ComTypes.IDataObject pdtInner, out System.Runtime.InteropServices.ComTypes.IDataObject ppdtobj);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern IntPtr ILFindLastID(IntPtr pidl);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern IntPtr ILClone(IntPtr pidl);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern Boolean ILRemoveLastID(IntPtr pidl);
    
            [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            public static extern void ILFree(IntPtr pidl);
    
            public const int DROPEFFECT_NONE = (0);
            [ComImport]
            [Guid("00000122-0000-0000-C000-000000000046")]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            public interface IDropTarget
            {
                HRESULT DragEnter(
                    [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
                    [In] int grfKeyState,
                    [In] POINT pt,
                    [In, Out] ref int pdwEffect);
    
                HRESULT DragOver(
                    [In] int grfKeyState,
                    [In] POINT pt,
                    [In, Out] ref int pdwEffect);
    
                HRESULT DragLeave();
    
                HRESULT Drop(
                    [In] System.Runtime.InteropServices.ComTypes.IDataObject pDataObj,
                    [In] int grfKeyState,
                    [In] POINT pt,
                    [In, Out] ref int pdwEffect);
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct POINT
            {
                public int x;
                public int y;
    
                public POINT(int X, int Y)
                {
                    this.x = X;
                    this.y = Y;
                }
            }


    • Edited by Castorix31 Friday, August 2, 2019 9:52 PM
    • Marked as answer by D A M Monday, August 5, 2019 3:29 PM
    Friday, August 2, 2019 9:51 PM
  • Hi D A M,

    Thank you for posting here.

    Based on your description, you want to launch Windows Photo Viewer programmatically.

    First, you could set Windows Photo Viewer as your default picture software.

    Second, you could try the following code.

    System.Diagnostics.Process.Start(path);

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, August 5, 2019 5:32 AM
    Moderator
  • Sure that's an option but what I'm really trying to do is allow the user to select from a list of the registered programs for that file type and use that as the viewer. This wouldn't be an issue if the Open With dialog that is used in Windows Explorer actually returned some useful information but it doesn't.
    Monday, August 5, 2019 2:49 PM
  • OK, it turns out all the methods mentioned in this thread work fine for non-complex paths. My actual path to the image file is something like C:\ProgramData\Company Name\Progeram Name\Captures\TimeStampedFile.png. In other words, it contains spaces. Quoting the string doesn't work and in the case of the shell COM methods described below returns E_INVALIDARG. So, can anyone get this to work using a path containing spaces?

    Edit: It turns out my path had an extra '\' embedded in it which cause the viewer to choke. After removing the extra backslash I was able to successfully open the file. Thanks to everyone who responded!

    • Edited by D A M Monday, August 5, 2019 3:28 PM
    Monday, August 5, 2019 2:53 PM