C++/CLI XML creation methods Dll in a WPF form - c#

Update: I have modified the post as per comments.
This is going to be a slightly long post i apologize for that, but i want people to understand what im trying to do before shooting it down. I've asked a few question previously about creating methods to create XMLs in C++/CLI and I want to continue using them.
Recently i started testing out C# and WPF and im really enjoying the creativity and freedom it offers for visual effects. I started converting the functions of an application i am currently working on into a DLL mostly so i don't have to redo the work I have already done and because i want to learn and gain some experience in writing DLL's and using interop.
Every function so far has only had a single input or output. However my final two functions (Which take a list of filenames and the hash of the file its self and for each file and hash saves it to an xml file) aren't working so well for me. Im getting output but not in the form i want it so obviously my logic is flawed but im not sure how to correct it.
The functions are very similar the only difference is the one creates a brand new xml while the second updates an existing xml. They both worked perfectly before as straight C++/CLI functions however now that i need to use them in C# i have to put them in iterations so they work for each of the files and their hashes displayed in the lists.
Below is one of the functions in the Dll where i have now replaced the previous hard-coded variables which would have been listBox2->Items[x]->ToString() as varibales such as CurrentFile which are now defined in the .cs.
public: void XMLUpdate(String^ Location, int NumberItems, String^ ProjectName,
String^ ProjectTC, String^ CurrentFile, String^ CurrentHash)
{
try
{
XmlDocument^ XmlDoc = gcnew XmlDocument();
XmlDoc->Load(Location);
XmlElement^ NewProject = XmlDoc->CreateElement("Project");
NewProject->SetAttribute("Name", ProjectName);
XmlDoc->DocumentElement->AppendChild(NewProject);
XmlElement^ NewTestCycle = XmlDoc->CreateElement("TestCycle");
NewTestCycle->SetAttribute("Number", ProjectTC);
NewProject->AppendChild(NewTestCycle);
XmlElement^ NewFile = XmlDoc->CreateElement("Files");
NewTestCycle->AppendChild(NewFile);
for (int x = 0; x < NumberItems; ++x)
{
String^ FileName = CurrentFile;
String^ Hash = CurrentHash;
XmlElement^ NewFileName = XmlDoc->CreateElement("FileName");
NewFileName->SetAttribute("File", FileName);
NewFile->AppendChild(NewFileName);
XmlElement^ NewHashCode = XmlDoc->CreateElement("HashCode");
NewHashCode->SetAttribute("Code", Hash);
NewFile->AppendChild(NewHashCode);
}
XmlDoc->Save(Location);
return;
}
catch(Exception^)
{
return;
}
}
Here is the call for the method from the dll in my WPF form:
private void button2_Click(object sender, RoutedEventArgs e)
{
DllTest.Funtions Functions = new DllTest.Funtions();
String Name = textBox1.Text;
String TC = textBox2.Text;
String Location = "C:\\Users\\brandonm\\Desktop\\Backup\\XML\\test1.xml";
int Number = listBox2.Items.Count;
for (int x = 0; x < listBox2.Items.Count; ++x)
{
Functions.XMLUpdate(Location, Number, TC, Name, listBox2.Items[x].ToString(),
listBox3.Items[x].ToString());
}
}
Output is only taking the last item in the list and duplicating it by the number in the list in this case the list had 3 filenames and the second list had 3 hashes here is an example:
<?xml version="1.0" encoding="utf-8"?>
<Project Name="New">
<TestCycle Number="1">
<Files>
<FileName
File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode
Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
<FileName
File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode
Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
<FileName
File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode
Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
</Files>
</TestCycle>
</Project>
</Project>
So here is the second function that updates an exisitng XML and gives me completely different output, still incorrect, from the output in the new function.
public: void XMLUpdate(String^ Location, int NumberItems, String^ ProjectName,
String^ ProjectTC, String^ CurrentFile, String^ CurrentHash)
{
try
{
XmlDocument^ XmlDoc = gcnew XmlDocument();
XmlDoc->Load(Location);
XmlElement^ NewProject = XmlDoc->CreateElement("Project");
NewProject->SetAttribute("Name", ProjectName);
XmlDoc->DocumentElement->AppendChild(NewProject);
XmlElement^ NewTestCycle = XmlDoc->CreateElement("TestCycle");
NewTestCycle->SetAttribute("Number", ProjectTC);
NewProject->AppendChild(NewTestCycle);
XmlElement^ NewFile = XmlDoc->CreateElement("Files");
NewTestCycle->AppendChild(NewFile);
for (int x = 0; x < NumberItems; ++x)
{
String^ FileName = CurrentFile;
String^ Hash = CurrentHash;
XmlElement^ NewFileName = XmlDoc->CreateElement("FileName");
NewFileName->SetAttribute("File", FileName);
NewFile->AppendChild(NewFileName);
XmlElement^ NewHashCode = XmlDoc->CreateElement("HashCode");
NewHashCode->SetAttribute("Code", Hash);
NewFile->AppendChild(NewHashCode);
}
XmlDoc->Save(Location);
return;
}
catch(Exception^)
{
return;
}
}
The method call:
private void button4_Click(object sender, RoutedEventArgs e)
{
DllTest.Funtions Functions = new DllTest.Funtions();
String Name = textBox1.Text;
String TC = textBox2.Text;
String path = "C:\\Users\\brandonm\\Desktop\\Backup\\XML\\test1.xml";
int Number = listBox2.Items.Count;
for (int x = 0; x < listBox2.Items.Count; ++x)
{
Functions.XMLNew(path, Name, TC, Number, listBox2.Items[x].ToString(),
listBox3.Items[x].ToString());
}
}
the output for this one which is closer to what i need since it using all of the items in the list but its duplicating them in every element i only want a single new element with the new files and their hashes.
<?xml version="1.0" encoding="utf-8"?>
<Project Name="New">
<TestCycle Number="1">
<Files>
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
</Files>
</TestCycle>
</Project>
<Project Name="2">
<TestCycle Number="New">
<Files>
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" />
<HashCode Code="0E-C2-B1-A4-3C-D8-C0-51-96-0F-FF-19-BC-3A-CE-AC" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" />
<HashCode Code="0E-C2-B1-A4-3C-D8-C0-51-96-0F-FF-19-BC-3A-CE-AC" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" />
<HashCode Code="0E-C2-B1-A4-3C-D8-C0-51-96-0F-FF-19-BC-3A-CE-AC" />
</Files>
</TestCycle>
</Project>
<Project Name="2">
<TestCycle Number="New">
<Files>
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" />
<HashCode Code="C0-7C-51-C2-92-70-1B-11-E0-26-6D-D5-B8-79-12-0D" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" />
<HashCode Code="C0-7C-51-C2-92-70-1B-11-E0-26-6D-D5-B8-79-12-0D" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" />
<HashCode Code="C0-7C-51-C2-92-70-1B-11-E0-26-6D-D5-B8-79-12-0D" />
</Files>
</TestCycle>
</Project>
<Project Name="2">
<TestCycle Number="New">
<Files>
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
</Files>
</TestCycle>
</Project>
</Project>
So now you can see the problem i have loops within loops causing output that repeats its self. I can post an example of my output if you need.
But for the life of me i cannot get around it, i have tried splitting up the functions in to parts but i get errors trying to do that.
Can anyone see a way around this? I only want to completely rewrite the methods in c# if its my only alternative since i want all the main functions in the dll. Please dont bash me for my lack of knowledge im still learning and testing alot of things for the first time.
Thanks

