Pass Parameters to ClickOnce Using ShellExecute - c#

I was attempting to use this Blog to pass an argument to an offline click-once application. Near the bottom of the blog there are example programs to download. I downloaded and published the program "TestRunningWithArgs" the C# version.
Now I am trying to pass an argument to the application which is not working. It keeps saying no "No arguments passed in".
I am trying to use the following code to pass an argument:
shellexecute("File Path\My Applicaiton.application","MyArgument")
This code runs the application but the sample application states it did not receive an argument. The language is visual basic (maybe 4 or 6?).
The code below works and allows internet explorer to run and a specific file be opened from sharepoint and I was wondering if there is a difference that I am missing.
shellexecute("C:\Program Files\Internet Explorer\iexplore.exe",FileLocation)
The only one I see is that the click once is a .application file vs a .exe and is there a way to get this to work?
Below is the code for the click once application, just copied from the supplied example program on the blog
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
GetArgsToShow();
}
/// Get the arguments and show them on the screen.
private void GetArgsToShow()
{
// Get the ActivationArguments from the SetupInformation property of the domain.
string[] activationData =
AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData;
if (activationData != null && activationData.Length > 0)
{
//querystring starts with ?; file association starts with "file:"
if (activationData.Length == 1 && activationData[0].Substring(0, 1) == "?")
{
ProcessQueryString(activationData);
}
else if (activationData.Length == 1 && activationData[0].Length >= 5 && activationData[0].Substring(0,5).ToLower() == #"file:")
{
ProcessFileAssociation(activationData);
}
else
{
ProcessCSVParameters(activationData);
}
}
else
{
if (activationData == null)
{
lstArgs.Items.Add("No arguments passed in.");
}
else
{
lstArgs.Items.Add(String.Format("Number of args = {0}", activationData.Length));
}
}
}
/// Convert a query string into Name/Value pairs and process it.
private void ProcessQueryString(string[] activationData)
{
NameValueCollection nvc =
System.Web.HttpUtility.ParseQueryString(activationData[0]);
//Get all the keys in the collection, then pull the values for each of them.
//I'm only passing each key once, with one value.
string[] theKeys = nvc.AllKeys;
foreach (string theKey in theKeys)
{
string[] theValue = nvc.GetValues(theKey);
lstArgs.Items.Add(string.Format("Key = {0}, Value = {1}", theKey, theValue[0]));
}
}
/// Process what you would get if you set up a file association,
/// and the user double-clicked on one of the associated file.
private void ProcessFileAssociation(string[] activationData)
{
//This is what you get when you set up a file association and the user double-clicks
// on an associated file.
Uri uri = new Uri(activationData[0]);
lstArgs.Items.Add(uri.LocalPath.ToString());
}
/// Process a comma-delimited string of values. Not: can't have spaces or double-quotes in the string,
/// it will only read the first argument.
private void ProcessCSVParameters(string[] activationData)
{
//I have to say here that I've only ever seen 1 entry passed in activationData,
// but I'm checking for multiples just in case.
//This takes each entry and splits it by comma and separates them into separate entries.
char[] myComma = { ',' };
foreach (string arg in activationData)
{
string[] myList = activationData[0].Split(myComma, StringSplitOptions.RemoveEmptyEntries);
foreach (string oneItem in myList)
lstArgs.Items.Add(oneItem);
}
}
}
EDIT
Well I tried accessing the .exe located in "C:\Users\userName\AppData\Local\Apps\2.0\5G9CGPWV.6O3\X7YPB07N.2Q2\test..tion_0000000000000000_0001.0000_03232931d88a66c9\" which did not work.

Found the file you have to call to send an argument.
shellexecute("C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\(Publisher Name)\My Application.appref-ms", Arguement)
The publisher name is specified in visual studio Publish Tab, options and then Publisher Name. This is also the Start Menu Folder where your program can be launched from.

Related

C# FolderBrowserDialog - how to include shared folders

