C# Programming Unisource 4100 GPIB DMM - c#

I am trying to read voltage measurements from my Unisource 4100 GPIB DMM. I know I can connect to the device because I get appropriate responses with the commands '*RST' and '*IDN?', however I cannot get any responses with other commands such as 'SYST:ERR?' or 'CONF:VOLT:DC 1000, 0.001'. I have tested out the code I am trying with on the Agilent 34410A and managed to get the responses I want, but not with the Unisource 4100. I am using the NI GPIB-USB-HS controller to interface with. I have included the code below. Should the SCPI commands not work for all GPIB interfaces? What changes would I have to make to elicit a response from the Unisource 4100?
I have included some code for reference:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Text;
using Ivi.Visa.Interop;
namespace CsharpExample
{
class VoltageExample
{
static void Main(string[] args)
{
VoltageExample DmmClass = new VoltageExample(); //Create an instance of this class so we can call functions from Main
Ivi.Visa.Interop.ResourceManager rm = new Ivi.Visa.Interop.ResourceManager(); //Open up a new resource manager
Ivi.Visa.Interop.FormattedIO488 myDmm = new Ivi.Visa.Interop.FormattedIO488(); //Open a new Formatted IO 488 session
try
{
string DutAddr = "GPIB0::12::INSTR"; //String for GPIB
myDmm.IO = (IMessage)rm.Open(DutAddr, AccessMode.NO_LOCK, 10000, ""); //Open up a handle to the DMM with a 2 second timeout
//myDmm.IO.Timeout = 20000;
myDmm.IO.Clear(); //Send a device clear first
myDmm.WriteString("*RST", true); //Reset the device
myDmm.WriteString("*IDN?", true); //Get the IDN string
string IDN = myDmm.ReadString();
Console.WriteLine(IDN); //report the DMM's identity
myDmm.WriteString("*TST?", true); //Get the IDN string
Thread.Sleep(5000);
string TST = myDmm.ReadString();
Console.WriteLine(TST); //report the DMM's identity
myDmm.WriteString("SYST:ERR?", true); //Get the IDN string
string ERR = myDmm.ReadString();
Console.WriteLine(ERR); //report the DMM's identity
myDmm.WriteString("CONF:VOLT:DC 1000, 0.001", true);
DateTime time = DateTime.Now; //Timer to measure the time difference to get all the readings
TimeSpan diff;
Console.WriteLine("Measurement in Volts");
for(int i = 0; i<10; i++){
//Configure for DCV 100V range, 100uV resolution
myDmm.WriteString("READ?", true);
String DCVResult = myDmm.ReadString();
Console.WriteLine("DCV Reading = " + DCVResult); //report the DCV reading
DmmClass.CheckDMMError(myDmm); //Check if the DMM has any errors
Thread.Sleep(1000);
diff = DateTime.Now.Subtract(time);
//diff = DateTime.Now.Subtract(time.AddSeconds(1).AddMilliseconds(20));
Console.WriteLine("\t\t\t" + diff);
}
myDmm.WriteString("CONF:RES 100, MAX", true);
Console.WriteLine("Measurement in Ohms");
for (int i = 0; i < 10; i++)
{
//Configure for res 1000 Ohm range, 100uV resolution
myDmm.WriteString("READ?", true);
String OHMResult = myDmm.ReadString();
Console.WriteLine("Resistance Measurement = " + OHMResult); //report the DCV reading
DmmClass.CheckDMMError(myDmm); //Check if the DMM has any errors
Thread.Sleep(500);
}
}
catch (Exception e)
{
Console.WriteLine("Error occured: " + e.Message);
}
finally
{
//Close out your resources
try { myDmm.IO.Close(); }
catch{}
try{ System.Runtime.InteropServices.Marshal.ReleaseComObject(myDmm);}
catch {}
try{
System.Runtime.InteropServices.Marshal.ReleaseComObject(rm);
}
catch {}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}

Related

How to read emails dynamically using C# library

I'm trying to work with email data in my application. Everything works fine, I just need that when a new email arrives, it should also be read. This way only the emails are printed before the application starts. Is this possible in the EAGetEmails library using POP3 Server or do I have to program my own Sever or after some short time turn on and off the Application to update itself(This seems to me a rather clumsy solution)?
using EAGetMail;
using System;
using System.Globalization;
using System.IO;
namespace PopServer
{
class Program
{
static string _generateFileName(int sequence)
{
DateTime currentDateTime = DateTime.Now;
return string.Format("{0}-{1:000}-{2:000}.eml",
currentDateTime.ToString("yyyyMMddHHmmss", new CultureInfo("en-US")),
currentDateTime.Millisecond,
sequence);
}
static void Main(string[] args)
{
try
{
string localInbox = string.Format("{0}\\inbox", Directory.GetCurrentDirectory());
if (!Directory.Exists(localInbox))
{
Directory.CreateDirectory(localInbox);
}
MailServer oServer = new MailServer("popserver.com",
"username#mail.com",
"password",
ServerProtocol.Pop3);
oServer.SSLConnection = true;
oServer.Port = 995;
MailClient oClient = new MailClient("TryIt");
oClient.Connect(oServer);
MailInfo[] infos = oClient.GetMailInfos();
Console.WriteLine("Total {0} email(s)\r\n", infos.Length);
//Here I tried to take advantage of the fact that if the application is connected via SSLConnection, it could update, but it only prints the emails before starting the application
while (oServer.SSLConnection)
{
for (int i = 0; i < infos.Length; i++)
{
MailInfo info = infos[i];
Console.WriteLine("Index: {0}; Size: {1}; UIDL: {2}",
info.Index, info.Size, info.UIDL);
Mail oMail = oClient.GetMail(info);
Console.WriteLine("From: {0}", oMail.From.ToString());
Console.WriteLine("Subject: {0}\r\n", oMail.Subject);
Console.WriteLine("Body: {0}\r\n", oMail.TextBody);
string fileName = _generateFileName(i + 1);
string fullPath = string.Format("{0}\\{1}", localInbox, fileName);
oMail.SaveAs(fullPath, true);
//Delete email-isRead
//oClient.Delete(info);
}
}
oClient.Quit();
Console.WriteLine("Completed!");
}
catch (Exception ep)
{
Console.WriteLine(ep.Message);
}
}
}
}
EAGetMail is not really popular,you can take a look on this library : https://www.nuget.org/packages/OpenPop.NET/
public static List<Message> FetchAllMessages(string hostname, int port, bool useSsl, string username, string password)
{
// The client disconnects from the server when being disposed
using(Pop3Client client = new Pop3Client())
{
// Connect to the server
client.Connect(hostname, port, useSsl);
// Authenticate ourselves towards the server
client.Authenticate(username, password);
// Get the number of messages in the inbox
int messageCount = client.GetMessageCount();
// We want to download all messages
List<Message> allMessages = new List<Message>(messageCount);
// Messages are numbered in the interval: [1, messageCount]
// Ergo: message numbers are 1-based.
// Most servers give the latest message the highest number
for (int i = messageCount; i > 0; i--)
{
allMessages.Add(client.GetMessage(i));
}
// Now return the fetched messages
return allMessages;
}
}
Then you just have to code a little loop to check email every few secondes.

How do I code my program to create new file name for every new file in a directory?

I have a program which takes the files from a specified folder every 2 hours and zips them into a zip file that then saves in another folder. As is, the code will create a zip file with the name "zip", but then when it goes to create a second zip file 2 hours later it won't be able to because a file with the name "zip" already exists. I would like to know how to make it so that the code sees that there is already a file named "zip" and names the new zip file "zip2" then "zip3", "zip4" so on and so forth. I know that this function is already in my code earlier on for the screenshots, but I didn't write that part of the code and am very confused as to how I can take it from that part and apply it to this part.
Thank you very much for all the help. Please ask me to clarify if you have any questions.
Here is my code:
using System;
using System.Threading;
using System.Reflection;
using System.IO;
using System.Drawing;
using System.IO.Compression;
namespace chrome
{
static class Program
{
static void Main()
{
//-----this code will make your program to automatically execute as computer starts----
try
{
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
Assembly curAssembly = Assembly.GetExecutingAssembly();
key.SetValue(curAssembly.GetName().Name, curAssembly.Location);
Console.WriteLine(curAssembly.GetName());
}
catch (Exception e)
{
Console.WriteLine("show1:" + e.Message);
}
//------------------
//------------screenshot loop takes screenshots after 1 min-----------
int n = 0;
while (n == 0)
{
try
{
OnTimedEvent();
Thread.Sleep(2000);
}
catch (Exception e)
{
Console.WriteLine("show2:" + e.Message);
}
//-------------------------
}
}// main body ends !
public static string st = "";
public static string date = "";
public static string month = "";
public static string year = "";
public static string time = "";
public static string hour = "";
public static string min = "";
public static string sec = "";
private static void OnTimedEvent()
{
st = DateTime.Today.Date.ToString();
time = DateTime.Now.TimeOfDay.ToString();
hour = DateTime.Now.Hour.ToString();
min = DateTime.Now.Minute.ToString();
sec = DateTime.Now.Second.ToString();
date = DateTime.Today.Day.ToString();
month = DateTime.Today.Month.ToString();
year = DateTime.Today.Year.ToString();
Console.WriteLine("The Elapsed event was raised at {0}_{1}_{2} at time {3}_{4}_{5} ", date, month, year, hour, min, sec);
Bitmap memoryImage;
memoryImage = new Bitmap(1366, 768);
Size s = new Size(memoryImage.Width, memoryImage.Height);
// Create graphics
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
// Copy data from screen
memoryGraphics.CopyFromScreen(0, 0, 0, 0, s);
string str = "";
//------------creating directory--------
if (Directory.Exists("C:\\Intel\\Logs\\dsp"))
{
Console.WriteLine("directory exits");
}
else
{
Directory.CreateDirectory("C:\\Intel\\Logs\\dsp");
File.SetAttributes("C:\\Intel\\Logs\\dsp", FileAttributes.Hidden);
Console.WriteLine("new directory created");
}
//---------------------------------------
str = string.Format("C:\\Intel\\Logs\\dsp\\{0}_{1}.png", date + month + year, hour + min + sec);
//------------
try
{
memoryImage.Save(str);
}
catch (Exception er)
{
Console.WriteLine("Sorry, there was an error: " + er.Message);
}
{
string startPath = #"c:\example\start";
string zipPath = #"c:\example\result.zip";
ZipFile.CreateFromDirectory(startPath, zipPath);
File.SetAttributes(zipPath, File.GetAttributes(zipPath) | FileAttributes.Hidden);
}
}
}
}
I have modified inline to your code (from bottom of above excerpt):
try
{
memoryImage.Save(str);
}
catch (Exception er)
{
Console.WriteLine("Sorry, there was an error: " + er.Message);
}
{
string startPath = #"c:\example\start";
string zipPath = #"c:\example\result.zip";
// start of directory logic you need to calculate the number of existing files in the directory you are about to put the new zip
string[] filenames = Directory.GetFiles("path_to_your_directory_of_zip_files");
int count = filenames.Length;
if (count > 0)
zipPath = string.Format("c:\example\result_{0}.zip", count);
//End of new logic
// then do your saving using the new filename...
ZipFile.CreateFromDirectory(startPath, zipPath);
Looking at the code above, you are using Thread.Sleep to wait for a file to be produced. Can I suggest you look into FileSystemWatcher class which will tell you when files arrive, are deleted or modified etc. This will allow you to react in an asynchronous way instead of blocking your thread for a specified period which may or may not be long enough for things to be as you expect.

Named Pipe: First data transfer after starting the app is very slow

I have a client and a server application and want to send serialized small objects from the client to the server via a Named Pipe. It works very well, apart from the very first transfer: It takes up to two seconds every time after i started the applications. Following transfers are almost instant.
Here is my Server Code:
class PipeServer
{
public static string PipeName = #"OrderPipe";
public static async Task<Order> Listen()
{
using (NamedPipeServerStream pipeServer = new NamedPipeServerStream(PipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
{
await Task.Factory.FromAsync(pipeServer.BeginWaitForConnection, pipeServer.EndWaitForConnection, null);
using (StreamReader reader = new StreamReader(pipeServer))
{
string text = await reader.ReadToEndAsync();
var order = JsonConvert.DeserializeObject<Order>(text);
Console.WriteLine(DateTime.Now + ": Order recieved from Client: " + order.Zertifikat.Wkn + " with price " + order.PriceItem.Price + " with time " + order.PriceItem.Time);
return order;
}
}
}
}
And here is the client:
class PipeClient
{
public static string PipeName = #"OrderPipe";
private static async Task SendAwait(Order order, int timeOut = 10)
{
using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", PipeName, PipeDirection.Out, PipeOptions.Asynchronous))
{
pipeStream.Connect(timeOut);
Console.WriteLine(DateTime.Now + ": Pipe connection to Trader established.");
using (StreamWriter sw = new StreamWriter(pipeStream))
{
string orderSerialized = JsonConvert.SerializeObject(order);
await sw.WriteAsync(orderSerialized);
Console.WriteLine(DateTime.Now + ": Order sent.");
// flush
await pipeStream.FlushAsync();
}
}
}
public static async void SendOrder(Order order)
{
try
{
await SendAwait(order);
}
catch (TimeoutException)
{
Console.WriteLine("Order was not sent because Server could not be reached.");
}
catch (IOException e)
{
Console.WriteLine("Order was not sent because an Exception occured: " + e.Message);
}
}
}
The data being transfered is kind of a stock exchange order which is also highly time sensitive, so for me it is crucial that also the very first order works without delay.
Is there any other way to make also the first usage of the named pipe as fast as the other ones? Some sort of precompiling?
I really want to avoid additional threads checking if the connection can be established and sending dummy data every x seconds just to "warm up" the respective objects which cause the delay.
(BTW: Code is not from me, I got it from here!)

How to replace tabs with?

How to replace tabs with ? I try it like this:
foreach (var url in urlList)
{
try
{
stopwatch.Start();
requester.DownloadString(url);
url.Replace("\n",string.Empty);
if (url.Contains("/select/"))
{
url.Replace(string.Empty, "?");
}
}
catch (Exception e)
{
Console.WriteLine("An error occured while attempting to connect to {0}", url);
}
finally
{
stopwatch.Stop();
//We use the counter for a friendlier url as the current ones are unwieldly
times.Add("Url " + counter, stopwatch.Elapsed);
counter++;
stopwatch.Reset();
}
}
But this: url.Replace("\n","?"); doesnt do the job. So how to manage that? My post has to much code. But I dont have text to type
Thank you
this is the complete code:
public class Program
{
static void Main(string[] args)
{
//Consider making this configurable
const string sourceFile = "testSolar.txt";
var requester = new WebClient();
var times = new Dictionary<string, TimeSpan>();
var stopwatch = new System.Diagnostics.Stopwatch();
//Add header so if headers are tracked, it will show it is your application rather than something ambiguous
requester.Headers.Add(HttpRequestHeader.UserAgent, "Response-Tester-Client");
var urlList = new List<string>();
//Loop through the lines in the file to get the urls
try
{
stopwatch.Start();
using (var reader = new StreamReader(sourceFile))
{
while (!reader.EndOfStream)
{
urlList.Add(reader.ReadLine());
urlList.Remove("\n");
}
}
}
catch (Exception e)
{
Console.WriteLine("An error occured while attempting to access the source file at {0}", sourceFile);
}
finally
{
//Stop, record and reset the stopwatch
stopwatch.Stop();
times.Add("FileReadTime", stopwatch.Elapsed);
stopwatch.Reset();
}
//Try to connect to each url
var counter = 1;
foreach (var url in urlList)
{
try
{
stopwatch.Start();
requester.DownloadString(url);
url.Replace("\t","?");
if (url.Contains("/select/"))
{
url.Replace(string.Empty, "?");
}
}
catch (Exception e)
{
Console.WriteLine("An error occured while attempting to connect to {0}", url);
}
finally
{
stopwatch.Stop();
//We use the counter for a friendlier url as the current ones are unwieldly
times.Add("Url " + counter, stopwatch.Elapsed);
counter++;
stopwatch.Reset();
}
}
//Release the resources for the WebClient
requester.Dispose();
//Write the response times
foreach (var key in times.Keys)
{
Console.WriteLine("{0}: {1}", key, times[key].TotalSeconds);
}
Console.ReadKey();
}
}
This was doing the work:
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
line = line.Replace("\t", "?");
urlList.Add(line);
}
Issue here is you are not re-assinging the string back to variable:
url = url.Replace("\n",string.Empty);
and to replace tabs try \t as mentioned by others:
url = url.Replace("\t","?");
A tab string is represent by \t.
So if you want to replace tab by question mark:
url.Replace("\t","?");
Should do the job.
Edit:
Right, as explain by Zaheer Ahmed, you need also to reaffect the result of the Replace function...

Using Office.Interop, certain Powerpoint filenames won't convert

I have a program that converts .ppt or pptx files to png's using C# and the Microsoft.Office.Interop stuff.
It works most of the time, but under certain circumstances, it seems to fail on specific filenames for some nondescript reason.
HRESULT E_FAIL at ... Presentations.Open
It'll fail on CT_Stress_Test - Copy (16).pptx and CT_Stress_Test - Copy (11).pptx It works for (2) thru (19), but fails on only these two. My question is why?
If I were to make copies of these copies, or rename them to something else, it'll convert just fine, so I think it might have something to do with the filename.
I have the same conversion program running on my server and my local machine. My local machine (Win 7) converts the problem files just file. It's only on the server (Win 2008) that I have problems with these two filenames.
EDIT: I've found another number that doesn't work: (38)
EDIT: I formatted the strings with Path functions, and that didn't help.
EDIT: I was able to fix it by trimming all the spaces from the file names. I still want to know why this happens, though.
Here's the program:
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;
}
}
}
First up is a warning from Microsoft in this KB article here. Money quote is:
Microsoft does not currently recommend, and does not support,
Automation of Microsoft Office applications from any unattended,
non-interactive client application or component (including ASP,
ASP.NET, DCOM, and NT Services), because Office may exhibit unstable
behaviour and/or deadlock when Office is run in this environment.
Next question is why not use OpenXML for this? Here's a simple sample to get you started which counts the number of slides in a deck.
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;
}
}
}

Categories

Resources