1

问题:

下面的程序应该读取 中指定的文件夹中的所有 XML 报告文件(*.rdl 文件),strPat根据我的代码对其进行修改,并将修改后的 XML 文件保存在文件夹<User>/Desktop/AutoModifiedReports/filename.rdl中,然后将修改后的 XML 文件复制回 中的文件夹strPat

我的问题是我在 CopyBack 过程中获得了未经授权的访问异常。该程序可以写入和覆盖目标目录中的文件。就在它第一次读取、修改然后复制回来时,它会得到一个未经授权的访问异常。

这发生在

 public static void CopyBack(string strFileName)
        {
            string strSavePath = GetSavePath();
            strSavePath = System.IO.Path.Combine(strSavePath, System.IO.Path.GetFileName(strFileName));

            if (System.IO.File.Exists(strSavePath))
            {
                System.IO.File.Copy(strSavePath, strFileName, true); // Exception - Unauthorized access
            }

        } // End Sub CopyBack

我没有看到任何让流打开或文件被锁定的地方。
谁能告诉我我到底做错了什么,以及如何纠正它?

using System;
using System.Collections.Generic;
using System.Windows.Forms;


namespace ReportModifier
{


    static class MalfunctioningProgram
    {

        public static string strLogPath = GetLogFilePath();


        public static string GetSavePath()
        {
            string strSavePath = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            strSavePath = System.IO.Path.Combine(strSavePath, "AutoModifiedReports");


            if (!System.IO.Directory.Exists(strSavePath))
                System.IO.Directory.CreateDirectory(strSavePath);

            return strSavePath;
        } // End Function GetSavePath


        public static string GetLogFilePath()
        { 
            string strLogfileLocation = System.IO.Path.Combine(GetSavePath(), "log.txt");

            if (System.IO.File.Exists(strLogfileLocation))
                System.IO.File.Delete(strLogfileLocation);

            return strLogfileLocation;
        } // End Function GetLogFilePath


        public static void LogMessage(string strMessage)
        {
            // Console.WriteLine(strMessage);
            System.IO.File.AppendAllText(strLogPath, strMessage + Environment.NewLine, System.Text.Encoding.UTF8);
        } // End Sub LogMessage


        public static void LogMessage(string str, params object[] args)
        {
            LogMessage(string.Format(str, args));
        } // End Sub LogMessage



        public static System.Xml.XmlDocument File2XmlDocument(string strFileName)
        {
            // http://blogs.msdn.com/b/tolong/archive/2007/11/15/read-write-xml-in-memory-stream.aspx
            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            // doc.Load(memorystream);
            // doc.Load(FILE_NAME);

            using (System.Xml.XmlTextReader xtrReader = new System.Xml.XmlTextReader(strFileName))
            {
                doc.Load(xtrReader);
                xtrReader.Close();
            } // End Using xtrReader

            return doc;
        } // End Function File2XmlDocument


        public static System.Xml.XmlNamespaceManager GetReportNamespaceManager(System.Xml.XmlDocument doc)
        {
            System.Xml.XmlNamespaceManager nsmgr = new System.Xml.XmlNamespaceManager(doc.NameTable);
            nsmgr.AddNamespace("dft", "http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition");

            return nsmgr;
        } // End Function GetReportNamespaceManager


        public static void SaveDocument(System.Xml.XmlDocument doc, string strFilename)
        {
            SaveDocument(doc, strFilename, false);
        } // End Sub SaveDocument


        public static void SaveDocument(System.Xml.XmlDocument doc, string strFilename, bool bDoReplace)
        {
            string strSavePath = GetSavePath();
            strSavePath = System.IO.Path.Combine(strSavePath, System.IO.Path.GetFileName(strFilename));

            if (bDoReplace)
            {
                doc.LoadXml(doc.OuterXml.Replace("xmlns=\"\"", ""));
            }

            using (System.Xml.XmlTextWriter xtw = new System.Xml.XmlTextWriter(strSavePath, System.Text.Encoding.UTF8))
            {
                xtw.Formatting = System.Xml.Formatting.Indented; // if you want it indented
                xtw.Indentation = 4;
                xtw.IndentChar = ' ';

                doc.Save(xtw);
                xtw.Flush();
                xtw.Close();
            } // End Using xtw

            doc = null;
        } // End Sub SaveDocument


