2014-10-04 57 views
0

我需要使用ShellExecuteExin C# 我的文件名有Unicode字符當我通過文件名給ShellExecuteEx它拋出異常 無法找到文件在C#中使用的ShellExecuteEx使用Unicode文件名

當功能finisheed Unicode字符的文件名更改爲「? 「

[Serializable] 
    public struct ShellExecuteInfo 
    { 
     public int Size; 
     public uint Mask; 
     public IntPtr hwnd; 
     public string Verb; 
     public string File; 
     public string Parameters; 
     public string Directory; 
     public uint Show; 
     public IntPtr InstApp; 
     public IntPtr IDList; 
     public string Class; 
     public IntPtr hkeyClass; 
     public uint HotKey; 
     public IntPtr Icon; 
     public IntPtr Monitor; 
    } 

    // Code For OpenWithDialog Box 
    [DllImport("shell32.dll", SetLastError = true)] 
    extern public static bool 
      ShellExecuteEx(ref ShellExecuteInfo lpExecInfo); 

    public const uint SW_NORMAL = 1; 

    public static void OpenAs(string file) 
    { 
     ShellExecuteInfo sei = new ShellExecuteInfo(); 
     sei.Size = Marshal.SizeOf(sei); 
     sei.Verb = "openas"; 
     sei.File = file; 
     sei.Show = SW_NORMAL; 
     if (!ShellExecuteEx(ref sei)) 
      throw new System.ComponentModel.Win32Exception(); 
    } 
+2

這是不必要的,請使用.NET ProcessStartInfo.Verb屬性。 – 2014-10-04 12:35:54

回答

1

默認字符集是ANSI。所以,你需要指定的字符集是Unicode:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct ShellExecuteInfo 
{ 
    .... 
} 

.... 

[DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
public static extern bool ShellExecuteEx(ref ShellExecuteInfo lpExecInfo); 

雖然個人,因爲這個長結構是永遠只能按引用傳遞,因爲你總是使用new保證初始化,我想聲明爲類:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public class ShellExecuteInfo 
{ 
    .... 
} 

.... 

[DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
public static extern bool ShellExecuteEx(ShellExecuteInfo lpExecInfo); 

請注意,我們刪除了ref,因爲類是引用類型。而不是一個值類型的結構。

我也會評論說,你得到的字段翻譯不正確,在圖標/監視器聯合。一個修正的翻譯是:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public class ShellExecuteInfo 
{ 
    public int Size; 
    public uint Mask; 
    public IntPtr hwnd; 
    public string Verb; 
    public string File; 
    public string Parameters; 
    public string Directory; 
    public int Show; 
    public IntPtr InstApp; 
    public IntPtr IDList; 
    public string Class; 
    public IntPtr hkeyClass; 
    public uint HotKey; 
    public IntPtr IconOrMonitor; 
    public IntPtr Process; 
} 

最後,爲了方便,這是值得添加一個構造函數的類初始化大小字段:

public ShellExecuteInfo() 
{ 
    Size = Marshal.SizeOf(this); 
} 

當然,你可以只使用Process.Start在問題的代碼:

ProcessStartInfo psi = new ProcessStartInfo(); 
psi.UseShellExecute = true; 
psi.Verb = "openas"; 
psi.FileName = file; 
Process.Start(psi); 
+0

當我使用ShellExecuteInfo - > Windows無法找到C(路徑是「C:/ MyDownloads」)和使用ProcessStartInfo時 - >「沒有應用程序與此操作的指定文件關聯」 – Mint 2014-10-05 09:33:36

+0

您沒有使用我的答案中的代碼。你需要兩個CharSet。你在功能上錯過了它。 Process.Start調用ShellExecuteEx。從Process.Start切換到ShellExecuteEx不會改變任何內容。 – 2014-10-05 11:22:28

+0

我用字符集,但沒有工作。我用你的答案,但沒有工作 – Mint 2014-10-08 06:11:04

0

打開一個URL

溶液1 - 的PInvoke沒有討厭的結構

[DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
internal static extern uint ShellExecute(IntPtr hwnd, string strOperation, string strFile, string strParameters, string strDirectory, Int32 nShowCmd); 

string link = "http://www.yahoo.com"; 
string def = string.Empty; 
IntPtr hWnd = (IntPtr)0; 
uint ret = ShellExecute(hWnd, def, link, def, def, 0); 

解決方案2:使用C#天然

Process.Start(new ProcessStartInfo("cmd", "/c start " + link) { CreateNoWindow = true }); 

解決方案3:更多C#

ProcessStartInfo URL = new ProcessStartInfo(); 
URL.FileName = link; 
URL.CreateNoWindow = true; 
URL.UseShellExecute = true; 
Process.Start(URL); 
相關問題