Related

Showing PDF-File with MVVM Cross on Android and IOS

I want to open a PDF on the Phone via the File-Path but i cant figure out how i could do this properly without using 3rd party packages.
You have any suggestion for this?
I already tried to use this on Android:
public void OpenFile(string filePath)
{
var fileToOpen = new Java.IO.File(filePath);
var uri = FileProvider.GetUriForFile(Application.Context, Application.Context.PackageName + ".fileprovider", fileToOpen);
var intent = new Intent();
var mime = IOUtil.GetMimeType(uri.ToString());
intent.SetAction(Intent.ActionView);
intent.SetDataAndType(uri, mime);
intent.SetFlags(ActivityFlags.NewTask);
intent.AddFlags(ActivityFlags.GrantReadUriPermission);
Application.Context.StartActivity(intent);
}
But i get the following Error:
Unhandled Exception:
Java.Lang.NullPointerException: Attempt to invoke virtual method
'android.content.res.XmlResourceParser
android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager,
java.lang.String)' on a null object reference
first you should addd this code to your manifest file :
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.easyphotopicker.fileprovider"
android:exported="false"
android:grantUriPermissions="true"
tools:replace="android:authorities">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths"
tools:replace="android:resource"/>
</provider>
and create filepaths :
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path name="root" path="" /> //root directory of the device new File("/");
<files-path name="files" path="" /> //context.getFilesDir()
<cache-path name="cache" path="" /> //context.getCacheDir()
<external-path name="external" path="" /> //Environment.getExternalStorageDirectory()
<external-files-path name="name" path="path" /> //context.getExternalFilesDirs()
<external-cache-path name="name" path="path" /> //getExternalCacheDirs()
</paths>
Your error is telling us that there is no file at the location matching that's passed into the function. There's a few ways of doing this, one of them is as shown. After accepting permissions to access folders and files, this should be one of the simplest ways. You seem to be close:
public void OpenPdfFile(string filename)
{
var f = new Java.IO.File(filename);
if (f.Exists())
{
System.Diagnostics.Debug.WriteLine("File exists!");
try
{
var openFileIntent = new Intent(Intent.ActionView);
openFileIntent.SetDataAndType(Android.Net.Uri.FromFile(f), "application/pdf");
openFileIntent.SetFlags(ActivityFlags.NoHistory);
StartActivity(Intent.CreateChooser(openFileIntent, "Open pdf file"));
}
catch (ActivityNotFoundException)
{
//handle when no available apps
}
}
}
I haven't tested your work, but the first thing would be to see if you added this to the Manifest file
android:authorities="com.{package}.{name}.fileprovider"
since your code says Application.Context.PackageName + ".fileprovider"