        public static void ChangeParameterPrompt(string strFilename, string strReportParameterName, string strReplacementText)
        {
            System.Xml.XmlDocument doc = File2XmlDocument(strFilename);
            System.Xml.XmlNamespaceManager nsmgr = GetReportNamespaceManager(doc);

            if (!HasParameter(doc, strReportParameterName))
                return;


            System.Xml.XmlNode xnParameterPrompt = GetParameterPrompt(doc, strReportParameterName);
            string strReportName = System.IO.Path.GetFileNameWithoutExtension(strFilename);

            if (xnParameterPrompt != null)
            {
                string strParameterValue = xnParameterPrompt.FirstChild.Value;
                xnParameterPrompt.FirstChild.Value = strReplacementText;
                LogMessage("Old value in {0}:\t{1}", strReportName, strParameterValue);
            }
            else
                LogMessage("{0}\tKein Parameter " + strReportParameterName, strReportName);

            SaveDocument(doc, strFilename);
        } // End Sub ChangeParameterPrompt


        public static void ChangeStichtag(string strFilename)
        {
            System.Xml.XmlDocument doc = File2XmlDocument(strFilename);
            System.Xml.XmlNamespaceManager nsmgr = GetReportNamespaceManager(doc);

            System.Xml.XmlNode xnStichtag = doc.SelectSingleNode("somequery", nsmgr);
            string strReportName = System.IO.Path.GetFileNameWithoutExtension(strFilename);

            if (!HasParameter(doc, "in_stichtag"))
                return;


            if (xnStichtag != null)
            {
                xnStichtag.FirstChild.Value = "=System.DateTime.Now.ToString(\"dd.MM.yyyy\")";
                string strStichTag = xnStichtag.FirstChild.Value;
                LogMessage("{0}\t{1}", strReportName, strStichTag);
            }
            else
                LogMessage("{0}\tKein Parameter Stichtag", strReportName);

            SaveDocument(doc, strFilename);
        } // End Sub ChangeStichtag



        public static string XmlEscape(string unescaped)
        {
            string strReturnValue = null;

            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            System.Xml.XmlNode node = doc.CreateElement("root");
            node.InnerText = unescaped;
            strReturnValue = node.InnerXml;
            node = null;
            doc = null;

            return strReturnValue; 
        } // End Function XmlEscape


        public static string XmlUnescape(string escaped)
        {
            string strReturnValue = null;

            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            System.Xml.XmlNode node = doc.CreateElement("root");
            node.InnerXml = escaped;
            strReturnValue = node.InnerText;
            node = null;
            doc = null;

            return strReturnValue;
        } // End Function XmlUnescape





        public static bool HasParameter(System.Xml.XmlDocument doc, string strParameterName)
        {
            strParameterName = XmlEscape(strParameterName);

            System.Xml.XmlNamespaceManager nsmgr = GetReportNamespaceManager(doc);
            System.Xml.XmlNode xnProc = doc.SelectSingleNode("somequery", nsmgr);

            return xnProc != null;
        } // End Function HasParameter




        public static System.Xml.XmlNode GetParameter(System.Xml.XmlDocument doc, string strParameterName)
        {
            strParameterName = XmlEscape(strParameterName);

            System.Xml.XmlNamespaceManager nsmgr = GetReportNamespaceManager(doc);
            System.Xml.XmlNode xnParam = doc.SelectSingleNode("somequery", nsmgr);

            return xnParam;
        } // End Function GetParameter


        public static System.Xml.XmlNode GetParameterPrompt(System.Xml.XmlDocument doc, string strParameterName)
        {
            strParameterName = XmlEscape(strParameterName);

            System.Xml.XmlNamespaceManager nsmgr = GetReportNamespaceManager(doc);
            System.Xml.XmlNode xnParam = doc.SelectSingleNode("somequery", nsmgr);

            return xnParam;
        } // End Function GetParameter


        public static void AddProc(string strFilename)
        {
            System.Xml.XmlDocument doc = File2XmlDocument(strFilename);

            System.Xml.XmlNamespaceManager nsmgr = GetReportNamespaceManager(doc);

            if (HasParameter(doc, "proc"))
                return;

            System.Xml.XmlNode xnMandant = GetParameter(doc, "in_mandant");

            string strReportName = System.IO.Path.GetFileNameWithoutExtension(strFilename);

            if (xnMandant != null)
            {
                LogMessage("{0}\t{1}", strReportName, xnMandant.FirstChild.Value);

                string frag = @"some xml fragment";

                System.Xml.XmlDocumentFragment xmlDocFrag = doc.CreateDocumentFragment();
                xmlDocFrag.InnerXml = frag;

                // System.Xml.XmlNode xn = 
                xnMandant.ParentNode.InsertAfter(xmlDocFrag, xnMandant);
            }
            else
                LogMessage("{0}\tKein Parameter in_mandant", strReportName);

            SaveDocument(doc, strFilename, true);
            //SaveDocument(doc, strFilename, "<ReportParameter Name=\"proc\" xmlns=\"\">", "<ReportParameter Name=\"proc\">");
        } // End Sub AddProc


