Diskuze: Načtení asociovaného souboru

C# .NET .NET (C# a Visual Basic) Načtení asociovaného souboru American English version English version

Avatar
jt.e
Člen
Avatar
jt.e:

Zdravím.
Jak se prosím v C# odchytává pokus uživatele otevřít soubor v aplikaci (WinForm)?

 
Odpovědět 23. února 20:44
Avatar
jt.e
Člen
Avatar
jt.e:

jedná se mi o otevření, když už aplikace běží (ne přes argument)

Editováno 23. února 20:59
 
Nahoru Odpovědět 23. února 20:58
Avatar
jt.e
Člen
Avatar
jt.e:

Ještě raději dodám, že mám takto bráním spuštění další instance aplikace:

static class Program
{

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    ///
    static Mutex mutex = new Mutex(false, "Prohlížeč 3.0");

    [STAThread]
    static void Main()
    {
        if (!mutex.WaitOne(TimeSpan.FromSeconds(2), false))
        {
            return;
        }

        try
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
        finally
        {
            mutex.ReleaseMutex();
        }
    }
}
 
Nahoru Odpovědět 23. února 21:24
Avatar
Michal Žůrek (misaz):

nijak, prostě se spustí ta přiřazená aplikace (popř tu co vybere uživatel v dialogu Otevřít v aplikaci), tak že ti ten soubor předají v parametrech příkazového řádku no a takto nově spuštěná aplikace si to nějak vykomunikuje s již otevřenou aplikací.

Nahoru Odpovědět 23. února 21:36
Nesnáším {}, proto se jim vyhýbám.
Avatar
Michal Žůrek (misaz):

i když nevím jestli ti to nějak půjde tím že ti to zablokuje ten mutex, ale snad jo.

Nahoru Odpovědět 23. února 21:37
Nesnáším {}, proto se jim vyhýbám.
Avatar
jt.e
Člen
Avatar
Odpovídá na Michal Žůrek (misaz)
jt.e:

Chápu, ale jak ty parametry předat spuštěné aplikaci?

 
Nahoru Odpovědět 23. února 21:52
Avatar
Odpovídá na jt.e
Michal Žůrek (misaz):

operační systém ti předá jako parametr příkazového řádku cestu k souboru na který uživatel poklikal.

Nahoru Odpovědět 23. února 22:05
Nesnáším {}, proto se jim vyhýbám.
Avatar
jt.e
Člen
Avatar
jt.e:

To chápu. Ale ne když poklepeš na soubor, tak se ti spustí další instance aplikace, když ta zjistí, že už běží jiná, tak jí musí ty své parametry nějak předat a poté se sama ukončit.

 
Nahoru Odpovědět 23. února 22:11
Avatar
jt.e
Člen
Avatar
jt.e:

