问题
I can't use OpenFileDialog in my application.
As an alternative I use GetOpenFileName() method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Reader
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class OpenFileName
{
public int lstructSize;
public IntPtr hwndOwner;
public IntPtr hInstance;
public string lpstrFilter = null;
public string lpstrCustomFilter = null;
public int lMaxCustomFilter;
public int lFilterIndex;
public string lpstrFile = null;
public int lMaxFile = 0;
public string lpstrFileTitle = null;
public int lMaxFileTitle = 0;
public string lpstrInitialDir = null;
public string lpstrTitle = null;
public int lFlags;
public ushort nFileOffset;
public ushort nFileExtension;
public string lpstrDefExt = null;
public int lCustData;
public int lpfHook;
public int lpTemplateName;
}
public class OpenDialog
{
[DllImport("Comdlg32.dll",CharSet = CharSet.Auto)]
public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
}
}
And then use it in OnClick event of a button like this:
OpenFileName qofn = new OpenFileName();
qofn.lstructSize = Marshal.SizeOf(qofn);
qofn.lpstrFile = "";
qofn.lMaxFile = 256;
qofn.lpstrFileTitle = "";
qofn.lMaxFileTitle = 64;
qofn.hInstance = this.Handle;
source.Text = "Wait...";
if (OpenDialog.GetOpenFileName(qofn))
{
MessageBox.Show("ofn.file: " + qofn. lpstrFile );
}
When application runs and button is clicked and I try to open file this is what happens:
1st try:
it returns the path to my file, but instead of c:\dira\dirb\dirc\filename.ext I have c:\dira\dirb\dircfilename.ext without '\' before the name of the file
2nd try
Everything is OK
next: there are random crashes, e.g. random access violation, or GUI freezes and application's process can't be kiled even in task manager, or other errors.
Usually dialog works 2-3 times before application crashes for good.
What is wrong with my code?
EDIT:
I can't use OpenFileDialog. I'm using WinPE 4.0 (Windows Assessment and Deployment Kit ADK). When I try OpenFileDIalog, it throws run time error 80040111. It's probably because the core is not supported (just like Server Core doesn't support OpenFileDialog, the error's the same). Probably on WinPE 4.0 they use GetOpenFileName in applications such as notepad. And it works for them.
回答1:
OK, I found this microsoft sample and it works:
// Copyright
// Microsoft Corporation
// All rights reserved
// OpenFileDlg.cs
using System;
using System.Text;
using System.Runtime.InteropServices;
/*
typedef struct tagOFN {
DWORD lStructSize;
HWND hwndOwner;
HINSTANCE hInstance;
LPCTSTR lpstrFilter;
LPTSTR lpstrCustomFilter;
DWORD nMaxCustFilter;
DWORD nFilterIndex;
LPTSTR lpstrFile;
DWORD nMaxFile;
LPTSTR lpstrFileTitle;
DWORD nMaxFileTitle;
LPCTSTR lpstrInitialDir;
LPCTSTR lpstrTitle;
DWORD Flags;
WORD nFileOffset;
WORD nFileExtension;
LPCTSTR lpstrDefExt;
LPARAM lCustData;
LPOFNHOOKPROC lpfnHook;
LPCTSTR lpTemplateName;
#if (_WIN32_WINNT >= 0x0500)
void * pvReserved;
DWORD dwReserved;
DWORD FlagsEx;
#endif // (_WIN32_WINNT >= 0x0500)
} OPENFILENAME, *LPOPENFILENAME;
*/
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Auto )]
public class OpenFileName
{
public int structSize = 0;
public IntPtr dlgOwner = IntPtr.Zero;
public IntPtr instance = IntPtr.Zero;
public String filter = null;
public String customFilter = null;
public int maxCustFilter = 0;
public int filterIndex = 0;
public String file = null;
public int maxFile = 0;
public String fileTitle = null;
public int maxFileTitle = 0;
public String initialDir = null;
public String title = null;
public int flags = 0;
public short fileOffset = 0;
public short fileExtension = 0;
public String defExt = null;
public IntPtr custData = IntPtr.Zero;
public IntPtr hook = IntPtr.Zero;
public String templateName = null;
public IntPtr reservedPtr = IntPtr.Zero;
public int reservedInt = 0;
public int flagsEx = 0;
}
public class LibWrap
{
//BOOL GetOpenFileName(LPOPENFILENAME lpofn);
[ DllImport( "Comdlg32.dll", CharSet=CharSet.Auto )]
public static extern bool GetOpenFileName([ In, Out ] OpenFileName ofn );
}
public class App
{
public static void Main()
{
OpenFileName ofn = new OpenFileName();
ofn.structSize = Marshal.SizeOf( ofn );
ofn.filter = "Log files\0*.log\0Batch files\0*.bat\0";
ofn.file = new String( new char[ 256 ]);
ofn.maxFile = ofn.file.Length;
ofn.fileTitle = new String( new char[ 64 ]);
ofn.maxFileTitle = ofn.fileTitle.Length;
ofn.initialDir = "C:\\";
ofn.title = "Open file called using platform invoke...";
ofn.defExt = "txt";
if( LibWrap.GetOpenFileName( ofn ))
{
Console.WriteLine( "Selected file with full path: {0}", ofn.file );
Console.WriteLine( "Selected file name: {0}", ofn.fileTitle );
Console.WriteLine( "Offset from file name: {0}", ofn.fileOffset );
Console.WriteLine( "Offset from file extension: {0}", ofn.fileExtension );
}
}
}
回答2:
The OpenFileDlg examples (like the one used in Arie's answer) are available Here.
The page has C#, C++, and VB examples. I have tested the VB example in WinPE 5.1 and it works great with the exception of the file type filter; It shows all file types all the time.
I was surprised to find that even with the WinPE-NetFX package installed in my WinPE image OpenFileDialog is not available in WinPE and trying to use it throws the error referenced in the question. These OpenFileDlg examples, which use the unmanaged GetOpenFileName function, are the only alternative that I have been able to find for use in WinPE.
来源:https://stackoverflow.com/questions/9088227/using-getopenfilename-instead-of-openfiledialog