        public static List<string> GetAllReports(string strPath)
        {
            List<string> ls = new List<string>();
            ls.AddRange(System.IO.Directory.GetFiles(strPath, "*.rdl"));

            return ls;
        } // End Function GetAllReports


        public static void CopyToSaveDirectory(string strFileName)
        {
            string strSavePath = GetSavePath();
            strSavePath = System.IO.Path.Combine(strSavePath, System.IO.Path.GetFileName(strFileName));

            System.IO.File.Copy(strFileName, strSavePath, true);
        } // End Sub CopyToSaveDirectory


        public static void CopyBack(string strFileName)
        {
            string strSavePath = GetSavePath();
            strSavePath = System.IO.Path.Combine(strSavePath, System.IO.Path.GetFileName(strFileName));

            if (System.IO.File.Exists(strSavePath))
            {
                System.IO.File.Copy(strSavePath, strFileName, true); // Exception - Unauthorized access
            }

        } // End Sub CopyBack


        public static void AlterReports(string strPath)
        {
            List<string> lsReports = GetAllReports(strPath);

            foreach (string strFileName in lsReports)
            {
                ChangeStichtag(strFileName);
                CopyBack(strFileName);
                ChangeParameterPrompt(strFileName, "in_standort", "Liegenschaft / Immeuble / Patrimonio immobiliare / Estate");
                CopyBack(strFileName);
                ChangeParameterPrompt(strFileName, "in_gebaeude", "Gebäude / Bâtiment / Edificio / Building");
                CopyBack(strFileName);
                ChangeParameterPrompt(strFileName, "in_geschoss", "Geschoss / Étage / Piano / Floor");
                CopyBack(strFileName);
                ChangeParameterPrompt(strFileName, "in_trakt", "Trakt / Aile / Ala / Wing");
                CopyBack(strFileName);
                ChangeParameterPrompt(strFileName, "in_haus", "Haus / Maison / Casa / House");
                CopyBack(strFileName);
                ChangeParameterPrompt(strFileName, "in_raum", "Raum / Pièce / Stanza / Room");
                CopyBack(strFileName);
                ChangeParameterPrompt(strFileName, "in_stichtag", "Stichtag / Jour de référence / Giorno di riferimento / Reporting date");
                CopyBack(strFileName);
                ChangeParameterPrompt(strFileName, "in_mietertrag", "Mindestertrag Mindestertrag / Rendement minimum / Rendimento minimo / Minimum yield");
                CopyBack(strFileName);
            } // Next strFileName

        } // End Sub InvestigateStichtag


        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {
            string strPath = @"S:\SomeBody\SomeFolder\Reports";

            AlterReports(strPath);

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine(" --- Press any key to continue --- ");
            Console.ReadKey();
        } // End Sub Main


    } // End Class Program


} // End Namespace ReportModifier
4

2 回答 2

1

看这段代码:

public static void CopyBack(string strFileName)
{
    string strSavePath = GetSavePath();
    strSavePath = System.IO.Path.Combine(strSavePath, System.IO.Path.GetFileName(strFileName));

    if (System.IO.File.Exists(strSavePath))
    {
        System.IO.File.Copy(strSavePath, strFileName, true); // Exception - Unauthorized access
    }
}

strFileName您似乎打算将文件从GetSavePath().

如果确实是这种情况,那么请注意您的参数File.Copy()是错误的。

它是Copy(String sourceFileName, string destFileName, bool overwrite)

因此,在这种情况下,您的代码应该是:

System.IO.File.Copy(strFileName, strSavePath, true);
于 2013-11-21T09:55:51.237 回答
0

没关系。
问题是文件是 SSRS 报告。
我将它们从报告解决方案文件夹(在源代码管理下)复制到另一个文件夹进行实验。
但是文件上的 WriteProtected 标志与文件一起被复制。
在visual studio中编辑并保存了一个,看看我是否有权在它们上面写。
这删除了写保护,从而解决了问题。

所以你必须做一个:

if(FileIsWriteProtected)
    Unprotect(file);

System.IO.File.Copy(Source, file.FullPath, true);

顺便说一句,这也解释了为什么我得到了 UnauthorizedAccessException。

于 2013-11-21T12:18:53.030 回答