I'm trying to create a shortcut in my C# WinForm application for users to launch Microsoft's "Digitizer to Monitor Mapping Tool" (MultiDigiMon.exe). However it seems that even if ran as an administrator my applications or cmd processes launched from it can not find the executable in question and I have no idea why.
My Short cut consists of a simple button with the click event hooked to the fallowing function.
private void TouchButton_Click(object sender, EventArgs e)
{
ProcessStartInfo start = new ProcessStartInfo("C:\\Windows\\System32\\cmd.exe");
start.WorkingDirectory = "C:\\Windows\\System32";
start.CreateNoWindow = false;
start.UseShellExecute = false;
//start.Arguments = "/K \"cd C:\\Windows\\System32 && MultiDigiMon.exe -touch\"";
Process.Start(start);
}
In my experience on Win10 systems, MultiDigiMon.exe can be always be found in C:\Windows\System32 (assuming the C drive is your root). Additionally the arguments line above was commented out to make the following screen shots as identical as possible.
On the left is the command prompt launched using the above code and on the right is a command prompt launched by typing cmd in to the OS's taskbar and and running the first result as administrator. As you can see both promps are marked as administrator but the left fails to launch MultiDigiMon.exe and won't even list the file exist using the dir command. the right seems to have no issue with either command. (MultiDigiMon.exe dose not seem to do anything at all if multiple touch screen devices are not connected and I do not believe that it give any text output especially if successful).
Finally I have also checked the permission on MultiDigiMon.exe and (with the exception of TrustedInstaller who has full control) everybody has read and execute right. Could someone explain why I can't launch MultiDigimon.exe form the left prompt or directly from my application?
As commented on by RbMm the issue was that since my application was being compiled to run on any cpu it was treated as a 32 bit application by the file system and redirected all access to the System32 directory to SysWOW64.
To get around this you can substitute "System32" width "Sysnative" as discussed here. In my case my final code ended up looking like the fallowing.
private void TouchButton_Click(object sender, EventArgs e)
{
ProcessStartInfo start = new ProcessStartInfo("C:\\Windows\\Sysnative\\MultiDigiMon.exe");
start.WorkingDirectory = "C:\\Windows\\System32";
start.CreateNoWindow = false;
start.UseShellExecute = false;
start.Arguments = "-touch";
Process.Start(start);
}
Related
Due to me having knowledge of launching apps I am aware that you have multiple ways of launching an application in C# .NET, but I'm running into a issue that occurs when attempting to launch a SDL2 application.
I have attempted the following using the Process class to:
Start the .exe file of the build.
Start the application using "cmd.exe /K" or "cmd.exe /c" followed by "exec" or "call" or "start" followed by "{path to file}" or "{path to batch file to launch the application}". Launching the application via a batch file and CMD works fine. But, whenever I attempt to even launch the application (even in a new instance of Command-Prompt launched from cmd.exe /? start cmd.exe ?params) it will yield no result.
What I can observe is that the application tries to open. It takes forever to launch into the Window mode (starting the 3D environment). After a timeout it will either, render a couple of frames of a blank window before closing or close immediately after opening the window.
So my question is, does anyone have succesfully made a launcher application for a SDL app written in C# .NET? Or knows a way to debug this behaviour? Because unfortunately, the app does not send out a error message and since SDL safely closes the application I can't observe a crash either.
Edit #1
I'm not doing anything fancy with parameters as there shouldn't be any. I already have another one functioning that launches a normal C# application as my launcher requires to open 2 programs. 1 SLD application, 1 COM:VBA controlling application.
Given:
string audioSpectrumProgram = "AudioSpectrum.exe";
string audioSpectrumBatchProgram = "AudioSpectrum.bat";
private void BtnLaunchPPTApp_OnClick()
{
//Powerpoint controlling application
pVBAApp = Process.Start(presenterProgram, $"\"{this.path}\" {this.audioFormatParams[0]} {((this.ckboxGenerate.Checked) ? "--create" : "")} lang={this.languageCodesParams[this.cboxLanguage.SelectedIndex]}");
}
Method 1:
private void BtnLaunchSDLApp_OnClick()
{
pVizualizer = Process.Start(audioSpectrumProgram); //file launched from local path (is correct)
}
Method 2:
pVizualizer = Process.Start(audioSpectrumBatchProgram); //file launched from local path (is correct)
Method 3:
ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
FileInfo spectrumFileInfo = new FileInfo(audioSpectrumProgram);
if (spectrumFileInfo.Exists)
info.Arguments = $"/c \"{spectrumFileInfo.FullName}\"";
pVizualizer = Process.Start(info);
Method 4:
based on senario of method 3. You don't have to parse arguments using ProcessStartInfo.
pVizualizer = Process.Start($"cmd.exe /K call \"{spectrumFileInfo.FullName}\"") //to observe what happens to the application
Edit #2
Not affected by changing the UseShellExecute to true or false
private void btnOpenVisualizer_Click(object sender, EventArgs e)
{
FileInfo spectrumFileInfo = new FileInfo(audioSpectrumProgram);
ProcessStartInfo info = new ProcessStartInfo(spectrumFileInfo.FullName);
info.UseShellExecute = true;
pVizualizer = new Process();
pVizualizer.StartInfo = info;
pVizualizer.EnableRaisingEvents = true;
pVizualizer.Exited += new EventHandler(myProcess_Exited);
pVizualizer.Start();
}
private void myProcess_Exited(object sender, System.EventArgs e)
{
Console.WriteLine(
$"Exit time : {pVizualizer.ExitTime}\n" +
$"Exit code : {pVizualizer.ExitCode}\n"
);
}
A general way of analyzing startup issues is to use SysInternals Process Monitor.
Record the application that is not starting up properly. Use a filter for your application. Then go through all items which don't have SUCCESS in the result column. Typically you want to do that bottom-up, since the last error is the one stopping your application from loading.
Like this you'll find common startup issues like:
missing DLLs or other dependencies
old DLLs or DLLs loaded from wrong location (e.g. registered COM components)
wrong working directory, e.g. access to non-existent config files
Ok For Future reference:
Pathing to the files can be correct and everything might be in order but if you are using DLLs for imports. Change the process's working directory.
The project will run, libs can "sometimes" be found but can cause a weird unknown bug like this one. So the most optimal way of running another C# instance with SDL or any other kind of library:
private void RunSDLProgram()
{
FileInfo spectrumFileInfo = new FileInfo("pathToFile.exe");
ProcessStartInfo info = new ProcessStartInfo(spectrumFileInfo.FullName);
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
info.UseShellExecute = false;
info.WorkingDirectory = spectrumFileInfo.DirectoryName;
pVizualizer = new Process();
pVizualizer.StartInfo = info;
pVizualizer.EnableRaisingEvents = true;
pVizualizer.Exited += new EventHandler(myProcess_Exited);
pVizualizer.Start();
}
private void myProcess_Exited(object sender, System.EventArgs e)
{
Console.WriteLine(
$"Exit time : {pVizualizer.ExitTime}\n" +
$"Exit code : {pVizualizer.ExitCode}\n" +
$"output : {pVizualizer.StandardOutput}\n" +
$"err : {pVizualizer.StandardError}\n"
);
}
Running a batch file will look at it's own directory and makes all references local, but it won't alter the working directory. (already had my suspicions about changing the work directory but I didn't see a way to call 2 opperations in process.start("cmd.exe");)
I want to open a file's location and select the file in explorer on Mac, Ubuntu from MonoDevelop.
This code is working on Windows (but it is not working on Mac and Ubuntu):
System.Diagnostics.Process.Start("explorer.exe", "/select, " + fileaddress);
Dim dir_path As String = "/media/os/test"
' Windows path example: dir_path = "C:\test"
Process.Start("file://" & dir_path)
Tested and worked on Ubuntu and Windows XP.
Source: http://www.stevenbrown.ca/blog/archives/156
By 2020-10, in mono 6.10, the above method didn't work on Ubuntu 20.04. The below approach solved the problem.
System.Diagnostics.Process.Start("mimeopen", "/var/tmp");
You can use 'open' on Mac, like this
System.Diagnostics.Process.Start("open", $"-R \"{File_Path_You_Wanna_Select}\"");
Here -R means reveal, to select in the Finder instead of opening.
To find more usage for open, just type open in terminal.
Using Process.Start() you bypass the .NET framework and move into the platform you're running onto, executing an arbitrary process.
On Windows you want to open the Windows Explorer, on Mac you want to open Finder and on Ubuntu it's simply called File Browser.
There is no Environment.OpenFileBrowser(string path) method in the framework, so you will have to let your program determine which platform it is running on, and open the approperiate file viewer.
See How to check the OS version at runtime e.g. windows or linux without using a conditional compilation statement to perform the former.
You are calling an OS specific (Windows) method. That won't work cross-platform.
Try the following inside a function/method:
Example - inside click event:
protected void OnOpen (object sender, EventArgs e)
{
using(FileChooserDialog chooser =
new FileChooserDialog(null,
"Select document to open...",
null,
FileChooserAction.Open,
"Open Selected File",
ResponseType.Accept,
"Discard & Return to Main Page",
ResponseType.Cancel))
{
if (chooser.Run () == (int)ResponseType.Accept)
{
System.IO.StreamReader file = System.IO.File.OpenText (chooser.Filename);
/* Copy the contents to editableTxtView <- This is the Widget Name */
editableTxtView.Buffer.Text = file.ReadToEnd ();
/* If you want to read the file into explorer, thunar, Notepad, etc.,
* you'll have to research that yourself. */
//Close file - - KEEP IT CLEAN - - & deAllocated memory!!
file.Close ();
}
}
}
The file has now been copied into an editable (Default) or read only (set in properties pad) textviewer Gtk widget. From there you should be able to manipulate it as you so choose.
We changed the logo-icon of our WPF application, and then the icon of the main executable. On my PC with Win 7, there is a problem with the refresh of the icon cache: the desktop shortcut to the main executable, and the preview of the icon of the executable, in Windows Explorer still shows the old icon.
Even restarting the system the problem persists.
I found that running this command solves the problem:
ie4uinit.exe-ClearIconCache
My problem is that I can't run it from code. I made two attempts.
First:
Dim si As New ProcessStartInfo()
si.CreateNoWindow = False
si.UseShellExecute = False
si.FileName = "ie4uinit.exe"
si.WindowStyle = ProcessWindowStyle.Hidden
si.Arguments = "-ClearIconCache"
Dim p As Process = Process.Start(si)
error: "Could not find the specified file" - I tried to input the full path but it still doesn't find the file
Second:
I put the command in a batch file
Dim si As New ProcessStartInfo("C:\test.bat")
si.UseShellExecute = False
si.RedirectStandardError = True
si.RedirectStandardInput = True
si.RedirectStandardOutput = True
si.CreateNoWindow = True
si.ErrorDialog = False
si.WindowStyle = ProcessWindowStyle.Hidden
Dim p As Process = Process.Start(si)
This time I get no errors, but not even the desired effect. If I double-click on the batch file instead, everything is working fine.
I'd like to adjust one of these procedure otherwise finding a new one to clear the windows icon cache. C# or Visual Basic is not important...
Pileggi
maybe it doesn't search for it in the path try using:
as the path "%WINDIR%\System32\ie4uinit.exe",
if this doesnt work try "C:\Windows\System32\ie4uinit.exe"
I found the solution: I had to build the executable that runs the batch file for "Any CPU", otherwise it has not sufficient permissions to run ie4unit.
Before I was trying building for "x86" and I was running the process on a Win7 64 bit...
I had a similar issue, trying to call ie4uinit from an Inno installer. The PATH did include the right system directories; however, doing a "dir" did not show that the file exists. In fact, there were over 100 *.exe files that could not be found from whatever shell was executing the command. Opening Explorer or a command window reveals the file is there (which of course we know). I think it is a permissions or access issue. I didn't have the patience to trace it further, but just copied ie4uinit.exe to a local directory and had my installer execute it there.
Enables or disables file system redirection for the calling thread.
[DllImport("Kernel32.dll")]
private static extern bool Wow64EnableWow64FsRedirection(bool Wow64FsEnableRedirection);
//.....
Wow64EnableWow64FsRedirection(false);
Dim p As Process = Process.Start(si)
Wow64EnableWow64FsRedirection(true);
You can try this:
Dim objProcess As System.Diagnostics.Process
objProcess = New System.Diagnostics.Process()
objProcess.StartInfo.FileName = "ie4uinit.exe"
objProcess.StartInfo.Arguments = "-ClearIconCache"
objProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal
objProcess.Start()
objProcess.WaitForExit()
objProcess.Close()
I have searched everywhere to find out how to make a custom minecraft launcher. I managed to create this code, which should work, but sadly it does not. I login but it never starts, however for a second I get the loading ring next to my mouse. This is my code:
ProcessStartInfo start = new ProcessStartInfo();
// Enter in the command line arguments, everything you would enter after the executable name itself
start.Arguments = #"-Xmx1G -Djava.library.path=%APPDATA%\.minecraft\versions\1.6.2\1.6.2-natives -cp %APPDATA%\.minecraft\libraries\net\sf\jopt-simple\jopt-simple\4.5\jopt-simple-4.5.jar;%APPDATA%\.minecraft\libraries\com\paulscode\codecjorbis\20101023\codecjorbis-20101023.jar;%APPDATA%\.minecraft\libraries\com\paulscode\codecwav\20101023\codecwav-20101023.jar;%APPDATA%\.minecraft\libraries\com\paulscode\libraryjavasound\20101123\libraryjavasound-20101123.jar;%APPDATA%\.minecraft\libraries\com\paulscode\librarylwjglopenal\20100824\librarylwjglopenal-20100824.jar;%APPDATA%\.minecraft\libraries\com\paulscode\soundsystem\20120107\soundsystem-20120107.jar;%APPDATA%\.minecraft\libraries\argo\argo\2.25_fixed\argo-2.25_fixed.jar;%APPDATA%\.minecraft\libraries\org\bouncycastle\bcprov-jdk15on\1.47\bcprov-jdk15on-1.47.jar;%APPDATA%\.minecraft\libraries\com\google\guava\guava\14.0\guava-14.0.jar;%APPDATA%\.minecraft\libraries\org\apache\commons\commons-lang3\3.1\commons-lang3-3.1.jar;%APPDATA%\.minecraft\libraries\commons-io\commons-io\2.4\commons-io-2.4.jar;%APPDATA%\.minecraft\libraries\net\java\jinput\jinput\2.0.5\jinput-2.0.5.jar;%APPDATA%\.minecraft\libraries\net\java\jutils\jutils\1.0.0\jutils-1.0.0.jar;%APPDATA%\.minecraft\libraries\com\google\code\gson\gson\2.2.2\gson-2.2.2.jar;%APPDATA%\.minecraft\libraries\org\lwjgl\lwjgl\lwjgl\2.9.0\lwjgl-2.9.0.jar;%APPDATA%\.minecraft\libraries\org\lwjgl\lwjgl\lwjgl_util\2.9.0\lwjgl_util-2.9.0.jar;%APPDATA%\.minecraft\versions\1.6.2\1.6.2.jar net.minecraft.client.main.Main --username playername --session token:"+ words[3] + #":" + words[4]+ #" --version 1.6.2 --gameDir %APPDATA%\.minecraft --assetsDir %APPDATA%\.minecraft\assets";
start.FileName = #"c:\Program Files (x86)\java\jre7\bin\javaw.exe";
// Do you want to show a console window?
start.CreateNoWindow = true;
System.Diagnostics.Process.Start(start);
This just does the loading ring by my mouse for a second, then nothing opens. No logs, crashes, errors, nothing wrong. This is Visual c# compiled on Visual Studio 2012.
The arguments you are giving have an environment variable in them - %APPDATA%.
The command line will expand this by default, but the .net library won't.
See How do I ensure c# Process.Start will expand environment variables?
As Pete Kirkham mentioned you need to set up environment variable.
You can set it before starting the Process like:
var appDataPath = "your path";
start.EnvironmentVariables.Add("APPDATA", appDataPath);
So I was writing an application that requires access to the registry.
I had not touched any build settings, wanting to get the thing working before I added the other touches, such as a description or name.
Out of the blue, I get an error that will not go away. ClickOnce does not support the request execution level 'requireAdministrator'. Now, I hadn't touched ClickOnce in this application. All I had done was include a manifest file requesting these permissions.
My problem now is that this error will not go away, and I cannot compile my program. Any advice on what to do? (Side note: I am about to go to bed, so I will check this tomorrow afternoon).
Edit: This comment gives a good answer, too.
Click once appears to get enabled whenever you click "Publish", whether you want it to or not! If you are using "requireAdministrator" then it appears that you cannot use ClickOnce, and therefore cannot "Publish" your project.
Original:
Turns out that under the Security tab, "Enable ClickOnce security settings" was checked. Even though I didn't check it.
Anyway, unchecking that stopped ClickOnce giving me errors. That took a while to find...
I know this an old question but I came here two years later so:
You can disable the ClicKOnce from the Security tab on project properites to help the issue; see below:
If you ever use the publishing wizard, or 'Publish Now', the click-once checkbox gets automatically selected...
I know this is old but I stumbled across it looking for answers. In my case, I AM using the publish function and I need to keep using it. I also need access to admin capabilities. So for that reason, none of the above answers worked for me.
I ended up adding a method to the very start of my application that checks if it's being run as an administrator and if it isn't, relaunch itself as an admin. To do this, you need the following references added.
using System;
using System.Diagnostics;
using System.Reflection;
using System.Security.Principal;
Then you will need to put this somewhere that your main method has handy access to. I'm using WPF so I added it to MainWindow.xaml.cs but you can add it anywhere early on in your code. Just remember to add "static" to these methods should you need it.
private void AdminRelauncher()
{
if (!IsRunAsAdmin())
{
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = Assembly.GetEntryAssembly().CodeBase;
proc.Verb = "runas";
try
{
Process.Start(proc);
Application.Current.Shutdown();
}
catch(Exception ex)
{
Console.WriteLine("This program must be run as an administrator! \n\n" + ex.ToString());
}
}
}
private bool IsRunAsAdmin()
{
try
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch (Exception)
{
return false;
}
}
Lastly, at the start of your program, add a reference to the method. In my case, I added it to MainWindow but adding it to Main works too.
public MainWindow()
{
InitializeComponent();
AdminRelauncher(); //This is the only important line here, add it to a place it gets run early on.
}
Hope this helps!
For .NET Core and .NET 5+
If you're stumbling upon this in the 20s, this is how you would change the above to work with .NET Core and .NET 5+
The only function that needs changing is the AdminRelauncher and it should look like this instead.
private static void AdminRelauncher()
{
if (!IsRunAsAdmin())
{
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = Assembly.GetEntryAssembly().Location.Replace(".dll", ".exe");
proc.Verb = "runas";
try
{
Process.Start(proc);
Environment.Exit(0);
}
catch (Exception ex)
{
Console.WriteLine("This program must be run as an administrator! \n\n" + ex.ToString());
}
}
}
The only big changes is as someone pointed out Application isn't always available. So Environment.Exit(0) can replace it and the filename needs to replace .exe with .dll. This has been tested as of .NET 6
For those who use uncheck "Enable ClickOnce security settings" can't work, to try the method I find.
First, leave your app.manifest requestedExecutionLevel item as is:
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
And then you edit your Program.cs file like this:
using System;
using System.Diagnostics;
using System.Reflection;
using System.Security.Principal;
using System.Windows.Forms;
restruct main method like:
static void Main()
{
var wi = WindowsIdentity.GetCurrent();
var wp = new WindowsPrincipal(wi);
bool runAsAdmin = wp.IsInRole(WindowsBuiltInRole.Administrator);
if (!runAsAdmin)
{
// It is not possible to launch a ClickOnce app as administrator directly,
// so instead we launch the app as administrator in a new process.
var processInfo = new ProcessStartInfo(Assembly.GetExecutingAssembly().CodeBase);
// The following properties run the new process as administrator
processInfo.UseShellExecute = true;
processInfo.Verb = "runas";
// Start the new process
try
{
Process.Start(processInfo);
}
catch (Exception)
{
// The user did not allow the application to run as administrator
MessageBox.Show("Sorry, but I don't seem to be able to start " +
"this program with administrator rights!");
}
// Shut down the current process
Application.Exit();
}
else
{
// We are running as administrator
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
It works on Windows 10 and Visual Studio 2019!
This action can be achieved by selecting "Enable ClickOnce security settings" (since it cannot be "unchecked" during a Publish, as stated) and then by selecting "This is a partial trust application". "Local Intranet" will be automatically selected in the drop-down menu which is perfectly fine.
Save your changes, Publish the application, done-skis. :-)
I have the same problem s I resolve it by unchecking the "Enable ClickOnce security settings"
To Find this option in Visual Studio Right Click on your Project ==>properties==>Select Security==> Enable ClickOnce security settings (This option was already checked so I unchecked it and my problem get resolved).
Here is the code snippet for VB.NET
If Not New WindowsPrincipal(WindowsIdentity.GetCurrent).IsInRole(WindowsBuiltInRole.Administrator) Then
Process.Start(New ProcessStartInfo With { _
.UseShellExecute = True, _
.WorkingDirectory = Environment.CurrentDirectory, _
.FileName = Assembly.GetEntryAssembly.CodeBase, _
.Verb = "runas"})
EDIT: But if you deploy in this way, some AV-Software blocks your code.
For anyone who's run into this, I thought I'd contribute what ended up working for me.
Yep, the 'Enable ClickOnce security settings' option automatically gets re-checked, if you un-check it, when you do Build > Publish .
For me, I don't need to 'Publish' -- it's a simple, portable .exe that creates Scheduled Tasks for my users and I needed to make sure it elevated, even when logged-in as an Administrator.
So I just grabbed my latest .exe from \bin\Release and that's what gets deployed on my clients' systems.
Worked just as expected -- i.e. when I put it on a system w/ UAC enabled/at its highest setting, the .exe has the 'shield' on it, and when I run it, even when logged-in as an Administrator, it elevates and I get the UAC prompt.
My little task scheduler app is now able to create the task without getting an 'Access Denied' error (which previously, could only be worked-around by right-clicking the .exe and clicking Run as Administrator).
Take a look in your app.Manifest file and you'll see this:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
There's instructions there in the comments, but just deleting the "requireAdministrator" and insert this in is place solved the problem for me:
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
just
Imports System.security
and
U will get no error and your application will be run as admin