• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 926
  • Last Modified:

Call console app with xml-parameter file

Hi
I have a website where I call a console .exe file with Process.Start
I have some arguments attached to the app.
One of the arguments is a xml-config file.
It works fine, the XML-configfile is called, the configfile points at some files on the server, or should do. But it dosn't work.
I have tried to run it on a local IIS, pointing the files out from the xml-file with local paths, and this works fine.
But on the webserver it dosn't work. ( I have tried to use local paths her too)
One more thing, I use Virtual mapping on the webserver.

Can someone help me out here ??
0
conceptdata
Asked:
conceptdata
  • 12
  • 8
1 Solution
 
Wardy_01Commented:
Ok ...

If it's not calling the console app try using Server.MapPath("~/YourApp.exe") or similar to translate the virtual path to a physical one.

If it is running the app but there's a problem it could be the config file or it could be permissions.

By default the web app will execute the app under the same account that it is running under which is likely to be the "NetworkService" account or something similar, this means that virtually any operation that the console app tries to perform that involves any writing to files / access outside of the web root scope will cause you major headaches.

You can use impersonation or just specify some account credentials on the process object you create to call the exe to get around that or you can run the web app pool account under another user (eg a domain user that has access to all resources that it may need across your dommain).

Unless you are running the app from the same location on both computers (eg C:\MyApp\MyApp.exe) and the files are all in that same folder you might find that your paths break so consider relative paths using something like ".\" + filename for a file in the Console apps root folder this may help resolve some path issues.

I would get the permissions right first (try hard coding a temp path in to the exe) then make it more dynamic.

Don't forget you have various layers of permissions to deal with ...

1. domain permissions (defined on dc)
2. computer / server permissions (defined in computer managers users / groups)
3. web service permissions (defined in iis manager)
4. ntfs permissions (defined on files and folders themselves)

Hope this helps.
any probs, let me know.
0
 
conceptdataAuthor Commented:
The Console app is in the same dir as my xml-configfile.
I have tried this : font metrics-file=".\arial.xml"  
And this E:\WWW\Checkpoint\WWW\pdfconvert\database\arial.xml
-- (Physocal server path : E:\WWW\Checkpoint\WWW\pdfconvert\)

One more thin, the exe-file is called and executed fine, It makes a PDF file from a xml and xsl file.
app called nFop.
But still the files from the config file is not "called"
normal command line : nfop.exe  -c userconfig.xml -xsl off.xsl -xml off.xml -pdf off.pdf

??
0
 
Wardy_01Commented:
Whats the config file ?
typically if its a standard config file for a .NET app its named something like "YourApp.exe.config".

For custom config files you would have to write the code to pickup and read the config file manually maybe using an xmldocument object or something.

Sounds to me like the latter is your problem.
0
Veeam and MySQL: How to Perform Backup & Recovery

MySQL and the MariaDB variant are among the most used databases in Linux environments, and many critical applications support their data on them. Watch this recorded webinar to find out how Veeam Backup & Replication allows you to get consistent backups of MySQL databases.

 
conceptdataAuthor Commented:
Config file attached.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<fonts>
		<font metrics-file="arial.xml" embed-file="arial.ttf" kerning="yes">
			<font-triplet name="Arial" style="normal" weight="normal"/>
		</font>
		<font metrics-file="arial-bold.xml" embed-file="arialbd.ttf" kerning="yes">
			<font-triplet name="Arial" style="normal" weight="bold"/>
		</font>
		<font metrics-file="arial-italic.xml" embed-file="ariali.ttf" kerning="yes">
			<font-triplet name="Arial" style="italic" weight="normal"/>
		</font>
		<font metrics-file="arial-italic-bold.xml" embed-file="arialbi.ttf" kerning="yes">
			<font-triplet name="Arial" style="italic" weight="bold"/>
		</font>
	  <font metrics-file="IDAutomationHC39XL.xml" embed-file="IDAutomationHC39XL.ttf" kerning="yes">
			<font-triplet name="IDAutomationHC39XL" style="normal" weight="normal"/>
		</font>
	</fonts>
