I have been trying to make a UWP app using the latest Windows 10 SDK and the latest version of Visual Studio 2019 that can launch bat files, but whenever I try to launch the bat file using a Process, and error occurs when doing proc.Start(). The error is the following:
System.ComponentModel.Win32Exception: 'The system cannot find the file specified'
Currently, the code is using the ms-appx protocol, but I have tried granting the app filesystem access by editing the app manifest and granting permissions through settings and giving it the full path to no avail. Sometimes, if the full path is specified in one string (and not concatenated), it gives an access denied error, even if the filesystem access is granted to the app and the windows folder can be accessed by Everyone. Using the ms-appx protocol, all I get is The system cannot find the file specified. The error should be self-explanatory, but the same exact code has worked inside of a C# Windows Forms App, but not in the UWP C# app.
Below is my code using the ms-appx protocol:
string InstallPath = "ms-appx:///App/InstallDir"
string batDir = InstallPath + "/Binaries/Win64/";
Proc = new Process();
Proc.StartInfo.WorkingDirectory = batDir;
Proc.StartInfo.FileName = batDir + "Launcher.bat";
Proc.StartInfo.CreateNoWindow = false;
Proc.Start();
The System.Diagnostics.Process.Start() method does not work in UWP. UWP applications much run in a sandbox. For the sake of system stability, the access to other processes is not supported.
You could try to use StorageFolder.GetFileAsync(String) method with a parameter which is the same full path, and the method will return a StorageFile instance. But the same full path used in Process.Start() will cause a Win32Exception.
Related
I have created a Windows shell extension that provides a menu to users when they right-click in File Explorer. This then invokes a small dialogue App.
I'm a novice at software development so there is probably some schoolboy error I'm making but I just can't see it.
For testing purposes I am hard-coding the path to the EXE and ensuring it's present on the VM.
private void CallExteralAddLocation(string sFullPath)
{
string sEXE = Path.Combine(Application.StartupPath, "AddLocation.exe");
WriteLog(sEXE);
// during testing, hard-code this path
sEXE = "C:\\temp\\AddLocation.exe";
System.Diagnostics.Process.Start(sEXE, sFullPath);
}
private void WriteLog(string sText)
{
using (StreamWriter sr = new StreamWriter("C:\\Temp\\ShellExtLog.txt"))
{
sr.WriteLine(sText);
}
}
It works fine on my host machine but when running on a VM running Windows 10, which is where I am testing it, the dialogue App does not get invoked.
I have checked that I can invoke the AddLocation.exe from a command window on the VM and that works as expected. So it looks like it's just not getting called.
As it's a shell extension it's very difficult to debug. I tried using MessageBoxes and writing to the console but those wouldn't work, so I have added the WriteLog so that I have some idea of what it's doing.
This works on the host machine i.e. a log file is created and it shows the path to the EXE, but no log file is created on the VM.
NOTE: When testing on either machine, I'm installing afresh from the application's MSI. Also note that the host is running Windows 11 and the VM is running Windows 10.
So, why does the same code fail to either run the EXE or create a log file on the VM?
I eventually worked out that the problem was how C# handles strings.
If you read through my problem above you will see that, weirdly the same code worked fine on Windows 11 but not on Windows 10.
The problem was that I was letting the compiler interpret the path string. I had 'escaped' the slashes as shown here and it should have worked fine:
sEXE = "C:\\temp\\AddLocation.exe";
Changing it to the following resolved the problem so that it works on both now:
sEXE = #"C:\temp\AddLocation.exe";
Similarly, whereas it wouldn't create a log file on Win10, changing the path to the log file to the following fixed it:
using (StreamWriter sr = new StreamWriter(#"C:\Temp\ShellExtLog.txt"))
Question: In my following case, how can I use allowElevation capability from a UWP app to execute code with elevated privileges on my Windows 10 desktop with the 1809 update. This good article from Stefan Wick explains a similar use of such a capability from UWP app to a WPF app but in my case I'm using a Class Library instead of an exe.
Details: In my UWP project in VS2019, I've added .NET Standard Class Library project. My one UWP method is calling following method of my class library project. But due to Sandbox nature of UWP - as expected - the app is throwing Access denied error at line Process.Start() of the code.
public void Process_Start_Test()
{
using (Process myProcess = new Process())
{
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.FileName = #"C:\DotNET2019\UWP\TestFolder\MyExeApp.exe";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start(); //Access denied error here
}
}
You can't call Process.Start from a .NET Standard library that is referenced by your sandboxed UWP app.
You need to create an actual elevated process (.exe) that calls Process.Start as Stefan's blog post explains.
The full-trust .exe may of course reference your class library where the Process_Start_Test() is defined, but the method has to be called from the full-trust process regardless of whether it's defined in a library.
I have a C# application that gets a list of directories inside a folder. This is done using the call
String[] projects = System.IO.Directory.GetDirectories("path/to/folder", "*", System.IO.SearchOption.TopDirectoryOnly);
This works fine on my machine, but after publishing (resulting in a setup.exe, as well as programName.application + Application Files) I tried running the program on a new machine and it threw an unhandled exception error.
The error was in regards to being unable to connect to a database, but the interesting part is that it was complaining about path not being valid, listing a path that only exists on my machine.
Does System.IO.Directory.GetDirectories not get reinitialized when running on another machine?
I guess the problem is with path/to/folder, as that path might not exist in new machine. Don't hard-code the path. Instead read it from config file (app.config using ConfigurationManager).
I get the following exception when I try to copy a file in my Windows Application...
Access to the path 'autorun.inf' is denied.
The file I am trying to copy is a shortcut file. However when I move the EXACT line of code in a standalone application, it executes flawlessly. Same user credentials. There is no difference on how I launch either application.
This is the line of code...
File.Copy(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "JEE Startup.lnk"), #"C:\Documents and Settings\All Users\Start Menu\Programs\Startup\JEE Startup.lnk", true);
I tried deleting the bin folder and rebuilding. No luck.
I have no idea what is wrong.
The application is being executed on an XP machine.
The scenario:
I have a Java based installer.
The Java based installer calls a C# program, whose job is to create a shortcut.
The shortcut location depends on if the installer is running as administrator or as a regular user. When running as admin, I'm trying to create a shortcut to "%ALLUSERSPROFILE%\Desktop", else I write to "%USERPROFILE%\Desktop".
My impression is that the issue seems to be a loss of administrative privilege when my Java program calls my C# shortcut maker program.
Notes:
I run my Java based installer as administrator (right click, run as administrator).
I'm able to verify the installer is running with administrator privileged because I can read registry keys that require administrative privilege.
I'm calling my C# program via 'Process process = Runtime.getRuntime().exec(command);'
When running the command manually through an administrative command prompt, the command works fine. (When outputting to "%ALLUSERSPROFILE%\Desktop")
When running the the same command manually, from a normal command prompt, I get System.UnauthorizedAccessException. (Which is to be expected). The program crashes in a similar was that it does when run from the installer.
The Exception:
Unhandled Exception: System.UnauthorizedAccessException: Access is
denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) at
IWshRuntimeLibrary.IWshShortcut.Save()
Any thoughts on what I'm missing? The installer needs to be flexible to run as both a normal user and as an administrator. How can I ensure this behavior?
Update 1
I attached a debugger to the C# program at runtime. It is throwing a:
DirectoryNoFoundException was unhandled
The system cannot find the path specified. (Exception from HRESULT: 0x80070003)
I added "mkdir" commands before my shortcutmaker commands. The mkdir commands, just ensure that the directories exist before trying to write to them.
Rebuilt the installer, ran it and when trying to mkdir "%ALLUSERSPROFILE%\Desktop", java throws an exception of
java.io.IOException: Cannot run program "mkdir": CreateProcess error=2, The system cannot find the file specified
java.io.IOException: Cannot run program "mkdir": CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
at java.lang.Runtime.exec(Unknown Source)
At this point, it looks like my process isn't getting admin access
Process process = Runtime.getRuntime().exec(command);
I'm going to see if I can find anything else.
Update 2
The following gave me some info that I tried: Enterprise Logging not translating environment variables in XML Trace Listener fileName specification
It suggested that %ALLUSERSPROFILE% was not getting translated.
Instead of %ALLUSERSPROFILE%, I got the environment variable values via:
String allUsersProfile = System.getenv("ALLUSERSPROFILE");
String userProfile = System.getenv("USERPROFILE");
I was then able to supply the actual values to the C# program. But I'm still having issues.
From a admin console I can navigate to "c:\ProgramData\Start Menu", but if I run "explorer" with administrative priviledges, I can navigate to "c:\ProgramData" but not see anything past that... Through some looking, I found out that "c:\ProgramData\Start Menu" is a protected operating system file. So I turned on the setting to see it. So now I can see it, but not go into it.
Using system internals, I elevated an explorer.exe to "system" access and still can't go into the folder (System internal elevation reference: http://verbalprocessor.com/2007/12/05/running-a-cmd-prompt-as-local-system/)
I right clicked on the folder and checked out the security tab. It looks like even my "System" user has limited access. I find this a bit baffling, that I can run the command from an admin command prompt that will write the shortcut to the desktop, but going through this other process I cannot... I also find the access to be a bit inconsistent.