I have an application that produces SVG diagrams, we would like to create an export to Visio option that would, ideally, behind the scenes (via server-side C#) take an SVG file and convert it directly to an MS Visio .vsdx file that the user can download and then ofcourse open and edit in Visio seamlessly (as opposed to having to download the SVG file, and then importing it themselves into Visio). In effect, trying to replicate the "Open SVG" functionality that the Visio GUI supplies in backend C#.
I have seen a lot of answers on going from Visio TO SVG, but this is the opposite.
I also know that .vsdx is simply a zip file, but with that extension. Inside are a bunch of visio specific files and folders - if anyone knows what is the bare minimum required of these files/folders and their contents and where the SVG fits in, perhaps that's one way to do it.
Any guidance would be much appreciated.
Dug this up, credit/source: https://programmer.group/5c650f3227420.html
SVG can be converted to Visio's vsd format. The method is very simple. The main method is to open the SVG file and save it as a vsd file. The invocation method is as follows:
/// <summary>
/// svg turn vsd
/// </summary>
/// <param name="svgFn">svn file name</param>
/// <param name="desVsdFn">Preserved vsd file name</param>
private static void Svg2Vsd(string svgFn, string desVsdFn)
{
var app = ComObj.Create("Visio.Application");
app["Visible"] = new ComObj(false);
var docs = app["Documents"];
short visOpenHidden = 64, visOpenRO = 2;
var doc = docs.Call("OpenEx", svgFn, visOpenHidden + visOpenRO);
doc.Call("SaveAs", desVsdFn);
doc.Call("Close");
var win = app["Window"];
app.Call("Quit");
}
Here I use a ComObj class I wrote myself. Its purpose is to make it easy to invoke Com components such as Office by reflection, and to make the code concise when invoking.
Why use reflection to invoke dynamically instead of directly referencing Com components? The main purpose is to reduce the dependence and coupling of program code to COM components, so as to facilitate the compilation and distribution of code deployment. Dynamic invocation can be compiled and run without adding component references. If the Com component is not installed on the server, you can also give an intuitive prompt instead of a program error.
The code for this class is as follows:
using System;
using System.Reflection;
namespace HZ.Common
{
/// <summary>
/// For convenience Com Object attributes, method calls
/// </summary>
public class ComObj
{
public static ComObj Create(string progId)
{
var type = Type.GetTypeFromProgID(progId);
if (type == null)
{
throw new Exception("Servers need to be installed" + progId + "To use this feature");
}
return new ComObj(Activator.CreateInstance(type));
}
private object _val;
/// <summary>
/// Actual value
/// </summary>
public object Val
{
get { return _val; }
}
public ComObj(object comObject)
{
_val = comObject;
}
public ComObj Call(string mehtod, params object[] args)
{
if (_val == null)
return null;
var ret = _val.GetType().InvokeMember(mehtod, BindingFlags.InvokeMethod, null, _val, args);
return new ComObj(ret);
}
public ComObj this[string property]
{
get
{
if (_val == null)
return null;
var ret = _val.GetType().InvokeMember(property, BindingFlags.GetProperty, null, _val, null);
return new ComObj(ret);
}
set
{
if (_val != null)
_val.GetType().InvokeMember(property, BindingFlags.SetProperty, null, _val, new object[] { value.Val });
}
}
}
}
Related
I'm searching for a way to make one resource manager that holds all the data form multiple resource files. Is this even possible? It would be useful for me if yes because I've got like 10+ resources files with translations. I want to make one wrapper class for this and make one resource manager so if I e.g. use rm.GetString("string"); I get this value from one of resource files. I probably think that this is not the best idea but... if you have any good ideas please share here!
I'm trying the following code:
var rm = new ResourceManager("ProjectNameSpace.ResourceName",
Assembly.GetExecutingAssembly());
By doing this I only load resources from file that I specified by: ProjectNameSpace.ResourceName, am I right?
Is there any nice workaround for this or different approach?
This is not exactly what you are asking about, but maybe it will help. This is some cut-down copy-and-paste code from a program I use that reads multiple resource files and creates a combined Dictionary of all of the icons in the resource files.
class Program
{
static void Main(string[] args)
{
IconManager.FindIconsInResources(Resources1.ResourceManager);
//IconManager.FindIconsInResources(Resources2.ResourceManager);
//IconManager.FindIconsInResources(Resources3.ResourceManager);
Image iconImage = IconManager.GetIcon("Incors_office_building_16x16");
}
}
public static class IconManager
{
private static readonly Dictionary<string, ResourceSet> _iconDictionary =
new Dictionary<string, ResourceSet>();
/// <summary>
/// Method to read the resources info for an assembly and find all of the icons and add them
/// to the icon collection.
/// </summary>
public static void FindIconsInResources(ResourceManager resourceManager)
{
// Get access to the resources (culture shouldn't matter, but has to be specified)
ResourceSet resourceSet =
resourceManager.GetResourceSet(CultureInfo.GetCultureInfo("en-us"), true, true);
if (resourceSet == null)
throw new Exception("Unable to create ResourceSet.");
// Top of loop to examine each resource object
foreach (DictionaryEntry dictionaryEntry in resourceSet)
{
// Check it's an icon (or some kind of graphic)
if (!(dictionaryEntry.Value is Bitmap))
continue;
// Get the resource name, which is basically the filename without ".png" and with '-'
// and blanks converted to '_'. Ignore .ico files.
string resourceKey = (string)dictionaryEntry.Key;
if (resourceKey.EndsWith("_ico", StringComparison.Ordinal))
continue;
// Add (or replace) the icon in the icon dictionary
_iconDictionary[resourceKey] = resourceSet;
}
}
/// <summary>
/// Method to get an icon image from one of several resource files.
/// </summary>
public static Image GetIcon(string iconName)
{
ResourceSet resourceSet;
_iconDictionary.TryGetValue(iconName, out resourceSet);
if (resourceSet == null)
return null;
return (Image)resourceSet.GetObject(iconName);
}
}
I'm working in c# and I'm passing in chart properties as a json string, for example:
{'chart':{
'series':{
'count':3,
'style':'3 Series Scaled Bars',
'data':[
{'x':'Brand','y':'Avg Comments','type':'barScaled','position':1}
{'x':'Brand','y':'Avg Likes','type':'barScaled','position':2}
{'x':'Brand','y':'Avg Shares','type':'barScaled','position':3}
]
}}}
What I'd like to be able to do is pass in something like this: 'markerSize': 8 and be able to set the property with the string name of the property, something likes this:
Excel.SeriesCollection lines = (Excel.SeriesCollection)chrt.SeriesCollection();
Excel.Series ser = sers.Item(1);
ser.Properties("markerSize") = 8;
Is that possible, or do I have to write code to handle each property that I need to be able to modify?
System.Reflection class may provide what you seek for.
In case some of properties will be in fact fields following code handles both situations.
For COM objects it supports only properties, I am too tired to think of a way to support both fields and properties for COM objects without ugly try-catch blocks.
Why previous code failed for Interop objects? Because they are evil COM objects.
While Reflection can normally return fields and properties for interface without any problem, for COM objects it failed because their true type during runtime is System._ComObject, which of course lacked properties you were looking for.
Workaround is to use Invoke method, which deals with horrors of COM on its own.
System._ComObject is hidden type, hence its tested as string instead of Type. (I am tired)
using System.Reflection;
...
/// <summary>
/// Dynamicaly sets property of given object with given value. No type casting is required. Supports COM objects properties.
/// </summary>
/// <param name="target">targeted object</param>
/// <param name="propertyName">property name</param>
/// <param name="value">desired value</param>
/// <returns>True if success, False if failure (non existing member)</returns>
static bool SetProperty(object target, string propertyName, object value)
{
Type t = target.GetType();
if(t.ToString()=="System.__ComObject")
{
t.InvokeMember(propertyName, BindingFlags.SetProperty, null, target, new object[] { value });
return true;
}
PropertyInfo propertyInfo = t.GetProperty(propertyName);
FieldInfo fieldInfo = t.GetField(propertyName);
if (propertyInfo != null)
{
propertyInfo.SetValue(target, Convert.ChangeType(value, propertyInfo.PropertyType, null));
return true;
}
if (fieldInfo!=null)
{
fieldInfo.SetValue(target, Convert.ChangeType(value, fieldInfo.FieldType, null));
return true;
}
return false;
}
//usage:
foo bar = new foo();
SetProperty(bar,"myPropertyOrField","myValue");
I'm trying to establish access to an embedded SQL resource file I've created in a Class Library. However, I'm not sure where to go from here.
I've accessed the resource using:
Assembly.GetExcecutingAssembly().GetManifestResourceStream("InsertTest.sql");
My understanding is that there is a way to access them in a strongly typed fashion, but I can't seem to get a handle on the project or the solution to browse through their respective properties or resources programatically.
What am I missing?
Although I did get some great suggestions (see Philip Daniels' answer - good stuff), none of them really addressed my specific concerns. However, I found that the easiest way to accomplish this was to do the following:
Right click your project and select 'Properties'
Select the 'Resources' tab. Create a new resources file if necessary.
In the upper left hand corner there is a drop down that defaults to 'Strings'. Click this box and choose 'Files'.
Drag and drop the resource file you'd like to embed in the project.
You can now access a strongly typed resource using the following syntax:
Project.Properties.Resources.ResourceName;
In my situation, this worked perfectly as I am storing inline SQL in these files and it returns the sql embedded in the file. Keep in mind, however, that by defaults these resources are linked and not embedded, but you can change their property to set them to embedded.
Hope this helps someone!
You're almost there. I have a couple of functions I use for this. You can do somehting very similar for images. I'm not sure it's worth creating properties like you want (you can do that through the Resources tab of the project properties if you insist).
/// <summary>
/// Gets an open stream on the specified embedded resource. It is the
/// caller's responsibility to call Dispose() on the stream.
/// The filename is of the format "folder.folder.filename.ext"
/// and is case sensitive.
/// </summary>
/// <param name="assembly">The assembly from which to retrieve the Stream.</param>
/// <param name="filename">Filename whose contents you want.</param>
/// <returns>Stream object.</returns>
public static Stream GetStream(Assembly assembly, string filename)
{
string name = String.Concat(assembly.GetName().Name, ".", filename);
Stream s = assembly.GetManifestResourceStream(name);
return s;
}
/// <summary>
/// Get the contents of an embedded file as a string.
/// The filename is of the format "folder.folder.filename.ext"
/// and is case sensitive.
/// </summary>
/// <param name="assembly">The assembly from which to retrieve the file.</param>
/// <param name="filename">Filename whose contents you want.</param>
/// <returns>String object.</returns>
public static string GetFileAsString(Assembly assembly, string filename)
{
using (Stream s = GetStream(assembly, filename))
using (StreamReader sr = new StreamReader(s))
{
string fileContents = sr.ReadToEnd();
return fileContents;
}
}
On a resource file you won't be able to have intellisense to build your sql script compare to have them as separate files in your project. You can create a helper class to access them in a strong type fashion:
public class Scripts
{
public static string Sql1
{
get
{
return GetResource("sql1.sql");
}
}
public static string Sql2
{
get
{
return GetResource("sql2.sql");
}
}
private static string GetResource(string name)
{
var assembly = Assembly.GetExecutingAssembly();
using(var stream = new StreamReader(assembly.GetManifestResourceStream("Myproject.Sql." + name)))
{
return stream.ReadToEnd();
}
}
}
For example, in Dapper, you can access your scripts like this:
using(var db = new SqlConnection("yourconnectionstring")){
db.Open();
var results = db.Query(Scripts.Sql1);
}
I need to convert a bunch of HTML files (about 30) to PDFs. Would be awesome if I could create a TOC and link pages, but right now I'd just be happy converting the individual files :)
I've tried a couple solutions already, the most successful was EO.PDF, but it put a nasty watermark on every page, and it couldn't handle files over a few meg, and some of mine are 10meg+.
I've read a lot of good things about wkhtmltopdf, and I found the wrapper for it, WkHTMLToSharp. I am unable to find any documentation, so I cobbled together the following bit of code, that is throwing an exception. I'd appreciate any help resolving this.
I noted the line that is causing the exception. The (very UNhelpful) exception is:
"The type initializer for 'WkHtmlToXSharp.WkHtmlToPdfConverter' threw an exception."
--CODE--
/// <summary>
/// Creates a PDF file from the HTML file passed in
/// </summary>
/// <param name="cFile">Full path to HTML file to generate PDF from</param>
/// <param name="pdfFile">Full path of PDF output file</param>
public static void WritePDF(string cFile, string pdfFile)
{
// Generates "The type initializer for
// 'WkHtmlToXSharp.WkHtmlToPdfConverter' threw an exception.":
WkHtmlToPdfConverter w = new WkHtmlToPdfConverter();
byte[] strHTML = w.Convert(cFile);
File.WriteAllBytes(pdfFile, strHTML);
w.Dispose();
}
After resolving the issue with the missing DLL, I discovered that bit of code actually converts a string of HTML, not a file. I CAN work with that, but would MUCH prefer to work with the HTML files.
In addition, none of the images are being displayed in the PDF file. They are all JPGs (I know there is an issue with GIFS).
Use WkHtmlToXSharp.
Download the latest DLL from Github
public static string ConvertHTMLtoPDF(string htmlFullPath, string pageSize, string orientation)
{
string pdfUrl = htmlFullPath.Replace(".html", ".pdf");
try
{
#region USING WkHtmlToXSharp.dll
//IHtmlToPdfConverter converter = new WkHtmlToPdfConverter();
IHtmlToPdfConverter converter = new MultiplexingConverter();
converter.GlobalSettings.Margin.Top = "0cm";
converter.GlobalSettings.Margin.Bottom = "0cm";
converter.GlobalSettings.Margin.Left = "0cm";
converter.GlobalSettings.Margin.Right = "0cm";
converter.GlobalSettings.Orientation = (PdfOrientation)Enum.Parse(typeof(PdfOrientation), orientation);
if (!string.IsNullOrEmpty(pageSize))
converter.GlobalSettings.Size.PageSize = (PdfPageSize)Enum.Parse(typeof(PdfPageSize), pageSize);
converter.ObjectSettings.Page = htmlFullPath;
converter.ObjectSettings.Web.EnablePlugins = true;
converter.ObjectSettings.Web.EnableJavascript = true;
converter.ObjectSettings.Web.Background = true;
converter.ObjectSettings.Web.LoadImages = true;
converter.ObjectSettings.Load.LoadErrorHandling = LoadErrorHandlingType.ignore;
Byte[] bufferPDF = converter.Convert();
System.IO.File.WriteAllBytes(pdfUrl, bufferPDF);
converter.Dispose();
#endregion
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
return pdfUrl;
}
I'd like to add an alternative suggestion: Don't use WkHtmlToXSharp - rather install wkhtmltopdf and use it directly. Spawning processes in c#.net is quite simple in my opinion and so it is a viable alternative.
I use that method and have recommended it to others with success, see an earlier answer I gave. I still find the example I used there a nice example, so I'll repeat it.
var pi = new ProcessStartInfo(#"c:\wkhtmltopdf\wkhtmltopdf.exe");
pi.CreateNoWindow = true;
pi.UseShellExecute = false;
pi.WorkingDirectory = #"c:\wkhtmltopdf\";
pi.Arguments = "http://www.google.com gogl.pdf";
using (var process = Process.Start(pi))
{
process.WaitForExit(99999);
Debug.WriteLine(process.ExitCode);
}
This question already has answers here:
How can I get the assembly last modified date?
(6 answers)
Closed 9 years ago.
How can I retrieve the Created date from the current .NET assembly?
I'd like to add some realy simple functionality where my app stops working one week after the build date of the main assembly. I already wrote the code that kills my app after a given date. I just need to programmatically retrieve the creation date from the assembly.
The following is based on: https://blog.codinghorror.com/determining-build-date-the-hard-way/
public static class ApplicationInformation
{
/// <summary>
/// Gets the executing assembly.
/// </summary>
/// <value>The executing assembly.</value>
public static System.Reflection.Assembly ExecutingAssembly
{
get { return executingAssembly ?? (executingAssembly = System.Reflection.Assembly.GetExecutingAssembly()); }
}
private static System.Reflection.Assembly executingAssembly;
/// <summary>
/// Gets the executing assembly version.
/// </summary>
/// <value>The executing assembly version.</value>
public static System.Version ExecutingAssemblyVersion
{
get { return executingAssemblyVersion ?? (executingAssemblyVersion = ExecutingAssembly.GetName().Version); }
}
private static System.Version executingAssemblyVersion;
/// <summary>
/// Gets the compile date of the currently executing assembly.
/// </summary>
/// <value>The compile date.</value>
public static System.DateTime CompileDate
{
get
{
if (!compileDate.HasValue)
compileDate = RetrieveLinkerTimestamp(ExecutingAssembly.Location);
return compileDate ?? new System.DateTime();
}
}
private static System.DateTime? compileDate;
/// <summary>
/// Retrieves the linker timestamp.
/// </summary>
/// <param name="filePath">The file path.</param>
/// <returns></returns>
/// <remarks>http://www.codinghorror.com/blog/2005/04/determining-build-date-the-hard-way.html</remarks>
private static System.DateTime RetrieveLinkerTimestamp(string filePath)
{
const int peHeaderOffset = 60;
const int linkerTimestampOffset = 8;
var b = new byte[2048];
System.IO.FileStream s = null;
try
{
s = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
s.Read(b, 0, 2048);
}
finally
{
if(s != null)
s.Close();
}
var dt = new System.DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(System.BitConverter.ToInt32(b, System.BitConverter.ToInt32(b, peHeaderOffset) + linkerTimestampOffset));
return dt.AddHours(System.TimeZone.CurrentTimeZone.GetUtcOffset(dt).Hours);
}
}
I don't think the assembly itself contains it's creation date. I suspect the closest you can get is the creation date of the assembly file itself:
File.GetCreationTime(Assembly.GetExecutingAssembly().Location)
should do the trick.
EDIT:
I think Jeff Atwood's solution, written up by "grenade" in this thread, is probably the better way to go now.
What's wrong with:
System.IO.File.GetLastWriteTime(Assembly.GetExecutingAssembly().Location);
Maybe this post on coding horror may help
This should work:
var entryAssembly = Assembly.GetEntryAssembly();
var fileInfo = new FileInfo(entryAssembly.Location);
var buildDate = fileInfo.LastWriteTime;
The best way to do this would be with a custom attribute that you set on the PreBuild of your assembly.
And then use the standard reflection to get the attribute you created.
But out of curiosity, why kill the app after the BUILD date?
If you're writing an application for a mobile device using the compact framwork, Assembly.Location is not available.
Here, I found an alternative:
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)