如何在.NET Core (C#)控制台应用程序中创建一个打开文件对话框?

4

我希望能够提供一个选择来自电脑任何位置的文件的选项。目前,我是这样明确给出路径的:

FileInfo existingFile = new FileInfo(@"C:\Users\User_name\Downloads\bank_statement.xlsx");

使用EPPlus操作Excel文件。如何直接从所需文件夹获取文件? 控制台应用程序.NET Core 3.1 C#。

4
对话框是GUI应用程序的资源,而不是控制台应用程序的资源。您可以要求用户从控制台输入路径并读取它,或者用户可以在启动应用程序时将其作为参数传递。 - undefined
1
不要像@Magnetron说的那样在控制台应用程序中使用GUI元素。相反,如果您需要用户提供的任何内容,请通过参数传递这些值:例如,application.exe -filename="C:\yourfile.xlsx" - undefined
asp.net是一个网页应用程序,而不是控制台应用程序。你可以有一个控制台应用程序或者一个图形用户界面应用程序(WinForms、WPF、Xamarin、MAUI),或者一个网页应用程序。 - undefined
这个问题的问题并不是没有解决办法,因为有很多。问题在于它是一个重复的问题,在发布之前应该进行研究。 - undefined
2
从控制台应用程序或系统服务中调用GUI API(如创建窗体或.NET控件)或直接调用系统文件对话框API是没有问题的。绝对没有任何问题。问题只在于如何做得好、干净,并且管理行为和问题。 - user12031933
2个回答

7
如果您真的想在控制台应用程序中打开对话框(而命令行参数不是一个选项),并且没有依赖关系,您可以调用comdlg32.dll中的GetOpenFileNamepinvoke.net提供了这些方法及其参数的C#定义。当然,这取决于平台(仅限Windows)。
using System;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace DemoApp
{
    // From https://www.pinvoke.net/default.aspx/Structures/OPENFILENAME.html
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct OpenFileName
    {
        public int lStructSize;
        public IntPtr hwndOwner;
        public IntPtr hInstance;
        public string lpstrFilter;
        public string lpstrCustomFilter;
        public int nMaxCustFilter;
        public int nFilterIndex;
        public string lpstrFile;
        public int nMaxFile;
        public string lpstrFileTitle;
        public int nMaxFileTitle;
        public string lpstrInitialDir;
        public string lpstrTitle;
        public int Flags;
        public short nFileOffset;
        public short nFileExtension;
        public string lpstrDefExt;
        public IntPtr lCustData;
        public IntPtr lpfnHook;
        public string lpTemplateName;
        public IntPtr pvReserved;
        public int dwReserved;
        public int flagsEx;
    }

    public class Program
    {
        // From https://www.pinvoke.net/default.aspx/comdlg32/GetOpenFileName.html
        [DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern bool GetOpenFileName(ref OpenFileName ofn);

        private static string ShowDialog()
        {
            var ofn = new OpenFileName();
            ofn.lStructSize = Marshal.SizeOf(ofn);
            // Define Filter for your extensions (Excel, ...)
            ofn.lpstrFilter = "Excel Files (*.xlsx)\0*.xlsx\0All Files (*.*)\0*.*\0";
            ofn.lpstrFile = new string(new char[256]);
            ofn.nMaxFile = ofn.lpstrFile.Length;
            ofn.lpstrFileTitle = new string(new char[64]);
            ofn.nMaxFileTitle = ofn.lpstrFileTitle.Length;
            ofn.lpstrTitle = "Open File Dialog...";
            if (GetOpenFileName(ref ofn))
                return ofn.lpstrFile;
            return string.Empty;
        }

        public static void Main(string[] args)
        {
            var filename = ShowDialog();
            Console.WriteLine(filename);
        }
    }
}

4
如果真的需要在控制台应用程序中使用.NET GUI组件,则应将其转换为UI应用程序。但是,此后该应用程序将变为GUI应用程序(而不是控制台应用程序)。
例如,您可以将其转换为WinForms应用程序。
打开项目文件并添加<UseWindowsForms>true</UseWindowsForms>
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UseWindowsForms>true</UseWindowsForms>
  </PropertyGroup>
</Project>

那么:

using System;
using System.Windows.Forms;

namespace ConsoleApp
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            if (DialogResult.OK == dialog.ShowDialog())
            {
                string path = dialog.FileName;
            }
            Console.WriteLine("Hello World!");
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接