</configuration>

Open in new window

0
 
Wardy_01Commented:
ok as you are specifying a name for the config file as a startup param you should also have a block of code in the "static void Main(object [] args)" method that handles this xml data ?

This would be in the program.cs file of your project source code.

sure thats not logically flawed somehow ?

0
 
conceptdataAuthor Commented:
Thats right

I have attached the project as a RAR-file renamed to .jpg
nfop-fw2.jpg
0
 
Wardy_01Commented:
on this connection i'd be here all day downloading that mate, im using a mobile internet connection.
I could probably have a look later from home.

It sounds to me like you have a coding issue rather than a server / config issue and that the problem you have is the loading of this config file.

Just paste me the main method in the program.cs class file maybe that might shed some light on the subject :)
0
 
conceptdataAuthor Commented:
main method

        public static void Main(string[] args)
        {
            int ExitCode = 0;
  
            try
            {
                CommandLineArguments cmdLineArgs = new CommandLineArguments(args);
 
                if (CheckParameters(cmdLineArgs))
                {
                    switch (cmdLineArgs.Arguments.Count)
                    {
                        case 2:
 
                            if (cmdLineArgs.HasUSERCONFIG && cmdLineArgs.HasFO && cmdLineArgs.HasPDF)
                            {
                                Fop.Net.NFop.Create_PDF_from_FO_with_CONFIG(cmdLineArgs.FO, cmdLineArgs.PDF, cmdLineArgs.USERCONFIG);
                            }
                            else if (cmdLineArgs.HasUSERCONFIG == false && cmdLineArgs.HasFO && cmdLineArgs.HasPDF)
                            {
                                Fop.Net.NFop.Create_PDF_from_FO(cmdLineArgs.FO, cmdLineArgs.PDF);
                            }
 
                            break;
                        case 3:
 
                            if (cmdLineArgs.HasUSERCONFIG && cmdLineArgs.HasXML && cmdLineArgs.HasXSL && cmdLineArgs.HasPDF)
                            {
                                Fop.Net.NFop.Create_PDF_from_XML_XSL_with_CONFIG(cmdLineArgs.XML, cmdLineArgs.XSL, cmdLineArgs.PDF, cmdLineArgs.USERCONFIG);
                            }
                            else if (cmdLineArgs.HasUSERCONFIG == false && cmdLineArgs.HasXML && cmdLineArgs.HasXSL && cmdLineArgs.HasPDF)
                            {
                                Fop.Net.NFop.Create_PDF_from_XML_XSL(cmdLineArgs.XML, cmdLineArgs.XSL, cmdLineArgs.PDF);
                            }
 
                            break;
                        case 4:
 
                            if (cmdLineArgs.HasUSERCONFIG && cmdLineArgs.HasXML && cmdLineArgs.HasXSL && cmdLineArgs.HasFOOUT && cmdLineArgs.HasPDF)
                            {
                                Fop.Net.NFop.Create_PDF_and_FO_from_XML_XSL_with_CONFIG(cmdLineArgs.XML, cmdLineArgs.XSL, cmdLineArgs.FOOUT, cmdLineArgs.PDF, cmdLineArgs.USERCONFIG);
                            }
                            else if (cmdLineArgs.HasUSERCONFIG == false && cmdLineArgs.HasXML && cmdLineArgs.HasXSL && cmdLineArgs.HasFOOUT && cmdLineArgs.HasPDF)
                            {
                                Fop.Net.NFop.Create_PDF_and_FO_from_XML_XSL(cmdLineArgs.XML, cmdLineArgs.XSL, cmdLineArgs.FOOUT, cmdLineArgs.PDF);
                            }
 
                            break;
                    }
                }
                else
                {
                    PrintUsage();
                }
            }
            catch (System.IO.FileNotFoundException fileNotFoundException)
            {
                ExitCode = 1;
                Console.WriteLine(fileNotFoundException.Message);
            }
            catch (CommandLineArgumentException commandLineArgumentException)
            {
                ExitCode = 1;
                Console.WriteLine("{0}:\t{1}", commandLineArgumentException.Message, commandLineArgumentException.ParamName);
            }
            catch (Exception exception)
            {
                ExitCode = 1;
                Console.WriteLine("{0}{1}{2}", exception.Message, Environment.NewLine, exception.StackTrace);
            }
 
            Environment.Exit(ExitCode);
        }