Nějak mi to funguje
Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace textshow
{
    static class Program
    {
        public const int WM_COPYDATA = 0x004A;
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        ///
        [STAThread]
        static void Main()
        {
            IntPtr h = FindWindowByCaption(IntPtr.Zero, "Prohlížeč 3.0");
            if (IntPtr.Zero == h)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
            else
            {
                String[] arguments = Environment.GetCommandLineArgs();
                if (arguments.Length > 1)
                {
                    SendParam(h, arguments[1]);
                }
            }
        }

        public static IntPtr IntPtrAlloc<T>(T param)
        {
            IntPtr retval = Marshal.AllocHGlobal(Marshal.SizeOf(param));
            Marshal.StructureToPtr(param, retval, false);
            return retval;
        }

        // Free a pointer to an arbitrary structure from the global heap.
        public static void IntPtrFree(ref IntPtr preAllocated)
        {
            if (IntPtr.Zero == preAllocated)throw (new NullReferenceException("Zero == preAllocated"));
            Marshal.FreeHGlobal(preAllocated);
            preAllocated = IntPtr.Zero;
        }

        public static void SendParam(IntPtr hWnd, string message)
        {
            try
            {
                COPYDATASTRUCT cds;
                cds.dwData = IntPtr.Zero;
                cds.cbData = 2 * (message.Length + 1); // TADY NEVÍM
                cds.lpData = Marshal.StringToHGlobalAuto(message.ToString());
                IntPtr cdsBuffer = IntPtrAlloc(cds);
                SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, cdsBuffer);
                IntPtrFree(ref cds.lpData);
                IntPtrFree(ref cdsBuffer);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}
ve Form1.cs
protected override void WndProc(ref Message m)
{
    if(m.Msg == Program.WM_COPYDATA)
    {
        try
        {
            COPYDATASTRUCT cds;
            cds = (COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT));
            string arg = Marshal.PtrToStringAuto(cds.lpData);

            LoadFromFile(arg);
        }
        catch (Exception ex)
        {
            textBox1.Text = ex.Message;
        }
    }

    base.WndProc(ref m);
}

Je pořád nemůžu přijít nato jak správně zaznamenat velikost objektu:
cds.cbData = 2 * (message.Length + 1); myslím nebude úplně správně
a můžete mi prosím říct co ještě mám nesprávně?

Editováno 24. února 20:12
 
Nahoru Odpovědět 24. února 20:09
Avatar
jt.e
Člen
Avatar
jt.e:

Oprava: Jen pořád nemůžu přijít na to, jak správně zaznamenat..

A prosím, kdyby mi někdo vysvětlil funkce IntPtrAlloc a IntPtrFree, ty mám z netu a moc nechápu co přesně dělají (Je mi pouze jasné že slouží k alokaci a uvolnění), ale jak přesně fungují a proč tam musí být...?

Editováno 24. února 20:23
 
Nahoru Odpovědět 24. února 20:21
Avatar
jt.e
Člen
Avatar
jt.e:

Takže asi hotovo.

//Program.cs

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace textshow
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        ///
        [STAThread]
        static void Main()
        {
            IntPtr h = Native.FindWindowByCaption(IntPtr.Zero, "Prohlížeč 3.0");
            if (IntPtr.Zero == h)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
            else
            {
                String[] arguments = Environment.GetCommandLineArgs();
                if (arguments.Length > 1)
                {
                    SendParam(h, arguments[1]);
                }
            }
        }

        public static void SendParam(IntPtr hWnd, string message)
        {
            try
            {
                COPYDATASTRUCT cds;
                cds.dwData = 2016;
                cds.cbData = 0;
                cds.lpData = message;

                IntPtr strprt = Marshal.AllocHGlobal(Marshal.SizeOf(cds)); ;
                Marshal.StructureToPtr(cds, strprt, false);
                Native.SendMessage(hWnd, Native.WM_COPYDATA, IntPtr.Zero, strprt);
                Native.IntPtrFree(ref strprt);
                Native.SetForegroundWindow(hWnd);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }

    //-------------------------------------------------------------------------
    public struct COPYDATASTRUCT
    {
        public int cbData;
        public int dwData;
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpData;
    }
    //-------------------------------------------------------------------------
    public static class Native
    {
        public const int WM_COPYDATA = 0x004A;

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        public static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);

        [DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        public static void IntPtrFree(ref IntPtr preAllocated)
        {
            if (IntPtr.Zero == preAllocated) return;

            Marshal.FreeHGlobal(preAllocated);
            preAllocated = IntPtr.Zero;
        }
    }
    //-------------------------------------------------------------------------
}
//============================================
//Form1.cs

using System;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;

namespace textshow
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public void LoadFromFile(string filename)
        {
            try
            {
                using (StreamReader r = new StreamReader(filename, Encoding.Default, true))
                {
                    textBox1.Clear();
                    textBox1.Text = r.ReadToEnd();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        public void LoadParams()
        {
            String[] arguments = Environment.GetCommandLineArgs();
            if (arguments.Length > 1)
            {
                if (File.Exists(arguments[1])) LoadFromFile(arguments[1]);
            }
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            LoadParams();
        }

        protected override void WndProc(ref Message m)
        {
            if(m.Msg == Native.WM_COPYDATA)
            {
                try
                {
                    COPYDATASTRUCT cds;
                    cds = (COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT));
                    if (cds.dwData == 2016)
                    {
                        LoadFromFile(cds.lpData);
                    }
                }
                catch (Exception ex)
                {
                    textBox1.Text = ex.Message;
                }
            }

            base.WndProc(ref m);
        }
    }
}
Akceptované řešení
+5 Zkušeností
Řešení problému
 
Nahoru Odpovědět 24. února 22:18
Avatar
jt.e
Člen
Avatar
jt.e:

jen kdyby to někdo potřeboval, tak ještě doporučím změnit data struktury pro podporu unicode cest k souborům:

public struct COPYDATASTRUCT
    {
        public int cbData;
        public int dwData;
        [MarshalAs(UnmanagedType.LPWStr)] ///<-
        public string lpData;
    }
 
Nahoru Odpovědět 25. února 19:10
Avatar
Odpovídá na jt.e
sadlomaslox25:

podle me to mas nejaky slozity. ja bych osobne pouzij asi jen

[STAThread]
static void Main(string[] args)
{
    try
    {
        NamedPipeServerStream server = new NamedPipeServerStream("myServer") ;
        Task.Factory.StartNew(() =>
        {
            var stream = new StreamReader(server);
            while (true)
            {
                server.WaitForConnection();
                var filePath = stream.ReadLine();
                server.Disconnect();
                MessageBox.Show($"File: {filePath}", "Title", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
            }
        });
    }
    catch (Exception ex)
    {
        using (var client = new NamedPipeClientStream("myServer"))
        using (var stream = new StreamWriter(client))
        {
            client.Connect(3000);
            stream.AutoFlush = true;
            stream.WriteLine(args?.FirstOrDefault() ?? "none");
        }
        return;
    }
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}
 
Nahoru Odpovědět 25. února 20:27
Avatar
jt.e
Člen
Avatar
Odpovídá na sadlomaslox25
jt.e:

A jak v tomto způsobu předám spuštěné aplikaci argumenty a spustím funkci LoadFromFile ? Mohl bych prosit o ukázku na daném projektu?

Editováno 25. února 21:53
 
Nahoru Odpovědět 25. února 21:51
Avatar
jt.e
Člen
Avatar
jt.e:

http://leteckaposta.cz/711220678

Editováno 25. února 21:58
 
Nahoru Odpovědět 25. února 21:55
Avatar
Odpovídá na jt.e
sadlomaslox25:
public partial class Form1 : Form
    {
        public Form1(string filename)
        {
            InitializeComponent();
            LoadFromFile(filename);
        }

        public void LoadFromFile(string filename)
        {
            if (!File.Exists(filename))
            {
                textBox1.Clear();
                MessageBox.Show("File not exists");
                return;
            }
            try
            {
                using (StreamReader r = new StreamReader(filename, Encoding.Default, true))
                {
                    textBox1.Clear();
                    textBox1.Text = r.ReadToEnd();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    ///
    [STAThread]
    static void Main(string[] args)
    {
        Form1 form = null;
        try
        {
            NamedPipeServerStream server = new NamedPipeServerStream("myServer");
            Task.Factory.StartNew(() =>
            {
                var stream = new StreamReader(server);
                while (true)
                {
                    server.WaitForConnection();
                    var filePath = stream.ReadLine();
                    server.Disconnect();
                    form.Invoke(new Action(() => form.LoadFromFile(filePath)));
                }
            });
        }
        catch (Exception ex)
        {
            using (var client = new NamedPipeClientStream("myServer"))
            using (var stream = new StreamWriter(client))
            {
                client.Connect(3000);
                stream.AutoFlush = true;
                stream.WriteLine(args?.FirstOrDefault() ?? "");
            }
            return;
        }
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(form = new Form1(args?.FirstOrDefault()));
    }
}
 
Nahoru Odpovědět  +1 25. února 23:19
Avatar
jt.e
Člen
Avatar
jt.e:

Díky moc. Sám bych to dohromady nedal, .Pipe, Invoke, FirstOrDefault jsou pro mě nové věci.

 
Nahoru Odpovědět 26. února 19:49
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 18 zpráv z 18.