I have a Xamarin application running on Windows, and I have a method which includes an opening of a pdf file like this:
var psi = new ProcessStartInfo
{
FileName = "cmd",
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
CreateNoWindow = true,
Arguments = $"/c start {filename}"
};
Process.Start(psi);
When this executes, the windows opens a dialog with the following message:
Windows cannot access the specified device, path, or file. You may not have the appropriate permissions to access the item.
The filename is a pdf file located in the LocalApplicationData, and I also have a database there, and the application is normally creating a database there and manipulates with it, so it should have a permission to access that folder. Also, when I run that pdf with double-click outside the application, the pdf opens normally with Chrome. How to solve this?
Unless you have a file there called "cmd" this won't work, as you have declared your filename as a string with the value "cmd".
Related
I have build a simple windows form where when i press a button run a process indicated in a TextBox
I have tried with this code
Try
System.Diagnostics.Process.Start(TextBox1.Text)
Catch ex As Exception
MsgBox("Error")
End Try
Code works, but I don't understand why I canno't run a .exe genereted from a compiled c project using gcc (which is my goal).
I have tried to execute as Administrator too.
Someone can explain me?
(Converting my comment to an answer)
Code works, but I don't understand why I canno't run a .exe genereted from a compiled c project using gcc (which is my goal).
I suspect the problem is that your gcc-compiled executable has runtime dependencies on files located in the same filesystem directory as your gcc-compiled executable and it references those files only by their short-names (e.g. "someFile.txt") instead of by their absolute-path filenames (e.g. "C:\my-gcc-program\bin\someFile.txt") then the OS looks inside that process' Working Directory (aka Current Directory).
Note that when your program uses Process.Start(String fileName) then the newly created (child) OS process inherits your process's Working Directory rather than it being reset to the new process' executable's filename's parent directory!
So if your child process expects "someFile.txt" to be in its working-directory then you need to launch the child-process with the correct working-directory instead of it inheriting it from your process.
You can do this in 2 different ways, both of which require you to use ProcessStartInfo instead of any of the Process.Start overloads that accept String fileName.
Option 1: Set ProcessStartInfo.WorkingDirectory directly:
ProcessStartInfo psi = new ProcessStartInfo()
{
FileName = #"C:\my-gcc-program\bin\program.exe",
WorkingDirectory = #"C:\my-gcc-program\bin",
}
using( Process p = Process.Start( psi ) )
{
p.WaitForExit();
}
Option 2: Use ProcessStartInfo.UseShellExecute;
The UseShellExecute option creates the new process as though the user started it through their OS shell, such as cmd.exe or Explorer.exe rather than as a child process of your process. (One of the many) effects of this option is that the OS handles setting the Working-directory of this new process automatically for you.
Note that in .NET Framework, this is true by default - but false in .NET Core (and will cause errors if used in UWP). Because it's not true by default in .NET Core you should set it explicitly if you're depending on it to work on all platforms besides UWP.
Note that when using UseShellExecute == true, you still must provide a valid WorkingDirectory path, however its purposes changes:
The WorkingDirectory property behaves differently when UseShellExecute is true than when UseShellExecute is false.
When UseShellExecute is true, the WorkingDirectory property specifies the location of the executable.
If WorkingDirectory is an empty string, the current directory is understood to contain the executable.
When UseShellExecute is true, the working directory of the application that starts the executable is also the working directory of the executable.
When UseShellExecute is false, the WorkingDirectory property is not used to find the executable. Instead, its value applies to the process that is started and only has meaning within the context of the new process.
ProcessStartInfo psi = new ProcessStartInfo()
{
FileName = #"program.exe",
WorkingDirectory = #"C:\my-gcc-program\bin",
UseShellExecute = true
}
using( Process p = Process.Start( psi ) )
{
p.WaitForExit();
}
I post here the code who I have written in Button click event. Maybe can be useful for someone
Try
Dim startInfo As New ProcessStartInfo
startInfo.UseShellExecute = True
startInfo.WorkingDirectory = "C:\workDirectory"
startInfo.FileName = TextBox1.Text
System.Diagnostics.Process.Start(startInfo)
Catch ex As Exception
MsgBox("Error")
End Try
Thanks #Dai for help
I create an executable based on a gui with several functions and files, and if I open the executable in the installation folder or using the desktop shortcut everything works fine. If I open through the starting menu, the executable doesn't incorporate the images and doesn’t run. What I can do to prevent this issue? Is it possible to prevent the shortcut in the windows starting menu?
I found a solution here:
You can use the following function to get the folder of the executed exe file:
function currentDir = getcurrentdir()
if isdeployed % Stand-alone mode.
[status, result] = system('path');
currentDir = char(regexpi(result, 'Path=(.*?);', 'tokens', 'once'));
else % MATLAB mode.
currentDir = pwd;
end
Call the function and use cd in the GUI opening function:
currentDir = getcurrentdir();
cd(currentDir);
I created a guide testing application, and used deploytool for compiling and packaging for external deployment.
For testing, I added a text label to the GUI (Tag name: text2).
In the GUI opening function I added the following code:
% --- Executes just before GuideApp is made visible.
function GuideApp_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
handles.text2.String = 'Starting...';
pause(1);
currentDir = getcurrentdir();
%Set the label's text to display currentDir.
handles.text2.String = currentDir;
%Change directory to the directory of the exe file.
cd(currentDir);
%Create a file in the directory (just for testing):
f = fopen('currentDir.txt', 'w');fprintf(f, '%s\r\n', currentDir);fclose(f);
% Update handles structure
guidata(hObject, handles);
The above solution is working correctly:
The text of label displays the path of the exe file.
currentDir.txt file is created in the path of the exe file.
On windows, MZ/PE executables often have an attibute called "Original File Name", used to describe the original file name assigned to an executable file when it was created.
It is readable to a Windows user from the "Details" tab of the file's "Properties" window (opened by rightclicking a file and selecting "Properties").
I found many other questions that discuss "original file name, so to make it clear, I'm talking about this field, for the mspaint.exe file:
I however, whould like to access/read this attribute (and potentially edit it) using batch files or the windows command line (not powershell, please!).
Thanks!
Windows does not have a built-in command line tool to read version information from PE files.
You can use a resource editor like Resource Hacker to export information but you still have to parse the exported file.
On WinVista+ (and WinXP with desktop search installed) you can read the information using the shell property system (the same API used by the file properties dialog).
A Microsoft developer has created a free tool called shellproperty.exe that you can use to read the System.OriginalFileName property.
With Windows Script Host it is also possible to access the property system if you use the ShellFolderItem.ExtendedProperty method.
And finally, a WSH script can be merged with a batch file to create a working polyglot with zero external dependencies:
#if (1 == 0) #end /*
#cscript.exe /E:jscript /nologo "%~f0" %*
#goto :eof
*/
var objShell = new ActiveXObject("shell.application");
var objFolder2, ssfSysDir = 0x25, propVal = "";
objFolder2 = objShell.NameSpace(ssfSysDir);
if (objFolder2 != null)
{
var objFolderItem;
objFolderItem = objFolder2.ParseName("mspaint.exe");
if (objFolderItem != null)
{
propVal = objFolderItem.ExtendedProperty("{0CEF7D53-FA64-11D1-A203-0000F81FEDEE},6");
WScript.Echo(propVal);
}
}
I have a process that creates Windows internet shortcut files (.url). The files are encoded in UTF-8. The files contain an [InternetShortcut] section, where a URL= is specified. In this case, these are file:/// protocol URLs, which allow people to open paths on their LAN. The URLs are all UNC paths.
Normally the process works fine. But when a UNC path contains Unicode characters, such as the "í" from the code sample below, Windows is unable to "find" the URL when an end user tries to open the internet shortcut from Windows Explorer:
A sample file follows:
[InternetShortcut]
URL=file:///\\lt-splourde\d$\POC\Montería Test\
IconIndex=1
When I open the sample .url file above with a text editor, I see the path with the proper Unicode characters. But when I try to open the file from Windows Explorer, in order to access the path, Windows reports that it is unable to access the path, and it seems to mangle the Unicode characters.
The source code that creates these shortcuts follows:
private void CreateShortcutAsUrl(string uncRootPath, string name, string path, int projectId)
{
path = path + (path.EndsWith(#"\") ? "" : #"\");
using (StreamWriter writer = new StreamWriter(
String.Format(#"{0}\{1}\{2}.url", uncRootPath,
ShortcutsDirectory, new FileServerController().SanitizeNameForDirectory(name)),
false, Encoding.UTF8))
{
writer.WriteLine(#"[InternetShortcut]");
writer.WriteLine(#"URL=file:///" + path);
writer.Flush();
}
}
Does anyone know of a solution for this issue?
Thanks!
(I had posted this on superuser originally, but I feel like the content is more programmer oriented)
Try the .NET equivalent of InternetCanonicalizeUrl, which is System.Uri.EscapeUriString, so something like this (assuming your URI is in szOriginalString
String szEscapedString = System.Uri.EscapeUriString(szOriginalString);
Then write szEscapedString as the URI instead of the original.
How do I register a custom protocol with Windows so that when clicking a link in an email or on a web page my application is opened and the parameters from the URL are passed to it?
Go to Start then in Find type regedit -> it should open Registry editor
Click Right Mouse on HKEY_CLASSES_ROOT then New -> Key
In the Key give the lowercase name by which you want urls to be called (in my case it will be testus://sdfsdfsdf) then Click Right Mouse on testus -> then New -> String Value and add URL Protocol without value.
Then add more entries like you did with protocol ( Right Mouse New -> Key ) and create hierarchy like testus -> shell -> open -> command and inside command change (Default) to the path where .exe you want to launch is, if you want to pass parameters to your exe then wrap path to exe in "" and add "%1" to look like: "c:\testing\test.exe" "%1"
To test if it works go to Internet Explorer (not Chrome or Firefox) and enter testus:have_you_seen_this_man this should fire your .exe (give you some prompts that you want to do this - say Yes) and pass into args testus://have_you_seen_this_man.
Here's sample console app to test:
using System;
namespace Testing
{
class Program
{
static void Main(string[] args)
{
if (args!= null && args.Length > 0)
Console.WriteLine(args[0]);
Console.ReadKey();
}
}
}
Hope this saves you some time.
The MSDN link is nice, but the security information there isn't complete. The handler registration should contain "%1", not %1. This is a security measure, because some URL sources incorrectly decode %20 before invoking your custom protocol handler.
PS. You'll get the entire URL, not just the URL parameters. But the URL might be subject to some mistreatment, besides the already mentioned %20->space conversion. It helps to be conservative in your URL syntax design. Don't throw in random // or you'll get into the mess that file:// is.
If anyone wants a .reg file for creating the association, see below:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\duck]
"URL Protocol"=""
[HKEY_CLASSES_ROOT\duck\shell]
[HKEY_CLASSES_ROOT\duck\shell\open]
[HKEY_CLASSES_ROOT\duck\shell\open\command]
#="\"C:\\Users\\duck\\source\\repos\\ConsoleApp1\\ConsoleApp1\\bin\\Debug\\net6.0\\ConsoleApp1.exe\" \"%1\""
Pasted that into notepad, the file -> save as -> duck.reg, and then run it. After running it, when you type duck://arg-here into chrome, ConsoleApp1.exe will run with "arg-here" as an argument. Double slashes are required for the path to the exe and double quotes must be escaped.
Tested and working on Windows 11 with Edge (the chrome version) and Chrome
There is an npm module for this purpose.
link :https://www.npmjs.com/package/protocol-registry
So to do this in nodejs you just need to run the code below:
First Install it
npm i protocol-registry
Then use the code below to register you entry file.
const path = require('path');
const ProtocolRegistry = require('protocol-registry');
console.log('Registering...');
// Registers the Protocol
ProtocolRegistry.register({
protocol: 'testproto', // sets protocol for your command , testproto://**
command: `node ${path.join(__dirname, './index.js')} $_URL_`, // $_URL_ will the replaces by the url used to initiate it
override: true, // Use this with caution as it will destroy all previous Registrations on this protocol
terminal: true, // Use this to run your command inside a terminal
script: false
}).then(async () => {
console.log('Successfully registered');
});
Then suppose someone opens testproto://test
then a new terminal will be launched executing :
node yourapp/index.js testproto://test
It also supports all other operating system.