C# App.Config File Path combine

I'm trying without success to use app.config keys with file path based.
This is my App.Config:
<appSettings>
<add key="States" value="NY,CA,MA" />
<add key="SourceFile_NY" value="C:\NY\file.xlsx" />
<add key="SourceFile_CA" value="C:\CA\file.xlsx" />
<add key="SourceFile_MA" value="C:\MA\file.xlsx" />
Now, on the main class, i'd like to obtain the file for each state given:
static void Main(string[] args)
{
var states = "NY,CA,MA".Split(',');
foreach (var state in states)
{
new SomeMethodFromOtherClass().class(SourceFile_ + XX);
}
}
I'm trying to get the file path based on the state on the SourceFile_ + XX part, but i can't find any good way to accomplish the call to the app.config value for each state
Make sure you add a reference in your project to System.Configuration.
Then you just do:
var ny = ConfigurationManager.AppSettings[sourcefile + "_NY"];

MonoDevelop Addin for NaCl using 'ProjectServiceExtension'

Hi all i'm trying to make a MonoDevelop addin that I can use to compile out Mono for NaCl projects... but i'm getting a null ref error and can't find enough information to figure out whats going wrong.
The null ref happens when I try to create a project from my Addin in MonoDevelop.
All resources are set to build as 'EmbeddedResource'.
Builder.cs:
using System;
using MonoDevelop.Projects;
using MonoDevelop.Core;
namespace MonoDevelop.MonoNaCl
{
public class Builder : ProjectServiceExtension
{
protected override BuildResult Build (IProgressMonitor monitor, SolutionEntityItem item, ConfigurationSelector configuration)
{
Console.WriteLine("Yahoo Build");
return base.Build (monitor, item, configuration);
}
protected override void Execute (IProgressMonitor monitor, SolutionEntityItem item, ExecutionContext context, ConfigurationSelector configuration)
{
Console.WriteLine("Yahoo Execute");
base.Execute (monitor, item, context, configuration);
}
}
}
MonoDevelop.MonoNaCl.addin.xml:
NOTE: I'm really not clear on the 'Extension's I should use and think the issue is in there.
<Addin namespace = "MonoDevelop"
id = "MonoNaCl"
name = "Mono for NaCl"
author = "Andrew Witte"
copyright = "BSD"
url = "http://www.URL.com"
description = "Support for developing MonoNaCl applications."
category = "NaCl Development"
version = "1.0">
<Dependencies>
<Addin id="Ide" version="3.0" />
<Addin id="Core" version="3.0" />
</Dependencies>
<Extension path = "/MonoDevelop/Ide/ProjectTemplates">
<ProjectTemplate id = "MonoNaClProject" resource = "MonoNaCl.xpt.xml"/>
</Extension>
<Extension path = "/MonoDevelop/ProjectModel/ProjectServiceExtensions">
<Class class = "MonoDevelop.MonoNaCl.Builder"/>
</Extension>
<!--<Extension path = "/MonoDevelop/ProjectModel/MSBuildItemTypes">
<SolutionItem type="MonoDevelop.MonoNaCl.Builder" extension="csproj" guid="{49DFC40D-C27A-4230-A637-8D9669269586}"/>
</Extension>-->
<Extension path="/MonoDevelop/ProjectModel/SerializableClasses">
<DataType class="MonoDevelop.MonoNaCl.Builde" />
</Extension>
</Addin>
MonoNaCl.xpt.xml:
<?xml version="1.0"?>
<Template originator = "Andrew Witte">
<TemplateConfiguration>
<_Name>MonoNaCl Project</_Name>
<_Category>C#/MonoNaCl</_Category>
<LanguageName>C#</LanguageName>
<_Description>Creates a MonoNaCl project.</_Description>
</TemplateConfiguration>
<Combine name = "${ProjectName}" directory = ".">
<Options>
<StartupProject>${ProjectName}</StartupProject>
</Options>
<Project name = "${ProjectName}" directory = "." type = "MonoNaCl">
<Options/>
</Project>
</Combine>
</Template>
And here is the Error after trying to create a project:
System.NullReferenceException: Object reference not set to an instance of an object
at MonoDevelop.Projects.SolutionFolderItemCollection.OnItemAdded (MonoDevelop.Projects.SolutionItem item) [0x0000b] in /Users/builder/data/lanes/monodevelop-mac-3.0.1/6642975f/source/monodevelop/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolderItemCollection.cs:59
at MonoDevelop.Projects.ItemCollection`1[MonoDevelop.Projects.SolutionItem].InsertItem (Int32 index, MonoDevelop.Projects.SolutionItem item) [0x00008] in /Users/builder/data/lanes/monodevelop-mac-3.0.1/6642975f/source/monodevelop/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ItemCollection.cs:39
at System.Collections.ObjectModel.Collection`1[MonoDevelop.Projects.SolutionItem].Add (MonoDevelop.Projects.SolutionItem item) [0x00000] in <filename unknown>:0
at MonoDevelop.Ide.Templates.SolutionDescriptor.CreateEntry (MonoDevelop.Projects.ProjectCreateInformation projectCreateInformation, System.String defaultLanguage) [0x0026c] in /Users/builder/data/lanes/monodevelop-mac-3.0.1/6642975f/source/monodevelop/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/SolutionDescriptor.cs:162
at MonoDevelop.Ide.Templates.ProjectTemplate.CreateWorkspaceItem (MonoDevelop.Projects.ProjectCreateInformation cInfo) [0x00000] in /Users/builder/data/lanes/monodevelop-mac-3.0.1/6642975f/source/monodevelop/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplate.cs:232
at MonoDevelop.Ide.Projects.NewProjectDialog.CreateProject () [0x001ef] in /Users/builder/data/lanes/monodevelop-mac-3.0.1/6642975f/source/monodevelop/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectDialog.cs:432
Remove the type="MonoNaCl" attribute definition in the Project element.
You don't have to set the project type, unless you are defining your own Project subclass.