Open in new window

0
 
conceptdataAuthor Commented:
Definition : Create_PDF_from_FO_with_CONFIG

        public static void Create_PDF_from_FO_with_CONFIG(string foFile, string pdfFile, string cfgFile)
        {
            string fo = Fop.Net.NFop.GetFo(foFile);
            byte[] bytes = Fop.Net.NFop.CreatePDF(fo, new org.apache.fop.apps.FileUrl(cfgFile));
            Fop.Net.NFop.CreateFile(bytes, pdfFile);
        }

Open in new window

0
 
conceptdataAuthor Commented:
definition : org.apache.fop.apps.FileUrl

using System;
 
namespace org.apache.fop.apps
{
    public class FileUrl
    {
        public FileUrl(string url);
 
        public override object MemberwiseClone();
        public override string ToString();
        public virtual java.net.URL toUrl();
    }
}

Open in new window

0
 
conceptdataAuthor Commented:
I think this code is the code that "reads" the ttf and xml font files ...
    * @return the URL to the metrics file
     */
    public URL getMetricsFile() throws FOPException {
        try {
            return URLBuilder.buildURL(Configuration.getFontBaseURL(), metricsFile);
        } catch (Exception e) {
            throw new FOPException("Invalid font metrics file: " + metricsFile 
                    + " (" + e.getMessage() + ")");
        }
    }
 
    /**
     * @return the url to the font
     */
    public URL getEmbedFile() throws FOPException {
        // check if it's a URL and convert it to a filename
        if (embedFile == null) return null;
        try {
            return URLBuilder.buildURL(Configuration.getFontBaseURL(), embedFile);
        } catch (Exception e) {
            throw new FOPException("Invalid font file (embedFile): " + embedFile 
                    + " (" + e.getMessage() + ")");
        }
    }

Open in new window

0
 
conceptdataAuthor Commented:
Some more info
	private static URL buildBaseURL(String directory) throws java.net.MalformedURLException
	{
		if (directory == null) return null;
		File dir = new File(directory);
		if (dir.isDirectory())
		{
			return dir.toURL();
		}
		else
		{
			URL baseURL = new URL(directory);
			return baseURL;
		}
	}

Open in new window

0
 
Wardy_01Commented:
erm .... I think its the logic in that switch statement in the main method.

