I need to open files of different types with their associated application. It works fine like this:
System.Diagnostics.Process.Start(#"C:\foo.jpg");
But when I need to open it with a specific user, I need to supply an executable, I can't open a document/image etc. ("The specified executable is not a valid application for this OS platform") Is there a smart workaround or would I need to get the associated application's data from registry and run the application with the document/image as argument? (So the question is not about how to run Process.Start() with arguments!)
Related
Recently I bumped into an issue where I need to open a webpage from an elevated application. I need the browser to be opened non elevated so I looked around and found this solution
This would definitely solve my issue except that CreateProcessAsUser does not accept URIs as a filename, the execution will fail with the error message being "The filename, directory name, or volume label syntax is incorrect"
Can someone tell me if there is a way to launch a website through CreateProcessAsUser or if there is a similar API that does the job.. Please note that my actual application is always elevated and thus I cannot uses the usual Process.Start(), CreateProcess() or ShellExecute()
There are two distinct families of functions that you will need to use to get this task done:
CreateProcess and related functions. These can be used to start a new process. You must supply a filename of an executable image.
ShellExecute and friends. These will apply verbs to files using the shell's rules for associating file classes to executables.
In order to open a URI you need to use one of the ShellExecute family. And in order to execute as a standard user from your elevated process, you need to use one of the CreateProcess family.
You cannot meet both your requirements with a single function. Your solution therefore is to use one of the CreateProcessXXX functions to create a process that runs as standard user. That process in turn will call ShellExecuteXXX. You will pass the URI as command line arguments to CreateProcessXXX.
You will therefore need to either create a distinct executable as your standard user launcher. Or re-use your existing executable but make it switch into launcher mode depending on the arguments that you pass it.
so what I'm trying to do is open a file (well, actually two folders, but I figure I'll start with a single file for now) using a third party comparison tool called UltraCompare. I'm working in a C# website project in Visual Studio 2010 (Express edition). I've seen how to open a file using a different program, here: Open a file with Notepad in C#.
Problem is, this only lets you open it using the default program for that file type. But I want to open it in a specified program. For example, a text file should open in UltraCompare, not notepad. Here's the code which does this:
string textBoxContents1 = TextBox1.Text;
Process.Start(textBoxContents1);
The textbox on the webform accepts a string, in which the user types the file's full path (not the most user-friendly design I know, but I'm not sure how to allow them to browse for a folder using a GUI interface in asp.NET). The file is then passed into the Process.Start() method, which opens it using the default program for that file type.
Is there any way to modify this to make it open using UltraCompare??
You can specify the program you want to open the file in:
Process.Start("yourprogram.exe", textBoxContents1);
Update
To open two files in Ultracompare, you'd probably do something like that:
Process.Start("yourprogram.exe", "file1.txt file2.txt");
Keep in mind that the second parameter of Process.Start method are the arguments passed to the program.
I said this is probably going to work because I assumed to be very likely that Ultracompare expects 2 arguments, but this might not be the case.
Quick question: Are you trying to do this for the client machine? Hope not
And I guess it looks into the PATH variable for finding your exe
I have a window application which performs some tasks, One of which is opening some files and we all know .net provides exe file for the application, which can be used as click to start.
I am calling this application application1.
Now I want to generate one more window application(simple exe), let us call it application2, which will open a form with some options(say the names of the files to be opened by application1) and a generate button.
On clicking the generate button, it should generate the exe file for the application1 with the data passed from application2.
Please suggest how can I do it.
EDIT
I need to generate exe which will be available on different systems which will perform some task on regular intervals. and the interval colud be different for different computers.
so I am asked to generate which will accept the time interval and will generate the exe for that interval
There are a number of ways to consider doing this:
use a reg key with the name of the settings file to read in, and then store the settings you write from app2, for app1 in the file, so app 1 can run it
you call app1 with a parameter with either the name of a file, or commandline parameters, and it updates its own applications settings file.
put the settings in a database, so any copy of app1 anywhere can find it, assuming all users would be able to see the db server
if app1 is always to be running while app2 is you could go with some interprocess communication but probably this is the more complex of the 4
Rather than recompiling an exe, it would make sense to have a config file that goes with.
Failing that, compiling .net is only that, you can have an exe that generates a .cs file (or updates one, and reruns the whole compile and outputs an exe.. take a google, on command line compilation) but I wouldnt be my choice.
I think what your looking for is for application1 to be able to receive command line arguments and application2 to allow you to pick files and run application1 and pass in those arguments.
I don't think its wish to be generating .exe's
Another way, although not that easy, would be to
write application 1 to try and read settings from class that does not exist, say SettingsOverride, by reflection; if not found, fall back to its own hard-coded settings
application 2 uses CodeDOM or similar to create a new assembly that provides a SettingsOverride class with the new saved settings
application 2 uses ILMerge to build the new .exe from application 1 and the settings assembly; the reflection code in application 1 should now pick up the new settings.
It's probably also possible to do this with embedded resources, though I'm not sure how. Finally you could put a string constant in your .exe, say 400 X characters, and then application 2 could scan the file to find that (as Unicode/UTF-16 text) and replace that with a string containing the new settings - but I'm not 100% if you then need to recompute a checksum or similar.
I know that it is possible to pass in parameters via URL to ClickOnce apps launched online. However, most users downloads setup.exe and launch it from their machine. Is there any way that I can re-write setup.exe at download, insert a code (let's say the user's email address), and then have the app launch with knowledge of the code? Assume that we can somehow re-sign setup.exe so that it is legit.
Assume .NET 3.5.
Update The goal here is to pass on either email address and/or referrer information to setup.exe so that even when the user runs the installer from a different machine and a different ip we can figure out who did the referral.
Update 2 Assume .NET 3.5 SP1, does it help? Apparently one can now pass parameters to .application while offline. Is it possible to embed parameters into the setup.exe so that it calls .application?ref=someone right when setup.exe is run?
Well, if your goal is to embed a customer id (email, code, etc) into the exe, the easiest way I can think of is using the IPropertyStorage and IPropertySetStorage interfaces. If you are feeling brave, you could call methods directly on IPropertySetStorage via p/invoke, or you could go the easy route and use Microsoft's prepared COM wrapper, which is called dsofile.dll.
Note that while dsofile is intended for office documents, it does indeed work on any file - including .exe files - you are just stuck with the pre-defined property names. Why not throw your customer id into something like the .Comments property. Just do it in such a way that you can parse it out again.
Here's a sample:
var doc = new OleDocumentPropertiesClass();
doc.Open(pathToFile);
doc.SummaryProperties.Comments = "joe#test.com";
doc.Save();
Of course, you need to first copy it to a temp location, and some time after the user downloads it you'll want to delete it.
You can bundle dsofile.dll with your application and register it as a dependancy and use it in your installer to read the property back out. Or if you can p/invoke the IPropertyStorage without it, then you won't have the dependancy.
The other thing to look into would be using the extended file properties that are read by the Shell32.dll. I just haven't been able to find a clean way to write them easily. If you go this route, please share how you wrote the properties to your .exe.
Have a look whether InPlaceHostingManager class can help you in this case. It won't probably do exactly what you have asked for. But may be able to help...
Any ClickOnce application based on an .exe file can be silently
installed and updated by a custom installer. A custom installer can
implement custom user experience during installation, including custom
dialog boxes for security and maintenance operations. To perform
installation operations, the custom installer uses the
InPlaceHostingManager class.
Walkthrough: Creating a Custom Installer for a ClickOnce Application
EDIT
I am not sure whether you could achieve what you want exactly in the way that you have described in the question. Check whether these threads help you.
Accessing Local and Remote Data in ClickOnce Applications
How to include custom data files in ClickOnce deployment?
How to: Retrieve Query String Information in an Online ClickOnce Application
How would you imagine to "rewrite" setup.exe at download? if instead of opening your application with the provided link (url) users are downloading the file locally directly from the network share, you can't intercept this.
I would try to play with permissions and have the users to execute it from the link provided to them, but unable to connect directly to the share or web address and download it. Not sure this is possible anyway.
You can try embedding that information as a resource into the exe.
Here's a c++ example of updating a resource of an exe. http://msdn.microsoft.com/en-us/library/ms648008(v=vs.85).aspx#_win32_Updating_Resources
You should combine approach by Charith and Josh - essentially, configure your web server so that you can generate a new setup based on URL parameters. Use custom installer to read from the referral information from resource for setup.exe. Check this link for how to manipulate resources for a native application in C# - you have to write to resource file while generating setup and need to read it from your custom installer.
Yet another way of generating custom setup would be to build your executable or helper assemblt from command line embedding the necessary information. And then build the setup from command line tools (see http://msdn.microsoft.com/en-us/library/xc3tc5xx.aspx). It appears to be quite cumbersome and will take long time to generate the custom setup as opposed to modifying the resource of already built setup.
A completely different approach would be to email the unique referral code (registration code) whenever user downloads the application. In the setup (or application), use custom installer to prompt user for this code. If the setup is invoked via URL then the code will be available from there and in such case Custom Installer need not ask for the code. The email that you send when user download the setup should inform user to preseve the code into some text file along with the setup file.
How Would I find another exe's path by knowing its name in .net?
Would I add name to the OS environment variable?
Would the other application have to 'register' itself somewhere else?
I need App A to start-up App B and call some WCF services on it.
Thanks!
To answer your question: you cannot know the path simply by knowing the name. An exe can reside anywhere on the file system. There can be multiple instances of it that don't know about each other. Multiple exe files that are completely different can have the same name.
You could take one of several approaches to get round this, depending on the exe you are targetting:
get the user to browse for the exe using a normal file browse dialog
search the file system
see what traces the target exe leaves on the system (filesystem, registry, environmental variables, etc) and use those traces to locate the exe
For either of these options you save the result so you don't have to execute it again when your app is run the next time.
Searching the filesystem could take some time, you are not guaranteed to find the exe (depending upon the user level your app is running as) and you may get false positives, especially if the app is called something dumb like setup.exe.
Getting the user to locate the exe the first time you run is possibly the most reliable way of locating it, but then you have to decide what to do if your app runs but the target exe is no longer at the specified location, or the user has chosen the wrong exe.
If you have some control over App B (i.e. it is your product), then you could consider adding some info to a known spot in the registry when App B gets installed, so that App A can locate it easily. You still need to have a plan B though in case the info is missing.
Reference a path to a shortcut of the exe in the config setting, that way if the exe ever moves around the shortcut will still be up-to-date. Try it, make a shortcut to a exe, then cut and paste the exe somewhere else, then double click the shortcut and you'll see it points to the exe's new location thus will not require changes to app A if the location app B changes.
Really, just make the App B a windows service and start it up when needed.
UPDATE:
Another suggestion would be to create a hard link to the AppB's EXE:
mklink /H AppB-link.exe path_to_actual_exe
Or a symbolic link to whole directory where App B resides:
mklink /D virtual_directory path_to_actual_directory