I create a FolderBrowserDialog as follows (only an excerpt -not complete code):
string tempSetWorkingPath = null;
try
{
FolderBrowserDialog folderDlg = new System.Windows.Forms.FolderBrowserDialog();
folderDlg.ShowNewFolderButton = true;
folderDlg.Description = "Selected your working folder. This is where your PDF files will be saved.";
folderDlg.RootFolder = Environment.SpecialFolder.MyComputer;
folderDlg.SelectedPath = (Convert.ToString(WorkingPath).Trim().Length == 0) ? ((int)Environment.SpecialFolder.MyComputer).ToString() : WorkingPath;
if (folderDlg.ShowDialog() == DialogResult.OK)
{
tempSetWorkingPath = folderDlg.SelectedPath;
}
else
{
tempSetWorkingPath = "";
}
}
...
The code works well, except the only folders that are showing are the local folders. Users have DropBox and OneDrive shared folders on their systems and to select one of those directories, the user needs to cycle through the windows user directories and select the folder from there. On some systems I have seen over the last few months, I've seen the DropBox and OneDrive directories appear below the DeskTop directory ... but I have not, despite hours of searching - found a way to achive that.
How can I achieve that?
MTIA
DWE
Given I have observed a large number of queries posted here and elsewhere regarding the inclusion of the directories, including shared directories and given the response by # Mailosz, it seems that the root folder property of the folder dialog holds the key - it Gets or sets the root folder where the browsing starts from and thats what my code was missing.
The full code to the function referred to in my question appears below, in the event it assists someone else.
/// <summary>
/// presents the user with a folder dialog
/// Returns a full qualified directory chosen by the user
/// </summary>
/// <param name="WorkingPath">if a fully qualified directory name is provided, then the folder structure in the folder dialog will open to the directory selected</param>
/// <returns>Returns a full qualified directory chosen by the user or if no directory was chosen, an empty string</returns>
public string SetWorkingPath(string WorkingPath)
{
string tempSetWorkingPath = null;
try
{
FolderBrowserDialog folderDlg = new System.Windows.Forms.FolderBrowserDialog();
// check our proposed working path and if its valid
if((!string.IsNullOrEmpty(WorkingPath) && (WorkingPath != null)))
{
if (!Directory.Exists(WorkingPath))
WorkingPath = string.Empty;
}
else // if we are empty or null set us to empty
{
WorkingPath = string.Empty;
}
folderDlg.ShowNewFolderButton = true;
folderDlg.Description = "Please select your working folder. This is where your PDF files will be saved.";
folderDlg.RootFolder = Environment.SpecialFolder.Desktop;//.MyComputer;
folderDlg.SelectedPath = (Convert.ToString(WorkingPath).Trim().Length == 0) ? ((int)Environment.SpecialFolder.MyComputer).ToString() : WorkingPath;
if (folderDlg.ShowDialog() == DialogResult.OK)
{
// make sure we have a backslash on the end of our directory string
tempSetWorkingPath = PathAddBackslash(folderDlg.SelectedPath);
}
else
{
// return an empty string
tempSetWorkingPath = string.Empty;
}
}
catch (Exception ex)
{
tempSetWorkingPath = string.Empty;
throw (ex);
}
return tempSetWorkingPath;
}
public string PathAddBackslash(string path)
{
// They're always one character but EndsWith is shorter than
// array style access to last path character. Change this
// if performance are a (measured) issue.
string separator1 = Path.DirectorySeparatorChar.ToString();
string separator2 = Path.AltDirectorySeparatorChar.ToString();
// Trailing white spaces are always ignored but folders may have
// leading spaces. It's unusual but it may happen. If it's an issue
// then just replace TrimEnd() with Trim(). Tnx Paul Groke to point this out.
path = path.TrimEnd();
// Argument is always a directory name then if there is one
// of allowed separators then I have nothing to do.
if (path.EndsWith(separator1) || path.EndsWith(separator2))
return path;
// If there is the "alt" separator then I add a trailing one.
// Note that URI format (file://drive:\path\filename.ext) is
// not supported in most .NET I/O functions then we don't support it
// here too. If you have to then simply revert this check:
// if (path.Contains(separator1))
// return path + separator1;
//
// return path + separator2;
if (path.Contains(separator2))
return path + separator2;
// If there is not an "alt" separator I add a "normal" one.
// It means path may be with normal one or it has not any separator
// (for example if it's just a directory name). In this case I
// default to normal as users expect.
return path + separator1;
}

full path as the filename