// assuming cmdLineArgs.Arguments is a typical collection.
 switch (cmdLineArgs.Arguments.Count)
                    {
                        case 2: // if the collection has 2 args
                            // this condition will never be met
                            if (cmdLineArgs.HasUSERCONFIG && cmdLineArgs.HasFO && cmdLineArgs.HasPDF)
                            {

You appear to have replicated this problem right down the entire switch block.
cmdLineArgs.Arguments.Count will tell you how many args were specified, it's not a 0 based reply like in an indexor ...

cmdLineArgs.Arguments[0]   <--- returns first arg

//if you had only 1 arg in the collection
cmdLineArgs.Arguments[1]   <--- would not exist but ....

// should return 1 not 0 ....
int argsNum = cmdLineArgs.Arguments.Count


Hopefully this is your problem unless I misunderstand something, although I don't have your definition for the CommandLineArguments class.
0
 
conceptdataAuthor Commented:
I don't think it is my problem.
Because that the other parameter is used, and the PDF file as created, but the fonts I specify in the userconfig file as not embedded, as it should.

Attached the CommandLineArguments
using System;
 
namespace NFopApp
{
    public class CommandLineArguments
    {
        public const string USERCONFIG_KEY = "-c";
        public const string FO_KEY = "-fo";
        public const string XML_KEY = "-xml";
        public const string XSL_KEY = "-xsl";
        public const string PDF_KEY = "-pdf";
        public const string FOOUT_KEY = "-foout";
        protected string _USER_CONFIG_PARAM = null;
 
        protected System.Collections.Generic.Dictionary<string, string> _arguments = null;
 
        protected static System.Collections.Generic.Dictionary<string, string> validArguments = null;
 
 
        public CommandLineArguments(string[] args)
        {
            Parse(args);
        }
 
        public virtual System.Collections.Generic.Dictionary<string, string> GetValidArguments()
        {
            if (validArguments == null)
            {
                validArguments = new System.Collections.Generic.Dictionary<string, string>();
                validArguments.Add(USERCONFIG_KEY, USERCONFIG_KEY);
                validArguments.Add(FO_KEY        , FO_KEY);
                validArguments.Add(XML_KEY       , XML_KEY);
                validArguments.Add(XSL_KEY       , XSL_KEY);
                validArguments.Add(PDF_KEY       , PDF_KEY);
                validArguments.Add(FOOUT_KEY     , FOOUT_KEY);
            }
 
            return validArguments;
        }
 
        protected bool ParseShort(string[] tokens, System.Collections.Generic.Dictionary<string, string> arguments)
        {
            if (tokens.Length == 2)
            {
                string arg0 = PrepareToken(tokens[0]);
                string arg1 = PrepareToken(tokens[1]);
 
                if (IsEmptyToken(arg0) == false && IsEmptyToken(arg1) == false)
                {
 
                    if (arg0.ToLower().EndsWith(".fo")  && arg1.ToLower().EndsWith(".pdf"))
                    {
                        arguments.Add(FO_KEY, arg0);
                        arguments.Add(PDF_KEY, arg1);
 
                        return true;
                    }
                    else if (arg0.ToLower().EndsWith(".pdf") && arg1.ToLower().EndsWith(".fo"))
                    {
                        arguments.Add(PDF_KEY, arg0);
                        arguments.Add(FO_KEY, arg1);
 
                        return true;
                    }
                    else
                    {
                        arguments.Add(FO_KEY, arg0);
                        arguments.Add(PDF_KEY, arg1);
 
                        return true;
                    }
                }
            }
 
            return false;
        }
 
        protected void ParseFull(string[] tokens, System.Collections.Generic.Dictionary<string, string> arguments)
        {
            for (int token_index = 0; token_index < tokens.Length; token_index++)
            {
                string token = PrepareToken(tokens[token_index]);
 
                if (IsEmptyToken(token) == false)
                {
                    if (IsValidToken(token))
                    {
                        if (HasNextToken(token_index, tokens.Length))
                        {
                            token_index++;
 
                            string value = PrepareToken(tokens[token_index]);
 
                            if (IsEmptyToken(value) == false)
                            {
                                if (token == USERCONFIG_KEY)
                                {
                                    _USER_CONFIG_PARAM = value;
                                }
                                else
                                {
                                    arguments.Add(token, value);
                                }
                            }
                        }
                    }
                }
            }
        }
 
        public virtual void Parse(string[] tokens)
        {
            if (tokens != null)
            {
                if (tokens.Length > 0)
                {
                    int tokensLength = tokens.Length;
 
                    _arguments = new System.Collections.Generic.Dictionary<string, string>(tokensLength);
 
                    if (ParseShort(tokens, _arguments)==false)
                    {
                        ParseFull(tokens, _arguments);
                    }
 
                    if (HasArguments && HasUSERCONFIG==false)
                    { 
                      string NFOP_USER_CONFIG_PATH = PrepareToken(Environment.GetEnvironmentVariable("NFOP_USER_CONFIG_PATH"));
 
                      if (IsEmptyToken(NFOP_USER_CONFIG_PATH) == false)
                      {
                          this._USER_CONFIG_PARAM = NFOP_USER_CONFIG_PATH;
                      }
 
                    }
                }
            }
 
        }
 
        public virtual bool HasNextToken(int current_index, int tokensLength)
        {
            return current_index < tokensLength;
        }
 
        public virtual bool IsEmptyToken(string token)
        {
            return string.IsNullOrEmpty(token);
        }
 
        public virtual string PrepareToken(string token)
        {
            if (token != null)
            {
                return token.Trim().ToLower();
            }
 
            return token;
        }
 
 
        public System.Collections.Generic.Dictionary<string, string> Arguments
        {
            get { return _arguments; }
        }
 
        public virtual bool HasArguments
        {
            get
            {
                if (_arguments == null) return false;
 
                return _arguments.Count > 0;
            }
        }
 
        public bool IsValidToken(string key)
        {
            System.Collections.Generic.Dictionary<string, string> validArguments = GetValidArguments();
 
            return validArguments.ContainsKey(key);
        }
 
        protected virtual bool HasKeyAndValue(string key)
        {
            if (HasArguments)
            {
                if (_arguments.ContainsKey(key))
                {
                    return string.IsNullOrEmpty(_arguments[key]) == false;
                }
            }
 
            return false;
        }
 
        protected virtual string GetValue(string key)
        {
            if (HasKeyAndValue(key))
            {
                return _arguments[key];
            }
 
            throw new CommandLineArgumentException("error : command line argument", string.Format("command line parameter {0} is not set",key));
        }
 
        public bool HasUSERCONFIG
        {
            get
            {
 
                return string.IsNullOrEmpty(_USER_CONFIG_PARAM)==false;
            }
        }
 
        public bool HasFO
        {
            get
            {
 
                return HasKeyAndValue(FO_KEY);
            }
        }
 
        public bool HasXML
        {
            get
            {
 
                return HasKeyAndValue(XML_KEY);
            }
        }
 
        public bool HasXSL
        {
            get
            {
 
                return HasKeyAndValue(XSL_KEY);
            }
        }
 
 
        public bool HasPDF
        {
            get
            {
 
                return HasKeyAndValue(PDF_KEY);
            }
        }
 
        public bool HasFOOUT
        {
            get
            {
 
                return HasKeyAndValue(FOOUT_KEY);
            }
        }
 
        public string USERCONFIG
        {
            get
            {
 
                return _USER_CONFIG_PARAM;
            }
        }
 
        public string FO
        {
            get
            {
 
                return GetValue(FO_KEY);
            }
        }
 
        public string XML
        {
            get
            {
 
                return GetValue(XML_KEY);
            }
        }
 
        public string XSL
        {
            get
            {
 
                return GetValue(XSL_KEY);
            }
        }
 
 
        public string PDF
        {
            get
            {
 
                return GetValue(PDF_KEY);
            }
        }
 
        public string FOOUT
        {
            get
            {
 
                return GetValue(FOOUT_KEY);
            }
        }
 
        public override string ToString()
        {
            System.Text.StringBuilder output = new System.Text.StringBuilder();
 
            if (HasArguments)
            {
                if (this.HasUSERCONFIG)     output.AppendFormat("-c {0}{1}"     ,this.USERCONFIG, Environment.NewLine);
                if (this.HasFO)             output.AppendFormat("-fo {0}{1}"    ,this.FO        , Environment.NewLine);
                if (this.HasXML)            output.AppendFormat("-xml {0}{1}"   ,this.XML       , Environment.NewLine);
                if (this.HasXSL)            output.AppendFormat("-xsl {0}{1}"   ,this.XSL       , Environment.NewLine);
                if (this.HasFOOUT)          output.AppendFormat("-foout {0}{1}" ,this.FOOUT     , Environment.NewLine);
                if (this.HasPDF)            output.AppendFormat("-pdf {0}{1}"   ,this.PDF       , Environment.NewLine);
            }
            else
            {
                output.Append("no command line parameters.");
            }
 
            return output.ToString();
        }
    }
}

Open in new window

0
 
Wardy_01Commented:
Ok ... Looking at that the logic in the switch is in fact wrong which won't help.
Dam dude ... this code is overkill on the wordyness.

its only a string of name value pairs, why not try something like this ...

NameValueCollection arguments = new NameValueCollection();

public void Parse(string cmdArgs)
{
        string [] tokens = cmdArgs.Split(' ');
       
        foreach(string token in tokens)
        {
               string [] tokenParts = token.Split('=');
               // remove the "-" on the argument name.
               arguments.Add(tokenParts[0].SubString(1), tokenParts[1]);
        }
}

.............

Instead of all this "HasThis" and "HasThat" try this ...

if( arguments["Config"] != null && GetArguments["pdf"] != null )
{
       // do stuff
}

......

Much less code and will probably compile to cleaner MSIL.
All that code can go in the class that calls up your current CommandLineArguments class and you'll have your args right there local so you can do your switch on "arguments.Count" in Program.cs

the whole switch statement relies on the UserConfig param so you should do this ...

if(arguments["UserConfig"] != null)
{
        switch(arguments.count)
            .... and so on
}

...........

No need for a custom collection class and I simplified your switch :)
I think you will find your apps less confusing if you use less wordy code and it might help you pin your problem down.
0
 
Wardy_01Commented:
having looked at this some more it might be logically better if you nest a few if's instead of using the switch.

It seems to me that the switch isn't really a decision maker but more a way to group your if's.

I notice that half your ifs rely on "cmdLineArgs.HasXML" so you could do this to extend my previous example ...

if(arguments["UserConfig"] != null)
{
        // do stuff that only relies on userconfig param

        if(arguments["xml"] != null)
        {
                 // do stuff that uses both userconfig and xml params
        }
}
else
{
       // minimum param requirement not met
       throw new Exception("Not information provided to continue");
}
0
 
conceptdataAuthor Commented:
Okay I see what you mean.
But it dosn't solve my problem, that is the files arial.ttf / arial.xml don't have the right path, so the nfop.exe can't find them.

BUT in my visual studio, debugging the project, the files are found with normal paths
( example C:\database\arial.ttf and C:\database\arial.xml )
and the same if I publish the project to my Local IIS-server (Localhost), still with normal (Local) paths
0
 
conceptdataAuthor Commented:
I have tried a workaround :
UserConfig.xml :
               <font metrics-file="http://checkpoint.c5style.dk/Global_Fonts/code39.xml"
               embed-file="http://checkpoint.c5style.dk/Global_Fonts/code39.ttf" kerning="yes">
              <font-triplet name="code39" style="normal" weight="normal"/>
              </font>
--- This works at localhost. Result : PDF file with the right font
--- But at the webserver. Result : no pdf at all.

Then I changed userconfig.xml to :
               <font metrics-file="checkpoint.c5style.dk/Global_Fonts/code39.xml"
               embed-file="checkpoint.c5style.dk/Global_Fonts/code39.ttf" kerning="yes">
              <font-triplet name="code39" style="normal" weight="normal"/>
              </font>
--- This works at localhost. Result : PDF file withOUT the right font
--- But at the webserver. Result : PDF file withOUT the right font
0
 
conceptdataAuthor Commented:
Hi again

I Found the error. Something about the font embedding.
You have helped med a lot Wardy_01, so the points is yours
0
 
Wardy_01Commented:
Hmmm ... ok ....

Well at least you got there in the end that's the main thing.
I still think that code should be reshuffled a bit though, it looks heavy when it's really not that complex.

Good luck with it.
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

  • 12
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now