ActivityLibrary for Sharepoint Designer

I'm trying to implement an MSDN tutorial to create an activity library for Sharepoint Designer, and it gives me this error:
Namespace1.CreateTaskInListOnSite' does not contain a definition for 'ListName' and no extension method 'ListName' accepting a ...
and the same for AssignedTo and 'SiteUrl`.
Shouldn't 'AssignedTo', 'ListName' and 'SiteUrl' be inherited members from SequenceActivity class?
Here is the code which is erred:
protected override ActivityExecutionStatus
Execute(ActivityExecutionContext executionContext)
{
try
{
SPSite sitecollection = new SPSite(this.SiteUrl); //here
SPWeb web = sitecollection.OpenWeb();
SPUser user = web.Users[this.AssignTo[0].ToString()]; // here
SPList list = web.Lists[this.ListName]; // and here
SPListItem item = list.Items.Add();
item["Title"] = this.TaskTitle;
item["AssignedTo"] = user;
item.Update();
}
catch (Exception ex)
{
EventLog.WriteEntry("MSDN Workflow", ex.ToString());
}
return ActivityExecutionStatus.Closed;
}
Here is the .actions file:
<?xml version="1.0" encoding="utf-8" ?>
<WorkflowInfo>
<Actions Sequential="then" Parallel="and">
<Action Name="Create Task in List On Site"
ClassName="Namespace1.CreateTaskInListOnSite"
Assembly="CustomWorkflowActivities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a3170baa21b0a3e9"
AppliesTo="all" Category="Cross Site Actions">
<RuleDesigner
Sentence="Create task titled %1 for %2 on site %3 in
list %4">
<FieldBind Field="TaskTitle" DesignerType="TextArea"
Id="1"/>
<FieldBind Field="AssignTo" DesignerType="Person"
Text="this user" Id="2"/>
<FieldBind Field="SiteUrl" DesignerType="TextArea" Id="3"/>
<FieldBind Field="ListName" DesignerType="TextArea" Id="4"/>
</RuleDesigner>
<Parameters>
<Parameter Name="TaskTitle" Type="System.String, mscorlib"
Direction="In" />
<Parameter Name="AssignTo" Type="System.String, mscorlib"
Direction="In" />
<Parameter Name="SiteUrl" Type="System.String, mscorlib"
Direction="In" />
<Parameter Name="ListName" Type="System.String, mscorlib"
Direction="In" />
</Parameters>
</Action>
The .ACTIONS file calls the ClassName as MSDN.HowTo.CreateTaskInListOnSite, where as in your code file you seem to use the namespace Namespace1. The two have to match.
So either you change .ACTIONS to this:
<Action Name="Create Task in List On Site"
ClassName="MSDN.HowTo.CreateTaskInListOnSite" .... />
or change the namespace definition in your code file to MSDN.HowTo.
The assembly attribute values also have to be correct. You can use the sn.exe tool to retrieve the public key token for your assembly.