Maybe someone knows a simple solution to my problem.
I do not know the entry of the file so it's not a static value.
It can be changed through the BizTalk gui and there we have a URI through the receiveport. But I do not believe it's accessible that easy. What I want to do is write out the full path as the filename. It works well with the messageID where the file is given a specific filepath name. But the Path-Name where the file was dropped is not working that well.
I keep getting this error :
Message:
Object reference not set to an instance of an object.
the message resource is present but the message is not found in the string/message table
-Does not say me much
Below you can see a snip from my code
internal static string UpdateMacroPathProperty(IBaseMessage baseMessage, string macroPathProperty, string macroDefsFile)
{
if (macroName == "MessageID")
{
contextPropertyValue = baseMessage.MessageID.ToString();
}
else if (macroName == "SourceFileName")
{
contextPropertyValue = Directory.GetCurrentDirectory();
}
}
This is an specific created pipeline. Has anyone encountered this problem or can point me in the right way.
I know that BizTalk has a built in function for this, BizTalk Server: List of Macros as the %SourceFileName% but I'm trying to save this as logs in a specific map structure so that it does not get processed.
It's adapter dependent; some adapters will use the FILE adapter's namespace even though they're not the file adapter, but this is the kind of logic that I've used in the past for this:
string adapterType = (string)pInMsg.Context.Read("InboundTransportType",
"http://schemas.microsoft.com/BizTalk/2003/system-properties");
string filePath = null;
if (adapterType != null)
{
if (adapterType == "FILE")
{
filePath = (string)pInMsg.Context.Read("ReceivedFileName",
"http://schemas.microsoft.com/BizTalk/2003/file-properties");
}
else if (adapterType.Contians("SFTP") && !adapterType.Contains("nsoftware"))
// nsoftware uses the FTP schema
{
filePath = (string)pInMsg.Context.Read("ReceivedFileName",
"http://schemas.microsoft.com/BizTalk/2012/Adapter/sftp-properties");
}
else if (adapterType.Contains("FTP"))
{
filePath = (string)pInMsg.Context.Read("ReceivedFileName",
"http://schemas.microsoft.com/BizTalk/2003/ftp-properties");
}
}
And then you can just fall back to the MessageID if you can't get the file path from any of these.

Spaces in filepath cause multiple instances of my application to appear when executed via Windows Context Menu

I've created a WPF Form application that can be called via the Windows Context menu. The application works great when I debug it. When I deploy it and right click on a file, if it has any spaces in the path, it only reads the path up to the space, but opens up a window for each space in the path. This is very annoying and I'm not sure how to fix this.
I've tried using Environment.GetCommandLineArgs() in my method as well as just using MainWindow(string filepath); both methods create the same problem.
This is a ClickOnce application so not sure if this would have anything to do with it, but I do capture the directory location of the executing assembly when it gets installed for the first time and have it update the registry in the HKEY_CLASSES_ROOT*\shell[APP}\command key. The default value is an expanded string with the location of the ClickOnce App executable and I have added "%1" so the filepath can be passed into it as an argument.
void checkRegistry()
{
RegistryKey baseKey=Registry.ClassesRoot.CreateSubKey("*\\shell", RegistryKeyPermissionCheck.ReadWriteSubTree);
//add the key
RegistryKey menuKey=baseKey.CreateSubKey("GetCRC");
menuKey.SetValue("", "Get CRC");
//add the command key
RegistryKey commandKey = menuKey.CreateSubKey("command");
string appfilePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
commandKey.SetValue("",String.Format("{0}\\GetCRC2.exe %1",appfilePath), RegistryValueKind.ExpandString);
commandKey.Close();
menuKey.Close();
baseKey.Close();
}
public MainWindow(string filePath)
{
InitializeComponent();
//check registry and add menu option
checkRegistry();
var args = Environment.GetCommandLineArgs();
if (args.Count() > 1)
{
this.filepath = args[1];
}
else
{
//run the file signatures
this.filepath = filePath;
}
textboxFilePath.Text = filepath;
calcSignatures();
}
public MainWindow()
{
InitializeComponent();
//check registry and add menu option if it doesn't exist
checkRegistry();
}
Try putting quotes around application name and file name:
string.Format("\"{0}\\GetCRC2.exe\" \"%1\"",appfilePath)
if the file is named "long hair"
args[1] will be "long" and args[2] will be "hair"
You should either input the filename in quotes or do something to deal with all the user input from the command line, like I dunno...
for args.length keep adding args and a space to the filename variable.
Sorry I'm not writing actual code, I barely know any c#

