I'd like to be able to start a ClickOnce application from another executable. I know how to do this with the browser using Process.Start("http://PathToMyApp"). However, this is returning null for the Process. Therefore, I cannot check to ensure that the process has started or kill the process later.
How can I launch a click once application and get its Process Id and determine whether or not it launched successfully?
You have to find the shortcut for the ClickOnce application and do a process.start on that. Here's an example:
string shortcutName =
string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.Programs),
"\\", PublisherName, "\\", ProductName, ".appref-ms");
process.Start(shortcutName);
where PublisherName and ProductName are those filled in on the Options dialog in the Publish tab for the application you want to start.
You can also pass arguments to a ClickOnce application if you start it this way, even if it's offline. Here is an article telling how to do that just in case you need that functionality as well.
Related
I have a custom application running as a the shell (Windows 10 Enterprise) for a particular user - i.e. the user boots straight into this application.
However, I want to be able to provide access to the WiFi settings form. I have read that the way to do this is something like
Process.Start("ms-settings:network-wifi");
or
Process.Start("ms-availablenetworks:");
However, as far as I can tell, that relies on explorer running as the shell.
I've tried...
Process proc = new Process();
proc.StartInfo.FileName = #"c:\windows\explorer.exe";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.Arguments = "ms-availablenetworks:";
proc.Start();
All of the above work fine if I run in a normal environment, i.e. with explorer as the shell.
But for this user (with my custom shell application), I get an instance of explorer.exe running and displaying an error, Class not registered
I have also come across using LaunchUriAsync() but I don't think that would help me here, besides it's only available for Windows Store applications for what I've read, which this is not.
Well I managed to get this working
First start explorer on its own, then a second Process.Start() to run the settings page.
Unfortunately, when explorer.exe runs, it displays the taskbar which I don't want. (I had previously assumed I'd be able to hide it with a group policy setting or something but this doesn't appear to be the case).
But I suppose that's another question...
my installer run as administrator, but on complete i want the exe to run as current user.
i am using nsis and already tried UAC
!insertmacro UAC_AsUser_ExecShell "" "some.exe" "" "" ""
but still it run as administrator.
tried to use task scheduler
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
td.Actions.Add(new ExecAction("" + path + "", "", null));
td.Settings.DisallowStartIfOnBatteries = false;
td.Settings.AllowHardTerminate = false;
td.Settings.StopIfGoingOnBatteries = false;
td.Settings.ExecutionTimeLimit = System.TimeSpan.Zero;
td.Settings.IdleSettings.StopOnIdleEnd = false;
// Register the task in the root folder
ts.RootFolder.RegisterTaskDefinition("task", td);
but the task also goto administrator and i cant get it to current user.
any ideas ?
My personal recommendation is that you just remove the option to run your application at the end of your installer. The user can just start it from the start menu, it should be highlighted as new and everything.
As you probably know, UAC really changed how common it is for applications to run as a different user than the "logged in" user. You just have to deal with the fact that UAC exists and decide if you feel it is worth the amount of time required to work around it and possible bugs and issues that might arise.
There are at least 4 ways to run something as the "current user", all of them have issues and can fail or end up running as the "wrong" non-admin user:
Use the token of the (hopefully) non-elevated parent, this is what the NSIS UAC plugin does.
Use the Windows Task Scheduler. This was a recommended practice in the early Vista days but I believe Microsoft has moved away from this method.
Use a shell COM object in the Explorer process that hosts the taskbar to call ShellExecute for you. The StdUtils plugin provides a ExecShellAsUser method that does this.
Use a Windows NT service. Because it runs as SYSTEM it can get the token handle of a user in any session.
If you decide that you still want to attempt to do this then you need to decide on your definition of current user before you choose a method.
Is it the user that logged in on the welcome screen? Is it the user the Explorer shell (Taskbar etc) is running as? Is it the parent process of your setup process? You should also keep in mind that runas.exe exists and a user might try to run something as a particular user for a reason...
I'm working on a online only winform application which I deploy using ClickOnce feature it uploads through FTP to the server and the user executes it online through http.
As you may already know, the Online only feature doesn't place any icons on the desktop, so everytime it runs the user got to run the setup.exe file to do it.
My question is, if there is anyway I could actually create an icon that may point to the setup file or any workaround to make sure the user got an accesible and easy way to run the app without having to look for the setup file everytime?
Users may not know a lot about computers so it can be a hard task to navigate all the way to the downloaded file everytime, and I want to make it easier for them.
I know that if I do an offline/online app it will solve the problem, but I would like it to be online only.
Any ideas?
you can create desktop shortcut manually on the first app run, and point it to either to your app's url, or path to downloaded file (I guess, url will be safer in case user deletes the file). Code can look something like this (need adjusting to your URL):
void CheckForShortcut()
{
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
if (ad.IsFirstRun)
{
Assembly code = Assembly.GetExecutingAssembly();
string company = string.Empty;
string description = string.Empty;
if (Attribute.IsDefined(code, typeof(AssemblyCompanyAttribute)))
{
AssemblyCompanyAttribute ascompany = (AssemblyCompanyAttribute)Attribute.GetCustomAttribute(code,
typeof(AssemblyCompanyAttribute));
company = ascompany.Company;
}
if (Attribute.IsDefined(code, typeof(AssemblyDescriptionAttribute)))
{
AssemblyDescriptionAttribute asdescription = (AssemblyDescriptionAttribute)Attribute.GetCustomAttribute(code,
typeof(AssemblyDescriptionAttribute));
description = asdescription.Description;
}
if (company != string.Empty && description != string.Empty)
{
string desktopPath = string.Empty;
desktopPath = string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
"\\", description, ".appref-ms");
string shortcutName = string.Empty;
shortcutName = string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.Programs),
"\\", company, "\\", description, ".appref-ms");
System.IO.File.Copy(shortcutName, desktopPath, true);
}
}
}
credits to http://geekswithblogs.net/murraybgordon/archive/2006/10/04/93203.aspx
What is your reason for wanting an online only ClickOnce app? I always recommend offline unless your app is really an edge case.
There's very little difference between online and offline. All the same files are downloaded to the same location on the client. Offline apps add an entry to the 'Add/Remove Programs', a start menu shortcut, and an optional desktop shortcut (if you are targeting .NET 3.5+). The ability to uninstall through Add/Remove Programs is key. It makes supporting your application much easier when users have install problems.
Also, you mention users running the setup.exe every time. This is unnecessary. The setup.exe will contain your bootstrapped pre-requisites and then launch the app when it finishes. If the user has run the setup.exe once, they only need to click the link to the .application file. That will definitely speed up the app's start time. Also, in many cases the user has to have admin privileges to run the setup.exe; clicking the .application doesn't (assuming someone with admin privileges has already run the setup.exe).
In conclusion, there really isn't an answer here :). But...
Make absolutely sure your reasoning is sound for not doing an offline install instead.
After running the setup.exe once, direct users to click on the .application url (or the desktop shortcut if you switch to offline) instead of the setup.exe.
As far as I know, there is no reliable way for running online only ClickOnce application than creating shortcut to that setup.exe.
If I run this command:
C:\WINDOWS\explorer.exe "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\::{2227A280-3AEA-1069-A2DE-08002B30309D}"
from the Windows shell (via Windows+R), my printer and faxes open in a new explorer.exe process. (So I have 2 running explorer.exe processes.)
If i execute:
Process.Start(#"C:\WINDOWS\explorer.exe", #"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\" +
#"::{21EC2020-3AEA-1069-A2DD-08002B30309D}\" +
#"::{2227A280-3AEA-1069-A2DE-08002B30309D}");
from a C# program, my printer and faxes open too, but as an child process of the main explorer.exe process (the one running the Windows shell, including the taskbar, etc.).
What can I do to start a second explorer.exe process with the printer and faxes window from C#?
Initial thoughts - check your "Launch folder windows in a separate process" in Folder Options (Organize -> Folder & Search Options -> View tab). This is unchecked by default, hence "Check" this and try your C# code again.
I know this setting affects the ShellExecute function but I am not sure if .NET's Diagnostic namespace uses the same route.
ShellExecute(handle, "explore", , NULL, NULL, SW_SHOWNORMAL);
Second thoughts - a similar issue has been already discussed in stackoverflow and this post might give you some idea.
Start new process, without being a child of the spawning process
Our setup has an embedded manifest that triggers the UAC before the application starts. (The applications runs as an admin user). However, if the setup needs to install the .NET Framework, we have to continue the setup after a reboot. For this reason, we have to create a registry key in the current user's RunOnce.
Unfortunatly, HKEY_CURRENT_USER points to the Administrator's registry. We need to find out the user that is currently logged in and started the installation. (Th normal USER clicked the setup.exe, an ADMIN entered his details in the UAC prompt. We need to find out who the USER was)
I've tried all the usual methods (Environment.UserName, WindowsIdentity.GetCurrent())
Thanks!
You can use the LsaEnumerateLogonSessions function to retreive what you need. However, it is a winapi C function call. If you need a managed version of it, I belive you can look at the source code for Cassia, which uses this function in its terminal services API. The call should be the same. You can also look here.
Also you can use the NetWkstaUserEnum WINAPI function. You can find a managed wrapper for it here
With Cassia library this code works fine:
ITerminalServicesManager manager = new TerminalServicesManager();
ITerminalServicesSession session = manager.CurrentSession;
string userInfo = session.DomainName + "\\" + session.UserName;
NTAccount account = session.UserAccount;
Run your initial setup.exe as a small executable that puts up a splash screen while invoking your real setup program as a child process. The small EXE is not run as admin and can pass the logged in user name to the child process. The child process invokes UAC and runs in the admin context but already has the logged in username as a command line parameter.
It is not possible to retrieve the original user if your application is ran as Administrator:
If a user launches Setup by right-clicking its EXE file and selecting
"Run as administrator", then this flag, unfortunately, will have no
effect, because Setup has no opportunity to run any code with the
original user credentials. The same is true if Setup is launched from
an already-elevated process. Note, however, that this is not an Inno
Setup-specific limitation; Windows Installer-based installers cannot
return to the original user credentials either in such cases.
Source : InnoSetup Help
As said by Matthew in comments, you should not run your application as Administrator but only trigger UAC when needed in your code.
This returns the name of the logged in Windows User by stripping out the domain:
using System.Security.Principal; // here is the security namespace you need
...
string userName = WindowsIdentity.GetCurrent().Name.Replace("\\", "|");
string[] split = userName.Split(new Char[] { '|' });
lblDebug.Text = (split.Count() > 1) ? split[1] : userName;