Kernel32 CopyFile找不到存在的文件c#

时间:2014-04-14 11:21:29

标签: c# windows winapi pinvoke

我调用了Kernel32的复制文件方法:

[DllImport("kernel32.dll",
           CharSet = CharSet.Unicode,
           CallingConvention = CallingConvention.StdCall,
           SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CopyFile(
                           [MarshalAs(UnmanagedType.LPStr)] string lpExistingFileName,
                           [MarshalAs(UnmanagedType.LPStr)] string lpNewFileName,
                           [MarshalAs(UnmanagedType.Bool)] bool bFailIfExists);
[DllImport("kernel32.dll")]
    public static extern uint GetLastError();

然而,当我调用它时,它从GetLastError()返回2,这意味着找不到文件。 路径肯定存在。

string newfile = Environment.CurrentDirectory + "\\temp" + Path.GetExtension(file);
uint i;
if (!CopyFile(file, newfile, true)) i = GetLastError();

我尝试使用此解决方案绕过LongPath异常。但即使使用普通文件,它似乎也无法正常工作。任何帮助将不胜感激。

这里是Form1的完整代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Shell32;
using System.Xml;
using System.Diagnostics;
using word = Microsoft.Office.Interop.Word;
using System.Runtime.InteropServices;

namespace DocumentCrawler
{
    public partial class Form1 : Form
    {
        [DllImport("kernel32.dll",
           CharSet = CharSet.Unicode,
           CallingConvention = CallingConvention.StdCall,
           SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CopyFile(
                           [MarshalAs(UnmanagedType.LPStr)] string lpExistingFileName,
                           [MarshalAs(UnmanagedType.LPStr)] string lpNewFileName,
                           [MarshalAs(UnmanagedType.Bool)] bool bFailIfExists);

        [DllImport("kernel32.dll")]
        public static extern uint GetLastError();

        public Form1()
        {
            InitializeComponent();
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            progressBar.Style = ProgressBarStyle.Marquee;
            lbProgress.Text = "Finding Word Documents";
            btnSearch.Enabled = false;
            lvResults.Clear();
            SearchDirectory(tbDirectory.Text, tbField.Text);
            btnSearch.Enabled = true;
        }

        void SearchDirectory(string path, string searchPattern)
        {
            List<string> docs = new List<string>();
            foreach (string d in Directory.GetDirectories(path))
            {
                SearchDirectory(path + "\\" + d.Remove(0, d.LastIndexOf('\\') + 1), searchPattern);
            }

            foreach (string f in Directory.GetFiles(path))
            {
                if (Path.GetExtension(f) == ".docx" || Path.GetExtension(f) == ".doc")
                {
                    docs.Add(f);
                }
            }

            progressBar.Value = 0;
            lbProgress.Text = "Processing Word Documents 0%";
            progressBar.Maximum = docs.Count;
            progressBar.Style = ProgressBarStyle.Blocks;

            foreach (string f in docs)
            {
                string txt = TextFromDocument(f);
                if (txt.Contains(searchPattern))
                {
                    lvResults.Items.Add(f);
                }
                progressBar.Value++;
                lbProgress.Text = "Processing Word Documents " + ((int)((float)progressBar.Value / (float)progressBar.Maximum * 100)) + "%";
            }
        }

        string TextFromDocument(string file)
        {
            string newfile = Environment.CurrentDirectory + "\\temp" + Path.GetExtension(file);
            uint i;
            if (!CopyFile(file, newfile, true)) i = GetLastError();
            object nullobj = System.Reflection.Missing.Value;
            word.Application wordApp = new word.Application();
            word.Document doc = wordApp.Documents.Open(newfile, false);

            doc.ActiveWindow.Selection.WholeStory();
            doc.ActiveWindow.Selection.Copy();
            string text = doc.Content.Text;

            doc.Close(ref nullobj, ref nullobj, ref nullobj);
            wordApp.Quit(ref nullobj, ref nullobj, ref nullobj);

            File.Delete(newfile);

            return text;
        }

        private void lvResults_DoubleClick(object sender, EventArgs e)
        {
            Process.Start(lvResults.SelectedItems[0].Text);
            lvResults.SelectedItems[0].ForeColor = Color.Purple;
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fd = new FolderBrowserDialog();
            if (fd.ShowDialog() == DialogResult.OK)
            {
                tbDirectory.Text = fd.SelectedPath;
                btnSearch.Enabled = true;
            }
        }
    }
}

提前致谢!

1 个答案:

答案 0 :(得分:5)

[DllImport("kernel32.dll",
   CharSet = CharSet.Unicode,
   CallingConvention = CallingConvention.StdCall,
   SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CopyFile(
                   [MarshalAs(UnmanagedType.LPStr)] string lpExistingFileName,
                   [MarshalAs(UnmanagedType.LPStr)] string lpNewFileName,
                   [MarshalAs(UnmanagedType.Bool)] bool bFailIfExists);

DllImport声明中,您选择CharSet.Unicode字符集。这意味着p / invoke函数将绑定到CopyFileW

然后你随后指示编组人员将参数编组为LPStr,ANSI字符串。这就是函数总是失败的原因。

正确的p / invoke将是:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool CopyFile(string lpExistingFileName, string lpNewFileName,
    bool bFailIfExists);

你绝对不应该调用GetLastError。相反,请使用Marshal.GetLastWin32Error中描述的原因documentation。{/ p>