C# - Method For Determining If Arguments Have Been Passed Fails

I am creating a Windows Forms Application with c# that can open up a file on startup if it is passed an argument containing the path to the file.
However, it doesn't accurately determine if arguments have been passed. Even when I pass no arguments, it still tries to open up a file.
Here's my code:
string[] args = Environment.GetCommandLineArgs();
if (args == null || args.Length == 0)
{
}
else
{
try
{
ListData ld = new LmReader.LmReader().readLmList(args[0]);
listItemsList.Items.Clear();
foreach (ListItemList li in ld.lil)
{
ListViewItem lvi = new ListViewItem(li.text);
lvi.Font = li.itemFont;
listItemsList.Items.Add(lvi);
}
filenameOpen = selectOpenLocation.FileName;
this.Text = "List Maker - " + Path.GetFileNameWithoutExtension(args[0]);
}
catch (Exception ex)
{
new Error().doError("Your list could not be opened.", ex);
}
}
What am I doing wrong?
Environment.GetCommandLineArgs() always at least returns one argument which is the excecutable file name and then contains the arguments you might have passed in.
So that's why your if condition nether matches
See documentation
From the docs:
The first element in the array contains the file name of the executing
program
Therefore
args.Length == 0
should be
args.Length <= 1
in your case.

If statement help ; different color to certain criteria

Im a beginner, and If statements are my weakness. I have a simple program that displays files names that are located in a certain folder. However, some files might have lines that begin with LIFT. I want to catch those files that have that certain line, and display the file name in a different color (preferably red). Here is what I have so far: Any assistance would be greatly appreciated!! Thanks!
public partial class ShippedOrders : System.Web.UI.Page
{
class Program
{
static void Main()
{
string[] array1 = Directory.GetFiles(#"C:\Kaplan\Replies\");
string[] array2 = Directory.GetFiles(#"C:\Kaplan\Replies\", "*.REP");
Console.WriteLine("---Files:---");
foreach (string name in array1)
{
Console.WriteLine(name);
}
Console.WriteLine("---REP Files: ---");
foreach (string name in array2)
{
Console.WriteLine(name);
}
}
}
}
Directory.GetFiles(directoryPath) will return an array of strings listing the file names (full paths) within that directory. You're going to have to actually open and read each file, using the string array returned. Read each file line by line in a loop and test if any lines begins with "LIFT".
Also the way you set up your code-behind for this webpage is funky. You're declaring a class inside the partial class of the page. Try setting up your code like this:
public partial class ShippedOrders : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
this.goFiles();
}
public void goFiles()
{
string[] array1 = Directory.GetFiles(#"C:\Kaplan\Replies\");
string[] array2 = Directory.GetFiles(#"C:\Kaplan\Replies\", "*.REP");
System.IO.StreamReader file = null;
string line = "";
bool hasLIFT = false;
Response.Write("---Files:---<br/>");
foreach (string name in array1)
{
file = new System.IO.StreamReader(#name);
while((line = file.ReadLine()) != null)
{
if(line.StartsWith("LIFT"))
{
hasLIFT = true;
break;
}
}
if(hasLIFT)
{
Response.Write("<span style=\"color:Red;\">" + name + "</span><br/>";
hasLIFT = false;
}
else
Response.Write(name + "<br/>";
}
//and can do the same for other array
}
}
You can change the console output color by using the Console.ForegroundColor property.
To know if the file contains the text you want, you need to open it and scan the file.
Then do this:
if (fileContainsText) Console.ForegroundColor = ConsoleColor.Red;
else Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(name);
EDIT
I didn't notice you were trying to write to Console inside an ASP.NET server page... in that case you need to tell us what kind of app you are creating... is it a Console application, a WebApplication or a Website... it depends.
The use of Console is not suited for web applications.
EDIT 2
By the way, you may use the Console only in console applications. A console application is a stand-alone windows application, that is different from a web application.
If you ever want to create a console app, in the New Project window, you can find it under Windows category, then you can find a project type called Console Application.
You can do like this inside your foreach loop:
if(name.contains("LIFT"))
{
//make red.
}
it does though have the issue that it only checks if the string (name) contains the string LIFT, and not if the string is in the beginning of the filename. If you want to check if LIFT is in the beggining of the file name you must use some of the Trim methods.

Categories

Resources