I am building a C# application that handles a custom protocol used in my web application.
The links are like:
Print
These are handled using a handler in the windows registry (URL:zebra-wp Protocol):
"C:\Program Files (x86)\[My App Name]\[My App].exe" "%1"
I am running the following code in my app:
class LabelData
{
public string name;
public string barcode;
}
static class Program
{
[STAThread]
static void Main(string[] args)
{
if (args.Length > 0 && args[0].StartsWith("zebra-wp://"))
{
// retrieve data from argument
string argData = args[0].Remove(0, 11);
string decodedJson = "";
try
{
// Undo URL Encoding
decodedJson = WebUtility.UrlDecode(argData);
}
catch (Exception ex)
{
string msg = "Couldn't print label, failed to decode data.";
msg += "\nData: " + argData;
msg += "Error: " + ex.Message;
MessageBox.Show(msg);
Application.Exit();
}
// Unpack JSON string
LabelData decodedData = new LabelData();
try
{
decodedData = JsonConvert.DeserializeObject<LabelData>(decodedJson);
}
catch (Exception ex)
{
string msg = "Couldn't print label, failed to unpack data.";
msg += "\nData: " + decodedJson;
msg += "Error: " + ex.Message;
MessageBox.Show(msg);
Application.Exit();
}
// Do things with object
When I debug the application I enter the link URL into the "Command line arguments" start up option.
The program works as expected and the JSON data is successfully decoded.
When I build and install, the JsonConvert.DeserializeObject function gives me the following error:
Data: {"barcode":"000063","name":"Food Fun - Magnetic Multicultural set"}
Error: Unexpected end while parsing comment. Path '', line 1, position 68.
Is something different about how VS launches an app with command line arguments in debug?
Is there a way to debug the application with the same command line arguments as when I click the URL?
I have found the issue, apparently when passing URI's to custom protocol handlers, Windows adds a trailing forward slash to the URI, checking for this in the code and removing it solves the problem.
Related
I have an application written in C# MVC 4, which will run on server, that has one certificate inside the project, in the App_Data folder. I need to get this certificate file to access a Web Service. The server is a Windows Server 2012, using iis7.
The code runs as expected locally, but it does not work on the server. There I receive the message "The system cannot find the file specified". But this file IS there (I return the content of this directory and the previous one, getting them on the browser's console).
I tried to rename the certificate from .pfx to .pcertx (a random one) and doesn't work on the server again, although it works locally.
Here's the code I'm using to try to get this file:
public string getCertificado()
{
string path = string.Empty;
try
{
path = HttpContext.Current.Server.MapPath(#"~\App_Data\CERTIFICATE.pcertx");
Byte[] rawCert = File.ReadAllBytes(path);
String certificado = Convert.ToBase64String(rawCert);
_X509Cert.Import(Convert.FromBase64String(certificado), "PASSWORD", X509KeyStorageFlags.PersistKeySet);
client.AddCerts(new X509Certificate[] { _X509Cert });
return string.Empty;
}
catch (Exception ex)
{
// In case of error, list the content of the current directory and the previous
string[] filePaths = Directory.GetFiles(HttpContext.Current.Server.MapPath(#"~\App_Data"));
string pastaAnterior = Path.GetFullPath(Path.Combine(HttpContext.Current.Server.MapPath(#"~\App_Data"), #"..\"));
string[] filePathsAnt = Directory.GetFiles(pastaAnterior);
return "Cannot get certificate." + ex.Message + "; " + ex.InnerException + "; Path: " + path + "; Folder content: " + string.Join("\n",filePaths) + "; Previous folder content" + string.Join("\n",filePathsAnt);
}
}
This is what I get from the browser's console:
"Não foi possível obter nenhum certificado.
The system cannot find the file specified.
Path: C:\Unisys\Management\Applications\sicopplustest\App_Data\CERTIFICATE.pcertx;
Caminho pasta:
C:\Unisys\Management\Applications\sicopplustest\App_Data\CERTIFICATE.pcertx
C:\Unisys\Management\Applications\sicopplustest\App_Data\DynamicAspx.xsl;
Caminho pasta anteriorC:\Unisys\Management\Applications\sicopplustest\ApplicationInfo.Debug.xml
C:\Unisys\Management\Applications\sicopplustest\ApplicationInfo.Release.xml
C:\Unisys\Management\Applications\sicopplustest\ApplicationInfo.xml
..."
If I got the certificate properly, no message would be sent.
I think it may be related to security, but how can I fix it? I don't know how to procede with this situation.
i've got a bit of a problem trying to set up a general error page in MVC.
I am handling all app errors in Global.asax.cs with the following code ->
protected void Application_Error(object sender, EventArgs e)
{
//if (Request.Url.ToString().StartsWith("http://localhost:"))
// return;
string msg;
Exception ex = Server.GetLastError().GetBaseException();
StringBuilder sb = new StringBuilder();
sb.AppendLine("Exception Found");
sb.AppendLine("Timestamp: " + System.DateTime.Now.ToString());
sb.AppendLine("Error in: " + Request.Url.ToString());
sb.AppendLine("Browser Version: " + Request.UserAgent.ToString());
sb.AppendLine("User IP: " + Request.UserHostAddress.ToString());
sb.AppendLine("Error Message: " + ex.Message);
sb.AppendLine("Stack Trace: " + ex.StackTrace);
msg = sb.ToString();
Server.ClearError();
Response.Redirect(string.Format("~/Error/Error?w={0}", msg ));
}
My problem is that i'm not getting a redirect. I see the same page URL and a blank page when i'm creating an error.
If i remove "errorMsg" and add a SIMPLE STRING, it works, redirects with the required param. Ex:
string test = "testme";
Response.Redirect(string.Format("~/Error/Error?w={0}", test));
That does redirect me to the error page with param "testme". What am i doing wrong here?
You to need escape all the parameters (UrlEncode). At the moment it is unescaped and has a whole bunch of new lines too.
Before you do that, I suggest you just append "hello world" parameter and re-display that to ensure your redirect page is working
We're developing a Click-Once WPF Windows Application that retrieves all its data from a database. I implemented a Form where a User could enter the corresponding data and using a SqlConnectionStringBuilder we build the Connection String and that works just fine.
We then add the Connection String to the ConfigurationManager using
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
If we use some other ConfigurationUserLevel, the application crashes (I don't know why yet, but I believe the Entity Framework Model tries to load the connection string and doesn't find it, because the file is not stored in the correct User Level?). Now, we store the connection string in a separate file and load it in App.config so we don't have to check it into Version Control:
<connectionStrings configSource="connections.config"/>
We don't deploy this file because it contains our own development connection strings. Rather, we create an empty file for deployment where the user-entered connection string will be stored. This works completely fine.
Our problem is that with a click-once update, the file will be "lost". What is the best way to store persistent per-user connection strings encrypted in a configuration file? Or should we completely switch to Registry? Or create our own encrypted File somewhere outside the %APPDATA%/Local/Apps/2.0/...../ folders and load it manually when initializing the Entity Framework Context?
You can go to MSDN site it might help you
https://msdn.microsoft.com/en-us/library/dd997001.aspx
with the help of below code, you need to modify this code for your requirement, hope this will help.
To create a custom ClickOnce application installer
In your ClickOnce application, add references to System.Deployment and System.Windows.Forms.
Add a new class to your application and specify any name. This walkthrough uses the name MyInstaller.
Add the following Imports or using statements to the top of your new class.
using System.Deployment.Application;
using System.Windows.Forms;
Add the following methods to your class.
These methods call InPlaceHostingManager methods to download the deployment manifest, assert appropriate permissions, ask the user for permission to install, and then download and install the application into the ClickOnce cache. A custom installer can specify that a ClickOnce application is pre-trusted, or can defer the trust decision to the AssertApplicationRequirements method call. This code pre-trusts the application
Note:- Permissions assigned by pre-trusting cannot exceed the permissions of the custom installer code.
InPlaceHostingManager iphm = null;
public void InstallApplication(string deployManifestUriStr)
{
try
{
Uri deploymentUri = new Uri(deployManifestUriStr);
iphm = new InPlaceHostingManager(deploymentUri, false);
}
catch (UriFormatException uriEx)
{
MessageBox.Show("Cannot install the application: " +
"The deployment manifest URL supplied is not a valid URL. " +
"Error: " + uriEx.Message);
return;
}
catch (PlatformNotSupportedException platformEx)
{
MessageBox.Show("Cannot install the application: " +
"This program requires Windows XP or higher. " +
"Error: " + platformEx.Message);
return;
}
catch (ArgumentException argumentEx)
{
MessageBox.Show("Cannot install the application: " +
"The deployment manifest URL supplied is not a valid URL. " +
"Error: " + argumentEx.Message);
return;
}
iphm.GetManifestCompleted += new EventHandler<GetManifestCompletedEventArgs>(iphm_GetManifestCompleted);
iphm.GetManifestAsync();
}
void iphm_GetManifestCompleted(object sender, GetManifestCompletedEventArgs e)
{
// Check for an error.
if (e.Error != null)
{
// Cancel download and install.
MessageBox.Show("Could not download manifest. Error: " + e.Error.Message);
return;
}
// bool isFullTrust = CheckForFullTrust(e.ApplicationManifest);
// Verify this application can be installed.
try
{
// the true parameter allows InPlaceHostingManager
// to grant the permissions requested in the applicaiton manifest.
iphm.AssertApplicationRequirements(true) ;
}
catch (Exception ex)
{
MessageBox.Show("An error occurred while verifying the application. " +
"Error: " + ex.Message);
return;
}
// Use the information from GetManifestCompleted() to confirm
// that the user wants to proceed.
string appInfo = "Application Name: " + e.ProductName;
appInfo += "\nVersion: " + e.Version;
appInfo += "\nSupport/Help Requests: " + (e.SupportUri != null ?
e.SupportUri.ToString() : "N/A");
appInfo += "\n\nConfirmed that this application can run with its requested permissions.";
// if (isFullTrust)
// appInfo += "\n\nThis application requires full trust in order to run.";
appInfo += "\n\nProceed with installation?";
DialogResult dr = MessageBox.Show(appInfo, "Confirm Application Install",
MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
if (dr != System.Windows.Forms.DialogResult.OK)
{
return;
}
// Download the deployment manifest.
iphm.DownloadProgressChanged += new EventHandler<DownloadProgressChangedEventArgs>(iphm_DownloadProgressChanged);
iphm.DownloadApplicationCompleted += new EventHandler<DownloadApplicationCompletedEventArgs>(iphm_DownloadApplicationCompleted);
try
{
// Usually this shouldn't throw an exception unless AssertApplicationRequirements() failed,
// or you did not call that method before calling this one.
iphm.DownloadApplicationAsync();
}
catch (Exception downloadEx)
{
MessageBox.Show("Cannot initiate download of application. Error: " +
downloadEx.Message);
return;
}
}
/*
private bool CheckForFullTrust(XmlReader appManifest)
{
if (appManifest == null)
{
throw (new ArgumentNullException("appManifest cannot be null."));
}
XAttribute xaUnrestricted =
XDocument.Load(appManifest)
.Element("{urn:schemas-microsoft-com:asm.v1}assembly")
.Element("{urn:schemas-microsoft-com:asm.v2}trustInfo")
.Element("{urn:schemas-microsoft-com:asm.v2}security")
.Element("{urn:schemas-microsoft-com:asm.v2}applicationRequestMinimum")
.Element("{urn:schemas-microsoft-com:asm.v2}PermissionSet")
.Attribute("Unrestricted"); // Attributes never have a namespace
if (xaUnrestricted != null)
if (xaUnrestricted.Value == "true")
return true;
return false;
}
*/
void iphm_DownloadApplicationCompleted(object sender, DownloadApplicationCompletedEventArgs e)
{
// Check for an error.
if (e.Error != null)
{
// Cancel download and install.
MessageBox.Show("Could not download and install application. Error: " + e.Error.Message);
return;
}
// Inform the user that their application is ready for use.
MessageBox.Show("Application installed! You may now run it from the Start menu.");
}
void iphm_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
// you can show percentage of task completed using e.ProgressPercentage
}
To attempt installation from your code, call the InstallApplication method. For example, if you named your class MyInstaller, you might call InstallApplication in the following way.
MyInstaller installer = new MyInstaller();
installer.InstallApplication(#"\\myServer\myShare\myApp.application");
MessageBox.Show("Installer object created.");
I am trying to catch an exception when my XSD is invalid and just display a message on the console detailing to the user what went wrong. However the message that is displayed on the console is not as I expected.
try
{
// doing stuff here
}
catch (XmlException e)
{
Console.WriteLine("ERROR: Schema " + e.Message);
return false;
}
I expected the output to be something like:
"ERROR: Schema ' is an unexpected token. The expected token is '>'. Line 15, position 38."
However the output that I get is:
"' is an unexpected token. The expected token is '>'. Line 15, position 38."
My string at the beginning is not displayed before the message.
I have tried storing the values in two strings and tried concatenating those 2 string with no success. Ideally I would like one string that contains the concatenation of both the 'ERROR' part and the message produced by the exception.
I think your schema contains a newline. The text ERROR: Schema ' must be somewhere higher in the output window.
You can check this using:
catch (XmlException e)
{
string message = "ERROR: Schema " + e.Message;
message = message.Replace(Environment.NewLine, "");
message = message.Replace("\n", "");
message = message.Replace("\r", "");
Console.WriteLine(message);
return false;
}
Try with:
try
{
// doing stuff here
}
catch (XmlException e)
{
errorMessage = "ERROR: Schema " + e.Message.toString();
Console.WriteLine(errorMessage );
return false;
}
I have a sync software, which loads CSV files from "Incoming" folder, processes them and then moves them to the "Archive" folder.
Today, I saw the following error with this sync software:
[23/06/2014 00:06:04 AM] : Failed to move file from
D:\IBI_ORDER_IMPORTER_FTP_SERVER\Template3\Fifty &
Dean\Incoming\5A040K___d6f1ca45937b4ceb98d29d0db4601bf4.csv to
D:\IBI_ORDER_IMPORTER_FTP_SERVER\Template3\Fifty &
Dean\Archive\5A040K___d6f1ca45937b4ceb98d29d0db4601bf4.csv - Could not
find a part of the path.
Here's a snippet taken out of the sync software, where the file is processed and moved:
public static void ProcessSingleUserFile(Int32 TemplateId, String ImportedBy, String FilePath)
{
// Always Rename File To Avoid Conflict
string FileName = Path.GetFileNameWithoutExtension(FilePath);
String NewFilePath = FilePath.Replace(FileName, Utils.RandomString() + "___" + FileName);
File.Move(FilePath, NewFilePath);
FilePath = NewFilePath;
// Log
SyncUtils.ConsoleLog(String.Format("Processing [ {0} as {1} ] By [ {2} ] On Template [ #{3} ]",
FileName + ".csv",
Path.GetFileName(FilePath),
ImportedBy,
TemplateId));
// Init
List<OrderDraft> myOrderDrafts = new List<OrderDraft>();
// Parsed Based On Template Id
if (TemplateId == Settings.Default.Multi_Order_Template_Id)
{
// Try Parse File
myOrderDrafts = Utils.ParseMultiImportFile(TemplateId, ImportedBy, FilePath, true);
}
else
{
// Try Parse File
myOrderDrafts.Add(Utils.ParseImportFile(TemplateId, ImportedBy, FilePath, true));
}
// Process Orders
foreach (OrderDraft myOrderDraft in myOrderDrafts)
{
/* code snipped */
}
// Archive File
File.Move(FilePath, FilePath.Replace("Incoming", "Archive"));
}
Any idea what this error means? and how to circumvent it?
I wrote a cut down version of the above to test this in a controlled environment and I am not getting the error with this code:
static void Main(string[] args)
{
try
{
string baseDir = #"C:\Users\Administrator\Desktop\FTP_SERVER\Template3\Fifty & Dean\Incoming\";
string[] filePaths = Directory.GetFiles(baseDir, "*.csv");
foreach (string filePath in filePaths)
{
// do some work here ...
// move file
string newFilePath = filePath.Replace("Incoming", "Archive");
File.Move(filePath, newFilePath);
Console.WriteLine("File successfully moved");
}
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
Console.ReadKey();
}
You need to include the checks to make sure that the paths exist at runtime and check the output, something very simple like:
if(!Directory.Exists(Path.GetDirectoryName(filePath)))
{
Console.WriteLine("filePath does not exist: " + filePath);
}
if(!Directory.Exists(Path.GetDirectoryName(newFilePath)))
{
Console.WriteLine("newFilePath does not exist: " + newFilePath);
}
File.Move(filePath, newFilePath);
The reason I am suggesting this method is due to a possibility that the paths momentarily become available or not under the multi-tasking OSs depending on a multitude of factors: network connectivity, permissions (pushed down by GPO at any time), firewall rules, AV exclusions getting blown away etc. Even running low on CPU or RAM may create issues. In short, you never know what exactly occurred when your code was running if you are only checking the paths availability after the fact.
Or if your issue is intermittent, you can try and catch the error and write information to some sort of a log similarly to below:
try
{
File.Move(filePath, newFilePath);
}
catch(Exception ex)
{
if(!Directory.Exists(Path.GetDirectoryName(filePath)))
{
Console.WriteLine("filePath does not exist: " + filePath);
}
if(!Directory.Exists(Path.GetDirectoryName(newFilePath)))
{
Console.WriteLine("newFilePath does not exist: " + newFilePath);
}
}
"Could not find a part of the path" exception could also thrown from File.Move if argument used was longer than MAX_PATH (260) in .NET Framework.
So I prepend the path I used with long path syntax before passing to File.Move and it worked.
// Prepend long file path support
if( !packageFile.StartsWith( #"\\?\" ) )
packageFile = #"\\?\" + packageFile;
See:
How to deal with files with a name longer than 259 characters?
I have this
Could not find a part of the path
happened to me when I
File.Move(mapfile_path , Path.Combine(newPath, mapFile));
. After some testing, I find out our server administrator has blocked any user application from writing to that directory in that [newPath]!
So, right click on that directory to observe the rights matrix on Security tab to see anything that would block you.
Another cause of DirectoryNotFoundException "could not find a part of the path" thrown by File.Move can be spaces at the end of the directory name. Consider the following code:
string destinationPath = "C:\\Folder1 "; //note the space on the end
string destinationFileNameAndPath = Path.Combine(destinationPath, "file.txt");
if (!Directory.Exists(destinationPath))
Directory.CreateDirectory(destinationPath);
File.Move(sourceFileNameAndPath, destinationFileNameAndPath);
You may expect this code to succeed, since it creates the destination directory if it doesn't already exist, but Directory.CreateDirectory seems to trim the extra space on the end of the directory name, whereas File.Move does not and gives the above exception.
In this circumstance, you can workaround this by trimming the extra space yourself, e.g. (depending on how you load your path variable, the below is obviously overkill for a hard-coded string)
string destinationPath = "C:\\Folder1 ".Trim();