0

我有一个程序可以将.ppt文件转换pptxpng's usingC#和这些Microsoft.Office.Interop东西。

它在大多数情况下都可以工作,但在某些情况下,它似乎由于某些难以描述的原因而在特定文件名上失败。

HRESULT E_FAIL at ... Presentations.Open

它会失败 CT_Stress_Test - Copy (16).pptx并且CT_Stress_Test - Copy (11).pptx它适用于(2)thru (19),但仅在这两个上失败。我的问题是为什么?

如果我要复制这些副本,或者将它们重命名为其他名称,它会转换得很好,所以我认为它可能与文件名有关。

我的服务器和本地机器上运行着相同的转换程序。我的本地机器(Win 7)将问题文件转换为文件。只有在服务器(Win 2008)上我对这两个文件名有问题。

编辑:我发现另一个不起作用的号码:(38)

编辑:我用函数格式化了字符串Path,但这没有帮助。

编辑:我能够通过修剪文件名中的所有空格来修复它。不过,我仍然想知道为什么会发生这种情况。

这是程序:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
using Microsoft.Office.Core;
using PowerPoint = Microsoft.Office.Interop.PowerPoint;
using System.Diagnostics;
using System.Timers;
using System.Security.Permissions;
using System.Collections.Concurrent;


namespace converter
{
    class Program
    {
        public static int threadLimit=0;
        public static string inDir;
        public static string outDir;
        public static string procDir;
        public static Thread[] converterThreads;
        public static BlockingCollection<string> todo;
        static void Main(string[] args)
        {
            todo = new BlockingCollection<string>();
            inDir = args[0];
            outDir = args[1]+"\\";
            procDir = args[2]+"\\";
            Int32.TryParse(args[3],out threadLimit);
            converterThreads = new Thread[threadLimit];

            FileSystemWatcher watcher = new FileSystemWatcher(inDir); //Watcher "thread"
            watcher.Filter = "*.ppt*";
            watcher.NotifyFilter = watcher.NotifyFilter | NotifyFilters.CreationTime;
            watcher.IncludeSubdirectories = false;
            watcher.Created += new FileSystemEventHandler(fileChanged); 
            watcher.EnableRaisingEvents = true;


            //Create consumer threads
            for(var i=0;i<threadLimit;i++)
            {
                Conversion con = new Conversion();
                converterThreads[i] = new Thread(new ThreadStart(con.watchCollection));
                converterThreads[i].Start();
            }


            //stay open
            Console.ReadLine();
        }

        //Producer
        private static void fileChanged(object sender, FileSystemEventArgs e)
        {
            if(!(e.FullPath.Contains("~$"))){ //Ignore temp files
                Console.WriteLine("found =" + e.FullPath);
                todo.Add(e.FullPath);
            }
        }
    }



    class Logger{

        static void toLog(String msg)    
        {
                //TODO: log file    
        }

    }




    //Consumer
    class Conversion
    {
        String input;
        String output;
        String outDir;
        String process;
        String nameWith;
        String nameWithout;
        string dir;
        static List<CorruptFile> cFiles = new List<CorruptFile>();
        int retryLimit = 20;

        public Conversion()
        {
            this.outDir = Program.outDir;
            this.process = Program.procDir;
        }

        //Continually watches collection for files to take.
        public void watchCollection()
        {
            while (true)
            {
                System.Threading.Thread.Sleep(1000);
                try
                {
                    dir = Program.todo.Take();
                    if (dir != null)
                    {
                        this.nameWithout = Path.GetFileNameWithoutExtension(dir);
                        this.nameWith = Path.GetFileName(dir);
                        this.output = Path.GetDirectoryName(dir) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(dir);
                        Console.WriteLine("output = " + this.output);
                        this.input = Path.GetFullPath(dir);
                        Console.WriteLine("thread took " + this.nameWith);
                        convertPpt();
                    }
                }
                catch (InvalidOperationException) { }
            }
        }