C# Storing multiple Items in multiple arrays for comparison

I have an application that reads File names and their equivalent Hash codes from an XML(After i have created the XML using the same application) and What i would like it to do is compare one XML (the files and their hash codes) to another XML(With possibly different files and hash codes). I'm trying to create a compare function so that i can compare the file names, first, between the two XMLs and then compare the Hash codes if the files exists in both XMLs.
(to help understand what im trying to achieve basically i have 2 listboxes next to each other, one for each of the xmls. Once i compare them i want both listboxes populated with all the file names but not the hashcodes and then to mark them in different colors depending if they are the same file, same file but different content or the file does not exist at all in the other XML.)
I'm struggling to find a way to store the file names and their hash codes.
Code(I am using a C++ Dll i created to do some of the work):
private String[] ProjOne()
{
//Intialize the functions in the DLL
DllTest.Funtions Functions = new DllTest.Funtions();
//Set the location where the XMLs can be found
String Directory = "C:\\Users\\brandonm\\Desktop\\Backup\\XML\\";
//Get and set the number of items in the directory
int NumFiles = Functions.GetNumFiles(Directory);
//Create a search string to be used to determine the fullpath name of the file
//selected from the combobox
String SelectedFile = comboBox1.SelectedItem.ToString();
String SearchString = "*" + SelectedFile + "*.XML";
//Get and set the TC that will be used to get the filenames and hashcodes
int SelectedTC = int.Parse(comboBox2.SelectedItem.ToString());
//Get and set an array containing a full path structure to the item selected from
//the combobox using the search string created earlier. Get files returns an array
//thus needs to be stored in an array
String[] FullPaths = new String[NumFiles];
FullPaths = System.IO.Directory.GetFiles("C:\\Users\\brandonm\\Desktop\\Backup\\XML", SearchString, System.IO.SearchOption.AllDirectories);
int number = FullPaths.GetLength(0);
// The number of items in the XML ie. Number of Filenames in a particular TC
int NumXMLItems = NumXMLItemsListOne();
// Initialize the array that will hold the Filenames and their equivalent Hashcodes
String[] FileNames = new String[NumXMLItems];
String[] HashCode = new String[NumXMLItems];
String[,] ProjectOne = new String[HashCode.Length, HashCode.Length];
//Itteration through the all the XMLs in the location to add the current items into their arrays
for (int x = 0; x < NumFiles; x++)
{
String FullPath = FullPaths[x];
XPathNavigator Root = new XPathDocument(FullPath).CreateNavigator();
foreach (XPathNavigator Cycle in Root.Select(String.Format(#"//TestCycle[#Number = '{0}']", SelectedTC)))
{
foreach (XPathNavigator Nav in Cycle.Select(#"Files/FileName/#File"))
{
int y = 0;
FileNames[y] = Nav.Value;
y = y + 1;
}
foreach (XPathNavigator Nav in Cycle.Select(#"Files/HashCode/#Code"))
{
int z = 0;
HashCode[z] = Nav.Value;
z = z + 1;
}
}
}
return FileNames;
}
XML:
<?xml version="1.0" encoding="utf-8"?>
<Projects>
<Project Name="tfasdtyf">
<TestCycle Number="2387468">
<Files>
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" />
<HashCode Code="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" />
<HashCode Code="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
</Files>
</TestCycle>
</Project>
<Project Name="tfasdtyf">
<TestCycle Number="23423">
<Files>
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" />
<HashCode Code="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" />
<HashCode Code="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
</Files>
</TestCycle>
</Project>
<Project Name="tfasdtyf">
<TestCycle Number="1112">
<Files>
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" />
<HashCode Code="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" />
<HashCode Code="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
</Files>
</TestCycle>
</Project>
<Project Name="tfasdtyf">
<TestCycle Number="999">
<Files>
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" />
<HashCode Code="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" />
<HashCode Code="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
</Files>
</TestCycle>
</Project>
<Project Name="tfasdtyf">
<TestCycle Number="34534">
<Files>
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" />
<HashCode Code="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" />
<HashCode Code="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" />
<FileName File="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" />
<HashCode Code="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
</Files>
</TestCycle>
</Project>
<Project Name="Music">
<TestCycle Number="12312">
<Files>
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 A1 Shut Ya Mouth.mp3" />
<HashCode Code="3E-92-80-93-D5-64-19-16-26-8D-39-2A-C7-0B-C8-EB" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 A1 Snake Eater.mp3" />
<HashCode Code="8B-DF-19-AE-87-52-64-2E-85-CF-57-4B-85-4D-CC-E9" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 A1 Stuck in the System.mp3" />
<HashCode Code="6A-30-A7-53-FF-29-A5-DF-6D-24-DF-41-74-EE-06-4D" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 Martin Solveig - Hello (Featuring Dragonette).mp3" />
<HashCode Code="93-90-A3-9C-BE-81-63-03-D7-96-1F-72-E4-ED-2D-32" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\01 Stimming - Funkworm.mp3" />
<HashCode Code="8F-E1-7A-F1-B7-80-C6-2F-DC-34-FD-82-A0-DA-35-5E" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\1. Downlink - Ignition.mp3" />
<HashCode Code="3D-89-B3-C2-73-A6-A0-85-02-C0-B4-F9-C8-09-14-C7" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\02 B1 Psychedelic Runway.mp3" />
<HashCode Code="00-72-5C-CE-25-73-98-31-69-71-68-48-31-A1-A3-5A" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\02 B1 Rapture.mp3" />
<HashCode Code="1E-A6-53-07-10-FD-A3-4C-EF-D6-92-7F-CE-97-88-6E" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\02_Digital-Controller.mp3" />
<HashCode Code="94-E0-CA-5F-2B-D2-56-7B-AF-2E-04-50-58-38-4D-B4" />
<FileName File="C:\Users\brandonm\Desktop\Stuff\Dubstep\2. Downlink - Gamma Ray.mp3" />
<HashCode Code="3C-7A-76-AD-A6-2C-D1-7E-61-24-C0-40-BD-A7-A9-41" />
</Files>
</TestCycle>
</Project>
</Projects>
I currently have another function identical to the one above so one for each listbox the only difference is the file and the testcyle number which determines where in the XML they will retrieve their files and hash codes. They store them in 4 separate arrays, 2 arrays per function. But obviously my function cannot return two arrays so it is currently only return the one.
2D arrays confuse me a lot and im not sure how i would get the information i need out of them when it comes down to the comparing i need to do. Can anyone direct me to a better way of doing this?
I dont want to really make 4 functions like the one above for the each set of filenames and then each set of hashcodes. But i'm still a beginner so maybe that is my best option?
It's better not to duplicate the function. You want to make a single function that can be used in all of your cases here.
As for storing the filenames and hashcodes, .NET has a lot of useful collection classes you can use. For example, you could use a Dictionary<string, string> like this:
Dictionary<string, string> dictionary = new Dictionary<string, string>();
for (int i = 0; i < NumFiles; i++)
{
dictionary.Add(FileNames[i], HashCode[i]);
}
The above code you could put right before your return statement in the function you provided. Then return the dictionary. Of course, you could make the entire function shorter by storing them directly in the dictionary, but I'll leave that for you to decide.
Now, wherever this function is called from, you might need to loop through this dictionary. Here's a way to do that:
foreach (var pair in dictionary)
{
string filename = pair.Key;
string hashcode = pair.Value;
// Do whatever you want with them here
}
No doubt there are other ways to do what you want. I am not completely sure what your overall goal is. You should experiment with other generic collections too, such as List<T>.
If HashCode belongs to a File, why isn't it a sub-element/attribute of it? It would make it way easier to parse.
Since you create the file, I'd create the structure like:
<Project Name="tfasdtyf">
<TestCycle Number="23423">
<Files>
<File Name="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\DllTest.dll" HashCode="0E-C5-03-AD-CC-21-62-49-D9-36-3F-C4-F1-17-BC-11" />
<File Name="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.exe" HashCode="60-46-A3-6F-82-E4-0A-00-2A-60-83-47-B2-16-F3-24" />
<File Name="C:\Users\brandonm\Documents\Visual Studio 2008\Projects\WpfDllTest\WpfDllTest\bin\x86\Release\WpfDllTest.vshost.exe" HashCode="76-7B-6F-37-0D-3A-F2-F4-32-D1-70-A5-75-3B-DE-95" />
</Files>
</TestCycle>
</Project>
Then with some XElement magic, you could use:
public class Project
{
XElement self;
public Project(XElement project)
{
self = project;
}
public TestCycle TestCycle
{
get
{
// If there are more than one TestCycle per project, you may end
// up creating something similar to TestCycle.Files (see TestCycle class below)
XElement testCycle = self.Element("TestCycle");
if(null == testCycle)
self.Add(testCycle = new XElement("TestCycle"));
return new TestCycle(testCycle);
}
}
public string Name
{
get { return return self.GetString("Name", string.Empty, ATTRIBUTE); }
set { self.Set("Name", value, ATTRIBUTE); } // see Set Extension method below
}
public static IEnumerable<Project> Load(string filename)
{
return XElement.Load(filename)).Elements("Project").Select(xp => new Project(xp));
}
}
public class TestCycle
{
XElement self;
public TestCycle(XElement testCycle)
{
self = testCycle;
}
private XElement XFiles
{
get
{
XElement files = self.Element("Files");
if(null == files)
self.Add(files = new XElement("Files"));
return files;
}
}
public IEnumerable<FileHash> Files
{
get
{
return XFiles.Elements("File").Select(xf => new FileHash(xf));
}
}
public int Number
{
get { return self.GetInt("Number", 0, ATTRIBUTE); }
set { self.Set("Number", value, ATTRIBUTE); } // see Set Extension method below
}
public FileHash AddFile(string name, string hashCode)
{
FileHash file = Files.FirstOrDefault(xf => xf.Name == name);
if(null != file)
file.self.Remove(); // replacing (but could throw an exception saying already exists instead)
XElement xFile = new XElement("File");
self.Add(xFile);
file = new FileHash(xFile)
{
Name = name,
HashCode = hashCode
};
return file;
}
}
public class FileHash
{
internal XElement self;
public FileHash(XElement fileHash)
{
self = fileHash;
}
public string Name
{
get { return self.GetString("Name", string.Empty, ATTRIBUTE); }
set { self.Set("Name", value, ATTRIBUTE); } // see Set Extension method below
}
public string HashCode
{
get { return return self.GetString("HashCode", string.Empty, ATTRIBUTE); }
set { self.Set("HashCode", value, ATTRIBUTE); } // see Set Extension method below
}
}
Extension methods:
public static XElementExtensions
{
public const bool ATTRIBUTE = true;
public const bool ELEMENT = false;
public const bool? BOTH = null;
public void Set(this XElement self, string name, object value, bool isAttribute)
{
string sValue = value.ToString();
XElement eValue = self.Element(name);
XAttribute aValue = self.Attribute(name);
if(null != eValue)
eValue.ReplaceWith(new XElement(name, sValue));
else if(null != aValue)
aValue.ReplaceWith(new XAttribute(name, sValue));
else if(isAttribute)
self.Add(new XAttribute(name, sValue));
else
self.Add(new XElement(name, sValue));
}
public string GetString(this XElement self, string name, string #default, bool? isAttribute)
{
XAttribute aValue = self.Attribute(name);
XElement eValue = self.Element(name);
if(null == isAttribute) // try both
{
if(null != aValue) return (string)aValue;
if(null != eValue) return (string)eValue;
return #default;
}
if(isAttribute && null != aValue)
return (string)aValue;
if(!isAttribute && null != eValue)
return (string)eValue);
return #default;
}
public int GetInt(this XElement self, string name, int #default, bool? isAttribute)
{
return Convert
.ToInt32(GetString(self, name, null, isAttribute) ?? #default.ToString());
}
}
Then you can use the code like:
Project[] projects = Project.Load(filename).ToArray();
foreach(Project project in projects)
{
Console.WriteLine("Project: " + project.Name);
Console.WriteLine("TestCycle: " + project.TestCycle.Number.ToString());
Console.WriteLine("Files:");
foreach(FileHash file in project.TestCycle.Files)
Console.WriteLine(string.Format(" Name: {0}, HashCode: {1}", file.Name, file.HashCode));
}
Or for your application, to compare two xml files:
var fileA = Project.Load(fileAname);
var fileB = Project.Load(fileBname);
I'm not quite sure how you mean, all the files, but I'll attempt it.
File[] filesA = fileA.SelectMany(project => project.TestCycle.Files).ToArray();
File[] filesB = fileB.SelectMany(project => project.TestCycle.Files).ToArray();
Using these Extension Methods:
public static IEnumerable<TSource> Except<TSource>
(
this IEnumerable<TSource> first,
IEnumerable<TSource> second,
Func<TSource, TSource, bool> comparer
)
{
return first.Except(second, new LambdaComparer<TSource>(comparer));
}
public static IEnumerable<TSource> Intersect<TSource>
(
this IEnumerable<TSource> first,
IEnumerable<TSource> second,
Func<TSource, TSource, bool> comparer
)
{
return first.Intersect(second, new LambdaComparer<TSource>(comparer));
}
And the LambdaComparer class:
public class LambdaComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, T, bool> equals;
private readonly Func<T, int> getHashCode;
public LambdaComparer(Func<T, T, bool> lambdaComparer) :
this(lambdaComparer, o => o.GetHashCode())
{
}
public LambdaComparer(Func<T, T, bool> lambdaComparer, Func<T, int> lambdaHash)
{
if (lambdaComparer == null)
throw new ArgumentNullException("lambdaComparer");
if (lambdaHash == null)
throw new ArgumentNullException("lambdaHash");
equals = lambdaComparer;
getHashCode = lambdaHash;
}
public bool Equals(T x, T y)
{
return equals(x, y);
}
public int GetHashCode(T obj)
{
return getHashCode(obj);
}
}
File[] filesInA_butNotInB = filesA.Except(filesB, (a,b) => a.Name == b.Name).ToArray();
File[] filesInBoth = filesA.Intersect(filesB, (a,b) => a.Name == b.Name).ToArray();
File[] filesInBoth_butDifferentHash = FilesA.Intersect(filesB, (a,b) => a.Name == b.Name && a.HashCode != b.HashCode).ToArray();
That should "get you started" ...
PS: I wrote (most of) this all by hand, not via compiler so there are probably some typo's that the compiler will catch.
PS: Also, all the .ToArray()'s are just because File[] is easier to read than IEnumerable<File>. It is easier to read but about the same typing either way.
PSS: I hope you find this useful. I love the Xml Linq way of handling things, so it was fun writing this out.

Categories

Resources