Please see the attached image showing how I need to stack text in CAD. Everything I've tried has failed to account for all situations.
Basically, I am using the coordinate of the text to try and determine how to arrange it properly. Any help would appreciated. My work is below:
private void swaptext()
{
using (ac.AcadDocumentLock)
{
using (var t = ac.StartTransaction)
{
try
{
MText tx1 = (MText)ids[0].GetObject(OpenMode.ForRead);
MText tx2 = (MText)ids[1].GetObject(OpenMode.ForRead);
string conts1 = tx1.Contents;
string conts2 = tx2.Contents;
Point3d pos1 = tx1.Location;
Point3d pos2 = tx2.Location;
if ((tx1.Contents.Contains("TWO")) && (pos1.X < pos2.X))
{
tx1.Contents = conts2;
tx2.Contents = conts1;
}
else if ((tx1.Contents.Contains("TWO")) && (pos1.Y < pos2.Y))
{
tx2.Contents = conts1;
tx1.Contents = conts2;
}
ids.Clear();
}
catch (System.Exception ex)
{
ac.AcadDocument.Editor.WriteMessage("Error: ==>\n{0}\nTrace: ==>\n{1}", ex.Message, ex.StackTrace);
}
t.Commit();
}
}
}
Stacking Text
if you just rotate the text back to 0 degrees, then you can just compare which text has higher Y coordinate. And that one should contain the word "ONE"
private void swaptext()
{
using (ac.AcadDocumentLock)
{
using (var t = ac.StartTransaction)
{
try
{
MText tx1 = (MText)ids[0].GetObject(OpenMode.ForRead);
MText tx2 = (MText)ids[1].GetObject(OpenMode.ForRead);
string conts1 = tx1.Contents;
string conts2 = tx2.Contents;
Extents3d Ex1 = tx1.GeometricExtents;
Extents3d Ex2 = tx2.GeometricExtents;
Point3d pos1 = Ex1.MaxPoint.RotateBy(-tx1.Rotation, tx1.Normal, tx1.Location);
Point3d pos2 = Ex2.MaxPoint.RotateBy(-tx2.Rotation, tx2.Normal, tx2.Location);
if ((tx1.Contents.Contains("TWO")) && (pos1.Y > pos2.Y))
{
tx1.Contents = conts2;
tx2.Contents = conts1;
}
else
if ((tx2.Contents.Contains("TWO")) && (pos2.Y > pos1.Y))
{
tx1.Contents = conts2;
tx2.Contents = conts1;
}
ids.Clear();
}
catch (System.Exception ex)
{
ac.AcadDocument.Editor.WriteMessage("Error: ==>\n{0}\nTrace: ==>\n{1}", ex.Message, ex.StackTrace);
}
t.Commit();
}
}
}
Related
I am developing a C# Windows Form program in which there are a number of called Methods (what in VB I called Subs). Excuse me if I'm using the wrong terms, new to C#. One of these methods is being ignored, CreateFolder(). When I set break points to debug and step through, the program gets to the called method and goes right through it like it like it was a blank line, no errors warning just goes through. The program is a bit large so I'm including what I hope is helpful. Sorry if too much. The method (sub) not being executed is CreateFolder(). Again, the debugger will stop on this line[CreateFolder()] in the ProcessEmail() routine but just goes on without going to the called code. Thoughts?
public partial class FrmProcessNew : Form
{
...bunch of global vaiables
private void FrmProcessNew_Load(object sender, EventArgs e)
{
chkBoxTesting.Checked = Convert.ToBoolean(ConfigurationManager.AppSettings["testing"]); //check if test to ignore bad credit cards
}
private void btnStart_Click(object sender, EventArgs e)
{
ProcessEmail(); //check for, process and then move new Outlook emails
}
public void ScrollBox(string box) //try to get scroll box right
{
if (box == "Text")
{
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
}
if (box == "List")
{ listBox1.TopIndex = listBox1.Items.Count - 1; }
}
public static int GetLineNumber(COMException ex) //Get the line number if an error occurs - from stack overflow
{
var lineNumber = 0;
const string lineSearch = ":line ";
var index = ex.StackTrace.LastIndexOf(lineSearch);
if (index != -1)
{
var lineNumberText = ex.StackTrace.Substring(index + lineSearch.Length);
if (int.TryParse(lineNumberText, out lineNumber))
{
}
}
return lineNumber;
}
private void ProcessEmail() // Process the new email
{
while (inboxFolder.Items.Count == 0) //check for any email in Inbox
{
textBox1.Text = textBox1.Text + ("Inbox is empty - Listening for New emails!\r\n");
ScrollBox("Text");
textBox1.Update();
Delay(); //wait 5 seconds
}
CreateFolder(); //Create new destination folder to move processed emails to - NOT FORWARDING TO THIS SUB!!
try
{
foreach (Microsoft.Office.Interop.Outlook.MailItem mailItem in inboxFolder.Items)
{
....processing stuff
}
catch (System.Runtime.InteropServices.COMException ex)
{
....capture error
}
finally
{
....reset stuff
}
}
public void CreateFolder() //Create Outlook Folders to store processed emails = NEVER GETS TO THIS CODE!!!
{
DateTime fldDate = DateTime.Now;
if (fldDate.DayOfWeek != DayOfWeek.Friday) //must process with a Friday date, set date to next Friday
{
fldDate = NextFriday(fldDate);
}
String myYear = fldDate.ToString("yyyy");
string myMonth = fldDate.ToString("MM");
string myDay = fldDate.ToString("dd"); //day of the month
string fileDate = (myYear.ToString()) + "-" + (myMonth.ToString()) + "-" + myDay; // build the Date for Destination "file";
try
{olDestinationFolder = ns.Folders[mailBoxName].Folders[("done")].Folders[(fileDate)]; }
catch
{ olDestinationFolder = ns.Folders[mailBoxName].Folders[("done")].Folders.Add(fileDate); }
try
{ olBadCreditFolder = ns.Folders[mailBoxName].Folders[("done")].Folders[(fileDate)].Folders[("BadCredit")]; }
catch
{ olBadCreditFolder = ns.Folders[mailBoxName].Folders[("done")].Folders[(fileDate)].Folders.Add("BadCredit"); }
try
{ olNonOrderEmails = ns.Folders[mailBoxName].Folders[("done")].Folders[(fileDate)].Folders[("Non-OrderEmails")]; }
catch
{ olNonOrderEmails = ns.Folders[mailBoxName].Folders[("done")].Folders[(fileDate)].Folders.Add("Non-OrderEmails"); }
}
private void Delay() //If no emails then want 5 seconds and try again
{
textBox1.Text = textBox1.Text + ("Inbox is empty - Listening for New emails!\r\n");
ScrollBox("Text");
textBox1.Update();
// await Task.Delay(5000); //Wait 5 seconds for new email
var t = Task.Run(async delegate
{
await Task.Delay(TimeSpan.FromSeconds(5.5));
ScrollBox("Text");
return 42;
});
}
static DateTime NextFriday(DateTime fldDate) //Find the next FRIDAY date.
{
do
{
fldDate = fldDate.AddDays(1);
}
while (fldDate.DayOfWeek != DayOfWeek.Friday);
return fldDate;
}
}
}
We try to use the sdk to use the cognitives services of Microsoft. We use the Interface IFaceOperatiosn which inside there's a method to send a picture by stream like:DetectWithStreamWithHttpMessagesAsync. When we try to use it, we reach a APIErrorException which the message is Bad request but don't know where is the problem so there's our code:
public async Task<List<FaceAPI.Face>> DetectFace(string picture)
{
try
{
Stream img = new FileStream(picture, FileMode.Open);
var res = await detect.DetectWithStreamWithHttpMessagesAsync(img);
List<FaceAPI.Face> result = new List<FaceAPI.Face>();
for (int i = 0; i < res.Body.Count; i++)
{
result.Add(new FaceAPI.Face { Age = (double)res.Body[i].FaceAttributes.Age, Bald = res.Body[i].FaceAttributes.Hair.Bald > 0.5 ? true : false, Beard = res.Body[i].FaceAttributes.FacialHair.Beard > 0.5 ? true : false, Gender = res.Body[i].FaceAttributes.Gender.Value.Equals(Gender.Male) ? true : false, Glasses = res.Body[i].FaceAttributes.Glasses.Value.Equals(GlassesType.NoGlasses) ? false : true, Hair = res.Body[i].FaceAttributes.Hair.HairColor.ToString(), Moustache = res.Body[i].FaceAttributes.FacialHair.Moustache > 0.5 ? true : false,Rectangle=new System.Drawing.Rectangle { X = res.Body[i].FaceRectangle.Left, Y = res.Body[i].FaceRectangle.Top, Height = res.Body[i].FaceRectangle.Height, Width = res.Body[i].FaceRectangle.Width } });
}
return result;
}
catch (APIErrorException e)
{
Debug.WriteLine(e.Message);
return null;
}
catch (SerializationException e)
{
Debug.WriteLine(e.Message);
return null;
}
catch (ValidationException e)
{
Debug.WriteLine(e.Message);
return null;
}
}
Normally it returns a list of Face.
You need to put a wich attribute you want retrieve for the detection like this:
var requiredFaceAttributes = new FaceAttributeType[] {
FaceAttributeType.Age,
FaceAttributeType.Hair,
FaceAttributeType.Gender,
FaceAttributeType.Smile,
FaceAttributeType.FacialHair,
FaceAttributeType.Glasses
};
var res = await detect.DetectWithStreamWithHttpMessagesAsync(picture,true,true,requiredFaceAttributes);
I have this Delegates thats been wrote like this
public static T GetInteropDelegate<T>(IntPtr handler)
{
string functionName = null;
var procAddress = IntPtr.Zero;
var supportedPlatform = UMPSettings.SupportedPlatform;
try
{
var attrs = typeof(T).GetCustomAttributes(typeof(InteropFunctionAttribute), false);
if (attrs.Length == 0)
throw new Exception("Could not find the LibVLCAttribute.");
var attr = (InteropFunctionAttribute)attrs[0];
functionName = attr.FunctionName;
if (_interopDelegates.ContainsKey(functionName))
return (T)Convert.ChangeType(_interopDelegates[attr.FunctionName], typeof(T), null);
if (supportedPlatform == UMPSettings.Platforms.Win)
procAddress = WindowsInterops.GetProcAddress(handler, attr.FunctionName);
if (supportedPlatform == UMPSettings.Platforms.Mac)
procAddress = MacInterops.dlsym(handler, attr.FunctionName);
if (supportedPlatform == UMPSettings.Platforms.Linux)
procAddress = LinuxInterops.dlsym(handler, attr.FunctionName);
if (procAddress == IntPtr.Zero)
throw new Win32Exception("Can't get process address from " + handler + " library: " + Marshal.GetLastWin32Error());
var delegateForFunctionPointer = Marshal.GetDelegateForFunctionPointer(procAddress, typeof(T));
_interopDelegates[attr.FunctionName] = delegateForFunctionPointer;
return (T)Convert.ChangeType(delegateForFunctionPointer, typeof(T), null);
}
catch (Exception e)
{
Debug.LogError("GetMethod error: " + functionName);
throw new MissingMethodException(string.Format("The address of the function '{0}' does not exist in " + handler + " library.", functionName), e);
}
}
Now the problem with this is that . It always throw the error
Exception: Could not find the LibVLCAttribute.
UMP.InteropLibraryLoader.GetInteropDelegate[libvlc_media_get_stats] (IntPtr handler) (at Assets/UniversalMediaPlayer/Scripts/Sources/InteropLibraryLoader.cs:149)
Rethrow as MissingMethodException: The address of the function '' does not exist in 235143168 library.
UMP.InteropLibraryLoader.GetInteropDelegate[libvlc_media_get_stats] (IntPtr handler) (at Assets/UniversalMediaPlayer/Scripts/Sources/InteropLibraryLoader.cs:173)
UMP.VlcMethods.LoadMethodsFromVLCLibrary (IntPtr handler) (at Assets/UniversalMediaPlayer/StreamingWork/VlcMethods.cs:59)
Now there's a script that holds my method of vlc
VlcMethod.cs
using System;
using System.Runtime.InteropServices;
using UMP.Wrappers;
namespace UMP
{
public class VlcMethods
{
private static VlcMethods instance = null;
public static VlcMethods Instance
{
get
{
if (instance == null)
{
instance = new VlcMethods();
}
return instance;
}
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int libvlc_media_get_stats(IntPtr p_md, out libvlc_media_stats_t p_stats);
public libvlc_media_get_stats Libvlc_media_get_stats;
public VlcMethods()
{
var libraryExtension = string.Empty;
var settings = UMPSettings.Instance;
IntPtr handler = InteropLibraryLoader.Load(Wrapper.LibraryVLCName, settings.UseExternalLibs, settings.AdditionalLibsPath, libraryExtension);
if (handler != IntPtr.Zero)
{
LoadMethodsFromVLCLibrary(handler);
}
}
~VlcMethods()
{
instance = null;
}
private void LoadMethodsFromVLCLibrary(IntPtr handler)
{
if (handler == IntPtr.Zero)
return;
try
{
//Libvlc_media_get_stats = (libvlc_media_get_stats)InteropLibraryLoader.GetInteropDelegate<libvlc_media_get_stats>(handler);
//[Pk Recode 29/12 2017]
Libvlc_media_get_stats = InteropLibraryLoader.GetInteropDelegate<libvlc_media_get_stats>(handler);
}
catch (Exception exception)
{
InteropLibraryLoader.Unload(handler);
throw new ArgumentException(
String.Format("No suitable " + Wrapper.LIBRARY_VLC_NAME + " could be found in the provided path: {0}", exception.Message),
Wrapper.LIBRARY_VLC_NAME + "Directory", exception);
}
}
}
}
Now i'm using also my vlc method for checking the network condition which is like this
libvlc_media_stats_t preStat;
VlcMethods.Instance.Libvlc_media_get_stats(mediaObj, out preStat);
while (true)
{
yield return new WaitForSeconds(1f);
libvlc_media_stats_t t;
VlcMethods.Instance.Libvlc_media_get_stats(mediaObj, out t);
int playedBuff = t.i_demux_read_bytes - preStat.i_demux_read_bytes;
int downBuff = t.i_read_bytes - preStat.i_read_bytes;
int storageBuff = t.i_read_bytes - t.i_demux_read_bytes;
sumStorageBuffer -= storagebuffQueue.Dequeue();
storagebuffQueue.Enqueue(storageBuff);
sumStorageBuffer += storageBuff;
sumDownBuff -= downBuffQueue.Dequeue();
downBuffQueue.Enqueue(downBuff);
sumDownBuff += downBuff;
averageStorageBuffer = (sumStorageBuffer / (float)storagebuffQueue.Count) / playedBuff;
averageDownloadBuffer = (sumDownBuff / (float)downBuffQueue.Count) / playedBuff;
preStat = t;
And now i don't know really why it is throwing that error. -_-. Anyone can site ? Thank you in advance. This is driving me nuts.
I came up with the idea that i need to delete my vlcmethod.cs and on my livecam.cs
private IEnumerator CheckNetworkCondition()
{
averageStorageBuffer = 0;
averageDownloadBuffer = 0;
Queue<float> storagebuffQueue = new Queue<float>();
float sumStorageBuffer = 0;
Queue<float> downBuffQueue = new Queue<float>();
float sumDownBuff = 0;
for (int i = 0; i < averageCount; i++)
{
storagebuffQueue.Enqueue(0);
downBuffQueue.Enqueue(0);
}
MediaStats? preStat = null;
while (true)
{
yield return new WaitForSeconds(1f);
var mediaStats = new MediaStats();
if (ump.PlatformPlayer is MediaPlayerStandalone)
mediaStats = (ump.PlatformPlayer as MediaPlayerStandalone).MediaStats;
if (ump.PlatformPlayer is MediaPlayerAndroid)
mediaStats = (ump.PlatformPlayer as MediaPlayerAndroid).MediaStats;
if (preStat == null)
preStat = mediaStats;
int playedBuff = mediaStats.DemuxReadBytes - preStat.Value.DemuxReadBytes;
int downBuff = mediaStats.InputReadBytes - preStat.Value.InputReadBytes;
int storageBuff = mediaStats.InputReadBytes - mediaStats.DemuxReadBytes;
sumStorageBuffer -= storagebuffQueue.Dequeue();
storagebuffQueue.Enqueue(storageBuff);
sumStorageBuffer += storageBuff;
sumDownBuff -= downBuffQueue.Dequeue();
downBuffQueue.Enqueue(downBuff);
sumDownBuff += downBuff;
averageStorageBuffer = (sumStorageBuffer / (float)storagebuffQueue.Count) / playedBuff;
averageDownloadBuffer = (sumDownBuff / (float)downBuffQueue.Count) / playedBuff;
preStat = mediaStats;
UpdatekNetworkCondition();
}
}
Following this actual solution I am trying to get all the words inside a TextChunk and each of its coordinates (actual page, top, bottom, left, right).
Since a TextChunk could be a phrase, a word or whatever, I tried to do this manually, counting on the last word's rectangle and cutting it each time. I noticed this manual method could be so buggy (I would need to manually count on special characters and so on), so I asked myself if ITextSharp provides any easier way to perform this.
My Chunk and LocationTextExtractionStragy inherited classes are the following:
public class Chunk
{
public Guid Id { get; set; }
public Rectangle Rect { get; set; }
public TextRenderInfo Render { get; set; }
public BaseFont BF { get; set; }
public string Text { get; set; }
public int FontSize { get; set; }
public Chunk(Rectangle rect, TextRenderInfo renderInfo)
{
this.Rect = rect;
this.Render = renderInfo;
this.Text = Render.GetText();
Initialize();
}
public Chunk(Rectangle rect, TextRenderInfo renderInfo, string text)
{
this.Rect = rect;
this.Render = renderInfo;
this.Text = text;
Initialize();
}
private void Initialize()
{
this.Id = Guid.NewGuid();
this.BF = Render.GetFont();
this.FontSize = ObtainFontSize();
}
private int ObtainFontSize()
{
return Convert.ToInt32(this.Render.GetSingleSpaceWidth() * 12 / this.BF.GetWidthPoint(" ", 12));
}
}
public class LocationTextExtractionPersonalizada : LocationTextExtractionStrategy
{
//Save each coordinate
public List<Chunk> ChunksInPage = new List<Chunk>();
//Automatically called on each chunk on PDF
public override void RenderText(TextRenderInfo renderInfo)
{
base.RenderText(renderInfo);
if (string.IsNullOrWhiteSpace(renderInfo.GetText())
|| renderInfo == null)
return;
//Get chunk Vectors
var bottomLeft = renderInfo.GetDescentLine().GetStartPoint();
var topRight = renderInfo.GetAscentLine().GetEndPoint();
//Create Rectangle based on previous Vectors
var rect = new Rectangle(
bottomLeft[Vector.I1],
bottomLeft[Vector.I2],
topRight[Vector.I1],
topRight[Vector.I2]);
if (rect == null)
return;
//Add each chunk with its coordinates
ChunksInPage.Add(new Chunk(rect, renderInfo));
}
}
So once I get the file and so on, I proceed this way:
private void ProcessContent()
{
for (int page= 1; page <= pdfReader.NumberOfPages; page++)
{
var strategy = new LocationTextExtractionPersonalizada();
var currentPageText = PdfTextExtractor.GetTextFromPage(
pdfReader,
page,
strategy);
//Here is where I want to get each word with its coordinates
var chunksWords= ChunkRawToWord(strategy.ChunksInPage);
}
}
private List<Chunk> ChunkRawToWord(IList<Chunk> chunks)
{
if (chunks == null || chunks[0] == null)
return null;
var words = new List<Chunk>();
//Poor RegEx pattern to get the word and its wathever
string pattern = #"[#&\w+]*(-*\/*\s*\:*\;*\,*\.*\(*\)*\%*\>*\<*)?";
var something = chunks[0].Render.GetCharacterRenderInfos();
for (int i = 0; i < chunks.Count; i++)
{
var wordsInChunk = Regex.Matches(
chunks[i].Text,
pattern,
RegexOptions.IgnoreCase);
var rectangleChunk = new Rectangle(chunks[i].Rect);
for (int j = 0; j < wordsInChunk.Count; j++)
{
if (string.IsNullOrWhiteSpace(wordsInChunk[j].Value))
continue;
var word = new Chunk(
rectangleChunk,
chunks[i].Render,
wordsInChunk[j].ToString());
if (j == 0)
{
word.Rect.Right = word.BF.GetWidthPoint(word.Text, word.FontSize);
words.Add(word);
continue;
}
if (words.Count <= 0)
continue;
word.Rect.Left = words[j - 1].Rect.Right;
word.Rect.Right = words[j - 1].Rect.Right + word.BF.GetWidthPoint(word.Text, word.FontSize);
words.Add(word);
}
}
return words;
}
Afterwards, I wrote a comment on Mkl's solution, being replied with "use getCharacterRenderInfos()", which I use and I get every single character into a TextRenderInfo's List.
I'm sorry but I'm starting to mix concepts, ways to find out how to apply that solution and blowing my mind.
I would really appreciate a hand here.
You can use the method TextRenderInfo.GetCharacterRenderInfos() to get a collection of TextRenderInfo for each and every char in your chunk. Then you can could regroup the individual characters into words and calculate the rectangle that contains the word using the coordinates of the first and last TextRenderInfo in that word.
In your custom text extraction strategy:
var _separators = new[] { "-", "(", ")", "/", " ", ":", ";", ",", "."};
protected virtual void ParseRenderInfo(TextRenderInfo currentInfo)
{
var resultInfo = new List<TextRenderInfo>();
var chars = currentInfo.GetCharacterRenderInfos();
foreach (var charRenderInfo in chars)
{
resultInfo.Add(charRenderInfo);
var currentChar = charRenderInfo.GetText();
if (_separators.Contains(currentChar))
{
ProcessWord(currentInfo, resultInfo);
resultInfo.Clear();
}
}
ProcessWord(currentInfo, resultInfo);
}
private void ProcessWord(TextRenderInfo charChunk, List<TextRenderInfo> wordChunks)
{
var firstRender = wordChunks.FirstOrDefault();
var lastRender = wordChunks.LastOrDefault();
if (firstRender == null || lastRender == null)
{
return;
}
var startCoords = firstRender.GetDescentLine().GetStartPoint();
var endCoords = lastRender.GetAscentLine().GetEndPoint();
var wordText = string.Join("", wordChunks.Select(x => x.GetText()));
var wordLocation = new LocationTextExtractionStrategy.TextChunkLocationDefaultImp(startCoords, endCoords, charChunk.GetSingleSpaceWidth());
_chunks.Add(new CustomTextChunk(wordText, wordLocation));
}
And how can i report to the user that there was a problem and that it's trying over again ? And should i just do it like i'm doing it now reseting everything and calling Init() again or should i use some timer and wait some seconds before trying again ?
In the class i did:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using System.Xml;
using HtmlAgilityPack;
using System.ComponentModel;
namespace TestingDownloads
{
class ExtractImages
{
static WebClient client;
static string htmltoextract;
public static List<string> countriescodes = new List<string>();
public static List<string> countriesnames = new List<string>();
public static List<string> DatesAndTimes = new List<string>();
public static List<string> imagesUrls = new List<string>();
static string firstUrlPart = "http://www.sat24.com/image2.ashx?region=";
static string secondUrlPart = "&time=";
static string thirdUrlPart = "&ir=";
public class ProgressEventArgs : EventArgs
{
public int Percentage { get; set; }
public string StateText { get; set; }
}
public event EventHandler<ProgressEventArgs> ProgressChanged;
public void Init()
{
object obj = null;
int index = 0;
ExtractCountires();
foreach (string cc in countriescodes)
{
// raise event here
ProgressChanged?.Invoke(obj,new ProgressEventArgs{ Percentage = 100 * index / countriescodes.Count, StateText = cc });
ExtractDateAndTime("http://www.sat24.com/image2.ashx?region=" + cc);
index +=1;
}
ImagesLinks();
}
public void ExtractCountires()
{
try
{
htmltoextract = "http://sat24.com/en/?ir=true";//"http://sat24.com/en/";// + regions;
client = new WebClient();
client.DownloadFile(htmltoextract, #"c:\temp\sat24.html");
client.Dispose();
string tag1 = "<li><a href=\"/en/";
string tag2 = "</a></li>";
string s = System.IO.File.ReadAllText(#"c:\temp\sat24.html");
s = s.Substring(s.IndexOf(tag1));
s = s.Substring(0, s.LastIndexOf(tag2) + tag2.ToCharArray().Length);
s = s.Replace("\r", "").Replace("\n", "").Replace(" ", "");
string[] parts = s.Split(new string[] { tag1, tag2 }, StringSplitOptions.RemoveEmptyEntries);
string tag3 = "<li><ahref=\"/en/";
for (int i = 0; i < parts.Length; i++)
{
if (i == 17)
{
//break;
}
string l = "";
if (parts[i].Contains(tag3))
l = parts[i].Replace(tag3, "");
string z1 = l.Substring(0, l.IndexOf('"'));
if (z1.Contains("</ul></li><liclass="))
{
z1 = z1.Replace("</ul></li><liclass=", "af");
}
countriescodes.Add(z1);
countriescodes.GroupBy(n => n).Any(c => c.Count() > 1);
string z2 = parts[i].Substring(parts[i].LastIndexOf('>') + 1);
if (z2.Contains("&"))
{
z2 = z2.Replace("&", " & ");
}
countriesnames.Add(z2);
countriesnames.GroupBy(n => n).Any(c => c.Count() > 1);
}
}
catch (Exception e)
{
if (countriescodes.Count == 0)
{
countriescodes = new List<string>();
countriesnames = new List<string>();
DatesAndTimes = new List<string>();
imagesUrls = new List<string>();
Init();
}
}
}
public void ExtractDateAndTime(string baseAddress)
{
try
{
var wc = new WebClient();
wc.BaseAddress = baseAddress;
HtmlDocument doc = new HtmlDocument();
var temp = wc.DownloadData("/en");
doc.Load(new MemoryStream(temp));
var secTokenScript = doc.DocumentNode.Descendants()
.Where(e =>
String.Compare(e.Name, "script", true) == 0 &&
String.Compare(e.ParentNode.Name, "div", true) == 0 &&
e.InnerText.Length > 0 &&
e.InnerText.Trim().StartsWith("var region")
).FirstOrDefault().InnerText;
var securityToken = secTokenScript;
securityToken = securityToken.Substring(0, securityToken.IndexOf("arrayImageTimes.push"));
securityToken = secTokenScript.Substring(securityToken.Length).Replace("arrayImageTimes.push('", "").Replace("')", "");
var dates = securityToken.Trim().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
var scriptDates = dates.Select(x => new ScriptDate { DateString = x });
foreach (var date in scriptDates)
{
DatesAndTimes.Add(date.DateString);
}
}
catch
{
countriescodes = new List<string>();
countriesnames = new List<string>();
DatesAndTimes = new List<string>();
imagesUrls = new List<string>();
this.Init();
}
}
public class ScriptDate
{
public string DateString { get; set; }
public int Year
{
get
{
return Convert.ToInt32(this.DateString.Substring(0, 4));
}
}
public int Month
{
get
{
return Convert.ToInt32(this.DateString.Substring(4, 2));
}
}
public int Day
{
get
{
return Convert.ToInt32(this.DateString.Substring(6, 2));
}
}
public int Hours
{
get
{
return Convert.ToInt32(this.DateString.Substring(8, 2));
}
}
public int Minutes
{
get
{
return Convert.ToInt32(this.DateString.Substring(10, 2));
}
}
}
public void ImagesLinks()
{
int cnt = 0;
foreach (string countryCode in countriescodes)
{
cnt++;
for (; cnt < DatesAndTimes.Count(); cnt++)
{
string imageUrl = firstUrlPart + countryCode + secondUrlPart + DatesAndTimes[cnt] + thirdUrlPart + "true";
imagesUrls.Add(imageUrl);
if (cnt % 10 == 0) break;
}
}
}
}
}
In both cases where i'm using try and catch if it's getting to the catch i'm trying over again the whole operation by reseting the Lists and calling Init() again.
Then in form1
ExtractImages ei = new ExtractImages();
public Form1()
{
InitializeComponent();
ProgressBar1.Minimum = 0;
ProgressBar1.Maximum = 100;
backgroundWorker1.RunWorkerAsync();
}
events of backgroundworker
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (backgroundWorker1.CancellationPending == true)
{
e.Cancel = true;
return; // this will fall to the finally and close everything
}
else
{
ei.ProgressChanged += (senders, eee) => backgroundWorker1.ReportProgress(eee.Percentage, eee.StateText);
ei.Init();
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
ProgressBar1.Value = e.ProgressPercentage;
label7.Text = e.UserState.ToString();
label8.Text = e.ProgressPercentage + "%";
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error == null)
{
ProgressBar1.Value = 100;
}
else
{
}
}
Another thing not sure if it's a problem. When there is no a problem with the class i see in form1 in label7 all the codes running from the first to the last.
But the progressBar1.Value and label8 both are getting only to 97% so i need in the completed event to add the progressBar1.Value = 100; is that fine or there is a problem with the reporting calculation in the class ?
For the 1st question:
Better catch the exception at client side and display the error msg, 'cause you probably need to control your program behavior accrodingly when sth went wrong.
Consider this: if the DOM struct of the page changed, according to you code, your program probably throw expections, with each exception catching, client.DownloadFile is excuted for one time, if this happens, u will need to know what go wrong, and if u donot change ur code behavior, such hi-freq client.DownloadFile excution will cause the firewall of the website block ur ip for a while.
Add a timer at client side is a good idea i think.
For the 2nd one:
did u define how to handle RunWorkerCompleted event?