        public void convertPpt()
        {
            try
            {
                var app = new PowerPoint.Application();
                var pres = app.Presentations;
                var file = pres.Open(input, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);
                file.SaveAs(output, Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType.ppSaveAsPNG, MsoTriState.msoTrue);
                file.Close();
                app.Quit();
                Console.WriteLine("file converted " + input);
                moveFile();
            }
            catch (Exception e)
            {
                Console.WriteLine("convertPpt failed " + e);
                try
                {
                    foreach (Process proc in Process.GetProcessesByName("POWERPNT"))
                    {
                        proc.Kill();
                        Console.WriteLine("process killed");
                    }
                }
                catch (Exception e3)
                {
                }

                try
                {
                    if (!(cFiles.Any(x => x.fileName == dir)))
                    {
                        cFiles.Add(new CorruptFile(dir));
                        Console.WriteLine("file added to watch list");
                        Program.todo.Add(dir);
                    }
                    else
                    {
                        var found = cFiles.Find(x => x.fileName == dir);
                        Console.WriteLine("in watch list = " + found.fileName);
                        if (found.numRetry >= retryLimit)
                        {
                            Console.WriteLine(nameWith+ " to be ignored");
                            try
                            {
                                cFiles.Remove(found);
                                Console.WriteLine("File ignored");
                                System.Threading.Thread.Sleep(300);
                                Console.WriteLine("Moving: " + input);
                                if (File.Exists("C:\\corrupt\\" + nameWith))
                                {
                                    File.Replace(input, "C:\\corrupt\\" + nameWith, null);
                                    Console.WriteLine("file moved to C:\\corrupt\\");
                                }
                                else
                                {
                                    File.Move(input, "C:\\corrupt\\" + nameWith);
                                    Console.WriteLine("file moved to C:\\corrupt\\");
                                }
                            }
                            catch(Exception e5)
                            {
                                Console.WriteLine("could not move file " + e5);
                            }
                        }
                        else
                        {
                            Console.WriteLine("retrying file on watch list");
                            found.numRetry++;
                            Program.todo.Add(dir);
                        }
                    }
                }
                catch { }


            }

            moveDir();
        }
        public void moveFile()
        {
            Console.WriteLine("moving" + input);
            try
            {
                System.Threading.Thread.Sleep(500);
                Console.WriteLine(string.Format("moving {0} to {1}", input, process + nameWith));
                if (File.Exists(process + nameWith))
                {
                    File.Replace(input, process + nameWith, null);
                }
                else
                {
                    File.Move(input, process + nameWith);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(string.Format("Unable to move the file {0} ", input) + e);
                try
                {
                    foreach (Process proc in Process.GetProcessesByName("POWERPNT"))
                    {
                        proc.Kill();
                    }
                }
                catch (Exception e3)
                {
                }
            }
        }

        public void moveDir()
        {
            if(!Directory.Exists(output)){
                return;
            }

            Console.WriteLine("moving dir " + output);
            try
            {
                Console.WriteLine(string.Format("moving dir {0} to {1} ", output, outDir + nameWithout));

                if (Directory.Exists(outDir + nameWithout))
                {
                    Directory.Delete(outDir + nameWithout, true);
                }
                if (Directory.Exists(output))
                {
                    Directory.Move(output, outDir + nameWithout);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(string.Format("Unable to move the directory {0} ", output) + e);
                try
                {
                    foreach (Process proc in Process.GetProcessesByName("POWERPNT"))
                    {
                        proc.Kill();
                    }
                }
                catch (Exception e3)
                {
                }
            }
        }
    }

    class CorruptFile{
        public string fileName;
        public int numRetry;

       public CorruptFile(string fn){
            fileName = fn;
        }
    }
}
4

1 回答 1

1

首先是微软在这篇知识库文章中的警告。金钱报价是:

Microsoft 目前不推荐也不支持任何无人值守、非交互式客户端应用程序或组件(包括 ASP、ASP.NET、DCOM 和 NT 服务)的 Microsoft Office 应用程序自动化,因为 Office 可能表现出不稳定的行为和/或在此环境中运行 Office 时出现死锁。

下一个问题是为什么不为此使用 OpenXML?这是一个简单的示例,可帮助您开始计算卡片组中幻灯片的数量。

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace OpenXmlDemo
{
    class PptOpenXmlDemo
    {
        public int PptGetSlideCount(string fileName)
        {
            //  Return the number of slides in a PowerPoint document.
            const string documentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
            const string presentationmlNamespace = "http://schemas.openxmlformats.org/presentationml/2006/main";

            int returnValue = 0;

            using (Package pptPackage = Package.Open(fileName, FileMode.Open, FileAccess.Read))
            {
                //  Get the main document part (presentation.xml).
                foreach (System.IO.Packaging.PackageRelationship relationship in pptPackage.GetRelationshipsByType(documentRelationshipType))
                {
                    //  There should be only a single relationship that refers to the document.
                    Uri documentUri = PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), relationship.TargetUri);
                    PackagePart documentPart = pptPackage.GetPart(documentUri);

                    //  Get the slide part from the package.
                    if (documentPart != null)
                    {
                        XmlDocument doc = new XmlDocument();
                        doc.Load(documentPart.GetStream());

                        //  Manage namespaces to perform XPath queries.
                        XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
                        nsManager.AddNamespace("p", presentationmlNamespace);

                        //  Retrieve the list of slide references from the document.
                        XmlNodeList nodes = doc.SelectNodes("//p:sldId", nsManager);
                        if (nodes != null)
                        {
                            returnValue = nodes.Count;
                        }
                    }
                    //  There is only one officeDocument part. Get out of the loop now.
                    break;
                }
            }
            return returnValue;
        }
    }
}
于 2013-11-07T16:51:52.013 回答